Skip to content
Snippets Groups Projects
Commit cb644f28 authored by Konstantin Osipov's avatar Konstantin Osipov
Browse files

Fixes gh-378 "assertion failed"

Do not align maxalloc (the limit on the amount of memory
used by the allocator), it's not necessary.

Make an effort to correctly align large (for 32 bit) prealloc
values (like, a few gigs).
parent 334a6fe5
No related branches found
No related tags found
No related merge requests found
...@@ -54,9 +54,10 @@ munmap_checked(void *addr, size_t size) ...@@ -54,9 +54,10 @@ munmap_checked(void *addr, size_t size)
static void * static void *
mmap_checked(size_t size, size_t align, int flags) mmap_checked(size_t size, size_t align, int flags)
{ {
/* The size must be a power of two. */ /* The alignment must be a power of two. */
assert((size & (size - 1)) == 0);
assert((align & (align - 1)) == 0); 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 * mmap twice the requested amount to be able to align
* the mapped address. * the mapped address.
...@@ -101,6 +102,7 @@ pow2round(size_t size) ...@@ -101,6 +102,7 @@ pow2round(size_t size)
#endif #endif
#define MAX(a, b) (a) > (b) ? (a) : (b) #define MAX(a, b) (a) > (b) ? (a) : (b)
#define MIN(a, b) (a) < (b) ? (a) : (b)
int int
slab_arena_create(struct slab_arena *arena, slab_arena_create(struct slab_arena *arena,
...@@ -116,18 +118,13 @@ 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)); arena->slab_size = small_round(MAX(slab_size, SLAB_MIN_SIZE));
if (maxalloc) { arena->maxalloc = maxalloc;
arena->maxalloc = small_round(MAX(maxalloc, /** Prealloc can not be greater than maxalloc */
arena->slab_size)); prealloc = MIN(prealloc, maxalloc);
} else { /** Extremely large sizes can not be aligned properly */
arena->maxalloc = 0; prealloc = MIN(prealloc, SIZE_MAX - arena->slab_size);
} /* Align prealloc around a fixed number of slabs. */
arena->prealloc = small_align(prealloc, arena->slab_size);
/* 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->used = 0; arena->used = 0;
......
...@@ -36,8 +36,12 @@ ...@@ -36,8 +36,12 @@
extern "C" { extern "C" {
#endif /* defined(__cplusplus) */ #endif /* defined(__cplusplus) */
enum { SLAB_MIN_SIZE = USHRT_MAX, enum {
SMALL_UNLIMITED = SIZE_MAX/2 + 1}; /* 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. * slab_arena -- a source of large aligned blocks of memory.
...@@ -121,7 +125,11 @@ slab_arena_mprotect(struct slab_arena *arena); ...@@ -121,7 +125,11 @@ slab_arena_mprotect(struct slab_arena *arena);
static inline size_t static inline size_t
small_align(size_t size, size_t alignment) 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. */ /** Round a number to the nearest power of two. */
......
...@@ -3,23 +3,23 @@ arena->maxalloc = 0 ...@@ -3,23 +3,23 @@ arena->maxalloc = 0
arena->used = 0 arena->used = 0
arena->slab_size = 65536 arena->slab_size = 65536
arena->prealloc = 65536 arena->prealloc = 65536
arena->maxalloc = 65536 arena->maxalloc = 1
arena->used = 0 arena->used = 0
arena->slab_size = 65536 arena->slab_size = 65536
arena->prealloc = 65536 arena->prealloc = 65536
arena->maxalloc = 65536 arena->maxalloc = 1
arena->used = 65536 arena->used = 65536
arena->slab_size = 65536 arena->slab_size = 65536
going beyond the limit: (nil) going beyond the limit: (nil)
arena->prealloc = 65536 arena->prealloc = 65536
arena->maxalloc = 65536 arena->maxalloc = 1
arena->used = 65536 arena->used = 65536
arena->slab_size = 65536 arena->slab_size = 65536
arena->prealloc = 65536 arena->prealloc = 65536
arena->maxalloc = 65536 arena->maxalloc = 1
arena->used = 65536 arena->used = 65536
arena->slab_size = 65536 arena->slab_size = 65536
arena->prealloc = 2097152 arena->prealloc = 2031616
arena->maxalloc = 4194304 arena->maxalloc = 3000000
arena->used = 0 arena->used = 0
arena->slab_size = 65536 arena->slab_size = 65536
...@@ -15,11 +15,11 @@ while true do ...@@ -15,11 +15,11 @@ while true do
i = i + 1 i = i + 1
end; 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(); space:len();
--- ---
- 73 - 62
... ...
i = 1; i = 1;
--- ---
...@@ -29,11 +29,11 @@ while true do ...@@ -29,11 +29,11 @@ while true do
i = i + 1 i = i + 1
end; 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(); space:len();
--- ---
- 146 - 124
... ...
i = 1; i = 1;
--- ---
...@@ -43,12 +43,12 @@ while true do ...@@ -43,12 +43,12 @@ while true do
i = i + 1 i = i + 1
end; 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 '' --# setopt delimiter ''
space:len() space:len()
--- ---
- 219 - 185
... ...
space.index['primary']:get{0} space.index['primary']:get{0}
--- ---
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment