changeset 6826:d0404c9a7675

Slab: simplified allocation from slots. Removed code that would cause an endless loop, and removed condition check that is always false. The first page in the slot list is guaranteed to satisfy an allocation.
author Ruslan Ermilov <ru@nginx.com>
date Wed, 07 Dec 2016 22:25:37 +0300
parents f6beb55792de
children 0e61510c56c4
files src/core/ngx_slab.c
diffstat 1 files changed, 66 insertions(+), 84 deletions(-) [+]
line wrap: on
line diff
--- a/src/core/ngx_slab.c
+++ b/src/core/ngx_slab.c
@@ -215,84 +215,71 @@ ngx_slab_alloc_locked(ngx_slab_pool_t *p
 
         if (shift < ngx_slab_exact_shift) {
 
-            do {
-                bitmap = (uintptr_t *) ngx_slab_page_addr(pool, page);
-
-                map = (1 << (ngx_pagesize_shift - shift))
-                          / (sizeof(uintptr_t) * 8);
-
-                for (n = 0; n < map; n++) {
-
-                    if (bitmap[n] != NGX_SLAB_BUSY) {
-
-                        for (m = 1, i = 0; m; m <<= 1, i++) {
-                            if (bitmap[n] & m) {
-                                continue;
-                            }
-
-                            bitmap[n] |= m;
-
-                            i = ((n * sizeof(uintptr_t) * 8) << shift)
-                                + (i << shift);
-
-                            if (bitmap[n] == NGX_SLAB_BUSY) {
-                                for (n = n + 1; n < map; n++) {
-                                    if (bitmap[n] != NGX_SLAB_BUSY) {
-                                        p = (uintptr_t) bitmap + i;
+            bitmap = (uintptr_t *) ngx_slab_page_addr(pool, page);
 
-                                        goto done;
-                                    }
-                                }
-
-                                prev = ngx_slab_page_prev(page);
-                                prev->next = page->next;
-                                page->next->prev = page->prev;
-
-                                page->next = NULL;
-                                page->prev = NGX_SLAB_SMALL;
-                            }
-
-                            p = (uintptr_t) bitmap + i;
+            map = (1 << (ngx_pagesize_shift - shift))
+                      / (sizeof(uintptr_t) * 8);
 
-                            goto done;
-                        }
-                    }
-                }
-
-                page = page->next;
+            for (n = 0; n < map; n++) {
 
-            } while (page);
-
-        } else if (shift == ngx_slab_exact_shift) {
-
-            do {
-                if (page->slab != NGX_SLAB_BUSY) {
+                if (bitmap[n] != NGX_SLAB_BUSY) {
 
                     for (m = 1, i = 0; m; m <<= 1, i++) {
-                        if (page->slab & m) {
+                        if (bitmap[n] & m) {
                             continue;
                         }
 
-                        page->slab |= m;
+                        bitmap[n] |= m;
+
+                        i = ((n * sizeof(uintptr_t) * 8) << shift)
+                            + (i << shift);
 
-                        if (page->slab == NGX_SLAB_BUSY) {
+                        if (bitmap[n] == NGX_SLAB_BUSY) {
+                            for (n = n + 1; n < map; n++) {
+                                if (bitmap[n] != NGX_SLAB_BUSY) {
+                                    p = (uintptr_t) bitmap + i;
+
+                                    goto done;
+                                }
+                            }
+
                             prev = ngx_slab_page_prev(page);
                             prev->next = page->next;
                             page->next->prev = page->prev;
 
                             page->next = NULL;
-                            page->prev = NGX_SLAB_EXACT;
+                            page->prev = NGX_SLAB_SMALL;
                         }
 
-                        p = ngx_slab_page_addr(pool, page) + (i << shift);
+                        p = (uintptr_t) bitmap + i;
 
                         goto done;
                     }
                 }
+            }
 
-                page = page->next;
+        } else if (shift == ngx_slab_exact_shift) {
+
+            for (m = 1, i = 0; m; m <<= 1, i++) {
+                if (page->slab & m) {
+                    continue;
+                }
+
+                page->slab |= m;
 
-            } while (page);
+                if (page->slab == NGX_SLAB_BUSY) {
+                    prev = ngx_slab_page_prev(page);
+                    prev->next = page->next;
+                    page->next->prev = page->prev;
+
+                    page->next = NULL;
+                    page->prev = NGX_SLAB_EXACT;
+                }
+
+                p = ngx_slab_page_addr(pool, page) + (i << shift);
+
+                goto done;
+            }
 
         } else { /* shift > ngx_slab_exact_shift */
 
@@ -301,38 +288,33 @@ ngx_slab_alloc_locked(ngx_slab_pool_t *p
             n = ((uintptr_t) 1 << n) - 1;
             mask = n << NGX_SLAB_MAP_SHIFT;
 
-            do {
-                if ((page->slab & NGX_SLAB_MAP_MASK) != mask) {
-
-                    for (m = (uintptr_t) 1 << NGX_SLAB_MAP_SHIFT, i = 0;
-                         m & mask;
-                         m <<= 1, i++)
-                    {
-                        if (page->slab & m) {
-                            continue;
-                        }
-
-                        page->slab |= m;
-
-                        if ((page->slab & NGX_SLAB_MAP_MASK) == mask) {
-                            prev = ngx_slab_page_prev(page);
-                            prev->next = page->next;
-                            page->next->prev = page->prev;
-
-                            page->next = NULL;
-                            page->prev = NGX_SLAB_BIG;
-                        }
-
-                        p = ngx_slab_page_addr(pool, page) + (i << shift);
-
-                        goto done;
-                    }
+            for (m = (uintptr_t) 1 << NGX_SLAB_MAP_SHIFT, i = 0;
+                 m & mask;
+                 m <<= 1, i++)
+            {
+                if (page->slab & m) {
+                    continue;
                 }
 
-                page = page->next;
+                page->slab |= m;
+
+                if ((page->slab & NGX_SLAB_MAP_MASK) == mask) {
+                    prev = ngx_slab_page_prev(page);
+                    prev->next = page->next;
+                    page->next->prev = page->prev;
 
-            } while (page);
+                    page->next = NULL;
+                    page->prev = NGX_SLAB_BIG;
+                }
+
+                p = ngx_slab_page_addr(pool, page) + (i << shift);
+
+                goto done;
+            }
         }
+
+        ngx_slab_error(pool, NGX_LOG_ALERT, "ngx_slab_alloc(): page is busy");
+        ngx_debug_point();
     }
 
     page = ngx_slab_alloc_pages(pool, 1);