Annotation of embedaddon/nginx/src/core/ngx_slab.c, revision 1.1

1.1     ! misho       1: 
        !             2: /*
        !             3:  * Copyright (C) Igor Sysoev
        !             4:  * Copyright (C) Nginx, Inc.
        !             5:  */
        !             6: 
        !             7: #include <ngx_config.h>
        !             8: #include <ngx_core.h>
        !             9: 
        !            10: 
        !            11: #define NGX_SLAB_PAGE_MASK   3
        !            12: #define NGX_SLAB_PAGE        0
        !            13: #define NGX_SLAB_BIG         1
        !            14: #define NGX_SLAB_EXACT       2
        !            15: #define NGX_SLAB_SMALL       3
        !            16: 
        !            17: #if (NGX_PTR_SIZE == 4)
        !            18: 
        !            19: #define NGX_SLAB_PAGE_FREE   0
        !            20: #define NGX_SLAB_PAGE_BUSY   0xffffffff
        !            21: #define NGX_SLAB_PAGE_START  0x80000000
        !            22: 
        !            23: #define NGX_SLAB_SHIFT_MASK  0x0000000f
        !            24: #define NGX_SLAB_MAP_MASK    0xffff0000
        !            25: #define NGX_SLAB_MAP_SHIFT   16
        !            26: 
        !            27: #define NGX_SLAB_BUSY        0xffffffff
        !            28: 
        !            29: #else /* (NGX_PTR_SIZE == 8) */
        !            30: 
        !            31: #define NGX_SLAB_PAGE_FREE   0
        !            32: #define NGX_SLAB_PAGE_BUSY   0xffffffffffffffff
        !            33: #define NGX_SLAB_PAGE_START  0x8000000000000000
        !            34: 
        !            35: #define NGX_SLAB_SHIFT_MASK  0x000000000000000f
        !            36: #define NGX_SLAB_MAP_MASK    0xffffffff00000000
        !            37: #define NGX_SLAB_MAP_SHIFT   32
        !            38: 
        !            39: #define NGX_SLAB_BUSY        0xffffffffffffffff
        !            40: 
        !            41: #endif
        !            42: 
        !            43: 
        !            44: #if (NGX_DEBUG_MALLOC)
        !            45: 
        !            46: #define ngx_slab_junk(p, size)     ngx_memset(p, 0xA5, size)
        !            47: 
        !            48: #elif (NGX_HAVE_DEBUG_MALLOC)
        !            49: 
        !            50: #define ngx_slab_junk(p, size)                                                \
        !            51:     if (ngx_debug_malloc)          ngx_memset(p, 0xA5, size)
        !            52: 
        !            53: #else
        !            54: 
        !            55: #define ngx_slab_junk(p, size)
        !            56: 
        !            57: #endif
        !            58: 
        !            59: static ngx_slab_page_t *ngx_slab_alloc_pages(ngx_slab_pool_t *pool,
        !            60:     ngx_uint_t pages);
        !            61: static void ngx_slab_free_pages(ngx_slab_pool_t *pool, ngx_slab_page_t *page,
        !            62:     ngx_uint_t pages);
        !            63: static void ngx_slab_error(ngx_slab_pool_t *pool, ngx_uint_t level,
        !            64:     char *text);
        !            65: 
        !            66: 
        !            67: static ngx_uint_t  ngx_slab_max_size;
        !            68: static ngx_uint_t  ngx_slab_exact_size;
        !            69: static ngx_uint_t  ngx_slab_exact_shift;
        !            70: 
        !            71: 
        !            72: void
        !            73: ngx_slab_init(ngx_slab_pool_t *pool)
        !            74: {
        !            75:     u_char           *p;
        !            76:     size_t            size;
        !            77:     ngx_int_t         m;
        !            78:     ngx_uint_t        i, n, pages;
        !            79:     ngx_slab_page_t  *slots;
        !            80: 
        !            81:     /* STUB */
        !            82:     if (ngx_slab_max_size == 0) {
        !            83:         ngx_slab_max_size = ngx_pagesize / 2;
        !            84:         ngx_slab_exact_size = ngx_pagesize / (8 * sizeof(uintptr_t));
        !            85:         for (n = ngx_slab_exact_size; n >>= 1; ngx_slab_exact_shift++) {
        !            86:             /* void */
        !            87:         }
        !            88:     }
        !            89:     /**/
        !            90: 
        !            91:     pool->min_size = 1 << pool->min_shift;
        !            92: 
        !            93:     p = (u_char *) pool + sizeof(ngx_slab_pool_t);
        !            94:     size = pool->end - p;
        !            95: 
        !            96:     ngx_slab_junk(p, size);
        !            97: 
        !            98:     slots = (ngx_slab_page_t *) p;
        !            99:     n = ngx_pagesize_shift - pool->min_shift;
        !           100: 
        !           101:     for (i = 0; i < n; i++) {
        !           102:         slots[i].slab = 0;
        !           103:         slots[i].next = &slots[i];
        !           104:         slots[i].prev = 0;
        !           105:     }
        !           106: 
        !           107:     p += n * sizeof(ngx_slab_page_t);
        !           108: 
        !           109:     pages = (ngx_uint_t) (size / (ngx_pagesize + sizeof(ngx_slab_page_t)));
        !           110: 
        !           111:     ngx_memzero(p, pages * sizeof(ngx_slab_page_t));
        !           112: 
        !           113:     pool->pages = (ngx_slab_page_t *) p;
        !           114: 
        !           115:     pool->free.prev = 0;
        !           116:     pool->free.next = (ngx_slab_page_t *) p;
        !           117: 
        !           118:     pool->pages->slab = pages;
        !           119:     pool->pages->next = &pool->free;
        !           120:     pool->pages->prev = (uintptr_t) &pool->free;
        !           121: 
        !           122:     pool->start = (u_char *)
        !           123:                   ngx_align_ptr((uintptr_t) p + pages * sizeof(ngx_slab_page_t),
        !           124:                                  ngx_pagesize);
        !           125: 
        !           126:     m = pages - (pool->end - pool->start) / ngx_pagesize;
        !           127:     if (m > 0) {
        !           128:         pages -= m;
        !           129:         pool->pages->slab = pages;
        !           130:     }
        !           131: 
        !           132:     pool->log_ctx = &pool->zero;
        !           133:     pool->zero = '\0';
        !           134: }
        !           135: 
        !           136: 
        !           137: void *
        !           138: ngx_slab_alloc(ngx_slab_pool_t *pool, size_t size)
        !           139: {
        !           140:     void  *p;
        !           141: 
        !           142:     ngx_shmtx_lock(&pool->mutex);
        !           143: 
        !           144:     p = ngx_slab_alloc_locked(pool, size);
        !           145: 
        !           146:     ngx_shmtx_unlock(&pool->mutex);
        !           147: 
        !           148:     return p;
        !           149: }
        !           150: 
        !           151: 
        !           152: void *
        !           153: ngx_slab_alloc_locked(ngx_slab_pool_t *pool, size_t size)
        !           154: {
        !           155:     size_t            s;
        !           156:     uintptr_t         p, n, m, mask, *bitmap;
        !           157:     ngx_uint_t        i, slot, shift, map;
        !           158:     ngx_slab_page_t  *page, *prev, *slots;
        !           159: 
        !           160:     if (size >= ngx_slab_max_size) {
        !           161: 
        !           162:         ngx_log_debug1(NGX_LOG_DEBUG_ALLOC, ngx_cycle->log, 0,
        !           163:                        "slab alloc: %uz", size);
        !           164: 
        !           165:         page = ngx_slab_alloc_pages(pool, (size >> ngx_pagesize_shift)
        !           166:                                           + ((size % ngx_pagesize) ? 1 : 0));
        !           167:         if (page) {
        !           168:             p = (page - pool->pages) << ngx_pagesize_shift;
        !           169:             p += (uintptr_t) pool->start;
        !           170: 
        !           171:         } else {
        !           172:             p = 0;
        !           173:         }
        !           174: 
        !           175:         goto done;
        !           176:     }
        !           177: 
        !           178:     if (size > pool->min_size) {
        !           179:         shift = 1;
        !           180:         for (s = size - 1; s >>= 1; shift++) { /* void */ }
        !           181:         slot = shift - pool->min_shift;
        !           182: 
        !           183:     } else {
        !           184:         size = pool->min_size;
        !           185:         shift = pool->min_shift;
        !           186:         slot = 0;
        !           187:     }
        !           188: 
        !           189:     ngx_log_debug2(NGX_LOG_DEBUG_ALLOC, ngx_cycle->log, 0,
        !           190:                    "slab alloc: %uz slot: %ui", size, slot);
        !           191: 
        !           192:     slots = (ngx_slab_page_t *) ((u_char *) pool + sizeof(ngx_slab_pool_t));
        !           193:     page = slots[slot].next;
        !           194: 
        !           195:     if (page->next != page) {
        !           196: 
        !           197:         if (shift < ngx_slab_exact_shift) {
        !           198: 
        !           199:             do {
        !           200:                 p = (page - pool->pages) << ngx_pagesize_shift;
        !           201:                 bitmap = (uintptr_t *) (pool->start + p);
        !           202: 
        !           203:                 map = (1 << (ngx_pagesize_shift - shift))
        !           204:                           / (sizeof(uintptr_t) * 8);
        !           205: 
        !           206:                 for (n = 0; n < map; n++) {
        !           207: 
        !           208:                     if (bitmap[n] != NGX_SLAB_BUSY) {
        !           209: 
        !           210:                         for (m = 1, i = 0; m; m <<= 1, i++) {
        !           211:                             if ((bitmap[n] & m)) {
        !           212:                                 continue;
        !           213:                             }
        !           214: 
        !           215:                             bitmap[n] |= m;
        !           216: 
        !           217:                             i = ((n * sizeof(uintptr_t) * 8) << shift)
        !           218:                                 + (i << shift);
        !           219: 
        !           220:                             if (bitmap[n] == NGX_SLAB_BUSY) {
        !           221:                                 for (n = n + 1; n < map; n++) {
        !           222:                                      if (bitmap[n] != NGX_SLAB_BUSY) {
        !           223:                                          p = (uintptr_t) bitmap + i;
        !           224: 
        !           225:                                          goto done;
        !           226:                                      }
        !           227:                                 }
        !           228: 
        !           229:                                 prev = (ngx_slab_page_t *)
        !           230:                                             (page->prev & ~NGX_SLAB_PAGE_MASK);
        !           231:                                 prev->next = page->next;
        !           232:                                 page->next->prev = page->prev;
        !           233: 
        !           234:                                 page->next = NULL;
        !           235:                                 page->prev = NGX_SLAB_SMALL;
        !           236:                             }
        !           237: 
        !           238:                             p = (uintptr_t) bitmap + i;
        !           239: 
        !           240:                             goto done;
        !           241:                         }
        !           242:                     }
        !           243:                 }
        !           244: 
        !           245:                 page = page->next;
        !           246: 
        !           247:             } while (page);
        !           248: 
        !           249:         } else if (shift == ngx_slab_exact_shift) {
        !           250: 
        !           251:             do {
        !           252:                 if (page->slab != NGX_SLAB_BUSY) {
        !           253: 
        !           254:                     for (m = 1, i = 0; m; m <<= 1, i++) {
        !           255:                         if ((page->slab & m)) {
        !           256:                             continue;
        !           257:                         }
        !           258: 
        !           259:                         page->slab |= m;
        !           260: 
        !           261:                         if (page->slab == NGX_SLAB_BUSY) {
        !           262:                             prev = (ngx_slab_page_t *)
        !           263:                                             (page->prev & ~NGX_SLAB_PAGE_MASK);
        !           264:                             prev->next = page->next;
        !           265:                             page->next->prev = page->prev;
        !           266: 
        !           267:                             page->next = NULL;
        !           268:                             page->prev = NGX_SLAB_EXACT;
        !           269:                         }
        !           270: 
        !           271:                         p = (page - pool->pages) << ngx_pagesize_shift;
        !           272:                         p += i << shift;
        !           273:                         p += (uintptr_t) pool->start;
        !           274: 
        !           275:                         goto done;
        !           276:                     }
        !           277:                 }
        !           278: 
        !           279:                 page = page->next;
        !           280: 
        !           281:             } while (page);
        !           282: 
        !           283:         } else { /* shift > ngx_slab_exact_shift */
        !           284: 
        !           285:             n = ngx_pagesize_shift - (page->slab & NGX_SLAB_SHIFT_MASK);
        !           286:             n = 1 << n;
        !           287:             n = ((uintptr_t) 1 << n) - 1;
        !           288:             mask = n << NGX_SLAB_MAP_SHIFT;
        !           289: 
        !           290:             do {
        !           291:                 if ((page->slab & NGX_SLAB_MAP_MASK) != mask) {
        !           292: 
        !           293:                     for (m = (uintptr_t) 1 << NGX_SLAB_MAP_SHIFT, i = 0;
        !           294:                          m & mask;
        !           295:                          m <<= 1, i++)
        !           296:                     {
        !           297:                         if ((page->slab & m)) {
        !           298:                             continue;
        !           299:                         }
        !           300: 
        !           301:                         page->slab |= m;
        !           302: 
        !           303:                         if ((page->slab & NGX_SLAB_MAP_MASK) == mask) {
        !           304:                             prev = (ngx_slab_page_t *)
        !           305:                                             (page->prev & ~NGX_SLAB_PAGE_MASK);
        !           306:                             prev->next = page->next;
        !           307:                             page->next->prev = page->prev;
        !           308: 
        !           309:                             page->next = NULL;
        !           310:                             page->prev = NGX_SLAB_BIG;
        !           311:                         }
        !           312: 
        !           313:                         p = (page - pool->pages) << ngx_pagesize_shift;
        !           314:                         p += i << shift;
        !           315:                         p += (uintptr_t) pool->start;
        !           316: 
        !           317:                         goto done;
        !           318:                     }
        !           319:                 }
        !           320: 
        !           321:                 page = page->next;
        !           322: 
        !           323:             } while (page);
        !           324:         }
        !           325:     }
        !           326: 
        !           327:     page = ngx_slab_alloc_pages(pool, 1);
        !           328: 
        !           329:     if (page) {
        !           330:         if (shift < ngx_slab_exact_shift) {
        !           331:             p = (page - pool->pages) << ngx_pagesize_shift;
        !           332:             bitmap = (uintptr_t *) (pool->start + p);
        !           333: 
        !           334:             s = 1 << shift;
        !           335:             n = (1 << (ngx_pagesize_shift - shift)) / 8 / s;
        !           336: 
        !           337:             if (n == 0) {
        !           338:                 n = 1;
        !           339:             }
        !           340: 
        !           341:             bitmap[0] = (2 << n) - 1;
        !           342: 
        !           343:             map = (1 << (ngx_pagesize_shift - shift)) / (sizeof(uintptr_t) * 8);
        !           344: 
        !           345:             for (i = 1; i < map; i++) {
        !           346:                 bitmap[i] = 0;
        !           347:             }
        !           348: 
        !           349:             page->slab = shift;
        !           350:             page->next = &slots[slot];
        !           351:             page->prev = (uintptr_t) &slots[slot] | NGX_SLAB_SMALL;
        !           352: 
        !           353:             slots[slot].next = page;
        !           354: 
        !           355:             p = ((page - pool->pages) << ngx_pagesize_shift) + s * n;
        !           356:             p += (uintptr_t) pool->start;
        !           357: 
        !           358:             goto done;
        !           359: 
        !           360:         } else if (shift == ngx_slab_exact_shift) {
        !           361: 
        !           362:             page->slab = 1;
        !           363:             page->next = &slots[slot];
        !           364:             page->prev = (uintptr_t) &slots[slot] | NGX_SLAB_EXACT;
        !           365: 
        !           366:             slots[slot].next = page;
        !           367: 
        !           368:             p = (page - pool->pages) << ngx_pagesize_shift;
        !           369:             p += (uintptr_t) pool->start;
        !           370: 
        !           371:             goto done;
        !           372: 
        !           373:         } else { /* shift > ngx_slab_exact_shift */
        !           374: 
        !           375:             page->slab = ((uintptr_t) 1 << NGX_SLAB_MAP_SHIFT) | shift;
        !           376:             page->next = &slots[slot];
        !           377:             page->prev = (uintptr_t) &slots[slot] | NGX_SLAB_BIG;
        !           378: 
        !           379:             slots[slot].next = page;
        !           380: 
        !           381:             p = (page - pool->pages) << ngx_pagesize_shift;
        !           382:             p += (uintptr_t) pool->start;
        !           383: 
        !           384:             goto done;
        !           385:         }
        !           386:     }
        !           387: 
        !           388:     p = 0;
        !           389: 
        !           390: done:
        !           391: 
        !           392:     ngx_log_debug1(NGX_LOG_DEBUG_ALLOC, ngx_cycle->log, 0, "slab alloc: %p", p);
        !           393: 
        !           394:     return (void *) p;
        !           395: }
        !           396: 
        !           397: 
        !           398: void
        !           399: ngx_slab_free(ngx_slab_pool_t *pool, void *p)
        !           400: {
        !           401:     ngx_shmtx_lock(&pool->mutex);
        !           402: 
        !           403:     ngx_slab_free_locked(pool, p);
        !           404: 
        !           405:     ngx_shmtx_unlock(&pool->mutex);
        !           406: }
        !           407: 
        !           408: 
        !           409: void
        !           410: ngx_slab_free_locked(ngx_slab_pool_t *pool, void *p)
        !           411: {
        !           412:     size_t            size;
        !           413:     uintptr_t         slab, m, *bitmap;
        !           414:     ngx_uint_t        n, type, slot, shift, map;
        !           415:     ngx_slab_page_t  *slots, *page;
        !           416: 
        !           417:     ngx_log_debug1(NGX_LOG_DEBUG_ALLOC, ngx_cycle->log, 0, "slab free: %p", p);
        !           418: 
        !           419:     if ((u_char *) p < pool->start || (u_char *) p > pool->end) {
        !           420:         ngx_slab_error(pool, NGX_LOG_ALERT, "ngx_slab_free(): outside of pool");
        !           421:         goto fail;
        !           422:     }
        !           423: 
        !           424:     n = ((u_char *) p - pool->start) >> ngx_pagesize_shift;
        !           425:     page = &pool->pages[n];
        !           426:     slab = page->slab;
        !           427:     type = page->prev & NGX_SLAB_PAGE_MASK;
        !           428: 
        !           429:     switch (type) {
        !           430: 
        !           431:     case NGX_SLAB_SMALL:
        !           432: 
        !           433:         shift = slab & NGX_SLAB_SHIFT_MASK;
        !           434:         size = 1 << shift;
        !           435: 
        !           436:         if ((uintptr_t) p & (size - 1)) {
        !           437:             goto wrong_chunk;
        !           438:         }
        !           439: 
        !           440:         n = ((uintptr_t) p & (ngx_pagesize - 1)) >> shift;
        !           441:         m = (uintptr_t) 1 << (n & (sizeof(uintptr_t) * 8 - 1));
        !           442:         n /= (sizeof(uintptr_t) * 8);
        !           443:         bitmap = (uintptr_t *) ((uintptr_t) p & ~(ngx_pagesize - 1));
        !           444: 
        !           445:         if (bitmap[n] & m) {
        !           446: 
        !           447:             if (page->next == NULL) {
        !           448:                 slots = (ngx_slab_page_t *)
        !           449:                                    ((u_char *) pool + sizeof(ngx_slab_pool_t));
        !           450:                 slot = shift - pool->min_shift;
        !           451: 
        !           452:                 page->next = slots[slot].next;
        !           453:                 slots[slot].next = page;
        !           454: 
        !           455:                 page->prev = (uintptr_t) &slots[slot] | NGX_SLAB_SMALL;
        !           456:                 page->next->prev = (uintptr_t) page | NGX_SLAB_SMALL;
        !           457:             }
        !           458: 
        !           459:             bitmap[n] &= ~m;
        !           460: 
        !           461:             n = (1 << (ngx_pagesize_shift - shift)) / 8 / (1 << shift);
        !           462: 
        !           463:             if (n == 0) {
        !           464:                 n = 1;
        !           465:             }
        !           466: 
        !           467:             if (bitmap[0] & ~(((uintptr_t) 1 << n) - 1)) {
        !           468:                 goto done;
        !           469:             }
        !           470: 
        !           471:             map = (1 << (ngx_pagesize_shift - shift)) / (sizeof(uintptr_t) * 8);
        !           472: 
        !           473:             for (n = 1; n < map; n++) {
        !           474:                 if (bitmap[n]) {
        !           475:                     goto done;
        !           476:                 }
        !           477:             }
        !           478: 
        !           479:             ngx_slab_free_pages(pool, page, 1);
        !           480: 
        !           481:             goto done;
        !           482:         }
        !           483: 
        !           484:         goto chunk_already_free;
        !           485: 
        !           486:     case NGX_SLAB_EXACT:
        !           487: 
        !           488:         m = (uintptr_t) 1 <<
        !           489:                 (((uintptr_t) p & (ngx_pagesize - 1)) >> ngx_slab_exact_shift);
        !           490:         size = ngx_slab_exact_size;
        !           491: 
        !           492:         if ((uintptr_t) p & (size - 1)) {
        !           493:             goto wrong_chunk;
        !           494:         }
        !           495: 
        !           496:         if (slab & m) {
        !           497:             if (slab == NGX_SLAB_BUSY) {
        !           498:                 slots = (ngx_slab_page_t *)
        !           499:                                    ((u_char *) pool + sizeof(ngx_slab_pool_t));
        !           500:                 slot = ngx_slab_exact_shift - pool->min_shift;
        !           501: 
        !           502:                 page->next = slots[slot].next;
        !           503:                 slots[slot].next = page;
        !           504: 
        !           505:                 page->prev = (uintptr_t) &slots[slot] | NGX_SLAB_EXACT;
        !           506:                 page->next->prev = (uintptr_t) page | NGX_SLAB_EXACT;
        !           507:             }
        !           508: 
        !           509:             page->slab &= ~m;
        !           510: 
        !           511:             if (page->slab) {
        !           512:                 goto done;
        !           513:             }
        !           514: 
        !           515:             ngx_slab_free_pages(pool, page, 1);
        !           516: 
        !           517:             goto done;
        !           518:         }
        !           519: 
        !           520:         goto chunk_already_free;
        !           521: 
        !           522:     case NGX_SLAB_BIG:
        !           523: 
        !           524:         shift = slab & NGX_SLAB_SHIFT_MASK;
        !           525:         size = 1 << shift;
        !           526: 
        !           527:         if ((uintptr_t) p & (size - 1)) {
        !           528:             goto wrong_chunk;
        !           529:         }
        !           530: 
        !           531:         m = (uintptr_t) 1 << ((((uintptr_t) p & (ngx_pagesize - 1)) >> shift)
        !           532:                               + NGX_SLAB_MAP_SHIFT);
        !           533: 
        !           534:         if (slab & m) {
        !           535: 
        !           536:             if (page->next == NULL) {
        !           537:                 slots = (ngx_slab_page_t *)
        !           538:                                    ((u_char *) pool + sizeof(ngx_slab_pool_t));
        !           539:                 slot = shift - pool->min_shift;
        !           540: 
        !           541:                 page->next = slots[slot].next;
        !           542:                 slots[slot].next = page;
        !           543: 
        !           544:                 page->prev = (uintptr_t) &slots[slot] | NGX_SLAB_BIG;
        !           545:                 page->next->prev = (uintptr_t) page | NGX_SLAB_BIG;
        !           546:             }
        !           547: 
        !           548:             page->slab &= ~m;
        !           549: 
        !           550:             if (page->slab & NGX_SLAB_MAP_MASK) {
        !           551:                 goto done;
        !           552:             }
        !           553: 
        !           554:             ngx_slab_free_pages(pool, page, 1);
        !           555: 
        !           556:             goto done;
        !           557:         }
        !           558: 
        !           559:         goto chunk_already_free;
        !           560: 
        !           561:     case NGX_SLAB_PAGE:
        !           562: 
        !           563:         if ((uintptr_t) p & (ngx_pagesize - 1)) {
        !           564:             goto wrong_chunk;
        !           565:         }
        !           566: 
        !           567:         if (slab == NGX_SLAB_PAGE_FREE) {
        !           568:             ngx_slab_error(pool, NGX_LOG_ALERT,
        !           569:                            "ngx_slab_free(): page is already free");
        !           570:             goto fail;
        !           571:         }
        !           572: 
        !           573:         if (slab == NGX_SLAB_PAGE_BUSY) {
        !           574:             ngx_slab_error(pool, NGX_LOG_ALERT,
        !           575:                            "ngx_slab_free(): pointer to wrong page");
        !           576:             goto fail;
        !           577:         }
        !           578: 
        !           579:         n = ((u_char *) p - pool->start) >> ngx_pagesize_shift;
        !           580:         size = slab & ~NGX_SLAB_PAGE_START;
        !           581: 
        !           582:         ngx_slab_free_pages(pool, &pool->pages[n], size);
        !           583: 
        !           584:         ngx_slab_junk(p, size << ngx_pagesize_shift);
        !           585: 
        !           586:         return;
        !           587:     }
        !           588: 
        !           589:     /* not reached */
        !           590: 
        !           591:     return;
        !           592: 
        !           593: done:
        !           594: 
        !           595:     ngx_slab_junk(p, size);
        !           596: 
        !           597:     return;
        !           598: 
        !           599: wrong_chunk:
        !           600: 
        !           601:     ngx_slab_error(pool, NGX_LOG_ALERT,
        !           602:                    "ngx_slab_free(): pointer to wrong chunk");
        !           603: 
        !           604:     goto fail;
        !           605: 
        !           606: chunk_already_free:
        !           607: 
        !           608:     ngx_slab_error(pool, NGX_LOG_ALERT,
        !           609:                    "ngx_slab_free(): chunk is already free");
        !           610: 
        !           611: fail:
        !           612: 
        !           613:     return;
        !           614: }
        !           615: 
        !           616: 
        !           617: static ngx_slab_page_t *
        !           618: ngx_slab_alloc_pages(ngx_slab_pool_t *pool, ngx_uint_t pages)
        !           619: {
        !           620:     ngx_slab_page_t  *page, *p;
        !           621: 
        !           622:     for (page = pool->free.next; page != &pool->free; page = page->next) {
        !           623: 
        !           624:         if (page->slab >= pages) {
        !           625: 
        !           626:             if (page->slab > pages) {
        !           627:                 page[pages].slab = page->slab - pages;
        !           628:                 page[pages].next = page->next;
        !           629:                 page[pages].prev = page->prev;
        !           630: 
        !           631:                 p = (ngx_slab_page_t *) page->prev;
        !           632:                 p->next = &page[pages];
        !           633:                 page->next->prev = (uintptr_t) &page[pages];
        !           634: 
        !           635:             } else {
        !           636:                 p = (ngx_slab_page_t *) page->prev;
        !           637:                 p->next = page->next;
        !           638:                 page->next->prev = page->prev;
        !           639:             }
        !           640: 
        !           641:             page->slab = pages | NGX_SLAB_PAGE_START;
        !           642:             page->next = NULL;
        !           643:             page->prev = NGX_SLAB_PAGE;
        !           644: 
        !           645:             if (--pages == 0) {
        !           646:                 return page;
        !           647:             }
        !           648: 
        !           649:             for (p = page + 1; pages; pages--) {
        !           650:                 p->slab = NGX_SLAB_PAGE_BUSY;
        !           651:                 p->next = NULL;
        !           652:                 p->prev = NGX_SLAB_PAGE;
        !           653:                 p++;
        !           654:             }
        !           655: 
        !           656:             return page;
        !           657:         }
        !           658:     }
        !           659: 
        !           660:     ngx_slab_error(pool, NGX_LOG_CRIT, "ngx_slab_alloc() failed: no memory");
        !           661: 
        !           662:     return NULL;
        !           663: }
        !           664: 
        !           665: 
        !           666: static void
        !           667: ngx_slab_free_pages(ngx_slab_pool_t *pool, ngx_slab_page_t *page,
        !           668:     ngx_uint_t pages)
        !           669: {
        !           670:     ngx_slab_page_t  *prev;
        !           671: 
        !           672:     page->slab = pages--;
        !           673: 
        !           674:     if (pages) {
        !           675:         ngx_memzero(&page[1], pages * sizeof(ngx_slab_page_t));
        !           676:     }
        !           677: 
        !           678:     if (page->next) {
        !           679:         prev = (ngx_slab_page_t *) (page->prev & ~NGX_SLAB_PAGE_MASK);
        !           680:         prev->next = page->next;
        !           681:         page->next->prev = page->prev;
        !           682:     }
        !           683: 
        !           684:     page->prev = (uintptr_t) &pool->free;
        !           685:     page->next = pool->free.next;
        !           686: 
        !           687:     page->next->prev = (uintptr_t) page;
        !           688: 
        !           689:     pool->free.next = page;
        !           690: }
        !           691: 
        !           692: 
        !           693: static void
        !           694: ngx_slab_error(ngx_slab_pool_t *pool, ngx_uint_t level, char *text)
        !           695: {
        !           696:     ngx_log_error(level, ngx_cycle->log, 0, "%s%s", text, pool->log_ctx);
        !           697: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>