Exemple #1
0
/* If shift is non-zero, it represents the number of places to move
 * blocks in memory. Calculate the new address for this block,
 * update its entry in the handle table, and then move its contents.
 *
 * Returns false if moving was unsucessful
 * (NULL callback or BUFLIB_CB_CANNOT_MOVE was returned)
 */
static bool
move_block(struct buflib_context* ctx, union buflib_data* block, int shift)
{
    char* new_start;
    union buflib_data *new_block, *tmp = block[1].handle;
    struct buflib_callbacks *ops = block[2].ops;
    if (!IS_MOVABLE(block))
        return false;

    int handle = ctx->handle_table - tmp;
    BDEBUGF("%s(): moving \"%s\"(id=%d) by %d(%d)\n", __func__, block[3].name,
            handle, shift, shift*(int)sizeof(union buflib_data));
    new_block = block + shift;
    new_start = tmp->alloc + shift*sizeof(union buflib_data);

    /* If move must be synchronized with use, user should have specified a
       callback that handles this */
    if (ops && ops->sync_callback)
        ops->sync_callback(handle, true);

    bool retval = false;
    if (!ops || ops->move_callback(handle, tmp->alloc, new_start)
                    != BUFLIB_CB_CANNOT_MOVE)
    {
        tmp->alloc = new_start; /* update handle table */
        memmove(new_block, block, block->val * sizeof(union buflib_data));
        retval = true;
    }

    if (ops && ops->sync_callback)
        ops->sync_callback(handle, false);

    return retval;
}
Exemple #2
0
/* If shift is non-zero, it represents the number of places to move
 * blocks in memory. Calculate the new address for this block,
 * update its entry in the handle table, and then move its contents.
 *
 * Returns false if moving was unsucessful
 * (NULL callback or BUFLIB_CB_CANNOT_MOVE was returned)
 */
static bool
move_block(struct buflib_context* ctx, union buflib_data* block, int shift)
{
    char* new_start;
    union buflib_data *new_block, *tmp = block[1].handle;
    struct buflib_callbacks *ops = block[2].ops;
    if (!IS_MOVABLE(block))
        return false;

    int handle = ctx->handle_table - tmp;
    BDEBUGF("%s(): moving \"%s\"(id=%d) by %d(%d)\n", __func__, block[3].name,
            handle, shift, shift*(int)sizeof(union buflib_data));
    new_block = block + shift;
    new_start = tmp->alloc + shift*sizeof(union buflib_data);

    /* disable IRQs to make accessing the buffer from interrupt context safe. */
    /* protect the move callback, as a cached global pointer might be updated
     * in it. and protect "tmp->alloc = new_start" for buflib_get_data() */
    /* call the callback before moving */
    if (ops && ops->sync_callback)
    {
        ops->sync_callback(handle, true);
    }
    else
    {
        disable_irq();
    }

    bool retval = false;
    if (!ops || ops->move_callback(handle, tmp->alloc, new_start)
            != BUFLIB_CB_CANNOT_MOVE)
    {
        tmp->alloc = new_start; /* update handle table */
        memmove(new_block, block, block->val * sizeof(union buflib_data));
        retval = true;
    }

    if (ops && ops->sync_callback)
    {
        ops->sync_callback(handle, false);
    }
    else
    {
        enable_irq();
    }

    return retval;
}
Exemple #3
0
/* Return the maximum allocatable contiguous memory in bytes */
size_t
buflib_allocatable(struct buflib_context* ctx)
{
    union buflib_data *this;
    size_t free_space = 0, max_free_space = 0;

    /* make sure buffer is as contiguous as possible  */
    if (!ctx->compact)
        buflib_compact(ctx);

    /* now look if there's free in holes */
    for(this = find_first_free(ctx); this < ctx->alloc_end; this += abs(this->val))
    {
        if (this->val < 0)
        {
            free_space += -this->val;
            continue;
        }
        /* an unmovable section resets the count as free space
         * can't be contigous */
        if (!IS_MOVABLE(this))
        {
            if (max_free_space < free_space)
                max_free_space = free_space;
            free_space = 0;
        }
    }

    /* select the best */
    max_free_space = MAX(max_free_space, free_space);
    max_free_space *= sizeof(union buflib_data);
    max_free_space = MAX(max_free_space, free_space_at_end(ctx));

    if (max_free_space > 0)
        return max_free_space;
    else
        return 0;
}