atomics: Move atomics/recounting support to separate files
[strongswan.git] / src / libstrongswan / utils / utils.h
index c42f881..bd3245d 100644 (file)
@@ -96,6 +96,7 @@
 #endif /* TRUE */
 
 #include "enum.h"
+#include "utils/atomics.h"
 #include "utils/strerror.h"
 #ifdef __APPLE__
 # include "compat/apple.h"
@@ -968,101 +969,6 @@ static inline size_t round_down(size_t size, size_t alignment)
        return size - (size % alignment);
 }
 
-/**
- * Special type to count references
- */
-typedef u_int refcount_t;
-
-/* use __atomic* built-ins with GCC 4.7 and newer */
-#ifdef __GNUC__
-# if (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 6))
-#  define HAVE_GCC_ATOMIC_OPERATIONS
-# endif
-#endif
-
-#ifdef HAVE_GCC_ATOMIC_OPERATIONS
-
-#define ref_get(ref) __atomic_add_fetch(ref, 1, __ATOMIC_RELAXED)
-/* The relaxed memory model works fine for increments as these (usually) don't
- * change the state of refcounted objects.  But here we have to ensure that we
- * free the right stuff if ref counted objects are mutable.  So we have to sync
- * with other threads that call ref_put().  It would be sufficient to use
- * __ATOMIC_RELEASE here and then call __atomic_thread_fence() with
- * __ATOMIC_ACQUIRE if we reach 0, but since we don't have control over the use
- * of ref_put() we have to make sure. */
-#define ref_put(ref) (!__atomic_sub_fetch(ref, 1, __ATOMIC_ACQ_REL))
-#define ref_cur(ref) __atomic_load_n(ref, __ATOMIC_RELAXED)
-
-#define _cas_impl(ptr, oldval, newval) ({ typeof(oldval) _old = oldval; \
-                       __atomic_compare_exchange_n(ptr, &_old, newval, FALSE, \
-                                                                               __ATOMIC_SEQ_CST, __ATOMIC_RELAXED); })
-#define cas_bool(ptr, oldval, newval) _cas_impl(ptr, oldval, newval)
-#define cas_ptr(ptr, oldval, newval) _cas_impl(ptr, oldval, newval)
-
-#elif defined(HAVE_GCC_SYNC_OPERATIONS)
-
-#define ref_get(ref) __sync_add_and_fetch(ref, 1)
-#define ref_put(ref) (!__sync_sub_and_fetch(ref, 1))
-#define ref_cur(ref) __sync_fetch_and_add(ref, 0)
-
-#define cas_bool(ptr, oldval, newval) \
-                                       (__sync_bool_compare_and_swap(ptr, oldval, newval))
-#define cas_ptr(ptr, oldval, newval) \
-                                       (__sync_bool_compare_and_swap(ptr, oldval, newval))
-
-#else /* !HAVE_GCC_ATOMIC_OPERATIONS && !HAVE_GCC_SYNC_OPERATIONS */
-
-/**
- * Get a new reference.
- *
- * Increments the reference counter atomically.
- *
- * @param ref  pointer to ref counter
- * @return             new value of ref
- */
-refcount_t ref_get(refcount_t *ref);
-
-/**
- * Put back a unused reference.
- *
- * Decrements the reference counter atomically and
- * says if more references available.
- *
- * @param ref  pointer to ref counter
- * @return             TRUE if no more references counted
- */
-bool ref_put(refcount_t *ref);
-
-/**
- * Get the current value of the reference counter.
- *
- * @param ref  pointer to ref counter
- * @return             current value of ref
- */
-refcount_t ref_cur(refcount_t *ref);
-
-/**
- * Atomically replace value of ptr with newval if it currently equals oldval.
- *
- * @param ptr          pointer to variable
- * @param oldval       old value of the variable
- * @param newval       new value set if possible
- * @return                     TRUE if value equaled oldval and newval was written
- */
-bool cas_bool(bool *ptr, bool oldval, bool newval);
-
-/**
- * Atomically replace value of ptr with newval if it currently equals oldval.
- *
- * @param ptr          pointer to variable
- * @param oldval       old value of the variable
- * @param newval       new value set if possible
- * @return                     TRUE if value equaled oldval and newval was written
- */
-bool cas_ptr(void **ptr, void *oldval, void *newval);
-
-#endif /* HAVE_GCC_ATOMIC_OPERATIONS */
-
 #ifndef HAVE_FMEMOPEN
 # ifdef HAVE_FUNOPEN
 #  define HAVE_FMEMOPEN