kore

An easy to use, scalable and secure web application framework for writing web APIs in C.
Commits | Files | Refs | README | LICENSE | git clone https://git.kore.io/kore.git

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:
includes/kore.h | 1+
src/pool.c | 42+++++++++++++++++++++++++++++++++++++++++-
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