gatomic: introduce G_ATOMIC_LOCK_FREE

We clean up the detection of if we should do 'real' atomic operations or
mutex-emulated ones with the introduction of a new (public) macro:
G_ATOMIC_LOCK_FREE.  If defined, our atomic operations are guaranteed to
be done in hardware.

We need to use __GCC_HAVE_SYNC_COMPARE_AND_SWAP_4 to determine if our
compiler supports GCC-style atomic operations from the gatomic.h header
because we might be building a program against GLib using a different
set of compiler options (or a different compiler) than was used to build
GLib itself.

Unfortunately, this macro is not available on clang, so it has currently
regressed to using the mutex emulation.  A bug about that has been
opened here:

  http://llvm.org/bugs/show_bug.cgi?id=11174
This commit is contained in:
Ryan Lortie
2011-10-18 16:21:50 -04:00
parent c9b6c3c85a
commit aba0f0c38b
6 changed files with 89 additions and 50 deletions

View File

@@ -50,22 +50,6 @@
* hardware memory barrier. Acquire and release or producer and
* consumer barrier semantics are not available through this API.
*
* On GCC, these macros are implemented using GCC intrinsic operations.
* On non-GCC compilers they will evaluate to function calls to
* functions implemented by GLib.
*
* If GLib itself was compiled with GCC then these functions will again
* be implemented by the GCC intrinsics. On Windows without GCC, the
* interlocked API is used to implement the functions.
*
* With non-GCC compilers on non-Windows systems, the functions are
* currently incapable of implementing true atomic operations --
* instead, they fallback to holding a global lock while performing the
* operation. This provides atomicity between the threads of one
* process, but not between separate processes. For this reason, one
* should exercise caution when attempting to use these options on
* shared memory regions.
*
* It is very important that all accesses to a particular integer or
* pointer be performed using only this API and that different sizes of
* operation are not mixed or used on overlapping memory regions. Never
@@ -82,6 +66,19 @@
* perform the operations normally and then release the lock.
**/
/**
* G_ATOMIC_LOCK_FREE:
*
* This macro is defined if the atomic operations of GLib are
* implemented using real hardware atomic operations. This means that
* the GLib atomic API can be used between processes and safely mixed
* with other (hardware) atomic APIs.
*
* If this macro is not defined, the atomic operations may be
* emulated using a mutex. In that case, the GLib atomic operations are
* only atomic relative to themselves and within a single process.
**/
/* NOTE CAREFULLY:
*
* This file is the lowest-level part of GLib.
@@ -93,12 +90,13 @@
* without risking recursion.
*/
#ifdef G_ATOMIC_OP_USE_GCC_BUILTINS
#ifdef G_ATOMIC_LOCK_FREE
#ifndef __GNUC__
#error Using GCC builtin atomic ops, but not compiling with GCC?
#endif
/* if G_ATOMIC_LOCK_FREE was defined by ./configure then we MUST
* implement the atomic operations in a lock-free manner.
*/
#if defined (__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4)
/**
* g_atomic_int_get:
* @atomic: a pointer to a #gint or #guint
@@ -612,9 +610,17 @@ gsize
return InterlockedXor (atomic, val);
#endif
}
#else
/* This error occurs when ./configure decided that we should be capable
* of lock-free atomics but we find at compile-time that we are not.
*/
#error G_ATOMIC_LOCK_FREE defined, but incapable of lock-free atomics.
#endif /* defined (__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4) */
#else /* G_ATOMIC_LOCK_FREE */
/* We are not permitted to call into any GLib functions from here, so we
* can not use GMutex.
*