<p>Corey Farrell has uploaded this change for <strong>review</strong>.</p><p><a href="https://gerrit.asterisk.org/8107">View Change</a></p><pre style="font-family: monospace,monospace; white-space: pre-wrap;">core: Create ast_atomic macro's.<br><br>Create ast_atomic macro's to provide a consistent interface to the<br>common functionality of __atomic and __sync built-in functions.<br><br>ASTERISK-27619<br><br>Change-Id: Ieba3f81832a0e25c5725ea067e5d6f742d33eb5b<br>---<br>M include/asterisk/lock.h<br>1 file changed, 96 insertions(+), 5 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;">git pull ssh://gerrit.asterisk.org:29418/asterisk refs/changes/07/8107/1</pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;">diff --git a/include/asterisk/lock.h b/include/asterisk/lock.h<br>index c3dd691..a46d047 100644<br>--- a/include/asterisk/lock.h<br>+++ b/include/asterisk/lock.h<br>@@ -617,19 +617,108 @@<br> #define pthread_create __use_ast_pthread_create_instead__<br> #endif<br> <br>-/* Support for atomic instructions. */<br>+/*!<br>+ * \brief Support for atomic instructions.<br>+ *<br>+ * These macros implement a uniform interface to use built-in atomic functionality.<br>+ * If available __atomic built-ins are prefered.  Legacy __sync built-ins are used<br>+ * as a fallback for older compilers.<br>+ *<br>+ * Detailed documentation can be found in the GCC manual, all API's are modeled after<br>+ * the __atomic interfaces but using the namespace ast_atomic.<br>+ *<br>+ * The memorder argument is always ignored by legacy __sync functions.  Invalid<br>+ * memorder arguments do not produce errors unless __atomic functions are supported<br>+ * as the argument is erased by the preprocessor.<br>+ *<br>+ * \note ast_atomic_fetch_nand and ast_atomic_nand_fetch purposely do not exist.<br>+ *       It's implementation was broken prior to gcc-4.4.<br>+ *<br>+ * @{<br>+ */<br> <br> #include "asterisk/inline_api.h"<br> <br> #if defined(HAVE_C_ATOMICS)<br>-#define ast_atomic_fetch_add(p, v, memorder)  __atomic_fetch_add(p, v, memorder)<br>-#define ast_atomic_sub_fetch(p, v, memorder)  __atomic_sub_fetch(p, v, memorder)<br>+/*! Atomic += */<br>+#define ast_atomic_fetch_add(ptr, val, memorder)  __atomic_fetch_add((ptr), (val), (memorder))<br>+#define ast_atomic_add_fetch(ptr, val, memorder)  __atomic_add_fetch((ptr), (val), (memorder))<br>+<br>+/*! Atomic -= */<br>+#define ast_atomic_fetch_sub(ptr, val, memorder)  __atomic_fetch_sub((ptr), (val), (memorder))<br>+#define ast_atomic_sub_fetch(ptr, val, memorder)  __atomic_sub_fetch((ptr), (val), (memorder))<br>+<br>+/*! Atomic &= */<br>+#define ast_atomic_fetch_and(ptr, val, memorder)  __atomic_fetch_and((ptr), (val), (memorder))<br>+#define ast_atomic_and_fetch(ptr, val, memorder)  __atomic_and_fetch((ptr), (val), (memorder))<br>+<br>+/*! Atomic |= */<br>+#define ast_atomic_fetch_or(ptr, val, memorder)   __atomic_fetch_or((ptr), (val), (memorder))<br>+#define ast_atomic_or_fetch(ptr, val, memorder)   __atomic_or_fetch((ptr), (val), (memorder))<br>+<br>+/*! Atomic xor = */<br>+#define ast_atomic_fetch_xor(ptr, val, memorder)  __atomic_fetch_xor((ptr), (val), (memorder))<br>+#define ast_atomic_xor_fetch(ptr, val, memorder)  __atomic_xor_fetch((ptr), (val), (memorder))<br>+<br>+#if 0<br>+/* Atomic compare and swap<br>+ *<br>+ * See comments near the __atomic implementation for why this is disabled.<br>+ */<br>+#define ast_atomic_compare_exchange_n(ptr, expected, desired, success_memorder, failure_memorder) \<br>+   __atomic_compare_exchange_n((ptr), (expected), (desired), 0, success_memorder, failure_memorder)<br>+<br>+#define ast_atomic_compare_exchange(ptr, expected, desired, success_memorder, failure_memorder) \<br>+      __atomic_compare_exchange((ptr), (expected), (desired), 0, success_memorder, failure_memorder)<br>+#endif<br>+<br> #elif defined(HAVE_GCC_ATOMICS)<br>-#define ast_atomic_fetch_add(p, v, memorder)  __sync_fetch_and_add(p, v)<br>-#define ast_atomic_sub_fetch(p, v, memorder)  __sync_sub_and_fetch(p, v)<br>+/*! Atomic += */<br>+#define ast_atomic_fetch_add(ptr, val, memorder)  __sync_fetch_and_add((ptr), (val))<br>+#define ast_atomic_add_fetch(ptr, val, memorder)  __sync_add_and_fetch((ptr), (val))<br>+<br>+/*! Atomic -= */<br>+#define ast_atomic_fetch_sub(ptr, val, memorder)  __sync_fetch_and_sub((ptr), (val))<br>+#define ast_atomic_sub_fetch(ptr, val, memorder)  __sync_sub_and_fetch((ptr), (val))<br>+<br>+/*! Atomic &= */<br>+#define ast_atomic_fetch_and(ptr, val, memorder)  __sync_fetch_and_and((ptr), (val))<br>+#define ast_atomic_and_fetch(ptr, val, memorder)  __sync_and_and_fetch((ptr), (val))<br>+<br>+/*! Atomic |= */<br>+#define ast_atomic_fetch_or(ptr, val, memorder)  __sync_fetch_and_or((ptr), (val))<br>+#define ast_atomic_or_fetch(ptr, val, memorder)  __sync_or_and_fetch((ptr), (val))<br>+<br>+/*! Atomic xor = */<br>+#define ast_atomic_fetch_xor(ptr, val, memorder)  __sync_fetch_and_xor((ptr), (val))<br>+#define ast_atomic_xor_fetch(ptr, val, memorder)  __sync_xor_and_fetch((ptr), (val))<br>+<br>+#if 0<br>+/* Atomic compare and swap<br>+ *<br>+ * The \a expected argument is a pointer, I'm guessing __atomic built-ins<br>+ * perform all memory reads/writes in a single atomic operation.  I don't<br>+ * believe this is possible to exactly replicate using __sync built-ins.<br>+ * Will need to determine potential use cases of this feature and write a<br>+ * wrapper which provides consistant behavior between __sync and __atomic<br>+ * implementations.<br>+ */<br>+#define ast_atomic_compare_exchange_n(ptr, expected, desired, success_memorder, failure_memorder) \<br>+     __sync_bool_compare_and_swap((ptr), *(expected), (desired))<br>+<br>+#define ast_atomic_compare_exchange(ptr, expected, desired, success_memorder, failure_memorder) \<br>+   __sync_bool_compare_and_swap((ptr), *(expected), *(desired))<br>+#endif<br>+<br> #else<br> #error "Atomics not available."<br> #endif<br>+<br>+/*! Atomic flag set */<br>+#define ast_atomic_flag_set(ptr, val, memorder)   ast_atomic_fetch_or((ptr), (val), (memorder))<br>+<br>+/*! Atomic flag clear */<br>+#define ast_atomic_flag_clear(ptr, val, memorder) ast_atomic_fetch_and((ptr), ~(val), (memorder))<br> <br> /*!<br>  * \brief Atomically add v to *p and return the previous value of *p.<br>@@ -652,4 +741,6 @@<br>   return ast_atomic_sub_fetch(p, 1, __ATOMIC_RELAXED) == 0;<br> })<br> <br>+/*! @} */<br>+<br> #endif /* _ASTERISK_LOCK_H */<br></pre><p>To view, visit <a href="https://gerrit.asterisk.org/8107">change 8107</a>. To unsubscribe, visit <a href="https://gerrit.asterisk.org/settings">settings</a>.</p><div itemscope itemtype="http://schema.org/EmailMessage"><div itemscope itemprop="action" itemtype="http://schema.org/ViewAction"><link itemprop="url" href="https://gerrit.asterisk.org/8107"/><meta itemprop="name" content="View Change"/></div></div>

<div style="display:none"> Gerrit-Project: asterisk </div>
<div style="display:none"> Gerrit-Branch: master </div>
<div style="display:none"> Gerrit-MessageType: newchange </div>
<div style="display:none"> Gerrit-Change-Id: Ieba3f81832a0e25c5725ea067e5d6f742d33eb5b </div>
<div style="display:none"> Gerrit-Change-Number: 8107 </div>
<div style="display:none"> Gerrit-PatchSet: 1 </div>
<div style="display:none"> Gerrit-Owner: Corey Farrell <git@cfware.com> </div>