📄 lock.h
字号:
#define gethostbyname __gethostbyname__is__not__reentrant__use__ast_gethostbyname__instead__#ifndef __linux__#define pthread_create __use_ast_pthread_create_instead__#endif/* * Same as above, definitions of ast_rwlock_t for the various cases: * simple wrappers for the pthread equivalent in the non-debug case, * more sophisticated tracking in the debug case. */typedef pthread_rwlock_t ast_rwlock_t;#ifdef HAVE_PTHREAD_RWLOCK_INITIALIZER#define AST_RWLOCK_INIT_VALUE PTHREAD_RWLOCK_INITIALIZER#else#define AST_RWLOCK_INIT_VALUE { 0 }#endif#ifdef DEBUG_THREADS#define ast_rwlock_init(rwlock) __ast_rwlock_init(__FILE__, __LINE__, __PRETTY_FUNCTION__, #rwlock, rwlock)#define ast_rwlock_destroy(rwlock) __ast_rwlock_destroy(__FILE__, __LINE__, __PRETTY_FUNCTION__, #rwlock, rwlock)#define ast_rwlock_unlock(a) _ast_rwlock_unlock(a, # a, __FILE__, __LINE__, __PRETTY_FUNCTION__)#define ast_rwlock_rdlock(a) _ast_rwlock_rdlock(a, # a, __FILE__, __LINE__, __PRETTY_FUNCTION__)#define ast_rwlock_wrlock(a) _ast_rwlock_wrlock(a, # a, __FILE__, __LINE__, __PRETTY_FUNCTION__)#define ast_rwlock_tryrdlock(a) _ast_rwlock_tryrdlock(a, # a, __FILE__, __LINE__, __PRETTY_FUNCTION__)#define ast_rwlock_trywrlock(a) _ast_rwlock_trywrlock(a, # a, __FILE__, __LINE__, __PRETTY_FUNCTION__)static inline int __ast_rwlock_init(const char *filename, int lineno, const char *func, const char *rwlock_name, ast_rwlock_t *prwlock){ int res; pthread_rwlockattr_t attr;#ifdef AST_MUTEX_INIT_W_CONSTRUCTORS int canlog = strcmp(filename, "logger.c"); if (*prwlock != ((ast_rwlock_t) AST_RWLOCK_INIT_VALUE)) { __ast_mutex_logger("%s line %d (%s): Warning: rwlock '%s' is already initialized.\n", filename, lineno, func, rwlock_name); return 0; }#endif /* AST_MUTEX_INIT_W_CONSTRUCTORS */ pthread_rwlockattr_init(&attr);#ifdef HAVE_PTHREAD_RWLOCK_PREFER_WRITER_NP pthread_rwlockattr_setkind_np(&attr, PTHREAD_RWLOCK_PREFER_WRITER_NP);#endif res = pthread_rwlock_init(prwlock, &attr); pthread_rwlockattr_destroy(&attr); return res;}static inline int __ast_rwlock_destroy(const char *filename, int lineno, const char *func, const char *rwlock_name, ast_rwlock_t *prwlock){ int res; int canlog = strcmp(filename, "logger.c");#ifdef AST_MUTEX_INIT_W_CONSTRUCTORS if (*prwlock == ((ast_rwlock_t) AST_RWLOCK_INIT_VALUE)) { __ast_mutex_logger("%s line %d (%s): Warning: rwlock '%s' is uninitialized.\n", filename, lineno, func, rwlock_name); return 0; }#endif /* AST_MUTEX_INIT_W_CONSTRUCTORS */ if ((res = pthread_rwlock_destroy(prwlock))) __ast_mutex_logger("%s line %d (%s): Error destroying rwlock %s: %s\n", filename, lineno, func, rwlock_name, strerror(res)); return res;}static inline int _ast_rwlock_unlock(ast_rwlock_t *lock, const char *name, const char *file, int line, const char *func){ int res;#ifdef AST_MUTEX_INIT_W_CONSTRUCTORS int canlog = strcmp(file, "logger.c"); if (*lock == ((ast_rwlock_t) AST_RWLOCK_INIT_VALUE)) { __ast_mutex_logger("%s line %d (%s): Warning: rwlock '%s' is uninitialized.\n", file, line, func, name); res = __ast_rwlock_init(file, line, func, name, lock); if (*lock == ((ast_rwlock_t) AST_RWLOCK_INIT_VALUE)) { __ast_mutex_logger("%s line %d (%s): Error: rwlock '%s' is uninitialized and unable to initialize.\n", file, line, func, name); } return res; }#endif /* AST_MUTEX_INIT_W_CONSTRUCTORS */ res = pthread_rwlock_unlock(lock); ast_remove_lock_info(lock); return res;}static inline int _ast_rwlock_rdlock(ast_rwlock_t *lock, const char *name, const char *file, int line, const char *func){ int res;#ifdef AST_MUTEX_INIT_W_CONSTRUCTORS int canlog = strcmp(file, "logger.c"); if (*lock == ((ast_rwlock_t) AST_RWLOCK_INIT_VALUE)) { /* Don't warn abount uninitialized lock. * Simple try to initialize it. * May be not needed in linux system. */ res = __ast_rwlock_init(file, line, func, name, lock); if (*lock == ((ast_rwlock_t) AST_RWLOCK_INIT_VALUE)) { __ast_mutex_logger("%s line %d (%s): Error: rwlock '%s' is uninitialized and unable to initialize.\n", file, line, func, name); return res; } }#endif /* AST_MUTEX_INIT_W_CONSTRUCTORS */ ast_store_lock_info(AST_RDLOCK, file, line, func, name, lock); res = pthread_rwlock_rdlock(lock); if (!res) ast_mark_lock_acquired(lock); else ast_remove_lock_info(lock); return res;}static inline int _ast_rwlock_wrlock(ast_rwlock_t *lock, const char *name, const char *file, int line, const char *func){ int res;#ifdef AST_MUTEX_INIT_W_CONSTRUCTORS int canlog = strcmp(file, "logger.c"); if (*lock == ((ast_rwlock_t) AST_RWLOCK_INIT_VALUE)) { /* Don't warn abount uninitialized lock. * Simple try to initialize it. * May be not needed in linux system. */ res = __ast_rwlock_init(file, line, func, name, lock); if (*lock == ((ast_rwlock_t) AST_RWLOCK_INIT_VALUE)) { __ast_mutex_logger("%s line %d (%s): Error: rwlock '%s' is uninitialized and unable to initialize.\n", file, line, func, name); return res; } }#endif /* AST_MUTEX_INIT_W_CONSTRUCTORS */ ast_store_lock_info(AST_WRLOCK, file, line, func, name, lock); res = pthread_rwlock_wrlock(lock); if (!res) ast_mark_lock_acquired(lock); else ast_remove_lock_info(lock); return res;}static inline int _ast_rwlock_tryrdlock(ast_rwlock_t *lock, const char *name, const char *file, int line, const char *func){ int res;#ifdef AST_MUTEX_INIT_W_CONSTRUCTORS int canlog = strcmp(file, "logger.c"); if (*lock == ((ast_rwlock_t) AST_RWLOCK_INIT_VALUE)) { /* Don't warn abount uninitialized lock. * Simple try to initialize it. * May be not needed in linux system. */ res = __ast_rwlock_init(file, line, func, name, lock); if (*lock == ((ast_rwlock_t) AST_RWLOCK_INIT_VALUE)) { __ast_mutex_logger("%s line %d (%s): Error: rwlock '%s' is uninitialized and unable to initialize.\n", file, line, func, name); return res; } }#endif /* AST_MUTEX_INIT_W_CONSTRUCTORS */ ast_store_lock_info(AST_RDLOCK, file, line, func, name, lock); res = pthread_rwlock_tryrdlock(lock); if (!res) ast_mark_lock_acquired(lock); else ast_remove_lock_info(lock); return res;}static inline int _ast_rwlock_trywrlock(ast_rwlock_t *lock, const char *name, const char *file, int line, const char *func){ int res;#ifdef AST_MUTEX_INIT_W_CONSTRUCTORS int canlog = strcmp(file, "logger.c"); if (*lock == ((ast_rwlock_t) AST_RWLOCK_INIT_VALUE)) { /* Don't warn abount uninitialized lock. * Simple try to initialize it. * May be not needed in linux system. */ res = __ast_rwlock_init(file, line, func, name, lock); if (*lock == ((ast_rwlock_t) AST_RWLOCK_INIT_VALUE)) { __ast_mutex_logger("%s line %d (%s): Error: rwlock '%s' is uninitialized and unable to initialize.\n", file, line, func, name); return res; } }#endif /* AST_MUTEX_INIT_W_CONSTRUCTORS */ ast_store_lock_info(AST_WRLOCK, file, line, func, name, lock); res = pthread_rwlock_trywrlock(lock); if (!res) ast_mark_lock_acquired(lock); else ast_remove_lock_info(lock); return res;}#else /* !DEBUG_THREADS */#define CHANNEL_DEADLOCK_AVOIDANCE(chan) \ ast_channel_unlock(chan); \ usleep(1); \ ast_channel_lock(chan);#define DEADLOCK_AVOIDANCE(lock) \ ast_mutex_unlock(lock); \ usleep(1); \ ast_mutex_lock(lock);static inline int ast_rwlock_init(ast_rwlock_t *prwlock){ int res; pthread_rwlockattr_t attr; pthread_rwlockattr_init(&attr);#ifdef HAVE_PTHREAD_RWLOCK_PREFER_WRITER_NP pthread_rwlockattr_setkind_np(&attr, PTHREAD_RWLOCK_PREFER_WRITER_NP);#endif res = pthread_rwlock_init(prwlock, &attr); pthread_rwlockattr_destroy(&attr); return res;}static inline int ast_rwlock_destroy(ast_rwlock_t *prwlock){ return pthread_rwlock_destroy(prwlock);}static inline int ast_rwlock_unlock(ast_rwlock_t *prwlock){ return pthread_rwlock_unlock(prwlock);}static inline int ast_rwlock_rdlock(ast_rwlock_t *prwlock){ return pthread_rwlock_rdlock(prwlock);}static inline int ast_rwlock_tryrdlock(ast_rwlock_t *prwlock){ return pthread_rwlock_tryrdlock(prwlock);}static inline int ast_rwlock_wrlock(ast_rwlock_t *prwlock){ return pthread_rwlock_wrlock(prwlock);}static inline int ast_rwlock_trywrlock(ast_rwlock_t *prwlock){ return pthread_rwlock_trywrlock(prwlock);}#endif /* !DEBUG_THREADS *//* Statically declared read/write locks */#ifndef HAVE_PTHREAD_RWLOCK_INITIALIZER#define __AST_RWLOCK_DEFINE(scope, rwlock) \ scope ast_rwlock_t rwlock; \static void __attribute__ ((constructor)) init_##rwlock(void) \{ \ ast_rwlock_init(&rwlock); \} \ \static void __attribute__ ((destructor)) fini_##rwlock(void) \{ \ ast_rwlock_destroy(&rwlock); \}#else#define __AST_RWLOCK_DEFINE(scope, rwlock) scope ast_rwlock_t rwlock = AST_RWLOCK_INIT_VALUE#endif#define AST_RWLOCK_DEFINE_STATIC(rwlock) __AST_RWLOCK_DEFINE(static, rwlock)/* * Support for atomic instructions. * For platforms that have it, use the native cpu instruction to * implement them. For other platforms, resort to a 'slow' version * (defined in utils.c) that protects the atomic instruction with * a single lock. * The slow versions is always available, for testing purposes, * as ast_atomic_fetchadd_int_slow() */int ast_atomic_fetchadd_int_slow(volatile int *p, int v);#include "asterisk/inline_api.h"#if defined(HAVE_OSX_ATOMICS)#include "libkern/OSAtomic.h"#endif/*! \brief Atomically add v to *p and return * the previous value of *p. * This can be used to handle reference counts, and the return value * can be used to generate unique identifiers. */#if defined(HAVE_GCC_ATOMICS)AST_INLINE_API(int ast_atomic_fetchadd_int(volatile int *p, int v),{ return __sync_fetch_and_add(p, v);})#elif defined(HAVE_OSX_ATOMICS) && (SIZEOF_INT == 4)AST_INLINE_API(int ast_atomic_fetchadd_int(volatile int *p, int v),{ return OSAtomicAdd32(v, (int32_t *) p) - v;})#elif defined(HAVE_OSX_ATOMICS) && (SIZEOF_INT == 8)AST_INLINE_API(int ast_atomic_fetchadd_int(volatile int *p, int v),{ return OSAtomicAdd64(v, (int64_t *) p) - v;#elif defined (__i386__) || defined(__x86_64__)#ifdef sunAST_INLINE_API(int ast_atomic_fetchadd_int(volatile int *p, int v),{ __asm __volatile ( " lock; xaddl %0, %1 ; " : "+r" (v), /* 0 (result) */ "=m" (*p) /* 1 */ : "m" (*p)); /* 2 */ return (v);})#else /* ifndef sun */AST_INLINE_API(int ast_atomic_fetchadd_int(volatile int *p, int v),{ __asm __volatile ( " lock xaddl %0, %1 ; " : "+r" (v), /* 0 (result) */ "=m" (*p) /* 1 */ : "m" (*p)); /* 2 */ return (v);})#endif#else /* low performance version in utils.c */AST_INLINE_API(int ast_atomic_fetchadd_int(volatile int *p, int v),{ return ast_atomic_fetchadd_int_slow(p, v);})#endif/*! \brief decrement *p by 1 and return true if the variable has reached 0. * Useful e.g. to check if a refcount has reached 0. */#if defined(HAVE_GCC_ATOMICS)AST_INLINE_API(int ast_atomic_dec_and_test(volatile int *p),{ return __sync_sub_and_fetch(p, 1) == 0;})#elif defined(HAVE_OSX_ATOMICS) && (SIZEOF_INT == 4)AST_INLINE_API(int ast_atomic_dec_and_test(volatile int *p),{ return OSAtomicAdd32( -1, (int32_t *) p) == 0;})#elif defined(HAVE_OSX_ATOMICS) && (SIZEOF_INT == 8)AST_INLINE_API(int ast_atomic_dec_and_test(volatile int *p),{ return OSAtomicAdd64( -1, (int64_t *) p) == 0;#elseAST_INLINE_API(int ast_atomic_dec_and_test(volatile int *p),{ int a = ast_atomic_fetchadd_int(p, -1); return a == 1; /* true if the value is 0 now (so it was 1 previously) */})#endif#ifndef DEBUG_CHANNEL_LOCKS/*! \brief Lock a channel. If DEBUG_CHANNEL_LOCKS is defined in the Makefile, print relevant output for debugging */#define ast_channel_lock(x) ast_mutex_lock(&x->lock_dont_use)/*! \brief Unlock a channel. If DEBUG_CHANNEL_LOCKS is defined in the Makefile, print relevant output for debugging */#define ast_channel_unlock(x) ast_mutex_unlock(&x->lock_dont_use)/*! \brief Try locking a channel. If DEBUG_CHANNEL_LOCKS is defined in the Makefile, print relevant output for debugging */#define ast_channel_trylock(x) ast_mutex_trylock(&x->lock_dont_use)#else#define ast_channel_lock(a) __ast_channel_lock(a, __FILE__, __LINE__, __PRETTY_FUNCTION__)/*! \brief Lock AST channel (and print debugging output)\note You need to enable DEBUG_CHANNEL_LOCKS for this function */int __ast_channel_lock(struct ast_channel *chan, const char *file, int lineno, const char *func);#define ast_channel_unlock(a) __ast_channel_unlock(a, __FILE__, __LINE__, __PRETTY_FUNCTION__)/*! \brief Unlock AST channel (and print debugging output)\note You need to enable DEBUG_CHANNEL_LOCKS for this function*/int __ast_channel_unlock(struct ast_channel *chan, const char *file, int lineno, const char *func);#define ast_channel_trylock(a) __ast_channel_trylock(a, __FILE__, __LINE__, __PRETTY_FUNCTION__)/*! \brief Lock AST channel (and print debugging output)\note You need to enable DEBUG_CHANNEL_LOCKS for this function */int __ast_channel_trylock(struct ast_channel *chan, const char *file, int lineno, const char *func);#endif#endif /* _ASTERISK_LOCK_H */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -