commit 33c0b3c7535efac6ab42fcfcb6530ed05e65a0b4
parent 3c43d1203c89d091e306160c4bc2301a9d378450
Author: Joris Vink <joris@coders.se>
Date: Tue, 12 Jul 2016 16:29:30 +0200
Make pools thread-safe if built with TASKS.
Use CAS to implement primitive spinlock ontop of the pool
if we have been built with TASKS=1.
This allows tasks to safely use kore_malloc() and kore_free()
since those are now backed by pools.
Diffstat:
2 files changed, 42 insertions(+), 1 deletion(-)
diff --git a/includes/kore.h b/includes/kore.h
@@ -348,6 +348,7 @@ struct kore_pool {
size_t slen;
size_t elms;
size_t inuse;
+ volatile int lock;
char *name;
LIST_HEAD(, kore_pool_region) regions;
diff --git a/src/pool.c b/src/pool.c
@@ -24,6 +24,11 @@
#define POOL_ELEMENT_BUSY 0
#define POOL_ELEMENT_FREE 1
+#if defined(KORE_USE_TASKS)
+static void pool_lock(struct kore_pool *);
+static void pool_unlock(struct kore_pool *);
+#endif
+
static void pool_region_create(struct kore_pool *, size_t);
static void pool_region_destroy(struct kore_pool *);
@@ -36,6 +41,7 @@ kore_pool_init(struct kore_pool *pool, const char *name,
if ((pool->name = strdup(name)) == NULL)
fatal("kore_pool_init: strdup %s", errno_s);
+ pool->lock = 0;
pool->elms = 0;
pool->inuse = 0;
pool->elen = len;
@@ -50,6 +56,7 @@ kore_pool_init(struct kore_pool *pool, const char *name,
void
kore_pool_cleanup(struct kore_pool *pool)
{
+ pool->lock = 0;
pool->elms = 0;
pool->inuse = 0;
pool->elen = 0;
@@ -69,10 +76,13 @@ kore_pool_get(struct kore_pool *pool)
u_int8_t *ptr;
struct kore_pool_entry *entry;
+#if defined(KORE_USE_TASKS)
+ pool_lock(pool);
+#endif
+
if (LIST_EMPTY(&(pool->freelist))) {
kore_log(LOG_NOTICE, "pool %s is exhausted (%d/%d)",
pool->name, pool->inuse, pool->elms);
-
pool_region_create(pool, pool->elms);
}
@@ -86,6 +96,10 @@ kore_pool_get(struct kore_pool *pool)
pool->inuse++;
+#if defined(KORE_USE_TASKS)
+ pool_unlock(pool);
+#endif
+
return (ptr);
}
@@ -94,6 +108,10 @@ kore_pool_put(struct kore_pool *pool, void *ptr)
{
struct kore_pool_entry *entry;
+#if defined(KORE_USE_TASKS)
+ pool_lock(pool);
+#endif
+
entry = (struct kore_pool_entry *)
((u_int8_t *)ptr - sizeof(struct kore_pool_entry));
@@ -104,6 +122,10 @@ kore_pool_put(struct kore_pool *pool, void *ptr)
LIST_INSERT_HEAD(&(pool->freelist), entry, list);
pool->inuse--;
+
+#if defined(KORE_USE_TASKS)
+ pool_unlock(pool);
+#endif
}
static void
@@ -163,3 +185,21 @@ pool_region_destroy(struct kore_pool *pool)
LIST_INIT(&pool->freelist);
pool->elms = 0;
}
+
+#if defined(KORE_USE_TASKS)
+static void
+pool_lock(struct kore_pool *pool)
+{
+ for (;;) {
+ if (__sync_bool_compare_and_swap(&pool->lock, 0, 1))
+ break;
+ }
+}
+
+static void
+pool_unlock(struct kore_pool *pool)
+{
+ if (!__sync_bool_compare_and_swap(&pool->lock, 1, 0))
+ fatal("pool_unlock: failed to release %s", pool->name);
+}
+#endif