[asterisk-commits] trunk r16601 - in /trunk: include/asterisk/lock.h utils.c

asterisk-commits at lists.digium.com asterisk-commits at lists.digium.com
Thu Mar 30 16:26:24 MST 2006


Author: rizzo
Date: Thu Mar 30 17:26:22 2006
New Revision: 16601

URL: http://svn.digium.com/view/asterisk?rev=16601&view=rev
Log:
initial implementation of support for native atomic ops.


Modified:
    trunk/include/asterisk/lock.h
    trunk/utils.c

Modified: trunk/include/asterisk/lock.h
URL: http://svn.digium.com/view/asterisk/trunk/include/asterisk/lock.h?rev=16601&r1=16600&r2=16601&view=diff
==============================================================================
--- trunk/include/asterisk/lock.h (original)
+++ trunk/include/asterisk/lock.h Thu Mar 30 17:26:22 2006
@@ -679,4 +679,50 @@
 #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 */

Modified: trunk/utils.c
URL: http://svn.digium.com/view/asterisk/trunk/utils.c?rev=16601&r1=16600&r2=16601&view=diff
==============================================================================
--- trunk/utils.c (original)
+++ trunk/utils.c Thu Mar 30 17:26:22 2006
@@ -39,6 +39,7 @@
 
 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/io.h"
 #include "asterisk/logger.h"
@@ -1049,6 +1050,16 @@
 	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
  * get values from config variables.



More information about the asterisk-commits mailing list