Revamp file locking
[fio.git] / smalloc.c
index 0b9abad301d56ba8cb4ab7b1fb077a149c25aa6b..85da7811c521f04b476d5fed1ff17c9dd811af7c 100644 (file)
--- a/smalloc.c
+++ b/smalloc.c
@@ -57,16 +57,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(lock);
+               fio_mutex_down_read(lock);
 }
 
-static inline void global_unlock(void)
+static inline void global_read_unlock(void)
 {
        if (lock)
-               fio_mutex_up(lock);
+               fio_mutex_up_read(lock);
+}
+
+static inline void global_write_lock(void)
+{
+       if (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)
@@ -240,7 +252,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 +268,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]);
        assert(!ret);
 }
 
@@ -314,7 +329,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 +338,7 @@ void sfree(void *ptr)
                }
        }
 
-       global_unlock();
+       global_read_unlock();
 
        assert(pool);
        sfree_pool(pool, ptr);
@@ -418,7 +433,7 @@ void *smalloc(unsigned int size)
 {
        unsigned int i;
 
-       global_lock();
+       global_read_lock();
        i = last_pool;
 
        do {
@@ -427,7 +442,7 @@ void *smalloc(unsigned int size)
 
                        if (ptr) {
                                last_pool = i;
-                               global_unlock();
+                               global_read_unlock();
                                return ptr;
                        }
                }
@@ -440,12 +455,15 @@ void *smalloc(unsigned int size)
                        break;
                else {
                        i = nr_pools;
+                       global_read_unlock();
                        if (add_pool(&mp[nr_pools]))
-                               break;
+                               goto out;
+                       global_read_lock();
                }
        } while (1);
 
-       global_unlock();
+       global_read_unlock();
+out:
        return NULL;
 }