mirror of
				https://github.com/openresty/openresty.git
				synced 2024-10-13 00:29:41 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			139 lines
		
	
	
		
			4.2 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			139 lines
		
	
	
		
			4.2 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| diff --git a/src/core/ngx_slab.c b/src/core/ngx_slab.c
 | |
| index c3a27f7..1bde432 100644
 | |
| --- a/src/core/ngx_slab.c
 | |
| +++ b/src/core/ngx_slab.c
 | |
| @@ -6,6 +6,7 @@
 | |
|  
 | |
|  #include <ngx_config.h>
 | |
|  #include <ngx_core.h>
 | |
| +#include <assert.h>
 | |
|  
 | |
|  
 | |
|  #define NGX_SLAB_PAGE_MASK   3
 | |
| @@ -111,6 +112,7 @@ ngx_slab_init(ngx_slab_pool_t *pool)
 | |
|      ngx_memzero(p, pages * sizeof(ngx_slab_page_t));
 | |
|  
 | |
|      pool->pages = (ngx_slab_page_t *) p;
 | |
| +    pool->npages = pages;
 | |
|  
 | |
|      pool->free.prev = 0;
 | |
|      pool->free.next = (ngx_slab_page_t *) p;
 | |
| @@ -118,6 +120,7 @@ ngx_slab_init(ngx_slab_pool_t *pool)
 | |
|      pool->pages->slab = pages;
 | |
|      pool->pages->next = &pool->free;
 | |
|      pool->pages->prev = (uintptr_t) &pool->free;
 | |
| +    pool->pages->prev_slab = 0;
 | |
|  
 | |
|      pool->start = (u_char *)
 | |
|                    ngx_align_ptr((uintptr_t) p + pages * sizeof(ngx_slab_page_t),
 | |
| @@ -625,9 +628,16 @@ ngx_slab_alloc_pages(ngx_slab_pool_t *pool, ngx_uint_t pages)
 | |
|          if (page->slab >= pages) {
 | |
|  
 | |
|              if (page->slab > pages) {
 | |
| +                /* adjust the next adjacent block's "prev_slab" field */
 | |
| +                p = &page[page->slab];
 | |
| +                if (p < pool->pages + pool->npages) {
 | |
| +                    p->prev_slab = page->slab - pages;
 | |
| +                }
 | |
| +
 | |
|                  page[pages].slab = page->slab - pages;
 | |
|                  page[pages].next = page->next;
 | |
|                  page[pages].prev = page->prev;
 | |
| +                page[pages].prev_slab = pages;
 | |
|  
 | |
|                  p = (ngx_slab_page_t *) page->prev;
 | |
|                  p->next = &page[pages];
 | |
| @@ -651,6 +661,7 @@ ngx_slab_alloc_pages(ngx_slab_pool_t *pool, ngx_uint_t pages)
 | |
|                  p->slab = NGX_SLAB_PAGE_BUSY;
 | |
|                  p->next = NULL;
 | |
|                  p->prev = NGX_SLAB_PAGE;
 | |
| +                p->prev_slab = 0;
 | |
|                  p++;
 | |
|              }
 | |
|  
 | |
| @@ -668,7 +679,7 @@ static void
 | |
|  ngx_slab_free_pages(ngx_slab_pool_t *pool, ngx_slab_page_t *page,
 | |
|      ngx_uint_t pages)
 | |
|  {
 | |
| -    ngx_slab_page_t  *prev;
 | |
| +    ngx_slab_page_t  *prev, *p;
 | |
|  
 | |
|      page->slab = pages--;
 | |
|  
 | |
| @@ -682,6 +693,53 @@ ngx_slab_free_pages(ngx_slab_pool_t *pool, ngx_slab_page_t *page,
 | |
|          page->next->prev = page->prev;
 | |
|      }
 | |
|  
 | |
| +    /* merge the next adjacent free block if it is free */
 | |
| +
 | |
| +    p = &page[page->slab];
 | |
| +    if (p < pool->pages + pool->npages
 | |
| +        && !(p->slab & NGX_SLAB_PAGE_START)
 | |
| +        && p->next != NULL
 | |
| +        && (p->prev & NGX_SLAB_PAGE_MASK) == NGX_SLAB_PAGE)
 | |
| +    {
 | |
| +        page->slab += p->slab;
 | |
| +
 | |
| +        /* remove the next adjacent block from the free list */
 | |
| +
 | |
| +        prev = (ngx_slab_page_t *) p->prev;
 | |
| +        prev->next = p->next;
 | |
| +        p->next->prev = p->prev;
 | |
| +
 | |
| +        /* adjust the "prev_slab" field in the next next adjacent block */
 | |
| +        if (p + p->slab < pool->pages + pool->npages) {
 | |
| +            p[p->slab].prev_slab = page->slab;
 | |
| +        }
 | |
| +
 | |
| +        ngx_memzero(p, sizeof(ngx_slab_page_t));
 | |
| +    }
 | |
| +
 | |
| +    if (page->prev_slab) {
 | |
| +        /* merge the previous adjacent block if it is free */
 | |
| +
 | |
| +        p = page - page->prev_slab;
 | |
| +        if (!(p->slab & NGX_SLAB_PAGE_START)
 | |
| +            && p->next != NULL
 | |
| +            && (p->prev & NGX_SLAB_PAGE_MASK) == NGX_SLAB_PAGE)
 | |
| +        {
 | |
| +            assert(p->slab == page->prev_slab);
 | |
| +
 | |
| +            p->slab += page->slab;
 | |
| +            ngx_memzero(page, sizeof(ngx_slab_page_t));
 | |
| +
 | |
| +            /* adjust the "prev_slab" field in the next adjacent block */
 | |
| +            if (p + p->slab < pool->pages + pool->npages) {
 | |
| +                p[p->slab].prev_slab = p->slab;
 | |
| +            }
 | |
| +
 | |
| +            /* skip adding "page" to the free list */
 | |
| +            return;
 | |
| +        }
 | |
| +    }
 | |
| +
 | |
|      page->prev = (uintptr_t) &pool->free;
 | |
|      page->next = pool->free.next;
 | |
|  
 | |
| diff --git a/src/core/ngx_slab.h b/src/core/ngx_slab.h
 | |
| index c5e420b..287ac79 100644
 | |
| --- a/src/core/ngx_slab.h
 | |
| +++ b/src/core/ngx_slab.h
 | |
| @@ -19,6 +19,8 @@ struct ngx_slab_page_s {
 | |
|      uintptr_t         slab;
 | |
|      ngx_slab_page_t  *next;
 | |
|      uintptr_t         prev;
 | |
| +    uintptr_t         prev_slab;
 | |
| +                         /* number of pages for the previous adjacent block */
 | |
|  };
 | |
|  
 | |
|  
 | |
| @@ -31,6 +33,8 @@ typedef struct {
 | |
|      ngx_slab_page_t  *pages;
 | |
|      ngx_slab_page_t   free;
 | |
|  
 | |
| +    ngx_uint_t        npages;
 | |
| +
 | |
|      u_char           *start;
 | |
|      u_char           *end;
 | |
|  
 |