int slab_arena_create(struct slab_arena *arena, struct quota *quota, size_t prealloc, uint32_t slab_size, int flags) { assert(flags & (MAP_PRIVATE | MAP_SHARED)); lf_lifo_init(&arena->cache); /* * Round up the user supplied data - it can come in * directly from the configuration file. Allow * zero-size arena for testing purposes. */ arena->slab_size = small_round(MAX(slab_size, SLAB_MIN_SIZE)); arena->quota = quota; /** Prealloc can not be greater than the quota */ prealloc = MIN(prealloc, quota_total(quota)); /** 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; arena->flags = flags; if (arena->prealloc) { arena->arena = mmap_checked(arena->prealloc, arena->slab_size, arena->flags); } else { arena->arena = NULL; } return arena->prealloc && !arena->arena ? -1 : 0; }
void * slab_map(struct slab_arena *arena) { void *ptr; if ((ptr = lf_lifo_pop(&arena->cache))) return ptr; /** Need to allocate a new slab. */ size_t used = __sync_add_and_fetch(&arena->used, arena->slab_size); if (used <= arena->prealloc) return arena->arena + used - arena->slab_size; if (used > arena->maxalloc) { __sync_sub_and_fetch(&arena->used, arena->slab_size); return NULL; } return mmap_checked(arena->slab_size, arena->slab_size, arena->flags); }
int slab_arena_create(struct slab_arena *arena, size_t prealloc, size_t maxalloc, uint32_t slab_size, int flags) { assert(flags & (MAP_PRIVATE | MAP_SHARED)); lf_lifo_init(&arena->cache); /* * Round up the user supplied data - it can come in * directly from the configuration file. Allow * zero-size arena for testing purposes. */ 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->used = 0; arena->flags = flags; if (arena->prealloc) { arena->arena = mmap_checked(arena->prealloc, arena->slab_size, arena->flags); } else { arena->arena = NULL; } return arena->prealloc && !arena->arena ? -1 : 0; }
void * slab_map(struct slab_arena *arena) { void *ptr; if ((ptr = lf_lifo_pop(&arena->cache))) return ptr; if (quota_use(arena->quota, arena->slab_size) < 0) return NULL; /** Need to allocate a new slab. */ size_t used = __sync_add_and_fetch(&arena->used, arena->slab_size); if (used <= arena->prealloc) return arena->arena + used - arena->slab_size; ptr = mmap_checked(arena->slab_size, arena->slab_size, arena->flags); if (!ptr) { __sync_sub_and_fetch(&arena->used, arena->slab_size); quota_release(arena->quota, arena->slab_size); } return ptr; }