diff options
author | Tobias Brunner <tobias@strongswan.org> | 2009-12-07 17:26:39 +0100 |
---|---|---|
committer | Tobias Brunner <tobias@strongswan.org> | 2009-12-23 17:01:30 +0100 |
commit | b1f35d0695f1c2aac009baba9fdc18e30730245a (patch) | |
tree | 940d1751e295f28ed40ab87970c41dafdf4f0bcc /src/libstrongswan/threading/mutex.c | |
parent | 14f7091280b8d12fcbc58a4ff986e94915ecd638 (diff) | |
download | strongswan-b1f35d0695f1c2aac009baba9fdc18e30730245a.tar.bz2 strongswan-b1f35d0695f1c2aac009baba9fdc18e30730245a.tar.xz |
Threading primitives separated.
Diffstat (limited to 'src/libstrongswan/threading/mutex.c')
-rw-r--r-- | src/libstrongswan/threading/mutex.c | 395 |
1 files changed, 2 insertions, 393 deletions
diff --git a/src/libstrongswan/threading/mutex.c b/src/libstrongswan/threading/mutex.c index 336340233..a3d131a05 100644 --- a/src/libstrongswan/threading/mutex.c +++ b/src/libstrongswan/threading/mutex.c @@ -16,183 +16,13 @@ #define _GNU_SOURCE #include <pthread.h> -#include <stdint.h> -#include <time.h> -#include <errno.h> #include <threading.h> #include <library.h> #include <debug.h> -typedef struct private_mutex_t private_mutex_t; -typedef struct private_r_mutex_t private_r_mutex_t; -typedef struct private_condvar_t private_condvar_t; -typedef struct private_rwlock_t private_rwlock_t; - -#ifdef LOCK_PROFILER - -/** - * Do not report mutexes with an overall waiting time smaller than this (in us) - */ -#define PROFILE_WAIT_TRESHHOLD 10000 - -/** - * Do not report mutexes with an overall lock count smaller than this - */ -#define PROFILE_LOCK_TRESHHOLD 1000 - - -#include <utils/backtrace.h> - -typedef struct lock_profile_t lock_profile_t; - -struct lock_profile_t { - - /** - * how long threads have waited for the lock in this mutex so far - */ - timeval_t waited; - - /** - * How many times the lock has been invoked - */ - u_int locked; - - /** - * backtrace where mutex has been created - */ - backtrace_t *backtrace; -}; - -/** - * Print and cleanup mutex profiler - */ -static void profiler_cleanup(lock_profile_t *profile) -{ - if (profile->waited.tv_sec > 0 || - profile->waited.tv_usec > PROFILE_WAIT_TRESHHOLD || - profile->locked > PROFILE_LOCK_TRESHHOLD) - { - fprintf(stderr, "%d.%03ds / %d times in lock created at:", - profile->waited.tv_sec, profile->waited.tv_usec, profile->locked); - profile->backtrace->log(profile->backtrace, stderr); - } - profile->backtrace->destroy(profile->backtrace); -} - -/** - * Initialize mutex profiler - */ -static void profiler_init(lock_profile_t *profile) -{ - profile->backtrace = backtrace_create(2); - timerclear(&profile->waited); - profile->locked = 0; -} - -#define profiler_start(profile) { \ - struct timeval _start, _end, _diff; \ - (profile)->locked++; \ - time_monotonic(&_start); - -#define profiler_end(profile) \ - time_monotonic(&_end); \ - timersub(&_end, &_start, &_diff); \ - timeradd(&(profile)->waited, &_diff, &(profile)->waited); } - -#else /* !LOCK_PROFILER */ - -#define lock_profile_t struct {} -#define profiler_cleanup(...) {} -#define profiler_init(...) {} -#define profiler_start(...) {} -#define profiler_end(...) {} - -#endif /* LOCK_PROFILER */ - -/** - * private data of mutex - */ -struct private_mutex_t { - - /** - * public functions - */ - mutex_t public; - - /** - * wrapped pthread mutex - */ - pthread_mutex_t mutex; - - /** - * is this a recursiv emutex, implementing private_r_mutex_t? - */ - bool recursive; - - /** - * profiling info, if enabled - */ - lock_profile_t profile; -}; - -/** - * private data of mutex, extended by recursive locking information - */ -struct private_r_mutex_t { - - /** - * Extends private_mutex_t - */ - private_mutex_t generic; - - /** - * thread which currently owns mutex - */ - pthread_t thread; - - /** - * times we have locked the lock, stored per thread - */ - pthread_key_t times; -}; - -/** - * private data of condvar - */ -struct private_condvar_t { - - /** - * public functions - */ - condvar_t public; - - /** - * wrapped pthread condvar - */ - pthread_cond_t condvar; -}; - -/** - * private data of rwlock - */ -struct private_rwlock_t { - - /** - * public functions - */ - rwlock_t public; - - /** - * wrapped pthread rwlock - */ - pthread_rwlock_t rwlock; - - /** - * profiling info, if enabled - */ - lock_profile_t profile; -}; +#include "mutex.h" +#include "lock_profiler.h" /** * Implementation of mutex_t.lock. @@ -328,224 +158,3 @@ mutex_t *mutex_create(mutex_type_t type) } } -/** - * Implementation of condvar_t.wait. - */ -static void _wait(private_condvar_t *this, private_mutex_t *mutex) -{ - if (mutex->recursive) - { - private_r_mutex_t* recursive = (private_r_mutex_t*)mutex; - - /* mutex owner gets cleared during condvar wait */ - recursive->thread = 0; - pthread_cond_wait(&this->condvar, &mutex->mutex); - recursive->thread = pthread_self(); - } - else - { - pthread_cond_wait(&this->condvar, &mutex->mutex); - } -} - -/** - * Implementation of condvar_t.timed_wait_abs. - */ -static bool timed_wait_abs(private_condvar_t *this, private_mutex_t *mutex, - timeval_t time) -{ - struct timespec ts; - bool timed_out; - - ts.tv_sec = time.tv_sec; - ts.tv_nsec = time.tv_usec * 1000; - - if (mutex->recursive) - { - private_r_mutex_t* recursive = (private_r_mutex_t*)mutex; - - recursive->thread = 0; - timed_out = pthread_cond_timedwait(&this->condvar, &mutex->mutex, - &ts) == ETIMEDOUT; - recursive->thread = pthread_self(); - } - else - { - timed_out = pthread_cond_timedwait(&this->condvar, &mutex->mutex, - &ts) == ETIMEDOUT; - } - return timed_out; -} - -/** - * Implementation of condvar_t.timed_wait. - */ -static bool timed_wait(private_condvar_t *this, private_mutex_t *mutex, - u_int timeout) -{ - timeval_t tv; - u_int s, ms; - - time_monotonic(&tv); - - s = timeout / 1000; - ms = timeout % 1000; - - tv.tv_sec += s; - tv.tv_usec += ms * 1000; - - if (tv.tv_usec > 1000000 /* 1s */) - { - tv.tv_usec -= 1000000; - tv.tv_sec++; - } - return timed_wait_abs(this, mutex, tv); -} - -/** - * Implementation of condvar_t.signal. - */ -static void _signal(private_condvar_t *this) -{ - pthread_cond_signal(&this->condvar); -} - -/** - * Implementation of condvar_t.broadcast. - */ -static void broadcast(private_condvar_t *this) -{ - pthread_cond_broadcast(&this->condvar); -} - -/** - * Implementation of condvar_t.destroy - */ -static void condvar_destroy(private_condvar_t *this) -{ - pthread_cond_destroy(&this->condvar); - free(this); -} - -/* - * see header file - */ -condvar_t *condvar_create(condvar_type_t type) -{ - switch (type) - { - case CONDVAR_TYPE_DEFAULT: - default: - { - pthread_condattr_t condattr; - private_condvar_t *this = malloc_thing(private_condvar_t); - - this->public.wait = (void(*)(condvar_t*, mutex_t *mutex))_wait; - this->public.timed_wait = (bool(*)(condvar_t*, mutex_t *mutex, u_int timeout))timed_wait; - this->public.timed_wait_abs = (bool(*)(condvar_t*, mutex_t *mutex, timeval_t time))timed_wait_abs; - this->public.signal = (void(*)(condvar_t*))_signal; - this->public.broadcast = (void(*)(condvar_t*))broadcast; - this->public.destroy = (void(*)(condvar_t*))condvar_destroy; - - pthread_condattr_init(&condattr); -#ifdef HAVE_CONDATTR_CLOCK_MONOTONIC - pthread_condattr_setclock(&condattr, CLOCK_MONOTONIC); -#endif - pthread_cond_init(&this->condvar, &condattr); - pthread_condattr_destroy(&condattr); - - return &this->public; - } - } -} - -/** - * Implementation of rwlock_t.read_lock - */ -static void read_lock(private_rwlock_t *this) -{ - int err; - - profiler_start(&this->profile); - err = pthread_rwlock_rdlock(&this->rwlock); - if (err != 0) - { - DBG1("!!! RWLOCK READ LOCK ERROR: %s !!!", strerror(err)); - } - profiler_end(&this->profile); -} - -/** - * Implementation of rwlock_t.write_lock - */ -static void write_lock(private_rwlock_t *this) -{ - int err; - - profiler_start(&this->profile); - err = pthread_rwlock_wrlock(&this->rwlock); - if (err != 0) - { - DBG1("!!! RWLOCK WRITE LOCK ERROR: %s !!!", strerror(err)); - } - profiler_end(&this->profile); -} - -/** - * Implementation of rwlock_t.try_write_lock - */ -static bool try_write_lock(private_rwlock_t *this) -{ - return pthread_rwlock_trywrlock(&this->rwlock) == 0; -} - -/** - * Implementation of rwlock_t.unlock - */ -static void rw_unlock(private_rwlock_t *this) -{ - int err; - - err = pthread_rwlock_unlock(&this->rwlock); - if (err != 0) - { - DBG1("!!! RWLOCK UNLOCK ERROR: %s !!!", strerror(err)); - } -} - -/** - * Implementation of rwlock_t.destroy - */ -static void rw_destroy(private_rwlock_t *this) -{ - pthread_rwlock_destroy(&this->rwlock); - profiler_cleanup(&this->profile); - free(this); -} - -/* - * see header file - */ -rwlock_t *rwlock_create(rwlock_type_t type) -{ - switch (type) - { - case RWLOCK_TYPE_DEFAULT: - default: - { - private_rwlock_t *this = malloc_thing(private_rwlock_t); - - this->public.read_lock = (void(*)(rwlock_t*))read_lock; - this->public.write_lock = (void(*)(rwlock_t*))write_lock; - this->public.try_write_lock = (bool(*)(rwlock_t*))try_write_lock; - this->public.unlock = (void(*)(rwlock_t*))rw_unlock; - this->public.destroy = (void(*)(rwlock_t*))rw_destroy; - - pthread_rwlock_init(&this->rwlock, NULL); - profiler_init(&this->profile); - - return &this->public; - } - } -} - |