From 727abcdec7ad92fc2fae2585c5c609e0663858a6 Mon Sep 17 00:00:00 2001 From: Mark Spencer Date: Wed, 9 Jun 2004 01:45:08 +0000 Subject: Merge FreeBSD locking fixes (bug #1411) git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@3176 65c4cc65-6c06-0410-ace0-fbb531ad65f3 --- include/asterisk/linkedlists.h | 3 - include/asterisk/lock.h | 154 ++++++++++++++++++++++++++++++++--------- include/asterisk/module.h | 2 +- 3 files changed, 124 insertions(+), 35 deletions(-) (limited to 'include') diff --git a/include/asterisk/linkedlists.h b/include/asterisk/linkedlists.h index 01067d5f0..b752b3adb 100755 --- a/include/asterisk/linkedlists.h +++ b/include/asterisk/linkedlists.h @@ -16,9 +16,6 @@ struct name { \ ast_mutex_t lock; \ } -#define AST_LIST_HEAD_INITIALIZER(head) \ - { NULL, AST_MUTEX_INITIALIZER } - #define AST_LIST_HEAD_SET(head,entry) do { \ (head)->first=(entry); \ ast_pthread_mutex_init(&(head)->lock,NULL); \ diff --git a/include/asterisk/lock.h b/include/asterisk/lock.h index c40a1ddcf..4c82928e2 100755 --- a/include/asterisk/lock.h +++ b/include/asterisk/lock.h @@ -28,6 +28,14 @@ 0x20 } } #endif +#ifdef __FreeBSD__ +#ifdef __GNUC__ +#define AST_MUTEX_INIT_W_CONSTRUCTORS +#else +#define AST_MUTEX_INIT_ON_FIRST_USE +#endif +#endif /* __FreeBSD__ */ + #ifdef DEBUG_THREADS #ifdef THREAD_CRASH @@ -41,9 +49,17 @@ /* From now on, Asterisk REQUIRES Recursive (not error checking) mutexes and will not run without them. */ +#ifdef PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP +#define AST_MUTEX_INIT_VAULE { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP, NULL, 0, NULL, 0 } +#else +#define AST_MUTEX_INIT_VAULE { PTHREAD_MUTEX_INITIALIZER, NULL, 0, NULL, 0 } +#endif -#define AST_MUTEX_INITIALIZER { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP, NULL, 0, NULL, 0 } +#ifdef PTHREAD_MUTEX_RECURSIVE_NP #define AST_MUTEX_KIND PTHREAD_MUTEX_RECURSIVE_NP +#else +#define AST_MUTEX_KIND PTHREAD_MUTEX_RECURSIVE +#endif struct ast_mutex_info { pthread_mutex_t mutex; @@ -55,38 +71,53 @@ struct ast_mutex_info { typedef struct ast_mutex_info ast_mutex_t; -static inline int ast_mutex_init(ast_mutex_t *t) { - static pthread_mutexattr_t attr; - static int init = 1; - int res; - extern int pthread_mutexattr_setkind_np(pthread_mutexattr_t *, int); - - if (init) { - pthread_mutexattr_init(&attr); - pthread_mutexattr_setkind_np(&attr, AST_MUTEX_KIND); - init = 0; - } - res = pthread_mutex_init(&t->mutex, &attr); +static inline int ast_pthread_mutex_init(ast_mutex_t *t, pthread_mutexattr_t *attr) +{ t->file = NULL; t->lineno = 0; t->func = 0; t->thread = 0; - return res; + return pthread_mutex_init(&t->mutex, attr); } -static inline int ast_pthread_mutex_init(ast_mutex_t *t, pthread_mutexattr_t *attr) +static inline int ast_mutex_init(ast_mutex_t *t) { - int res; - res = pthread_mutex_init(&t->mutex, attr); - t->file = NULL; - t->lineno = 0; - t->func = 0; - t->thread = 0; - return res; + static pthread_mutexattr_t attr; + pthread_mutexattr_init(&attr); + pthread_mutexattr_settype(&attr, AST_MUTEX_KIND); + return ast_pthread_mutex_init(t, &attr); } -static inline int __ast_pthread_mutex_lock(char *filename, int lineno, char *func, ast_mutex_t *t) { +#if defined(AST_MUTEX_INIT_W_CONSTRUCTORS) +/* if AST_MUTEX_INIT_W_CONSTRUCTORS is defined, use file scope + constrictors/destructors to create/destroy mutexes. */ +#define __AST_MUTEX_DEFINE(scope,mutex) \ + scope ast_mutex_t mutex = AST_MUTEX_INIT_VAULE; \ +static void __attribute__ ((constructor)) init_##mutex(void) \ +{ \ + ast_mutex_init(&mutex); \ +} \ +static void __attribute__ ((destructor)) fini_##mutex(void) \ +{ \ + ast_mutex_destroy(&mutex); \ +} +#elif defined(AST_MUTEX_INIT_ON_FIRST_USE) || !defined(AST_MUTEX_INIT_W_CONSTRUCTORS) +/* if AST_MUTEX_INIT_ON_FIRST_USE is defined, mutexes are created on + first use. The performance impact on FreeBSD should be small since + the pthreads library does this itself to initialize errror checking + (defaulty type) mutexes. If nither is defined, the pthreads librariy + does the initialization itself on first use. */ +#define __AST_MUTEX_DEFINE(scope,mutex) \ + scope ast_mutex_t mutex = AST_MUTEX_INIT_VAULE +#endif /* AST_MUTEX_INIT_W_CONSTRUCTORS */ + +static inline int __ast_pthread_mutex_lock(char *filename, int lineno, char *func, ast_mutex_t *t) +{ int res; +#ifdef AST_MUTEX_INIT_ON_FIRST_USE + if(*t->mutex == (ast_mutex_t)AST_MUTEX_KIND) + ast_mutex_init(t->mutex); +#endif res = pthread_mutex_lock(&t->mutex); if (!res) { t->file = filename; @@ -107,6 +138,10 @@ static inline int __ast_pthread_mutex_lock(char *filename, int lineno, char *fun static inline int __ast_pthread_mutex_trylock(char *filename, int lineno, char *func, ast_mutex_t *t) { int res; +#ifdef AST_MUTEX_INIT_ON_FIRST_USE + if(*t->mutex == (ast_mutex_t)AST_MUTEX_KIND) + ast_mutex_init(t->mutex); +#endif res = pthread_mutex_trylock(&t->mutex); if (!res) { t->file = filename; @@ -166,26 +201,83 @@ static inline int __ast_pthread_mutex_destroy(char *filename, int lineno, char * /* From now on, Asterisk REQUIRES Recursive (not error checking) mutexes and will not run without them. */ -#define AST_MUTEX_INITIALIZER PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP +#ifdef PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP +#define AST_MUTEX_INIT_VAULE PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP +#else +#define AST_MUTEX_INIT_VAULE PTHREAD_MUTEX_INITIALIZER +#endif + +#ifdef PTHREAD_MUTEX_RECURSIVE_NP #define AST_MUTEX_KIND PTHREAD_MUTEX_RECURSIVE_NP +#else +#define AST_MUTEX_KIND PTHREAD_MUTEX_RECURSIVE +#endif typedef pthread_mutex_t ast_mutex_t; -#define ast_mutex_lock(t) pthread_mutex_lock(t) -#define ast_mutex_unlock(t) pthread_mutex_unlock(t) -#define ast_mutex_trylock(t) pthread_mutex_trylock(t) -static inline int ast_mutex_init(ast_mutex_t *t) +static inline int ast_mutex_init(ast_mutex_t *pmutex) { pthread_mutexattr_t attr; pthread_mutexattr_init(&attr); pthread_mutexattr_settype(&attr, AST_MUTEX_KIND); - return pthread_mutex_init(t, &attr); + return pthread_mutex_init(pmutex, &attr); +} +#define ast_pthread_mutex_init(pmutex,a) pthread_mutex_init(pmutex,a) +#define ast_mutex_unlock(pmutex) pthread_mutex_unlock(pmutex) +#define ast_mutex_destroy(pmutex) pthread_mutex_destroy(pmutex) + +#if defined(AST_MUTEX_INIT_W_CONSTRUCTORS) +/* if AST_MUTEX_INIT_W_CONSTRUCTORS is defined, use file scope + constrictors/destructors to create/destroy mutexes. */ +#define __AST_MUTEX_DEFINE(scope,mutex) \ + scope ast_mutex_t mutex = AST_MUTEX_INIT_VAULE; \ +static void __attribute__ ((constructor)) init_##mutex(void) \ +{ \ + ast_mutex_init(&mutex); \ +} \ +static void __attribute__ ((destructor)) fini_##mutex(void) \ +{ \ + ast_mutex_destroy(&mutex); \ +} + +#define ast_mutex_lock(pmutex) pthread_mutex_lock(pmutex) +#define ast_mutex_trylock(pmutex) pthread_mutex_trylock(pmutex) + +#elif defined(AST_MUTEX_INIT_ON_FIRST_USE) +/* if AST_MUTEX_INIT_ON_FIRST_USE is defined, mutexes are created on + first use. The performance impact on FreeBSD should be small since + the pthreads library does this itself to initialize errror checking + (defaulty type) mutexes.*/ +#define __AST_MUTEX_DEFINE(scope,mutex) \ + scope ast_mutex_t mutex = AST_MUTEX_INIT_VAULE + +static inline int ast_mutex_lock(ast_mutex_t *pmutex) +{ + if(*pmutex == (ast_mutex_t)AST_MUTEX_KIND) + ast_mutex_init(pmutex); + return pthread_mutex_lock(pmutex); +} +static inline int ast_mutex_trylock(ast_mutex_t *pmutex) +{ + if(*pmutex == (ast_mutex_t)AST_MUTEX_KIND) + ast_mutex_init(pmutex); + return pthread_mutex_trylock(pmutex); } -#define ast_pthread_mutex_init(t,a) pthread_mutex_init(t,a) -#define ast_mutex_destroy(t) pthread_mutex_destroy(t) +#else +/* By default, use static initialization of mutexes.*/ +#define __AST_MUTEX_DEFINE(scope,mutex) \ + scope ast_mutex_t mutex = AST_MUTEX_INIT_VAULE +#define ast_mutex_lock(pmutex) pthread_mutex_lock(pmutex) +#define ast_mutex_trylock(pmutex) pthread_mutex_trylock(pmutex) +#endif /* AST_MUTEX_INIT_W_CONSTRUCTORS */ #endif /* DEBUG_THREADS */ +#define AST_MUTEX_DEFINE_STATIC(mutex) __AST_MUTEX_DEFINE(static,mutex) +#define AST_MUTEX_DEFINE_EXPORTED(mutex) __AST_MUTEX_DEFINE(/**/,mutex) + + +#define AST_MUTEX_INITIALIZER __use_AST_MUTEX_DEFINE_STATIC_rather_than_AST_MUTEX_INITIALIZER__ #define gethostbyname __gethostbyname__is__not__reentrant__use__ast_gethostbyname__instead__ #endif diff --git a/include/asterisk/module.h b/include/asterisk/module.h index b7a5184e8..aba72980d 100755 --- a/include/asterisk/module.h +++ b/include/asterisk/module.h @@ -152,7 +152,7 @@ void ast_unregister_atexit(void (*func)(void)); struct localuser *next; \ } -#define LOCAL_USER_DECL static ast_mutex_t localuser_lock = AST_MUTEX_INITIALIZER; \ +#define LOCAL_USER_DECL AST_MUTEX_DEFINE_STATIC(localuser_lock); \ static struct localuser *localusers = NULL; \ static int localusecnt = 0; -- cgit v1.2.3