Sword nginx slab源码解析二(初始化)

/*
设计说明:
    当page划分的slot块小于128个字节时候,pre的后两位为NGX_SLAB_SMALL
    当page划分的slot块等于128个字节时候,pre的后两位为NGX_SLAB_EXACT
    当page划分的slot块大于128个字节时候,pre的后两位为NGX_SLAB_BIG
    当page划分的slot块大于2048个字节时候,pre的后两位为NGX_SLAB_PAGE
*/
#define NGX_SLAB_PAGE_MASK   3
#define NGX_SLAB_PAGE        0
#define NGX_SLAB_BIG         1
#define NGX_SLAB_EXACT       2
#define NGX_SLAB_SMALL       3

#if (NGX_PTR_SIZE == 4)

#define NGX_SLAB_PAGE_FREE   0
#define NGX_SLAB_PAGE_BUSY   0xffffffff
#define NGX_SLAB_PAGE_START  0x80000000

#define NGX_SLAB_SHIFT_MASK  0x0000000f
#define NGX_SLAB_MAP_MASK    0xffff0000
#define NGX_SLAB_MAP_SHIFT   16

#define NGX_SLAB_BUSY        0xffffffff

#else /* (NGX_PTR_SIZE == 8) */

#define NGX_SLAB_PAGE_FREE   0
#define NGX_SLAB_PAGE_BUSY   0xffffffffffffffff
#define NGX_SLAB_PAGE_START  0x8000000000000000

#define NGX_SLAB_SHIFT_MASK  0x000000000000000f
#define NGX_SLAB_MAP_MASK    0xffffffff00000000
#define NGX_SLAB_MAP_SHIFT   32

#define NGX_SLAB_BUSY        0xffffffffffffffff

#endif


#define ngx_slab_slots(pool)                                                  \
    (ngx_slab_page_t *) ((u_char *) (pool) + sizeof(ngx_slab_pool_t))

#define ngx_slab_page_type(page)   ((page)->prev & NGX_SLAB_PAGE_MASK)

#define ngx_slab_page_prev(page)                                              \
    (ngx_slab_page_t *) ((page)->prev & ~NGX_SLAB_PAGE_MASK)

#define ngx_slab_page_addr(pool, page)                                        \
    ((((page) - (pool)->pages) << ngx_pagesize_shift)                         \
     + (uintptr_t) (pool)->start)


#if (NGX_DEBUG_MALLOC)

#define ngx_slab_junk(p, size)     ngx_memset(p, 0xA5, size)

#elif (NGX_HAVE_DEBUG_MALLOC)

#define ngx_slab_junk(p, size)                                                \
    if (ngx_debug_malloc)          ngx_memset(p, 0xA5, size)

#else

#define ngx_slab_junk(p, size)

#endif

static ngx_slab_page_t *ngx_slab_alloc_pages(ngx_slab_pool_t *pool,
    ngx_uint_t pages);
static void ngx_slab_free_pages(ngx_slab_pool_t *pool, ngx_slab_page_t *page,
    ngx_uint_t pages);
static void ngx_slab_error(ngx_slab_pool_t *pool, ngx_uint_t level,
    char *text);


static ngx_uint_t  ngx_slab_max_size;
static ngx_uint_t  ngx_slab_exact_size;
static ngx_uint_t  ngx_slab_exact_shift;


void ngx_slab_sizes_init(void)
{
    ngx_uint_t  n;

    /*
    知识补充:
        32位机器上,ngx_pagesize一般为4096字节
    */

    /*
    设计说明:
        ngx_slab_max_size 2048字节
        ngx_slab_exact_size 128字节
        ngx_slab_exact_shift 7    ngx_slab_exact_size对应的页偏移量,4096对应的偏移量是12
    */

    ngx_slab_max_size = ngx_pagesize / 2;
    ngx_slab_exact_size = ngx_pagesize / (8 * sizeof(uintptr_t));
    for (n = ngx_slab_exact_size; n >>= 1; ngx_slab_exact_shift++) 
    {
        /* void */
    }
}


void ngx_slab_init(ngx_slab_pool_t *pool)
{
    u_char           *p;
    size_t            size;
    ngx_int_t         m;
    ngx_uint_t        i, n, pages;
    ngx_slab_page_t  *slots, *page;

    // 设置可以分配的最小字节数,pool->min_shift默认是3,即pool->min_size = 8
    pool->min_size = (size_t) 1 << pool->min_shift;

    // 获取slot相对地址
    slots = ngx_slab_slots(pool);

    p = (u_char *) slots;

    // 获取slab池子大小
    size = pool->end - p;

    // 初始化数据(没啥意义)
    ngx_slab_junk(p, size);
    /*
    设计说明:
        ngx_pagesize_shift 是页偏移量,4096字节的偏移量是12
    */
    n = ngx_pagesize_shift - pool->min_shift;

    /*
    设计说明:
        slot 一般只用来标记 8 16 32 64 128 256 512 1024 2048 一个9个
    */
    for (i = 0; i < n; i++) 
    {
        /* only "next" is used in list head */
        slots[i].slab = 0;
        slots[i].next = &slots[i];
        slots[i].prev = 0;
    }

    // 跳过slot列表
    p += n * sizeof(ngx_slab_page_t);

    // 设置slab池状态
    pool->stats = (ngx_slab_stat_t *) p;
    ngx_memzero(pool->stats, n * sizeof(ngx_slab_stat_t));

    // 跳过stats列表
    p += n * sizeof(ngx_slab_stat_t);

    // 更新size,刨除 slots+stats
    size -= n * (sizeof(ngx_slab_page_t) + sizeof(ngx_slab_stat_t));

    // 计算剩余页数
    pages = (ngx_uint_t) (size / (ngx_pagesize + sizeof(ngx_slab_page_t)));

    pool->pages = (ngx_slab_page_t *) p;
    ngx_memzero(pool->pages, pages * sizeof(ngx_slab_page_t));

    // 页数据
    page = pool->pages;

    /* only "next" is used in list head */
    pool->free.slab = 0;
    pool->free.next = page;
    pool->free.prev = 0;

    // 记录可以分配的页数目
    page->slab = pages;
    page->next = &pool->free;
    page->prev = (uintptr_t) &pool->free;

    // 设置起始点(字节对齐)
    pool->start = ngx_align_ptr(p + pages * sizeof(ngx_slab_page_t),
                                ngx_pagesize);

    /*
    设计说明:
        因为字节对齐,会浪费一定的内存空间,因此需要重新计算pages
    */
    m = pages - (pool->end - pool->start) / ngx_pagesize;
    if (m > 0) {
        pages -= m;
        page->slab = pages;
    }

    // 设置slab池的末尾节点
    pool->last = pool->pages + pages;
    pool->pfree = pages;

    pool->log_nomem = 1;
    pool->log_ctx = &pool->zero;
    pool->zero = '\0';
}

 

posted on 2022-07-23 12:26  寒魔影  阅读(82)  评论(0编辑  收藏  举报

导航