smalloc: when adding a new pool, make it big enough to hold the failing alloc
[fio.git] / smalloc.c
index 0b9abad301d56ba8cb4ab7b1fb077a149c25aa6b..28f82633b23661c9e49f80612ac2c6d550c4fa8e 100644 (file)
--- a/smalloc.c
+++ b/smalloc.c
 #undef ENABLE_RESIZE           /* define to enable pool resizing */
 #define MP_SAFE                        /* define to made allocator thread safe */
 
-#define INITIAL_SIZE   65536   /* new pool size */
+#define INITIAL_SIZE   1048576 /* new pool size */
 #define MAX_POOLS      32      /* maximum number of pools to setup */
 
+unsigned int smalloc_pool_size = INITIAL_SIZE;
+
 #ifdef ENABLE_RESIZE
-#define MAX_SIZE       8 * INITIAL_SIZE
+#define MAX_SIZE       8 * smalloc_pool_size
 static unsigned int resize_error;
 #endif
 
@@ -57,16 +59,28 @@ static inline void pool_unlock(struct pool *pool)
                fio_mutex_up(pool->lock);
 }
 
-static inline void global_lock(void)
+static inline void global_read_lock(void)
+{
+       if (lock)
+               fio_mutex_down_read(lock);
+}
+
+static inline void global_read_unlock(void)
 {
        if (lock)
-               fio_mutex_down(lock);
+               fio_mutex_up_read(lock);
 }
 
-static inline void global_unlock(void)
+static inline void global_write_lock(void)
 {
        if (lock)
-               fio_mutex_up(lock);
+               fio_mutex_down_write(lock);
+}
+
+static inline void global_write_unlock(void)
+{
+       if (lock)
+               fio_mutex_up_write(lock);
 }
 
 #define hdr_free(hdr)          ((hdr)->size & 0x80000000)
@@ -206,7 +220,7 @@ fail:
 #endif
 }
 
-static int add_pool(struct pool *pool)
+static int add_pool(struct pool *pool, unsigned int alloc_size)
 {
        struct mem_hdr *hdr;
        void *ptr;
@@ -217,7 +231,11 @@ static int add_pool(struct pool *pool)
        if (fd < 0)
                goto out_close;
 
-       pool->size = INITIAL_SIZE;
+       if (alloc_size > smalloc_pool_size)
+               pool->size = alloc_size;
+       else
+               pool->size = smalloc_pool_size;
+
        if (ftruncate(fd, pool->size) < 0)
                goto out_unlink;
 
@@ -240,7 +258,9 @@ static int add_pool(struct pool *pool)
        pool->room = hdr->size = pool->size - sizeof(*hdr);
        pool->largest_block = pool->room;
        hdr_mark_free(hdr);
+       global_write_lock();
        nr_pools++;
+       global_write_unlock();
        return 0;
 out_unlink:
        if (pool->map)
@@ -254,11 +274,12 @@ out_close:
 
 void sinit(void)
 {
-       int ret = add_pool(&mp[0]);
+       int ret;
 
 #ifdef MP_SAFE
-       lock = fio_mutex_init(1);
+       lock = fio_mutex_rw_init();
 #endif
+       ret = add_pool(&mp[0], INITIAL_SIZE);
        assert(!ret);
 }
 
@@ -314,7 +335,7 @@ void sfree(void *ptr)
        struct pool *pool = NULL;
        unsigned int i;
 
-       global_lock();
+       global_read_lock();
 
        for (i = 0; i < nr_pools; i++) {
                if (ptr_valid(&mp[i], ptr)) {
@@ -323,7 +344,7 @@ void sfree(void *ptr)
                }
        }
 
-       global_unlock();
+       global_read_unlock();
 
        assert(pool);
        sfree_pool(pool, ptr);
@@ -349,7 +370,7 @@ restart:
        do {
                if (combine(pool, prv, hdr))
                        hdr = prv;
-                       
+
                if (hdr_free(hdr) && hdr_size(hdr) >= size)
                        break;
 
@@ -418,7 +439,7 @@ void *smalloc(unsigned int size)
 {
        unsigned int i;
 
-       global_lock();
+       global_read_lock();
        i = last_pool;
 
        do {
@@ -427,7 +448,7 @@ void *smalloc(unsigned int size)
 
                        if (ptr) {
                                last_pool = i;
-                               global_unlock();
+                               global_read_unlock();
                                return ptr;
                        }
                }
@@ -440,12 +461,15 @@ void *smalloc(unsigned int size)
                        break;
                else {
                        i = nr_pools;
-                       if (add_pool(&mp[nr_pools]))
-                               break;
+                       global_read_unlock();
+                       if (add_pool(&mp[nr_pools], size))
+                               goto out;
+                       global_read_lock();
                }
        } while (1);
 
-       global_unlock();
+       global_read_unlock();
+out:
        return NULL;
 }