X-Git-Url: https://git.kernel.dk/?p=fio.git;a=blobdiff_plain;f=smalloc.c;h=447d5c55fe3336986c490c068a5f919a100b55cf;hp=5ba20047b37676ec8659dffc53dd6459061a5e4d;hb=45a65144dd71ecc963a94d3dfd7bc01d4bde664a;hpb=e43606c2b13ad7fc1af2bbe4a61cf8480ee3a532 diff --git a/smalloc.c b/smalloc.c index 5ba20047..447d5c55 100644 --- a/smalloc.c +++ b/smalloc.c @@ -16,6 +16,8 @@ #include "mutex.h" #include "arch/arch.h" #include "os/os.h" +#include "smalloc.h" +#include "log.h" #define SMALLOC_REDZONE /* define to detect memory corruption */ @@ -23,27 +25,27 @@ #define SMALLOC_BPI (sizeof(unsigned int) * 8) #define SMALLOC_BPL (SMALLOC_BPB * SMALLOC_BPI) -#define INITIAL_SIZE 8192*1024 /* new pool size */ -#define MAX_POOLS 128 /* maximum number of pools to setup */ +#define INITIAL_SIZE 16*1024*1024 /* new pool size */ +#define MAX_POOLS 8 /* maximum number of pools to setup */ #define SMALLOC_PRE_RED 0xdeadbeefU #define SMALLOC_POST_RED 0x5aa55aa5U unsigned int smalloc_pool_size = INITIAL_SIZE; -const int int_mask = sizeof(int) - 1; +static const int int_mask = sizeof(int) - 1; struct pool { struct fio_mutex *lock; /* protects this pool */ void *map; /* map of blocks */ unsigned int *bitmap; /* blocks free/busy map */ - unsigned int free_blocks; /* free blocks */ - unsigned int nr_blocks; /* total blocks */ - unsigned int next_non_full; - unsigned int mmap_size; + size_t free_blocks; /* free blocks */ + size_t nr_blocks; /* total blocks */ + size_t next_non_full; + size_t mmap_size; }; struct block_hdr { - unsigned int size; + size_t size; #ifdef SMALLOC_REDZONE unsigned int prered; #endif @@ -52,7 +54,7 @@ struct block_hdr { static struct pool mp[MAX_POOLS]; static unsigned int nr_pools; static unsigned int last_pool; -static struct fio_mutex *lock; +static struct fio_rwlock *lock; static inline void pool_lock(struct pool *pool) { @@ -66,22 +68,22 @@ static inline void pool_unlock(struct pool *pool) static inline void global_read_lock(void) { - fio_mutex_down_read(lock); + fio_rwlock_read(lock); } static inline void global_read_unlock(void) { - fio_mutex_up_read(lock); + fio_rwlock_unlock(lock); } static inline void global_write_lock(void) { - fio_mutex_down_write(lock); + fio_rwlock_write(lock); } static inline void global_write_unlock(void) { - fio_mutex_up_write(lock); + fio_rwlock_unlock(lock); } static inline int ptr_valid(struct pool *pool, void *ptr) @@ -91,13 +93,13 @@ static inline int ptr_valid(struct pool *pool, void *ptr) return (ptr >= pool->map) && (ptr < pool->map + pool_size); } -static inline unsigned int size_to_blocks(unsigned int size) +static inline size_t size_to_blocks(size_t size) { return (size + SMALLOC_BPB - 1) / SMALLOC_BPB; } static int blocks_iter(struct pool *pool, unsigned int pool_idx, - unsigned int idx, unsigned int nr_blocks, + unsigned int idx, size_t nr_blocks, int (*func)(unsigned int *map, unsigned int mask)) { @@ -152,19 +154,19 @@ static int mask_set(unsigned int *map, unsigned int mask) } static int blocks_free(struct pool *pool, unsigned int pool_idx, - unsigned int idx, unsigned int nr_blocks) + unsigned int idx, size_t nr_blocks) { return blocks_iter(pool, pool_idx, idx, nr_blocks, mask_cmp); } static void set_blocks(struct pool *pool, unsigned int pool_idx, - unsigned int idx, unsigned int nr_blocks) + unsigned int idx, size_t nr_blocks) { blocks_iter(pool, pool_idx, idx, nr_blocks, mask_set); } static void clear_blocks(struct pool *pool, unsigned int pool_idx, - unsigned int idx, unsigned int nr_blocks) + unsigned int idx, size_t nr_blocks) { blocks_iter(pool, pool_idx, idx, nr_blocks, mask_clear); } @@ -179,6 +181,7 @@ static int find_next_zero(int word, int start) static int add_pool(struct pool *pool, unsigned int alloc_size) { int bitmap_blocks; + int mmap_flags; void *ptr; #ifdef SMALLOC_REDZONE @@ -197,8 +200,14 @@ static int add_pool(struct pool *pool, unsigned int alloc_size) pool->nr_blocks = bitmap_blocks; pool->free_blocks = bitmap_blocks * SMALLOC_BPB; - ptr = mmap(NULL, alloc_size, PROT_READ|PROT_WRITE, - MAP_SHARED | OS_MAP_ANON, -1, 0); + mmap_flags = OS_MAP_ANON; +#ifdef CONFIG_ESX + mmap_flags |= MAP_PRIVATE; +#else + mmap_flags |= MAP_SHARED; +#endif + ptr = mmap(NULL, alloc_size, PROT_READ|PROT_WRITE, mmap_flags, -1, 0); + if (ptr == MAP_FAILED) goto out_fail; @@ -206,14 +215,14 @@ static int add_pool(struct pool *pool, unsigned int alloc_size) pool->map = ptr; pool->bitmap = (void *) ptr + (pool->nr_blocks * SMALLOC_BPL); - pool->lock = fio_mutex_init(1); + pool->lock = fio_mutex_init(FIO_MUTEX_UNLOCKED); if (!pool->lock) goto out_fail; nr_pools++; return 0; out_fail: - fprintf(stderr, "smalloc: failed adding pool\n"); + log_err("smalloc: failed adding pool\n"); if (pool->map) munmap(pool->map, pool->mmap_size); return 1; @@ -221,11 +230,21 @@ out_fail: void sinit(void) { - int ret; + int i, ret; + + lock = fio_rwlock_init(); + + for (i = 0; i < MAX_POOLS; i++) { + ret = add_pool(&mp[i], INITIAL_SIZE); + if (ret) + break; + } - lock = fio_mutex_rw_init(); - ret = add_pool(&mp[0], INITIAL_SIZE); - assert(!ret); + /* + * If we added at least one pool, we should be OK for most + * cases. + */ + assert(i); } static void cleanup_pool(struct pool *pool) @@ -248,7 +267,7 @@ void scleanup(void) cleanup_pool(&mp[i]); if (lock) - fio_mutex_remove(lock); + fio_rwlock_remove(lock); } #ifdef SMALLOC_REDZONE @@ -275,14 +294,14 @@ static void sfree_check_redzone(struct block_hdr *hdr) unsigned int *postred = postred_ptr(hdr); if (hdr->prered != SMALLOC_PRE_RED) { - fprintf(stderr, "smalloc pre redzone destroyed!\n"); - fprintf(stderr, " ptr=%p, prered=%x, expected %x\n", + log_err("smalloc pre redzone destroyed!\n" + " ptr=%p, prered=%x, expected %x\n", hdr, hdr->prered, SMALLOC_PRE_RED); assert(0); } if (*postred != SMALLOC_POST_RED) { - fprintf(stderr, "smalloc post redzone destroyed!\n"); - fprintf(stderr, " ptr=%p, postred=%x, expected %x\n", + log_err("smalloc post redzone destroyed!\n" + " ptr=%p, postred=%x, expected %x\n", hdr, *postred, SMALLOC_POST_RED); assert(0); } @@ -344,13 +363,17 @@ void sfree(void *ptr) global_read_unlock(); - assert(pool); - sfree_pool(pool, ptr); + if (pool) { + sfree_pool(pool, ptr); + return; + } + + log_err("smalloc: ptr %p not from smalloc pool\n", ptr); } -static void *__smalloc_pool(struct pool *pool, unsigned int size) +static void *__smalloc_pool(struct pool *pool, size_t size) { - unsigned int nr_blocks; + size_t nr_blocks; unsigned int i; unsigned int offset; unsigned int last_idx; @@ -403,9 +426,9 @@ fail: return ret; } -static void *smalloc_pool(struct pool *pool, unsigned int size) +static void *smalloc_pool(struct pool *pool, size_t size) { - unsigned int alloc_size = size + sizeof(struct block_hdr); + size_t alloc_size = size + sizeof(struct block_hdr); void *ptr; /* @@ -431,15 +454,19 @@ static void *smalloc_pool(struct pool *pool, unsigned int size) return ptr; } -void *smalloc(unsigned int size) +void *smalloc(size_t size) { - unsigned int i; + unsigned int i, end_pool; + + if (size != (unsigned int) size) + return NULL; global_write_lock(); i = last_pool; + end_pool = nr_pools; do { - for (; i < nr_pools; i++) { + for (; i < end_pool; i++) { void *ptr = smalloc_pool(&mp[i], size); if (ptr) { @@ -449,29 +476,35 @@ void *smalloc(unsigned int size) } } if (last_pool) { - last_pool = 0; + end_pool = last_pool; + last_pool = i = 0; continue; } - if (nr_pools + 1 > MAX_POOLS) - break; - else { - i = nr_pools; - if (add_pool(&mp[nr_pools], size)) - goto out; - } + break; } while (1); -out: global_write_unlock(); return NULL; } +void *scalloc(size_t nmemb, size_t size) +{ + void *ret; + + ret = smalloc(nmemb * size); + if (ret) + memset(ret, 0, nmemb * size); + + return ret; +} + char *smalloc_strdup(const char *str) { - char *ptr; + char *ptr = NULL; ptr = smalloc(strlen(str) + 1); - strcpy(ptr, str); + if (ptr) + strcpy(ptr, str); return ptr; }