diff options
author | Tobias Brunner <tobias@strongswan.org> | 2010-03-26 16:59:33 +0100 |
---|---|---|
committer | Tobias Brunner <tobias@strongswan.org> | 2010-04-06 12:47:39 +0200 |
commit | fb111e55074afef3e082e9e3c4e63d75684d32fa (patch) | |
tree | 5f9264c94159ca697b3722c9ad6422e0f87f96e8 /src | |
parent | 8c9f5bad8bfb68f0c6665bdbced3e9a9e8dfd555 (diff) | |
download | strongswan-fb111e55074afef3e082e9e3c4e63d75684d32fa.tar.bz2 strongswan-fb111e55074afef3e082e9e3c4e63d75684d32fa.tar.xz |
Make in-memory pool thread-safe.
Diffstat (limited to 'src')
-rw-r--r-- | src/libhydra/attributes/mem_pool.c | 51 | ||||
-rw-r--r-- | src/libhydra/attributes/mem_pool.h | 2 |
2 files changed, 36 insertions, 17 deletions
diff --git a/src/libhydra/attributes/mem_pool.c b/src/libhydra/attributes/mem_pool.c index bba793f28..4b258151d 100644 --- a/src/libhydra/attributes/mem_pool.c +++ b/src/libhydra/attributes/mem_pool.c @@ -18,6 +18,7 @@ #include <debug.h> #include <utils/hashtable.h> +#include <threading/rwlock.h> #define POOL_LIMIT (sizeof(uintptr_t)*8) @@ -66,6 +67,11 @@ struct private_mem_pool_t { * hashtable [identity => identity], handles identity references */ hashtable_t *ids; + + /** + * lock to safely access the pool + */ + rwlock_t *lock; }; /** @@ -162,13 +168,21 @@ METHOD(mem_pool_t, get_size, u_int, METHOD(mem_pool_t, get_online, u_int, private_mem_pool_t *this) { - return this->online->get_count(this->online); + u_int count; + this->lock->read_lock(this->lock); + count = this->online->get_count(this->online); + this->lock->unlock(this->lock); + return count; } METHOD(mem_pool_t, get_offline, u_int, private_mem_pool_t *this) { - return this->offline->get_count(this->offline); + u_int count; + this->lock->read_lock(this->lock); + count = this->offline->get_count(this->offline); + this->lock->unlock(this->lock); + return count; } METHOD(mem_pool_t, acquire_address, host_t*, @@ -185,16 +199,17 @@ METHOD(mem_pool_t, acquire_address, host_t*, return requested->clone(requested); } - while (TRUE) + if (!requested->is_anyaddr(requested) && + requested->get_family(requested) != + this->base->get_family(this->base)) { - if (!requested->is_anyaddr(requested) && - requested->get_family(requested) != - this->base->get_family(this->base)) - { - DBG1("IP pool address family mismatch"); - break; - } + DBG1("IP pool address family mismatch"); + return NULL; + } + this->lock->write_lock(this->lock); + while (TRUE) + { /* check for a valid offline lease, refresh */ offset = (uintptr_t)this->offline->remove(this->offline, id); if (offset) @@ -255,6 +270,7 @@ METHOD(mem_pool_t, acquire_address, host_t*, DBG1("pool '%s' is full, unable to assign address", this->name); break; } + this->lock->unlock(this->lock); if (offset) { @@ -266,9 +282,11 @@ METHOD(mem_pool_t, acquire_address, host_t*, METHOD(mem_pool_t, release_address, bool, private_mem_pool_t *this, host_t *address, identification_t *id) { - uintptr_t offset; + bool found = FALSE; if (this->size != 0) { + uintptr_t offset; + this->lock->write_lock(this->lock); offset = (uintptr_t)this->online->remove(this->online, id); if (offset) { @@ -277,11 +295,12 @@ METHOD(mem_pool_t, release_address, bool, { DBG1("lease %H by '%Y' went offline", address, id); this->offline->put(this->offline, id, (void*)offset); - return TRUE; + found = TRUE; } } + this->lock->unlock(this->lock); } - return FALSE; + return found; } /** @@ -335,6 +354,7 @@ METHOD(enumerator_t, lease_enumerator_destroy, void, { DESTROY_IF(this->current); this->inner->destroy(this->inner); + this->pool->lock->unlock(this->pool->lock); free(this); } @@ -342,7 +362,7 @@ METHOD(mem_pool_t, create_lease_enumerator, enumerator_t*, private_mem_pool_t *this) { lease_enumerator_t *enumerator; - + this->lock->read_lock(this->lock); INIT(enumerator, .public = { .enumerate = (void*)_lease_enumerate, @@ -351,7 +371,6 @@ METHOD(mem_pool_t, create_lease_enumerator, enumerator_t*, .pool = this, .inner = this->ids->create_enumerator(this->ids), ); - return &enumerator->public; } @@ -371,6 +390,7 @@ METHOD(mem_pool_t, destroy, void, this->ids->destroy(this->ids); this->online->destroy(this->online); this->offline->destroy(this->offline); + this->lock->destroy(this->lock); DESTROY_IF(this->base); free(this->name); free(this); @@ -401,6 +421,7 @@ mem_pool_t *mem_pool_create(char *name, host_t *base, int bits) (hashtable_equals_t)id_equals, 16), .ids = hashtable_create((hashtable_hash_t)id_hash, (hashtable_equals_t)id_equals, 16), + .lock = rwlock_create(RWLOCK_TYPE_DEFAULT), ); if (base) diff --git a/src/libhydra/attributes/mem_pool.h b/src/libhydra/attributes/mem_pool.h index 6685fd61a..bb963de93 100644 --- a/src/libhydra/attributes/mem_pool.h +++ b/src/libhydra/attributes/mem_pool.h @@ -28,8 +28,6 @@ typedef struct mem_pool_t mem_pool_t; /** * An in-memory IP address pool. - * - * @note the implementation is not thread-safe. */ struct mem_pool_t { |