📄 ngx_slab.c
字号:
bitmap[0] = (2 << n) - 1; map = (1 << (ngx_pagesize_shift - shift)) / (sizeof(uintptr_t) * 8); for (i = 1; i < map; i++) { bitmap[i] = 0; } page->slab = shift; page->next = &slots[slot]; page->prev = (uintptr_t) &slots[slot] | NGX_SLAB_SMALL; slots[slot].next = page; p = ((page - pool->pages) << ngx_pagesize_shift) + s * n; p += (uintptr_t) pool->start; goto done; } else if (shift == ngx_slab_exact_shift) { page->slab = 1; page->next = &slots[slot]; page->prev = (uintptr_t) &slots[slot] | NGX_SLAB_EXACT; slots[slot].next = page; p = (page - pool->pages) << ngx_pagesize_shift; p += (uintptr_t) pool->start; goto done; } else { /* shift > ngx_slab_exact_shift */ page->slab = ((uintptr_t) 1 << NGX_SLAB_MAP_SHIFT) | shift; page->next = &slots[slot]; page->prev = (uintptr_t) &slots[slot] | NGX_SLAB_BIG; slots[slot].next = page; p = (page - pool->pages) << ngx_pagesize_shift; p += (uintptr_t) pool->start; goto done; } } p = 0;done: ngx_log_debug1(NGX_LOG_DEBUG_ALLOC, ngx_cycle->log, 0, "slab alloc: %p", p); return (void *) p;}voidngx_slab_free(ngx_slab_pool_t *pool, void *p){ ngx_shmtx_lock(&pool->mutex); ngx_slab_free_locked(pool, p); ngx_shmtx_unlock(&pool->mutex);}voidngx_slab_free_locked(ngx_slab_pool_t *pool, void *p){ size_t size; uintptr_t slab, m, *bitmap; ngx_uint_t n, type, slot, shift, map; ngx_slab_page_t *slots, *page; ngx_log_debug1(NGX_LOG_DEBUG_ALLOC, ngx_cycle->log, 0, "slab free: %p", p); if ((u_char *) p < pool->start || (u_char *) p > pool->end) { ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, 0, "ngx_slab_free(): outside of pool"); goto fail; } n = ((u_char *) p - pool->start) >> ngx_pagesize_shift; page = &pool->pages[n]; slab = page->slab; type = page->prev & NGX_SLAB_PAGE_MASK; switch (type) { case NGX_SLAB_SMALL: shift = slab & NGX_SLAB_SHIFT_MASK; size = 1 << shift; if ((uintptr_t) p & (size - 1)) { goto wrong_chunk; } n = ((uintptr_t) p & (ngx_pagesize - 1)) >> shift; m = (uintptr_t) 1 << (n & (sizeof(uintptr_t) * 8 - 1)); n /= (sizeof(uintptr_t) * 8); bitmap = (uintptr_t *) ((uintptr_t) p & ~(ngx_pagesize - 1)); if (bitmap[n] & m) { if (page->next == NULL) { slots = (ngx_slab_page_t *) ((u_char *) pool + sizeof(ngx_slab_pool_t)); slot = shift - pool->min_shift; page->next = slots[slot].next; slots[slot].next = page; page->prev = (uintptr_t) &slots[slot] | NGX_SLAB_SMALL; page->next->prev = (uintptr_t) page | NGX_SLAB_SMALL; } bitmap[n] &= ~m; n = (1 << (ngx_pagesize_shift - shift)) / 8 / (1 << shift); if (n == 0) { n = 1; } if (bitmap[0] & ~(((uintptr_t) 1 << n) - 1)) { goto done; } map = (1 << (ngx_pagesize_shift - shift)) / (sizeof(uintptr_t) * 8); for (n = 1; n < map; n++) { if (bitmap[n]) { goto done; } } ngx_slab_free_pages(pool, page, 1); goto done; } goto chunk_already_free; case NGX_SLAB_EXACT: m = (uintptr_t) 1 << (((uintptr_t) p & (ngx_pagesize - 1)) >> ngx_slab_exact_shift); size = ngx_slab_exact_size; if ((uintptr_t) p & (size - 1)) { goto wrong_chunk; } if (slab & m) { if (slab == NGX_SLAB_BUSY) { slots = (ngx_slab_page_t *) ((u_char *) pool + sizeof(ngx_slab_pool_t)); slot = ngx_slab_exact_shift - pool->min_shift; page->next = slots[slot].next; slots[slot].next = page; page->prev = (uintptr_t) &slots[slot] | NGX_SLAB_EXACT; page->next->prev = (uintptr_t) page | NGX_SLAB_EXACT; } page->slab &= ~m; if (page->slab) { goto done; } ngx_slab_free_pages(pool, page, 1); goto done; } goto chunk_already_free; case NGX_SLAB_BIG: shift = slab & NGX_SLAB_SHIFT_MASK; size = 1 << shift; if ((uintptr_t) p & (size - 1)) { goto wrong_chunk; } m = (uintptr_t) 1 << ((((uintptr_t) p & (ngx_pagesize - 1)) >> shift) + NGX_SLAB_MAP_SHIFT); if (slab & m) { if (page->next == NULL) { slots = (ngx_slab_page_t *) ((u_char *) pool + sizeof(ngx_slab_pool_t)); slot = shift - pool->min_shift; page->next = slots[slot].next; slots[slot].next = page; page->prev = (uintptr_t) &slots[slot] | NGX_SLAB_BIG; page->next->prev = (uintptr_t) page | NGX_SLAB_BIG; } page->slab &= ~m; if (page->slab & NGX_SLAB_MAP_MASK) { goto done; } ngx_slab_free_pages(pool, page, 1); goto done; } goto chunk_already_free; case NGX_SLAB_PAGE: if ((uintptr_t) p & (ngx_pagesize - 1)) { goto wrong_chunk; } if (slab == NGX_SLAB_PAGE_FREE) { ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, 0, "ngx_slab_free(): page is already free"); goto fail; } if (slab == NGX_SLAB_PAGE_BUSY) { ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, 0, "ngx_slab_free(): pointer to wrong page"); goto fail; } n = ((u_char *) p - pool->start) >> ngx_pagesize_shift; size = slab & ~NGX_SLAB_PAGE_START; ngx_slab_free_pages(pool, &pool->pages[n], size); size <<= ngx_pagesize_shift; goto done; } /* not reached */ return;done: ngx_slab_junk(p, size); return;wrong_chunk: ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, 0, "ngx_slab_free(): pointer to wrong chunk"); goto fail;chunk_already_free: ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, 0, "ngx_slab_free(): chunk is already free");fail: return;}static ngx_slab_page_t *ngx_slab_alloc_pages(ngx_slab_pool_t *pool, ngx_uint_t pages){ ngx_slab_page_t *page, *p; for (page = pool->free.next; page != &pool->free; page = page->next) { if (page->slab >= pages) { if (page->slab > pages) { page[pages].slab = page->slab - pages; page[pages].next = page->next; page[pages].prev = page->prev; p = (ngx_slab_page_t *) page->prev; p->next = &page[pages]; page->next->prev = (uintptr_t) &page[pages]; } else { p = (ngx_slab_page_t *) page->prev; p->next = page->next; page->next->prev = page->prev; } page->slab = pages | NGX_SLAB_PAGE_START;#if (NGX_DEBUG) page->next = NULL; page->prev = NGX_SLAB_PAGE;#endif if (--pages == 0) { return page; } for (p = page + 1; pages; pages--) { p->slab = NGX_SLAB_PAGE_BUSY;#if (NGX_DEBUG) p->next = NULL; p->prev = NGX_SLAB_PAGE;#endif p++; } return page; } } ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, NGX_ENOMEM, "ngx_slab_alloc(): failed"); return NULL;}static voidngx_slab_free_pages(ngx_slab_pool_t *pool, ngx_slab_page_t *page, ngx_uint_t pages){ ngx_slab_page_t *prev; page->slab = pages--; if (pages) { ngx_memzero(&page[1], pages * sizeof(ngx_slab_page_t)); } if (page->next) { prev = (ngx_slab_page_t *) (page->prev & ~NGX_SLAB_PAGE_MASK); prev->next = page->next; page->next->prev = page->prev; } page->prev = (uintptr_t) &pool->free; page->next = pool->free.next; page->next->prev = (uintptr_t) page; pool->free.next = page;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -