diff --git a/src/lib/small/slab_arena.c b/src/lib/small/slab_arena.c index 6d30c355d0cac246f366e7c765f2fe0924940631..0d3a6e301e10f9466b6a31474c819150686d15be 100644 --- a/src/lib/small/slab_arena.c +++ b/src/lib/small/slab_arena.c @@ -54,9 +54,10 @@ munmap_checked(void *addr, size_t size) static void * mmap_checked(size_t size, size_t align, int flags) { - /* The size must be a power of two. */ - assert((size & (size - 1)) == 0); + /* The alignment must be a power of two. */ assert((align & (align - 1)) == 0); + /* The size must be a multiple of alignment */ + assert((size & (align - 1)) == 0); /* * mmap twice the requested amount to be able to align * the mapped address. @@ -101,6 +102,7 @@ pow2round(size_t size) #endif #define MAX(a, b) (a) > (b) ? (a) : (b) +#define MIN(a, b) (a) < (b) ? (a) : (b) int slab_arena_create(struct slab_arena *arena, @@ -116,18 +118,13 @@ slab_arena_create(struct slab_arena *arena, */ arena->slab_size = small_round(MAX(slab_size, SLAB_MIN_SIZE)); - if (maxalloc) { - arena->maxalloc = small_round(MAX(maxalloc, - arena->slab_size)); - } else { - arena->maxalloc = 0; - } - - /* Align arena around a fixed number of slabs. */ - arena->prealloc = small_align(small_round(prealloc), - arena->slab_size); - if (arena->maxalloc < arena->prealloc) - arena->prealloc = arena->maxalloc; + arena->maxalloc = maxalloc; + /** Prealloc can not be greater than maxalloc */ + prealloc = MIN(prealloc, maxalloc); + /** Extremely large sizes can not be aligned properly */ + prealloc = MIN(prealloc, SIZE_MAX - arena->slab_size); + /* Align prealloc around a fixed number of slabs. */ + arena->prealloc = small_align(prealloc, arena->slab_size); arena->used = 0; diff --git a/src/lib/small/slab_arena.h b/src/lib/small/slab_arena.h index 1531b816d760ba23f98198258fd25f84dad14e32..322fb80a08d19ad1d8227999a70f2adb1b252aa3 100644 --- a/src/lib/small/slab_arena.h +++ b/src/lib/small/slab_arena.h @@ -36,8 +36,12 @@ extern "C" { #endif /* defined(__cplusplus) */ -enum { SLAB_MIN_SIZE = USHRT_MAX, - SMALL_UNLIMITED = SIZE_MAX/2 + 1}; +enum { + /* Smallest possible slab size. */ + SLAB_MIN_SIZE = USHRT_MAX, + /** The largest allowed amount of memory of a single arena. */ + SMALL_UNLIMITED = SIZE_MAX/2 + 1 +}; /** * slab_arena -- a source of large aligned blocks of memory. @@ -121,7 +125,11 @@ slab_arena_mprotect(struct slab_arena *arena); static inline size_t small_align(size_t size, size_t alignment) { - return (size + alignment - 1) & ~(alignment - 1); + /* Must be a power of two */ + assert((alignment & (alignment - 1)) == 0); + /* Bit arithmetics won't work for a large size */ + assert(size <= SIZE_MAX - alignment); + return (size - 1 + alignment) & ~(alignment - 1); } /** Round a number to the nearest power of two. */ diff --git a/test/unit/slab_arena.result b/test/unit/slab_arena.result index b8ec4d8b0bc1ed9f472a997b83ea64185f994463..5af7304e7433542a38978afa3798c659d0d8bd4e 100644 --- a/test/unit/slab_arena.result +++ b/test/unit/slab_arena.result @@ -3,23 +3,23 @@ arena->maxalloc = 0 arena->used = 0 arena->slab_size = 65536 arena->prealloc = 65536 -arena->maxalloc = 65536 +arena->maxalloc = 1 arena->used = 0 arena->slab_size = 65536 arena->prealloc = 65536 -arena->maxalloc = 65536 +arena->maxalloc = 1 arena->used = 65536 arena->slab_size = 65536 going beyond the limit: (nil) arena->prealloc = 65536 -arena->maxalloc = 65536 +arena->maxalloc = 1 arena->used = 65536 arena->slab_size = 65536 arena->prealloc = 65536 -arena->maxalloc = 65536 +arena->maxalloc = 1 arena->used = 65536 arena->slab_size = 65536 -arena->prealloc = 2097152 -arena->maxalloc = 4194304 +arena->prealloc = 2031616 +arena->maxalloc = 3000000 arena->used = 0 arena->slab_size = 65536 diff --git a/test/wal/oom.result b/test/wal/oom.result index 9c14e32bfa6a2db4c703afac31ddf0e1664c3d36..089a7c863cee3698aad087f5e4726a1ced3fe041 100644 --- a/test/wal/oom.result +++ b/test/wal/oom.result @@ -15,11 +15,11 @@ while true do i = i + 1 end; --- -- error: Failed to allocate 313 bytes in slab allocator for tuple +- error: Failed to allocate 268 bytes in slab allocator for tuple ... space:len(); --- -- 73 +- 62 ... i = 1; --- @@ -29,11 +29,11 @@ while true do i = i + 1 end; --- -- error: Failed to allocate 314 bytes in slab allocator for tuple +- error: Failed to allocate 268 bytes in slab allocator for tuple ... space:len(); --- -- 146 +- 124 ... i = 1; --- @@ -43,12 +43,12 @@ while true do i = i + 1 end; --- -- error: Failed to allocate 314 bytes in slab allocator for tuple +- error: Failed to allocate 265 bytes in slab allocator for tuple ... --# setopt delimiter '' space:len() --- -- 219 +- 185 ... space.index['primary']:get{0} ---