Esempio n. 1
0
static c_binding
c_bindingNew(
    c_scope scope,
    c_metaObject object)
{
    c_binding result;

    result = c_binding(c_mmMalloc(MM(scope),C_SIZEOF(c_binding)));
    if (result) {
        result->object = c_keep(object);
        result->nextInsOrder = NULL;
    }

    return result;
}
Esempio n. 2
0
void *
c_mmCacheMalloc (
    c_mmCache _this)
{
    c_voidp  object;
    c_long   size;
    c_block  block, ref;
    c_sample sample;

#ifndef NDEBUG
    _this->access++;
    assert(_this->access == 1);
#endif

    if (_this->incomplete == NULL) {
        /** There are no blocks that have free space so a new
            block must be allocated. This block will be the only
            incomplete block and therefore _this->incomplete must
            be set to this block as well as _this->last.
        */
        size = blockSize(_this->count,_this->size);
        block = c_mmMalloc(_this->mm,size);
        block->prev = _this->last;
        block->next = NULL;
        block->used = 1;
        block->count = 1;
        block->firstFree = NULL;
        if (_this->last != NULL) {
            c_block(_this->last)->next = block;
        }
        _this->last = block;
        if (block->count < _this->count) {
            /* In the rare situation that blocks are specified to
               provide space for only one object _this->incomplete
               must NOT be set to the new block.
            */
            _this->incomplete = block;
        }
        if (_this->cache == NULL) {
            _this->cache = block;
        }
        /** Get a reference to the first sample and initialise the sample.
        */
        sample = blockSample(block,_this->size,0);
#ifdef C_MM_CONFIDENCE
        sample->confidence = C_MM_CONFIDENCE;
#endif /* C_MM_CONFIDENCE */
        sample->block = block;
        /** Get the address of the first object to be returned.
        */
        object = sampleObject(sample);
        /** Update the cache statistics.
        */
        _this->allocated += size;
        /* While blockSize(_this->count,_this->size) memory has been allocated,
         * only _this->size * _this->count is available (rest is headers), so
         * add that amount to the free-memory. */
        _this->free += blockFreeSize(_this);
    } else {
        block = _this->incomplete;
        if (block->firstFree == NULL) {
            assert(block->count <= _this->count);
            sample = blockSample(block,_this->size,block->count);
#ifdef C_MM_CONFIDENCE
            sample->confidence = C_MM_CONFIDENCE;
#endif /* C_MM_CONFIDENCE */
            sample->block = block;
            object = sampleObject(sample);
            block->count++;
        } else {
            sample = block->firstFree;
            block->firstFree = sample->nextFree;
#ifdef C_MM_CONFIDENCE
            sample->confidence = C_MM_CONFIDENCE;
#endif /* C_MM_CONFIDENCE */
            sample->nextFree = NULL;
            object = sampleObject(sample);
        }
        block->used++;
        if (block->used == _this->count) {
            _this->incomplete = block->next;
        } else {
            ref = block;
            while ((ref->prev != NULL) && (ref->prev->used < block->used)) {
                ref = ref->prev;
            }
#ifndef NDEBUG
            assert(_this->access == 1);
#endif
            if (ref != block) {
                /* need to reorder blocks because blocks are ordered */
                /* by available space. Less space is put in front of */
                /* blocks having more space.                         */
                /* block must be placed in front of ref.             */
                if (block->next != NULL) {
                    block->next->prev = block->prev;
                } else {
                    /* Block is last in the row so _this->last needs */
                    /* to be updated to the forelast block.          */
                    assert(_this->last == block);
                    _this->last = block->prev;
                }
                assert(block->prev != NULL);
                block->prev->next = block->next;
                /* block is now removed from the list. */
                /* Now insert block before ref.        */
                if (ref->prev != NULL) {
                    ref->prev->next = block;
                }
                block->prev = ref->prev;
                ref->prev = block;
                block->next = ref;
                if (block->prev == NULL) {
                    /* Block is first in the row so _this->cache needs */
                    /* to be updated to this block.                    */
                    _this->cache = block;
                }
                if (_this->incomplete == block->next) {
                    _this->incomplete = block;
                }
            }
        }
    }
    /* One extra slot has been malloc'd , so substract '1 * size' from free.*/
    _this->free -= _this->size;

#ifndef NDEBUG
    assert(_this->access == 1);
#endif

#ifndef NDEBUG
    {
        /** This piece of debugging code verifies the consistentcy of the
            c_mmCache. The code will walk over all allocated memory blocks
            and verify if all prev and next pointers have correct values.
            This code also verifies if the first incomplete block encountered
            during the walk is the same as refered by _this->incomplete.
            If an assertion fails in this code then it is likely that the
            consistency is corrupted during this method because all actions
            on the cache verify consistentcy at the end of the action. But also
            multy threaded access may have corrupted the consistency since the
            cache itself does not protect against MT access.
        */
        c_bool incomplete = FALSE;

        block = _this->cache;
        if (block != NULL) {
            /** The current block is the first block in the list.
                So now verify if the block->prev field is NULL.
            */
            assert(block->prev == NULL);
        }
        while (block != NULL) {
            if (!incomplete && block->used < _this->count) {
                incomplete = TRUE;
                /** The current block is the first incomplete block in the list.
                    So now verify if the _this->incomplete field refers to this block.
                */
                assert(_this->incomplete == block);
            }
            if (block->next != NULL) {
                /* The current block is not the last so verify if the next block refers
                   to this block and verify that the next block does not have more free
                   space then this block. All blocks are ordered by available free space.
                   Less space blocks must be in front of more space blocks in the list.
                */
                assert(block->next->prev == block);
                assert(block->next->used <= block->used);
            } else {
                /** The current block is the last block in the list.
                   So now verify if the _this->last field refers to this block.
                */
                assert(_this->last == block);
            }
            block = block->next;
        }
    }
#endif
#ifndef NDEBUG
    _this->access--;
    assert(_this->access == 0);
#endif /* NDEBUG */
#ifdef C_MM_CONFIDENCE
    sample = c_sample((c_address)object - sampleHeaderSize);
    assert(sample->confidence == C_MM_CONFIDENCE);
#endif /* C_MM_CONFIDENCE */

    return object;
}