Пример #1
0
void
c_mmCacheDestroy (
    c_mmCache _this)
{
    c_block b;
    c_block remove;

    assert(_this != NULL);
    /* assert(_this->cache == NULL); */
    /* assert(_this->incomplete == NULL); */
    /* assert(_this->last == NULL); */
    /* assert(_this->allocated == 0); */
    /* assert(_this->free == 0); */

    b = _this->cache;
    while (b != NULL) {
        remove = b;
        b = b->next;
        c_mmFree(_this->mm, remove);
    }

    _this->cache = NULL;
    _this->incomplete = NULL;
    _this->last = NULL;

    /* Do not use c_mmFree here, because the created cache has to be removed
     * from the cache-list in the memory manager. */
    c_mmFreeCache(_this->mm,_this);
}
Пример #2
0
static c_bool
c_bindingFree (
    c_binding binding,
    c_mm mm)
{
    if (binding == NULL) {
        return TRUE;
    }
    c_free(binding->object);
    c_mmFree(mm,binding);
    return TRUE;
}
Пример #3
0
void
c_mmCacheFree (
    c_mmCache _this,
    void *memory)
{
    c_block block, ref;
    c_sample sample;
    c_long size;

    assert(_this != NULL);
    assert(memory != NULL);

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

    sample = c_sample((c_address)memory - sampleHeaderSize);
#ifdef C_MM_CONFIDENCE
    assert(sample->confidence == C_MM_CONFIDENCE);
    sample->confidence = 0;
#endif /* C_MM_CONFIDENCE */
    block = sample->block;
    assert(block->used > 0);
    block->used--;
#if 0
    if ((block->used == 0) && (block->next)) {
#else
    if (block->used == 0) {
#endif
        if (block->prev == NULL) {
            _this->cache = block->next;
        } else {
            block->prev->next = block->next;
        }
        if (block->next != NULL) {
            block->next->prev = block->prev;
        }
        if (_this->last == block) {
            _this->last = block->prev;
        }
        if (_this->incomplete == block) {
            _this->incomplete = block->next;
        }
        c_mmFree(_this->mm, block);
        size = blockSize(_this->count,_this->size);
        _this->allocated -= size;
        _this->free -= blockFreeSize(_this);;
    } else {
        sample->nextFree = block->firstFree;
        block->firstFree = sample;
        ref = block;
        while ((ref->next != NULL) && (ref->next->used >= block->used)) {
            ref = ref->next;
        }
#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 after ref.                   */
            if (block->prev != NULL) {
                block->prev->next = block->next;
            } else {
                /* Block is first in the row so _this->cache needs */
                /* to be updated to the second block in the row.   */
                assert(_this->cache == block);
                _this->cache = block->next;
            }
            assert(block->next != NULL);
            block->next->prev = block->prev;
            /* block is now removed from the list. */
            /* Now insert block after ref.         */
            if (_this->incomplete == block) {
                _this->incomplete = block->next;
            }
            if (ref->next != NULL) {
                ref->next->prev = block;
            }
            block->next = ref->next;
            ref->next = block;
            block->prev = ref;
            if (block->next == NULL) {
                /* Block is last in the row so _this->last needs */
                /* to be updated to this block.                  */
                _this->last = block;
            }
        }
        if ((_this->incomplete == NULL) || (_this->incomplete == block->next)) {
            _this->incomplete = block;
        }
    }
    /* One slot has been freed , so add '1 * size' to 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
}

c_size
c_mmCacheGetAllocated(
    c_mmCache _this)
{
    assert(_this);

    return _this->allocated;
}