summaryrefslogtreecommitdiff
path: root/include
diff options
context:
space:
mode:
authorLuigi Rizzo <rizzo@icir.org>2006-03-30 23:26:22 +0000
committerLuigi Rizzo <rizzo@icir.org>2006-03-30 23:26:22 +0000
commita7ec530a6489e966461388aeec32fbc9dd5d4bef (patch)
treed523df419b44c5c8864b03fcdb19286787e75e01 /include
parent9a9ab4e7cf91955b6e74bbbc73428911c9b6063b (diff)
initial implementation of support for native atomic ops.
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@16601 65c4cc65-6c06-0410-ace0-fbb531ad65f3
Diffstat (limited to 'include')
-rw-r--r--include/asterisk/lock.h46
1 files changed, 46 insertions, 0 deletions
diff --git a/include/asterisk/lock.h b/include/asterisk/lock.h
index 7c144a657..8795bf0c3 100644
--- a/include/asterisk/lock.h
+++ b/include/asterisk/lock.h
@@ -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__
#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 */