Commit e4ff22ec authored by Maria Matejka's avatar Maria Matejka
Browse files

Atomic: Add support for atomic operations since gcc 4.4

Anyway, we suggest using a compiler that supports C11 atomic_* calls directly.
We don't guarantee that the legacy atomic operation would work in all cases.
parent 422a6b6f
Loading
Loading
Loading
Loading
+24 −0
Original line number Diff line number Diff line
@@ -20,6 +20,30 @@ AC_DEFUN([BIRD_CHECK_THREAD_LOCAL],
  )
])

AC_DEFUN([BIRD_CHECK_OLD_SYNC],
[
  AC_CACHE_CHECK(
    [whether GCC old-style __sync_* calls are available],
    [bird_cv_old_sync],
    [
      AC_COMPILE_IFELSE([
	AC_LANG_PROGRAM([
	  #include <stdint.h>
	], [
	  uint64_t value = 0;
	  __sync_fetch_and_add(&value, 64);
	  __sync_fetch_and_sub(&value, 42);
	  uint64_t old = __sync_val_compare_and_swap(&value, 22, 64);
	])
      ],
      [bird_cv_old_sync=yes],
      [bird_cv_old_sync=no],
      )
    ]
  )
])


AC_DEFUN([BIRD_CHECK_PTHREADS],
[
  bird_tmp_cflags="$CFLAGS"
+11 −0
Original line number Diff line number Diff line
@@ -120,6 +120,17 @@ if test "$bird_cv_thread_local" = yes ; then
  AC_DEFINE([HAVE_THREAD_LOCAL], [1], [Define to 1 if _Thread_local is available])
fi

AC_CHECK_HEADER([stdatomic.h],
		[AC_DEFINE([HAVE_ATOMIC], [1], [Define to 1 if stdatomic.h is present])],
		[
		BIRD_CHECK_OLD_SYNC
		if test "$bird_cv_old_sync" = no ; then
		  AC_MSG_ERROR([No atomic operations available.])
		fi
		],
		[]
		)

if test "$enable_pthreads" != no ; then
  BIRD_CHECK_PTHREADS

lib/atomic.h

0 → 100644
+36 −0
Original line number Diff line number Diff line
#ifndef _BIRD_ATOMIC_H_
#define _BIRD_ATOMIC_H_

#if HAVE_ATOMIC
#include <stdatomic.h>
#else

#define _Atomic

#define atomic_load(ptr) __sync_val_compare_and_swap(ptr, 0, 0)
#define atomic_load_explicit(ptr, mem) atomic_load(ptr)
#define atomic_store(ptr, val) __sync_lock_test_and_set(ptr, val)

#define atomic_fetch_add(ptr, val) __sync_fetch_and_add((ptr), (val))
#define atomic_fetch_add_explicit(ptr, val, memory) __sync_fetch_and_add((ptr), (val))
#define atomic_fetch_sub(ptr, val) __sync_fetch_and_sub((ptr), (val))
#define atomic_fetch_sub_explicit(ptr, val, memory) __sync_fetch_and_sub((ptr), (val))

#define atomic_compare_exchange_weak(ptr, desired, wanted) ({ \
    typeof(desired) _desptr = desired; /* save the pointer */ \
    typeof(*_desptr) _old = __sync_val_compare_and_swap(ptr, *_desptr, wanted); /* do the exchange */ \
    int result = _old == *_desptr; /* get the return value */ \
    *_desptr = _old; /* store the old value */ \
    result; /* and return */ })

#define atomic_compare_exchange_strong(ptr, desired, wanted) \
  atomic_compare_exchange_weak(ptr, desired, wanted)

#define atomic_compare_exchange_weak_explicit(ptr, desired, wanted, success, failure) \
  atomic_compare_exchange_weak(ptr, desired, wanted)

#define atomic_compare_exchange_strong_explicit(ptr, desired, wanted, success, failure) \
  atomic_compare_exchange_weak(ptr, desired, wanted)

#endif
#endif