From c1be64eaffb5b2eefa410b7ba35f85cff9b16638 Mon Sep 17 00:00:00 2001 From: Martin Willi Date: Wed, 5 Nov 2008 15:51:57 +0000 Subject: [PATCH] wrapped rwlock with profiling support --- src/libstrongswan/utils/mutex.c | 220 ++++++++++++++++++++++---------- src/libstrongswan/utils/mutex.h | 44 +++++++ 2 files changed, 200 insertions(+), 64 deletions(-) diff --git a/src/libstrongswan/utils/mutex.c b/src/libstrongswan/utils/mutex.c index 326a93255..d6edb3082 100644 --- a/src/libstrongswan/utils/mutex.c +++ b/src/libstrongswan/utils/mutex.c @@ -19,7 +19,6 @@ #include #include -#include #include #include @@ -27,14 +26,77 @@ #include #include +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_TRESHHOLD 1000 -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; +#include + +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 + */ + struct timeval waited; + + /** + * 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_TRESHHOLD) + { + fprintf(stderr, "%d.%06ds in lock created at:", + profile->waited.tv_sec, profile->waited.tv_usec); + 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(3); + timerclear(&profile->waited); +} + +#define profiler_start(profile) { \ + struct timeval _start, _end, _diff; \ + gettimeofday(&_start, NULL); + +#define profiler_end(profile) \ + gettimeofday(&_end, NULL); \ + 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 @@ -51,22 +113,15 @@ struct private_mutex_t { */ pthread_mutex_t mutex; -#ifdef LOCK_PROFILER - /** - * how long threads have waited for the lock in this mutex so far - */ - struct timeval waited; - - /** - * backtrace where mutex has been created - */ - backtrace_t *backtrace; -#endif /* LOCK_PROFILER */ - /** * is this a recursiv emutex, implementing private_r_mutex_t? */ bool recursive; + + /** + * profiling info, if enabled + */ + lock_profile_t profile; }; /** @@ -106,65 +161,39 @@ struct private_condvar_t { pthread_cond_t condvar; }; -#ifdef LOCK_PROFILER /** - * Print and cleanup mutex profiler + * private data of rwlock */ -static void profiler_cleanup(private_mutex_t *this) -{ - if (this->waited.tv_sec > 0 || - this->waited.tv_usec > PROFILE_TRESHHOLD) - { - fprintf(stderr, "waited %d.%06ds in mutex, created at:", - this->waited.tv_sec, this->waited.tv_usec); - this->backtrace->log(this->backtrace, stderr); - } - this->backtrace->destroy(this->backtrace); -} +struct private_rwlock_t { -/** - * Initialize mutex profiler - */ -static void profiler_init(private_mutex_t *this) -{ - this->backtrace = backtrace_create(3); - timerclear(&this->waited); -} - -/** - * Implementation of mutex_t.lock. - */ -static void lock(private_mutex_t *this) -{ - struct timeval start, end, diff; - - gettimeofday(&start, NULL); - if (pthread_mutex_lock(&this->mutex)) - { - DBG1("!!!! MUTEX %sLOCK ERROR, your code is buggy !!!", ""); - } - gettimeofday(&end, NULL); + /** + * public functions + */ + rwlock_t public; - timersub(&end, &start, &diff); - timeradd(&this->waited, &diff, &this->waited); -} -#else /* !LOCK_PROFILER */ - -/** dummy implementations */ -static void profiler_cleanup(private_mutex_t *this) {} -static void profiler_init(private_mutex_t *this) {} + /** + * wrapped pthread rwlock + */ + pthread_rwlock_t rwlock; + + /** + * profiling info, if enabled + */ + lock_profile_t profile; +}; /** * Implementation of mutex_t.lock. */ static void lock(private_mutex_t *this) { + profiler_start(&this->profile); if (pthread_mutex_lock(&this->mutex)) { DBG1("!!!! MUTEX %sLOCK ERROR, your code is buggy !!!", ""); } + profiler_end(&this->profile); } -#endif /* LOCK_PROFILER */ /** * Implementation of mutex_t.unlock. @@ -224,7 +253,7 @@ static void unlock_r(private_r_mutex_t *this) */ static void mutex_destroy(private_mutex_t *this) { - profiler_cleanup(this); + profiler_cleanup(&this->profile); pthread_mutex_destroy(&this->mutex); free(this); } @@ -234,7 +263,7 @@ static void mutex_destroy(private_mutex_t *this) */ static void mutex_destroy_r(private_r_mutex_t *this) { - profiler_cleanup(&this->generic); + profiler_cleanup(&this->generic.profile); pthread_mutex_destroy(&this->generic.mutex); pthread_key_delete(this->times); free(this); @@ -258,7 +287,7 @@ mutex_t *mutex_create(mutex_type_t type) pthread_mutex_init(&this->generic.mutex, NULL); pthread_key_create(&this->times, NULL); this->generic.recursive = TRUE; - profiler_init(&this->generic); + profiler_init(&this->generic.profile); this->thread = 0; return &this->generic.public; @@ -274,7 +303,7 @@ mutex_t *mutex_create(mutex_type_t type) pthread_mutex_init(&this->mutex, NULL); this->recursive = FALSE; - profiler_init(this); + profiler_init(&this->profile); return &this->public; } @@ -391,3 +420,66 @@ condvar_t *condvar_create(condvar_type_t type) } } +/** + * Implementation of rwlock_t.read_lock + */ +static void read_lock(private_rwlock_t *this) +{ + profiler_start(&this->profile); + pthread_rwlock_rdlock(&this->rwlock); + profiler_end(&this->profile); +} + +/** + * Implementation of rwlock_t.write_lock + */ +static void write_lock(private_rwlock_t *this) +{ + profiler_start(&this->profile); + pthread_rwlock_wrlock(&this->rwlock); + profiler_end(&this->profile); +} + +/** + * Implementation of rwlock_t.unlock + */ +static void rw_unlock(private_rwlock_t *this) +{ + pthread_rwlock_unlock(&this->rwlock); +} + +/** + * 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_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.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; + } + } +} + diff --git a/src/libstrongswan/utils/mutex.h b/src/libstrongswan/utils/mutex.h index cf557c35c..626371bf4 100644 --- a/src/libstrongswan/utils/mutex.h +++ b/src/libstrongswan/utils/mutex.h @@ -23,8 +23,10 @@ typedef struct mutex_t mutex_t; typedef struct condvar_t condvar_t; +typedef struct rwlock_t rwlock_t; typedef enum mutex_type_t mutex_type_t; typedef enum condvar_type_t condvar_type_t; +typedef enum rwlock_type_t rwlock_type_t; #include @@ -46,6 +48,14 @@ enum condvar_type_t { CONDVAR_DEFAULT = 0, }; +/** + * Type of read-write lock. + */ +enum rwlock_type_t { + /** default condvar */ + RWLOCK_DEFAULT = 0, +}; + /** * Mutex wrapper implements simple, portable and advanced mutex functions. */ @@ -104,6 +114,32 @@ struct condvar_t { void (*destroy)(condvar_t *this); }; +/** + * Read-Write lock wrapper. + */ +struct rwlock_t { + + /** + * Acquire the read lock. + */ + void (*read_lock)(rwlock_t *this); + + /** + * Acquire the write lock. + */ + void (*write_lock)(rwlock_t *this); + + /** + * Release any acquired lock. + */ + void (*unlock)(rwlock_t *this); + + /** + * Destroy the read-write lock. + */ + void (*destroy)(rwlock_t *this); +}; + /** * Create a mutex instance. * @@ -120,4 +156,12 @@ mutex_t *mutex_create(mutex_type_t type); */ condvar_t *condvar_create(condvar_type_t type); +/** + * Create a read-write lock instance. + * + * @param type type of rwlock to create + * @return unlocked rwlock instance + */ +rwlock_t *rwlock_create(rwlock_type_t type); + #endif /* MUTEX_H_ @}*/