Example #1
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;
}
Example #2
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;
}
Example #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;
}
Example #4
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;
}
Example #5
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;
}
Example #6
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;
}
Example #7
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;
}
Example #8
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;
}
Example #9
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;
}