diff options
author | Tobias Brunner <tobias@strongswan.org> | 2012-01-21 16:11:28 +0100 |
---|---|---|
committer | Tobias Brunner <tobias@strongswan.org> | 2012-05-02 14:45:38 +0200 |
commit | 4d21000cf71c9f89d81c1c54a0fc11be7a0c04b2 (patch) | |
tree | 8ba607cd86fcbd94b08ddf003e39c0e8c5367bb8 /src/libstrongswan | |
parent | 0e474f9148deebcd3a24205f0110c884c9b67f60 (diff) | |
download | strongswan-4d21000cf71c9f89d81c1c54a0fc11be7a0c04b2.tar.bz2 strongswan-4d21000cf71c9f89d81c1c54a0fc11be7a0c04b2.tar.xz |
Added recursive read_lock support to our own implementation of rwlock_t.
Diffstat (limited to 'src/libstrongswan')
-rw-r--r-- | src/libstrongswan/threading/rwlock.c | 39 |
1 files changed, 35 insertions, 4 deletions
diff --git a/src/libstrongswan/threading/rwlock.c b/src/libstrongswan/threading/rwlock.c index 15dc0b334..e0d727b65 100644 --- a/src/libstrongswan/threading/rwlock.c +++ b/src/libstrongswan/threading/rwlock.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008-2009 Tobias Brunner + * Copyright (C) 2008-2012 Tobias Brunner * Copyright (C) 2008 Martin Willi * Hochschule fuer Technik Rapperswil * @@ -23,6 +23,7 @@ #include "rwlock.h" #include "condvar.h" #include "mutex.h" +#include "thread_value.h" #include "lock_profiler.h" typedef struct private_rwlock_t private_rwlock_t; @@ -62,6 +63,11 @@ struct private_rwlock_t { condvar_t *readers; /** + * thread local value to keep track whether the current thread is a reader + */ + thread_value_t *is_reading; + + /** * number of waiting writers */ u_int waiting_writers; @@ -189,14 +195,24 @@ rwlock_t *rwlock_create(rwlock_type_t type) * of incoming readers. Reader starvation is not prevented (this could happen * if there are more writers than readers). * - * The implementation does not support recursive locking and readers must not - * acquire the lock exclusively at the same time and vice-versa (this is not - * checked or enforced so behave yourself to prevent deadlocks). + * The implementation supports recursive locking of the read lock but not of + * the write lock. Readers must not acquire the lock exclusively at the same + * time and vice-versa (this is not checked or enforced so behave yourself to + * prevent deadlocks). */ METHOD(rwlock_t, read_lock, void, private_rwlock_t *this) { + uintptr_t reading; + + reading = (uintptr_t)this->is_reading->get(this->is_reading); + if (reading > 0) + { /* we allow readers to acquire the lock recursively */ + this->is_reading->set(this->is_reading, (void*)(reading + 1)); + return; + } + profiler_start(&this->profile); this->mutex->lock(this->mutex); while (this->writer || this->waiting_writers) @@ -206,6 +222,8 @@ METHOD(rwlock_t, read_lock, void, this->reader_count++; profiler_end(&this->profile); this->mutex->unlock(this->mutex); + + this->is_reading->set(this->is_reading, (void*)1); } METHOD(rwlock_t, write_lock, void, @@ -241,6 +259,15 @@ METHOD(rwlock_t, try_write_lock, bool, METHOD(rwlock_t, unlock, void, private_rwlock_t *this) { + uintptr_t reading; + + reading = (uintptr_t)this->is_reading->get(this->is_reading); + if (reading > 1) + { /* readers have to unlock an equal number of times */ + this->is_reading->set(this->is_reading, (void*)(reading - 1)); + return; + } + this->mutex->lock(this->mutex); if (this->writer == pthread_self()) { @@ -263,6 +290,8 @@ METHOD(rwlock_t, unlock, void, } } this->mutex->unlock(this->mutex); + + this->is_reading->set(this->is_reading, NULL); } METHOD(rwlock_t, destroy, void, @@ -271,6 +300,7 @@ METHOD(rwlock_t, destroy, void, this->mutex->destroy(this->mutex); this->writers->destroy(this->writers); this->readers->destroy(this->readers); + this->is_reading->destroy(this->is_reading); profiler_cleanup(&this->profile); free(this); } @@ -298,6 +328,7 @@ rwlock_t *rwlock_create(rwlock_type_t type) .mutex = mutex_create(MUTEX_TYPE_DEFAULT), .writers = condvar_create(CONDVAR_TYPE_DEFAULT), .readers = condvar_create(CONDVAR_TYPE_DEFAULT), + .is_reading = thread_value_create(NULL), ); profiler_init(&this->profile); |