summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRuslan Ermilov <ru@nginx.com>2017-07-04 18:32:30 +0300
committerRuslan Ermilov <ru@nginx.com>2017-07-04 18:32:30 +0300
commitd0071f08e88660aab9af84f4210c1a4a32f34980 (patch)
tree9e0f2266fe6ee4e0e1f4443ba9461f8996540f9d
parent75c3f8958be4ae7284a46f1d61d79193e6bc5d95 (diff)
downloadnginx-d0071f08e88660aab9af84f4210c1a4a32f34980.tar.gz
Slab: fixed small allocations on systems with large pagesize.
Notably, on ppc64 with 64k pagesize, slab 0 (of size 8) requires 128 64-bit elements for bitmasks. The code bogusly assumed that one uintptr_t is enough for bitmasks plus at least one free slot.
-rw-r--r--src/core/ngx_slab.c17
1 files changed, 13 insertions, 4 deletions
diff --git a/src/core/ngx_slab.c b/src/core/ngx_slab.c
index 587987023..9e7796d50 100644
--- a/src/core/ngx_slab.c
+++ b/src/core/ngx_slab.c
@@ -339,11 +339,17 @@ ngx_slab_alloc_locked(ngx_slab_pool_t *pool, size_t size)
}
/* "n" elements for bitmap, plus one requested */
- bitmap[0] = ((uintptr_t) 2 << n) - 1;
+
+ for (i = 0; i < (n + 1) / (8 * sizeof(uintptr_t)); i++) {
+ bitmap[i] = NGX_SLAB_BUSY;
+ }
+
+ m = ((uintptr_t) 1 << ((n + 1) % (8 * sizeof(uintptr_t)))) - 1;
+ bitmap[i] = m;
map = (ngx_pagesize >> shift) / (8 * sizeof(uintptr_t));
- for (i = 1; i < map; i++) {
+ for (i = i + 1; i < map; i++) {
bitmap[i] = 0;
}
@@ -506,13 +512,16 @@ ngx_slab_free_locked(ngx_slab_pool_t *pool, void *p)
n = 1;
}
- if (bitmap[0] & ~(((uintptr_t) 1 << n) - 1)) {
+ i = n / (8 * sizeof(uintptr_t));
+ m = ((uintptr_t) 1 << (n % (8 * sizeof(uintptr_t)))) - 1;
+
+ if (bitmap[i] & ~m) {
goto done;
}
map = (ngx_pagesize >> shift) / (8 * sizeof(uintptr_t));
- for (i = 1; i < map; i++) {
+ for (i = i + 1; i < map; i++) {
if (bitmap[i]) {
goto done;
}