/* 
 * Copyright (C) 2020,  Paul Sheer. All rights reserved.
 * 
 * This software is provided without warranty. The author(s) disclaim liability for damages
 * related to this software. All risk is assumed by you.
 * 
 */


int dfwmalloc_prepare (struct malloc_calc *precalc, size_t n);

static inline void *malloc_precalc (struct malloc_calc *precalc)
{
    struct control_block *cb;
    cb = precalc->cbh->partial_blocks_first;
    if (__builtin_expect (cb && cb->free_count, 1)) {
        if (__builtin_expect (cb->free_count == cb->used_count, 0))
            precalc->cbhs->cb_refs++;
        cb->free_count--;
#ifdef WITH_ACCOUNTS
        precalc->cbhs->total_alloced += precalc->len;
        precalc->cbhs->cb_total_blocks++;
        precalc->cbhs->total_free--;
#endif
        return dfwmalloc_cb_get_min_block (cb);
    } else if (cb && cb->used_count < cb->total_count) {
        void *u;
        u = CB_POINTER (cb, precalc->page_info, cb->used_count);
        if (cb->free_count == cb->used_count)
            precalc->cbhs->cb_refs++;
        cb->used_count++;
#ifdef WITH_ACCOUNTS
        precalc->cbhs->total_alloced += precalc->len;
        precalc->cbhs->cb_total_blocks++;
#endif
        return u;
    }
    return malloc (precalc->len);
}

static inline void free_precalc (struct malloc_calc *precalc, void *u)
{
    struct control_block *cb;
    cb = (struct control_block *) (void *) ((unsigned long long) u & precalc->mask);
    if (__builtin_expect ((cb->free_count + 1) == cb->used_count || !(cb->cb_magic_flags & CB_FLAG_PARTIAL_LINKED), 0)) {
        free (u);
        return;
    }
    dfwmalloc_cb_insert_free_block (cb, u);
#ifdef WITH_ACCOUNTS
    precalc->cbhs->total_alloced -= precalc->len;
    precalc->cbhs->cb_total_blocks--;
    precalc->cbhs->total_free++;
#endif
}


