mirror of
https://github.com/asterisk/asterisk.git
synced 2025-10-27 14:41:58 +00:00
initial implementation of support for native atomic ops.
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@16601 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
@@ -679,4 +679,50 @@ static inline int ast_cond_timedwait(ast_cond_t *cond, ast_mutex_t *t, const str
|
|||||||
#define pthread_create __use_ast_pthread_create_instead__
|
#define pthread_create __use_ast_pthread_create_instead__
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Initial 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"
|
||||||
|
|
||||||
|
/*! \brief Atomically add v to *pp 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 ( __i386__)
|
||||||
|
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);
|
||||||
|
})
|
||||||
|
#else /* low performance version in utils.c */
|
||||||
|
AST_INLINE_AP(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.
|
||||||
|
*/
|
||||||
|
AST_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 /* _ASTERISK_LOCK_H */
|
#endif /* _ASTERISK_LOCK_H */
|
||||||
|
|||||||
11
utils.c
11
utils.c
@@ -39,6 +39,7 @@
|
|||||||
|
|
||||||
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||||
|
|
||||||
|
#define AST_API_MODULE /* ensure that inlinable API functions will be built in lock.h if required */
|
||||||
#include "asterisk/lock.h"
|
#include "asterisk/lock.h"
|
||||||
#include "asterisk/io.h"
|
#include "asterisk/io.h"
|
||||||
#include "asterisk/logger.h"
|
#include "asterisk/logger.h"
|
||||||
@@ -1049,6 +1050,16 @@ void __ast_string_field_index_build(struct ast_string_field_mgr *mgr,
|
|||||||
va_end(ap2);
|
va_end(ap2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
AST_MUTEX_DEFINE_STATIC(fetchadd_m); /* used for all fetc&add ops */
|
||||||
|
int ast_atomic_fetchadd_int_slow(volatile int *p, int v)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
ast_mutex_lock(&fetchadd_m);
|
||||||
|
ret = *p;
|
||||||
|
*p += v;
|
||||||
|
ast_mutex_unlock(&fetchadd_m);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
/*! \brief
|
/*! \brief
|
||||||
* get values from config variables.
|
* get values from config variables.
|
||||||
|
|||||||
Reference in New Issue
Block a user