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;
 | 
						|
 
 |