Beispiel #1
0
//参数值为使用到的slabclass数组元素个数  
//为slabclass数组的每一个元素(使用到的元素)分配内存 
static void slabs_preallocate (const unsigned int maxslabs) {
    int i;
    unsigned int prealloc = 0;

    /* pre-allocate a 1MB slab in every size class so people don't get
       confused by non-intuitive "SERVER_ERROR out of memory"
       messages.  this is the most common question on the mailing
       list.  if you really don't want this, you can rebuild without
       these three lines.  */

    //遍历slabclass数组
    for (i = POWER_SMALLEST; i <= POWER_LARGEST; i++) {
        if (++prealloc > maxslabs)//当然是只遍历使用了的数组元素
            return;
        if (do_slabs_newslab(i) == 0) {//为每一个slabclass_t分配一个内存页
            //如果分配失败,将退出程序.因为这个预分配的内存是后面程序运行的基础
            //如果这里分配失败了,后面的代码无从执行。所以就直接退出程序
            fprintf(stderr, "Error while preallocating slab memory!\n"
                "If using -L or other prealloc options, max memory must be "
                "at least %d megabytes.\n", power_largest);
            exit(1);
        }
    }

}
Beispiel #2
0
void* Slab::do_slabs_alloc(size_t size, unsigned int id) {
    void* ret = 0;
    struct base_item *it = 0;
    slabclass& p = mem_base[id];

    if (id < POWER_SMALLEST || id > POWER_LARGEST) {
        return (void*)0;
    }

    //查看是否freelist上没有东西了
    if (! (p.sl_curr != 0 || do_slabs_newslab(id) != 0) ) {
        return (void*)0;
    }
    else if (p.sl_curr != 0) {
        //从freelist取出一个给他
        it = (struct base_item*)(p.slots);
        p.slots = it->next;
        if (it->next) 
            it->next->prev = 0;
        p.sl_curr--;
        ret = (void*)it;
    }

    if (ret) {
        p.requested += size;
    }

    return ret;
}
Beispiel #3
0
/*@null@*/
static void *do_slabs_alloc(const size_t size, unsigned int id) {
    slabclass_t *p;
    void *ret = NULL;

    if (id < POWER_SMALLEST || id > power_largest) {
        MEMCACHED_SLABS_ALLOCATE_FAILED(size, 0);
        return NULL;
    }

    p = &slabclass[id];


    /* fail unless we have space at the end of a recently allocated page,
       we have something on our freelist, or we could allocate a new page */
    if (! (p->end_page_ptr != 0 || p->sl_curr != 0 ||
           do_slabs_newslab(id) != 0)) {
        /* We don't have more memory available */
        ret = NULL;
    } else if (p->sl_curr != 0) {
        /* return off our freelist */
#ifdef TEST_LRU
        item *it = (item *)p->slots;
        p->slots = it->next;
        if (it->next) it->next->prev = 0;
        p->sl_curr--;
        ret = (void *)it;
#endif

#ifdef TEST_CLOCK
        /* return off our freelist */
        slabbed_item* sl_it = (slabbed_item *)p->slots;
        p->slots = sl_it->next;
        if (sl_it->next) sl_it->next->prev = 0;
        p->sl_curr--;
        ret = (void *)sl_it;
#endif
    } else {
        /* if we recently allocated a whole page, return from that */
        assert(p->end_page_ptr != NULL);
        ret = p->end_page_ptr;
        if (--p->end_page_free != 0) {
            p->end_page_ptr = ((caddr_t)p->end_page_ptr) + p->size;
        } else {
            p->end_page_ptr = 0;
        }
        /* item *it = (item *)ret; */
        /* reset_version(it); */
    }

    if (ret) {
        p->requested += size;
        MEMCACHED_SLABS_ALLOCATE(size, id, p->size, ret);
    } else {
        MEMCACHED_SLABS_ALLOCATE_FAILED(size, id);
    }

    return ret;
}
Beispiel #4
0
/*@null@*/
static void *do_slabs_alloc(const size_t size, unsigned int id) {
    slabclass_t *p;
    void *ret = NULL;
    item *it = NULL;

    if (id < POWER_SMALLEST || id > power_largest) {
        MEMCACHED_SLABS_ALLOCATE_FAILED(size, 0);
        return NULL;
    }

    p = &slabclass[id];
    assert(p->sl_curr == 0 || ((item *)p->slots)->slabs_clsid == 0);

#ifdef USE_SYSTEM_MALLOC
    if (mem_limit && mem_malloced + size > mem_limit) {
        MEMCACHED_SLABS_ALLOCATE_FAILED(size, id);
        return 0;
    }
    mem_malloced += size;
    ret = malloc(size);
    MEMCACHED_SLABS_ALLOCATE(size, id, 0, ret);
    return ret;
#endif

    /* fail unless we have space at the end of a recently allocated page,
       we have something on our freelist, or we could allocate a new page */
    if (! (p->end_page_ptr != 0 || p->sl_curr != 0 ||
           do_slabs_newslab(id) != 0)) {
        /* We don't have more memory available */
        ret = NULL;
    } else if (p->sl_curr != 0) {
        /* return off our freelist */
        it = (item *)p->slots;
        p->slots = it->next;
        if (it->next) it->next->prev = 0;
        p->sl_curr--;
        ret = (void *)it;
    } else {
        /* if we recently allocated a whole page, return from that */
        assert(p->end_page_ptr != NULL);
        ret = p->end_page_ptr;
        if (--p->end_page_free != 0) {
            p->end_page_ptr = ((caddr_t)p->end_page_ptr) + p->size;
        } else {
            p->end_page_ptr = 0;
        }
    }

    if (ret) {
        p->requested += size;
        MEMCACHED_SLABS_ALLOCATE(size, id, p->size, ret);
    } else {
        MEMCACHED_SLABS_ALLOCATE_FAILED(size, id);
    }

    return ret;
}
Beispiel #5
0
/* This calculation ends up adding sizeof(void *) to the item size. */
static void *do_slabs_alloc_chunked(const size_t size, slabclass_t *p, unsigned int id) {
    void *ret = NULL;
    item *it = NULL;
    int x;
    int csize = p->size - sizeof(item_chunk);
    unsigned int chunks_req = size / csize;
    if (size % csize != 0)
        chunks_req++;
    while (p->sl_curr < chunks_req) {
        if (do_slabs_newslab(id) == 0)
            break;
    }

    if (p->sl_curr >= chunks_req) {
        item_chunk *chunk = NULL;

        /* Configure the head item in the chain. */
        it = (item *)p->slots;
        p->slots = it->next;
        if (it->next) it->next->prev = 0;

        /* Squirrel away the "top chunk" into h_next for now */
        it->h_next = (item *)p->slots;
        assert(it->h_next != 0);
        chunk = (item_chunk *) it->h_next;

        /* roll down the chunks, marking them as such. */
        for (x = 0; x < chunks_req-1; x++) {
            chunk->it_flags &= ~ITEM_SLABBED;
            chunk->it_flags |= ITEM_CHUNK;
            /* Chunks always have a direct reference to the head item */
            chunk->head = it;
            chunk->size = p->size - sizeof(item_chunk);
            chunk->used = 0;
            chunk = chunk->next;
        }

        /* The final "next" is now the top of the slab freelist */
        p->slots = chunk;
        if (chunk && chunk->prev) {
            /* Disconnect the final chunk from the chain */
            chunk->prev->next = 0;
            chunk->prev = 0;
        }

        it->it_flags &= ~ITEM_SLABBED;
        it->it_flags |= ITEM_CHUNKED;
        it->refcount = 1;
        p->sl_curr -= chunks_req;
        ret = (void *)it;
    } else {
        ret = NULL;
    }

    return ret;
}
Beispiel #6
0
static void slabs_preallocate(const unsigned int maxslabs)
{
    int i;
    unsigned int prealloc = 0;

    /* pre-allocate a 1MB slab in every size class so people don't get
       confused by non-intuitive "SERVER_ERROR out of memory"
       messages.  this is the most common question on the mailing
       list.  if you really don't want this, you can rebuild without
       these three lines.  */

    for (i = POWER_SMALLEST; i <= POWER_LARGEST; i++) {
        if (++prealloc > maxslabs)
            return;
        do_slabs_newslab(i);
    }

    /* slab class 0 is used for collection items and small-size kv items */
    do_slabs_newslab(0);
}
Beispiel #7
0
/*@null@*/
static void *do_slabs_alloc(const size_t size, unsigned int id) {
    slabclass_t *p;
    void *ret = NULL;

    if (id < POWER_SMALLEST || id > power_largest) {
        MEMCACHED_SLABS_ALLOCATE_FAILED(size, 0);
	printf("%s:%d returning NULL from here\n", __func__, __LINE__);
        return NULL;
    }
    p = &slabclass[id];
    assert(p->sl_curr == 0 || ((item *)p->slots)->slabs_clsid == 0);

    DBG_INFO(DBG_ASSOC_HOPSCOTCH, "%s:%d: sl_curr = %u\n", __func__, __LINE__, p->sl_curr);
    /* fail unless we have space at the end of a recently allocated page,
       we have something on our freelist, or we could allocate a new page */
    if (! (p->sl_curr != 0 || do_slabs_newslab(id) != 0)) {
        /* We don't have more memory available */
	DBG_INFO(DBG_ASSOC_HOPSCOTCH, "%s:%d returning NULL from here\n", __func__, __LINE__);
        ret = NULL;
    } else if (p->sl_curr != 0) {
        /* return off our freelist */
#ifdef HOPSCOTCH_CLOCK
		slabbed_item* sl_it = (slabbed_item *)p->slots;
		p->slots = sl_it->next;
		if (sl_it->next) sl_it->next->prev = 0;
		//DBG_INFO(DBG_ASSOC_HOPSCOTCH, "%s:%d: before it_flags = %u\n", __func__, __LINE__, sl_it->it_flags);
		//__sync_fetch_and_and(&sl_it->it_flags, ~ITEM_SLABBED);
		//DBG_INFO(DBG_ASSOC_HOPSCOTCH, "%s:%d: after it_flags = %u\n", __func__, __LINE__, sl_it->it_flags);
		ret = (void *)sl_it;
#else
        item *it = (item *)p->slots;
        p->slots = it->next;
        if (it->next) it->next->prev = 0;
        /* Kill flag and initialize refcount here for lock safety in slab
         * mover's freeness detection. */
		DBG_INFO(DBG_ASSOC_HOPSCOTCH, "%s:%d: before it_flags = %u\n", __func__, __LINE__, sl_it->it_flags);
        it->it_flags &= ~ITEM_SLABBED;
		DBG_INFO(DBG_ASSOC_HOPSCOTCH, "%s:%d: after it_flags = %u\n", __func__, __LINE__, sl_it->it_flags);
        it->refcount = 1;
        ret = (void *)it;
#endif
        p->sl_curr--;
    }

    if (ret) {
        p->requested += size;
        MEMCACHED_SLABS_ALLOCATE(size, id, p->size, ret);
    } else {
        MEMCACHED_SLABS_ALLOCATE_FAILED(size, id);
    }

    DBG_INFO(DBG_ASSOC_HOPSCOTCH, "%s:%d returning ret = %p from here\n", __func__, __LINE__, ret);
    return ret;
}
Beispiel #8
0
void Slab::slabs_preallocate(const unsigned int maxslabs) {
    int i;
    unsigned int prealloc = 0;

    for ( i = POWER_SMALLEST; i < power_largest; i++) {
        if (++prealloc > maxslabs)
            return;
        if (do_slabs_newslab(i) == 0) {
            std::cerr << "Error while preallocating slab class "<< i << " memory!\n"; 
            exit(1);
        }
    }
}
Beispiel #9
0
/*@null@*/
static void *do_slabs_alloc(struct default_engine *engine, const size_t size, unsigned int id) {
    slabclass_t *p;
    void *ret = NULL;

    if (id < POWER_SMALLEST || id > engine->slabs.power_largest) {
        MEMCACHED_SLABS_ALLOCATE_FAILED(size, 0);
        return NULL;
    }

    p = &engine->slabs.slabclass[id];

#ifdef USE_SYSTEM_MALLOC
    if (engine->slabs.mem_limit && engine->slabs.mem_malloced + size > engine->slabs.mem_limit) {
        MEMCACHED_SLABS_ALLOCATE_FAILED(size, id);
        return 0;
    }
    engine->slabs.mem_malloced += size;
    ret = malloc(size);
    MEMCACHED_SLABS_ALLOCATE(size, id, 0, ret);
    return ret;
#endif

    /* fail unless we have space at the end of a recently allocated page,
       we have something on our freelist, or we could allocate a new page */
    if (! (p->end_page_ptr != 0 || p->sl_curr != 0 ||
           do_slabs_newslab(engine, id) != 0)) {
        /* We don't have more memory available */
        ret = NULL;
    } else if (p->sl_curr != 0) {
        /* return off our freelist */
        ret = p->slots[--p->sl_curr];
    } else {
        /* if we recently allocated a whole page, return from that */
        cb_assert(p->end_page_ptr != NULL);
        ret = p->end_page_ptr;
        if (--p->end_page_free != 0) {
            p->end_page_ptr = ((unsigned char *)p->end_page_ptr) + p->size;
        } else {
            p->end_page_ptr = 0;
        }
    }

    if (ret) {
        p->requested += size;
        MEMCACHED_SLABS_ALLOCATE(size, id, p->size, ret);
    } else {
        MEMCACHED_SLABS_ALLOCATE_FAILED(size, id);
    }

    return ret;
}
Beispiel #10
0
/*@null@*/
static void *do_slabs_alloc(const size_t size, unsigned int id, uint64_t *total_bytes,
        unsigned int flags) {
    slabclass_t *p;
    void *ret = NULL;
    item *it = NULL;

    if (id < POWER_SMALLEST || id > power_largest) {
        MEMCACHED_SLABS_ALLOCATE_FAILED(size, 0);
        return NULL;
    }
    p = &slabclass[id];
    assert(p->sl_curr == 0 || ((item *)p->slots)->slabs_clsid == 0);
    if (total_bytes != NULL) {
        *total_bytes = p->requested;
    }

    if (size <= p->size) {
        /* fail unless we have space at the end of a recently allocated page,
           we have something on our freelist, or we could allocate a new page */
        if (p->sl_curr == 0 && flags != SLABS_ALLOC_NO_NEWPAGE) {
            do_slabs_newslab(id);
        }

        if (p->sl_curr != 0) {
            /* return off our freelist */
            it = (item *)p->slots;
            p->slots = it->next;
            if (it->next) it->next->prev = 0;
            /* Kill flag and initialize refcount here for lock safety in slab
             * mover's freeness detection. */
            it->it_flags &= ~ITEM_SLABBED;
            it->refcount = 1;
            p->sl_curr--;
            ret = (void *)it;
        } else {
            ret = NULL;
        }
    } else {
        /* Dealing with a chunked item. */
        ret = do_slabs_alloc_chunked(size, p, id);
    }

    if (ret) {
        p->requested += size;
        MEMCACHED_SLABS_ALLOCATE(size, id, p->size, ret);
    } else {
        MEMCACHED_SLABS_ALLOCATE_FAILED(size, id);
    }

    return ret;
}
Beispiel #11
0
/*@null@*/
static void *do_slabs_alloc(slabs_t* pst, const size_t size, unsigned int id) {
    slabclass_t *p;
    void *ret = NULL;
    slabheader_t *it = NULL;

    if (id < POWER_SMALLEST || id > pst->power_largest) {
        //MEMCACHED_SLABS_ALLOCATE_FAILED(size, 0);
        return NULL;
    }

    p = &pst->slabclass[id];
    //assert(p->sl_curr == 0 || ((slabheader_t*)p->slots)->slabs_clsid == 0);

    /* fail unless we have space at the end of a recently allocated page,
       we have something on our freelist, or we could allocate a new page */
    if (! (p->end_page_ptr != 0 || p->sl_curr != 0 ||
           do_slabs_newslab(pst, id) != 0)) {
        /* We don't have more memory available */
        ret = NULL;
    } else if (p->sl_curr != 0) {
        /* return off our freelist */
        it = (slabheader_t*)p->slots;
        p->slots = it->next;
        if (it->next) it->next->prev = 0;
        p->sl_curr--;
        ret = (void *)it;
    } else {
        /* if we recently allocated a whole page, return from that */
        assert(p->end_page_ptr != NULL);
        ret = p->end_page_ptr;
        if (--p->end_page_free != 0) {
            p->end_page_ptr = ((caddr_t)p->end_page_ptr) + p->size;
        } else {
            p->end_page_ptr = 0;
        }
    }

    if (ret) {
        p->requested += size;
        //MEMCACHED_SLABS_ALLOCATE(size, id, p->size, ret);
    } else {
        //MEMCACHED_SLABS_ALLOCATE_FAILED(size, id);
    }
    //printf("alloc ps:%p sid:%u p:%p np:%p cnt:%u used:%lu rest:%u \n", pst, id, ret, p->end_page_ptr, p->sl_curr, p->requested, p->end_page_free);

    return ret;
}
Beispiel #12
0
// 从slabclass中申请size大小的空间
static void *do_slabs_alloc(const size_t size, unsigned int id) {
    slabclass_t *p;
    void *ret = NULL;
    item *it = NULL;

    if (id < POWER_SMALLEST || id > power_largest) {
        MEMCACHED_SLABS_ALLOCATE_FAILED(size, 0);
        return NULL;
    }

    p = &slabclass[id];
	// 可以看出,有slab中的空间不仅只能通过slab_list获得,还可以通过slots来获得,
	// 因为free出来的item是放在slots中的,即slots中的item其实是存储slab中的,由于
	// 不好判断slab中的item是否被释放,所以搞出来一个slots来存储释放的item,这样就
	// 不需要判断,而直接用即可。 这真是将指针的好处体现得淋漓尽致 
    assert(p->sl_curr == 0 || ((item *)p->slots)->slabs_clsid == 0);

    /* fail unless we have space at the end of a recently allocated page,
       we have something on our freelist, or we could allocate a new page */
	// 这个新版本已经将所有用户内存分配都改为从slots中进行了,在newslab中的时候
	// 已经将item信息全部存储slots中了。
	// 当前sl_curr为0时,即没有了item,然后newslab,这样又有item放进去了,所以下面可以继续
	// 分配
    if (! (p->sl_curr != 0 || do_slabs_newslab(id) != 0)) {
        /* We don't have more memory available */
        ret = NULL;
    } else if (p->sl_curr != 0) {
        /* return off our freelist */
		// 这里是从slots的头开始分配的
        it = (item *)p->slots;
        p->slots = it->next;
        if (it->next) it->next->prev = 0;
        p->sl_curr--;
        ret = (void *)it;
    }

    if (ret) {
        p->requested += size;
        MEMCACHED_SLABS_ALLOCATE(size, id, p->size, ret);
    } else {
        MEMCACHED_SLABS_ALLOCATE_FAILED(size, id);
    }

    return ret;
}
Beispiel #13
0
/*@null@*/
static void *do_slabs_alloc(const size_t size, unsigned int id) {
    slabclass_t *p;
    void *ret = NULL;
    item *it = NULL;

    if (id < POWER_SMALLEST || id > power_largest) {
        MEMCACHED_SLABS_ALLOCATE_FAILED(size, 0);
        return NULL;
    }

    p = &slabclass[id];
    assert(p->sl_curr == 0 || ((item *)p->slots)->slabs_clsid == 0);

    /* fail unless we have space at the end of a recently allocated page,
       we have something on our freelist, or we could allocate a new page */
    /* 确保最后一个slab 有空闲的chunk */
    if (! (p->sl_curr != 0 || do_slabs_newslab(id) != 0))
    {
        /* We don't have more memory available */
        ret = NULL;
    }
    //从slabclass_t的空闲item链表中获取一个item
    else if (p->sl_curr != 0)
    {
        /* return off our freelist */
        it = (item *)p->slots;
        p->slots = it->next;
        if (it->next) it->next->prev = 0;
        p->sl_curr--;
        ret = (void *)it;
    }

    if (ret)
    {
        p->requested += size;
        MEMCACHED_SLABS_ALLOCATE(size, id, p->size, ret);
    }
    else {
        MEMCACHED_SLABS_ALLOCATE_FAILED(size, id);
    }

    return ret;
}
Beispiel #14
0
// 从指定的 slabclass, 即 slabclass[id], 分配大小为 size 的内存块供申请者使用.
//
//  分配的原则是, 优先从 slots 指向的空闲链表中分配, 空闲链表没有, 才从 slab 中分配一个空闲的 chunk.
static void *do_slabs_alloc(const size_t size, unsigned int id, unsigned int *total_chunks) {
    slabclass_t *p;
    void *ret = NULL;
    item *it = NULL;

    if (id < POWER_SMALLEST || id > power_largest) {
        MEMCACHED_SLABS_ALLOCATE_FAILED(size, 0);
        return NULL;
    }
    p = &slabclass[id];
    assert(p->sl_curr == 0 || ((item *)p->slots)->slabs_clsid == 0);

    *total_chunks = p->slabs * p->perslab;
    /* fail unless we have space at the end of a recently allocated page,
       we have something on our freelist, or we could allocate a new page */
    // p->sl_curr == 0 && do_slabs_newslab(id) == 0
    // TODO 若分配新的slab后,什么都不干?
    if (! (p->sl_curr != 0 || do_slabs_newslab(id) != 0)) {
        /* We don't have more memory available */
        ret = NULL;
    } else if (p->sl_curr != 0) {
        /* return off our freelist */
        it = (item *)p->slots;
        p->slots = it->next;
        if (it->next) it->next->prev = 0;
        /* Kill flag and initialize refcount here for lock safety in slab
         * mover's freeness detection. */
        it->it_flags &= ~ITEM_SLABBED;
        it->refcount = 1;
        p->sl_curr--;
        ret = (void *)it;
    }

    if (ret) {
        p->requested += size;
        MEMCACHED_SLABS_ALLOCATE(size, id, p->size, ret);
    } else {
        MEMCACHED_SLABS_ALLOCATE_FAILED(size, id);
    }

    return ret;
}
Beispiel #15
0
//向slabclass申请一个item。在调用该函数之前,已经调用slabs_clsid函数确定  
//本次申请是向哪个slabclass_t申请item了,参数id就是指明是向哪个slabclass_t  
//申请item。如果该slabclass_t是有空闲item,那么就从空闲的item队列中分配一个  
//如果没有空闲item,那么就申请一个内存页。再从新申请的页中分配一个item  
//返回值为得到的item,如果没有内存了,返回NULL
static void *do_slabs_alloc(const size_t size, unsigned int id) {
    slabclass_t *p;
    void *ret = NULL;
    item *it = NULL;

    if (id < POWER_SMALLEST || id > power_largest) {//下标越界
        MEMCACHED_SLABS_ALLOCATE_FAILED(size, 0);
        return NULL;
    }

    p = &slabclass[id];
    assert(p->sl_curr == 0 || ((item *)p->slots)->slabs_clsid == 0);

    /* fail unless we have space at the end of a recently allocated page,
       we have something on our freelist, or we could allocate a new page */
    //如果p->sl_curr等于0,就说明该slabclass_t没有空闲的item了
    //此时需要调用do_slabs_newslab申请一个内存页
    if (! (p->sl_curr != 0 || do_slabs_newslab(id) != 0)) {
        /* We don't have more memory available */
        //当p->sl_curr等于0并且do_slabs_newslab的返回值等于0时,进入这里
        ret = NULL;
    } else if (p->sl_curr != 0) {
        //除非do_slabs_newslab调用失败,否则都会来到这里.无论一开始sl_curr是否为0。
        //p->slots指向第一个空闲的item,此时要把第一个空闲的item分配出去
        /* return off our freelist */
        it = (item *)p->slots;
        p->slots = it->next;//slots指向下一个空闲的item
        if (it->next) it->next->prev = 0;
        p->sl_curr--;//空闲数目减一
        ret = (void *)it;
    }

    if (ret) {
        p->requested += size;//增加本slabclass分配出去的字节数
        MEMCACHED_SLABS_ALLOCATE(size, id, p->size, ret);
    } else {
        MEMCACHED_SLABS_ALLOCATE_FAILED(size, id);
    }

    return ret;
}
Beispiel #16
0
//分配每个slab的内存空间,maxslabs表示已经初始化的slab的最大编号,即下标
static void slabs_preallocate (const unsigned int maxslabs)
{
    int i;
    unsigned int prealloc = 0;
    /* pre-allocate a 1MB slab in every size class so people don't get confused by non-intuitive
    "SERVER_ERROR out of memory" messages.  this is the most common question on the mailing list.
    if you really don't want this, you can rebuild without these three lines.  */
    for (i = POWER_SMALLEST; i <= POWER_LARGEST; i++)
    {
        if (++prealloc > maxslabs) return;
        //执行分配操作,对第i个slabclass执行分配操作
        if (do_slabs_newslab(i) == 0)
        {
            fprintf(stderr, "Error while preallocating slab memory!\n"
                "If using -L or other prealloc options, max memory must be "
                "at least %d megabytes.\n", power_largest);
            exit(1);
        }
    }

}
Beispiel #17
0
/*@null@*/
void *do_slabs_alloc(const size_t size) {
    slabclass_t *p;

    unsigned int id = slabs_clsid(size);
    if (id < POWER_SMALLEST || id > power_largest)
        return NULL;

    p = &slabclass[id];
    assert(p->sl_curr == 0 || ((item *)p->slots[p->sl_curr - 1])->slabs_clsid == 0);

#ifdef USE_SYSTEM_MALLOC
    if (mem_limit && mem_malloced + size > mem_limit)
        return 0;
    mem_malloced += size;
    return malloc(size);
#endif

    /* fail unless we have space at the end of a recently allocated page,
       we have something on our freelist, or we could allocate a new page */
    if (! (p->end_page_ptr != 0 || p->sl_curr != 0 || do_slabs_newslab(id) != 0))
        return 0;

    /* return off our freelist, if we have one */
    if (p->sl_curr != 0)
        return p->slots[--p->sl_curr];

    /* if we recently allocated a whole page, return from that */
    if (p->end_page_ptr) {
        void *ptr = p->end_page_ptr;
        if (--p->end_page_free != 0) {
            p->end_page_ptr += p->size;
        } else {
            p->end_page_ptr = 0;
        }
        return ptr;
    }

    return NULL;  /* shouldn't ever get here */
}