glib: Rewrite gatomic.[ch]
authorRyan Lortie <desrt@desrt.ca>
Sat, 28 May 2011 19:59:18 +0000 (15:59 -0400)
committerRyan Lortie <desrt@desrt.ca>
Sat, 28 May 2011 20:10:44 +0000 (16:10 -0400)
 - remove all inline assembly versions

 - implement the atomic operations using either GCC intrinsics, the
   Windows interlocked API or a mutex-based fallback

 - drop gatomic-gcc.c since these are now defined in the header file.
   Adjust Makefile.am accordingly.

 - expand the set of operations: support 'get', 'set', 'compare and
   exchange', 'add', 'or', and 'xor' for both integers and pointers

 - deprecate g_atomic_int_exchange_and_add since g_atomic_int_add (as
   with all the new arithmetic operations) now returns the prior value

 - unify the use of macros: all functions are now wrapped in macros that
   perform the proper casts and checks

 - remove G_GNUC_MAY_ALIAS use; it was never required for the integer
   operations (since casting between pointers that only vary in
   signedness of the target is explicitly permitted) and we avoid the
   need for the pointer operations by using simple 'void *' instead of
   'gpointer *' (which caused the 'type-punned pointer' warning)

 - provide function implementations of g_atomic_int_inc and
   g_atomic_int_dec_and_test: these were strictly macros before

 - improve the documentation to make it very clear exactly which types
   of pointers these operations may be used with

 - remove a few uses of the now-deprecated g_atomic_int_exchange_and_add

 - drop initialisation of gatomic from gthread (by using a GStaticMutex
   instead of a GMutex)

 - update glib.symbols and documentation sections files

Closes #650823 and #650935

docs/reference/glib/glib-sections.txt
glib/Makefile.am
glib/gatomic-gcc.c [deleted file]
glib/gatomic.c
glib/gatomic.h
glib/glib.symbols
glib/gthread.c
glib/gthreadpool.c
glib/tests/atomic.c
gobject/gobject.c

index f1a8c4f598abd93d469f42a406c6f6bfb68a74fb..a290ac1e6e294fd2ff3a398e8464c97643362868 100644 (file)
@@ -759,17 +759,28 @@ g_async_queue_sort_unlocked
 
 <SECTION>
 <TITLE>Atomic Operations</TITLE>
-<FILE>atomic_operations</FILE>g
+<FILE>atomic_operations</FILE>
 g_atomic_int_get
 g_atomic_int_set
-g_atomic_int_add
-g_atomic_int_exchange_and_add
+g_atomic_int_inc
+g_atomic_int_dec_and_test
 g_atomic_int_compare_and_exchange
+g_atomic_int_add
+g_atomic_int_and
+g_atomic_int_or
+g_atomic_int_xor
+
+<SUBSECTION>
 g_atomic_pointer_get
 g_atomic_pointer_set
 g_atomic_pointer_compare_and_exchange
-g_atomic_int_inc
-g_atomic_int_dec_and_test
+g_atomic_pointer_add
+g_atomic_pointer_and
+g_atomic_pointer_or
+g_atomic_pointer_xor
+
+<SUBSECTION>
+g_atomic_int_exchange_and_add
 
 <SUBSECTION Private>
 G_ATOMIC_OP_MEMORY_BARRIER_NEEDED
index d0da7b21a9939fa4b2cc6c82be8a76d91bfba730..7d333a8120ac1c9a8dc4a086381560e12475d2e2 100644 (file)
@@ -42,12 +42,6 @@ gregex_c =
 gregex_h =
 endif
 
-if HAVE_GCC_BUILTINS_FOR_ATOMIC_OPERATIONS
-gatomic_c = gatomic-gcc.c
-else
-gatomic_c = gatomic.c
-endif
-
 SUBDIRS = libcharset $(PRINTF_SUBDIR) $(MAYBE_PCRE) update-pcre . tests
 
 DIST_SUBDIRS = libcharset gnulib pcre update-pcre tests
@@ -121,7 +115,7 @@ libglib_2_0_la_SOURCES =    \
        glib_probes.d           \
        garray.c                \
        gasyncqueue.c           \
-       $(gatomic_c)            \
+       gatomic.c               \
        gbacktrace.c            \
        gbase64.c               \
        gbitlock.c              \
diff --git a/glib/gatomic-gcc.c b/glib/gatomic-gcc.c
deleted file mode 100644 (file)
index 09cd3aa..0000000
+++ /dev/null
@@ -1,104 +0,0 @@
-/* GLIB - Library of useful routines for C programming
- * gatomic-gcc.c: atomic operations using GCC builtins.
- * Copyright (C) 2009 Hiroyuki Ikezoe
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-#include "config.h"
-
-#include "gatomic.h"
-
-/* All atomic operations are available as macros evaluating
- * to gcc builtins (when using gcc builtins for atomic operations).
- * For ABI stability, we provide functions for them too.
- *
- * To avoid interference, undefine the macros first.
- */
-
-#undef g_atomic_int_exchange_and_add
-#undef g_atomic_int_compare_and_exchange
-#undef g_atomic_int_add
-#undef g_atomic_int_get
-#undef g_atomic_int_set
-#undef g_atomic_pointer_compare_and_exchange
-#undef g_atomic_pointer_get
-#undef g_atomic_pointer_set
-
-gint
-g_atomic_int_exchange_and_add (volatile gint G_GNUC_MAY_ALIAS *atomic,
-                               gint                            val)
-{
-  return __sync_fetch_and_add (atomic, val);
-}
-
-void
-g_atomic_int_add (volatile gint G_GNUC_MAY_ALIAS *atomic,
-                  gint                            val)
-{
-  __sync_fetch_and_add (atomic, val);
-}
-
-gboolean
-g_atomic_int_compare_and_exchange (volatile gint G_GNUC_MAY_ALIAS *atomic,
-                                   gint                            oldval,
-                                   gint                            newval)
-{
-  return __sync_bool_compare_and_swap (atomic, oldval, newval);
-}
-
-gboolean
-g_atomic_pointer_compare_and_exchange (volatile gpointer G_GNUC_MAY_ALIAS *atomic,
-                                       gpointer                            oldval,
-                                       gpointer                            newval)
-{
-  return __sync_bool_compare_and_swap (atomic, oldval, newval);
-}
-
-void
-_g_atomic_thread_init (void)
-{
-}
-
-gint
-g_atomic_int_get (volatile gint G_GNUC_MAY_ALIAS *atomic)
-{
-  __sync_synchronize ();
-  return *atomic;
-}
-
-void
-g_atomic_int_set (volatile gint G_GNUC_MAY_ALIAS *atomic,
-                  gint                            newval)
-{
-  *atomic = newval;
-  __sync_synchronize ();
-}
-
-gpointer
-g_atomic_pointer_get (volatile gpointer G_GNUC_MAY_ALIAS *atomic)
-{
-  __sync_synchronize ();
-  return *atomic;
-}
-
-void
-g_atomic_pointer_set (volatile gpointer G_GNUC_MAY_ALIAS *atomic,
-                      gpointer                            newval)
-{
-  *atomic = newval;
-  __sync_synchronize ();
-}
index f90eb059cde1379f19398fe1c4eaaec29b80f804..0da78b96230b20162083f913da381ab1555dc600 100644 (file)
@@ -1,35 +1,27 @@
-/* GLIB - Library of useful routines for C programming
- * Copyright (C) 1995-1997  Peter Mattis, Spencer Kimball and Josh MacDonald
+/*
+ * Copyright © 2011 Ryan Lortie
  *
- * g_atomic_*: atomic operations.
- * Copyright (C) 2003 Sebastian Wilhelmi
- * Copyright (C) 2007 Nokia Corporation
+ * This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * licence, or (at your option) any later version.
  *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  * Lesser General Public License for more details.
  *
  * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ * USA.
+ *
+ * Author: Ryan Lortie <desrt@desrt.ca>
  */
 
 #include "config.h"
 
-#if defined (G_ATOMIC_ARM)
-#include <sched.h>
-#endif
-
 #include "gatomic.h"
-#include "gthread.h"
-#include "gthreadprivate.h"
 
 /**
  * SECTION:atomic_operations
  * @short_description: basic atomic integer and pointer operations
  * @see_also: #GMutex
  *
- * The following functions can be used to atomically access integers and
- * pointers. They are implemented as inline assembler function on most
- * platforms and use slower fall-backs otherwise. Using them can sometimes
- * save you from using a performance-expensive #GMutex to protect the
- * integer or pointer.
- *
- * The most important usage is reference counting. Using
- * g_atomic_int_inc() and g_atomic_int_dec_and_test() makes reference
- * counting a very fast operation.
- *
- * <note><para>You must not directly read integers or pointers concurrently
- * accessed by multiple threads, but use the atomic accessor functions
- * instead. That is, always use g_atomic_int_get() and g_atomic_pointer_get()
- * for read outs. They provide the neccessary synchonization mechanisms
- * like memory barriers to access memory locations concurrently.
- * </para></note>
- *
- * <note><para>If you are using those functions for anything apart from
- * simple reference counting, you should really be aware of the implications
- * of doing that. There are literally thousands of ways to shoot yourself
- * in the foot. So if in doubt, use a #GMutex. If you don't know, what
- * memory barriers are, do not use anything but g_atomic_int_inc() and
- * g_atomic_int_dec_and_test().
- * </para></note>
- *
- * <note><para>It is not safe to set an integer or pointer just by assigning
- * to it, when it is concurrently accessed by other threads with the following
- * functions. Use g_atomic_int_compare_and_exchange() or
- * g_atomic_pointer_compare_and_exchange() respectively.
- * </para></note>
- */
+ * The following is a collection of compiler macros to provide atomic
+ * access to integer and pointer-sized values.
+ *
+ * The macros that have 'int' in the name will operate on pointers to
+ * #gint and #guint.  The macros with 'pointer' in the name will operate
+ * on pointers to any pointer-sized value, including #gsize.  There is
+ * no support for 64bit operations on platforms with 32bit pointers
+ * because it is not generally possible to perform these operations
+ * atomically.
+ *
+ * The get, set and exchange operations for integers and pointers
+ * nominally operate on #gint and #gpointer, respectively.  Of the
+ * arithmetic operations, the 'add' operation operates on (and returns)
+ * signed integer values (#gint and #gssize) and the 'and', 'or', and
+ * 'xor' operations operate on (and return) unsigned integer values
+ * (#guint and #gsize).
+ *
+ * All of the operations act as a full compiler and (where appropriate)
+ * 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
+ * read or assign directly from or to a value -- always use this API.
+ *
+ * For simple reference counting purposes you should use
+ * g_atomic_int_inc() and g_atomic_int_dec_and_test().  Other uses that
+ * fall outside of simple reference counting patterns are prone to
+ * subtle bugs and occasionally undefined behaviour.  It is also worth
+ * noting that since all of these operations require global
+ * synchronisation of the entire machine, they can be quite slow.  In
+ * the case of performing multiple atomic operations it can often be
+ * faster to simply acquire a mutex lock around the critical area,
+ * perform the operations normally and then release the lock.
+ **/
+
+#ifdef G_ATOMIC_OP_USE_GCC_BUILTINS
+
+#ifndef __GNUC__
+#error Using GCC builtin atomic ops, but not compiling with GCC?
+#endif
 
-#if defined (__GNUC__)
-# if defined (G_ATOMIC_I486)
-/* Adapted from CVS version 1.10 of glibc's sysdeps/i386/i486/bits/atomic.h 
- */
+/**
+ * g_atomic_int_get:
+ * @atomic: a pointer to a #gint or #guint
+ *
+ * Gets the current value of @atomic.
+ *
+ * This call acts as a full compiler and hardware memory barrier (before
+ * the get).
+ *
+ * Returns: the value of the integer
+ *
+ * Since: 2.4
+ **/
 gint
-g_atomic_int_exchange_and_add (volatile gint G_GNUC_MAY_ALIAS *atomic, 
-                              gint           val)
+(g_atomic_int_get) (volatile gint *atomic)
 {
-  gint result;
-
-  __asm__ __volatile__ ("lock; xaddl %0,%1"
-                        : "=r" (result), "=m" (*atomic) 
-                       : "0" (val), "m" (*atomic));
-  return result;
+  return g_atomic_int_get (atomic);
 }
+
+/**
+ * g_atomic_int_set:
+ * @atomic: a pointer to a #gint or #guint
+ * @newval: a new value to store
+ *
+ * Sets the value of @atomic to @newval.
+ *
+ * This call acts as a full compiler and hardware memory barrier (after
+ * the set).
+ *
+ * Since: 2.4
+ **/
 void
-g_atomic_int_add (volatile gint G_GNUC_MAY_ALIAS *atomic, 
-                 gint           val)
+(g_atomic_int_set) (volatile gint *atomic,
+                    gint           newval)
 {
-  __asm__ __volatile__ ("lock; addl %1,%0"
-                       : "=m" (*atomic) 
-                       : "ir" (val), "m" (*atomic));
+  g_atomic_int_set (atomic, newval);
 }
 
-gboolean
-g_atomic_int_compare_and_exchange (volatile gint G_GNUC_MAY_ALIAS *atomic, 
-                                  gint           oldval, 
-                                  gint           newval)
+/**
+ * g_atomic_int_inc:
+ * @atomic: a pointer to a #gint or #guint
+ *
+ * Increments the value of @atomic by 1.
+ *
+ * This call acts as a full compiler and hardware memory barrier.
+ *
+ * Since: 2.4
+ **/
+void
+(g_atomic_int_inc) (volatile gint *atomic)
 {
-  gint result;
-  __asm__ __volatile__ ("lock; cmpxchgl %2, %1"
-                       : "=a" (result), "=m" (*atomic)
-                       : "r" (newval), "m" (*atomic), "0" (oldval)); 
-
-  return result == oldval;
+  g_atomic_int_inc (atomic);
 }
 
-/* The same code as above, as on i386 gpointer is 32 bit as well.
- * Duplicating the code here seems more natural than casting the
- * arguments and calling the former function */
-
+/**
+ * g_atomic_int_dec_and_test:
+ * @atomic: a pointer to a #gint or #guint
+ *
+ * Decrements the value of @atomic by 1.
+ *
+ * This call acts as a full compiler and hardware memory barrier.
+ *
+ * Returns: %TRUE if the resultant value is zero
+ *
+ * Since: 2.4
+ **/
 gboolean
-g_atomic_pointer_compare_and_exchange (volatile gpointer G_GNUC_MAY_ALIAS *atomic, 
-                                      gpointer           oldval, 
-                                      gpointer           newval)
+(g_atomic_int_dec_and_test) (volatile gint *atomic)
 {
-  gpointer result;
-  __asm__ __volatile__ ("lock; cmpxchgl %2, %1"
-                       : "=a" (result), "=m" (*atomic)
-                       : "r" (newval), "m" (*atomic), "0" (oldval)); 
-
-  return result == oldval;
+  return g_atomic_int_dec_and_test (atomic);
 }
 
-# elif defined (G_ATOMIC_SPARCV9)
-/* Adapted from CVS version 1.3 of glibc's sysdeps/sparc/sparc64/bits/atomic.h
- */
-#  define ATOMIC_INT_CMP_XCHG(atomic, oldval, newval)                  \
-  ({                                                                   \
-     gint __result;                                                    \
-     __asm__ __volatile__ ("cas [%4], %2, %0"                          \
-                           : "=r" (__result), "=m" (*(atomic))         \
-                           : "r" (oldval), "m" (*(atomic)), "r" (atomic),\
-                           "0" (newval));                              \
-     __result == oldval;                                               \
-  })
-
-#  if GLIB_SIZEOF_VOID_P == 4 /* 32-bit system */
-gboolean
-g_atomic_pointer_compare_and_exchange (volatile gpointer G_GNUC_MAY_ALIAS *atomic, 
-                                      gpointer           oldval, 
-                                      gpointer           newval)
-{
-  gpointer result;
-  __asm__ __volatile__ ("cas [%4], %2, %0"
-                       : "=r" (result), "=m" (*atomic)
-                       : "r" (oldval), "m" (*atomic), "r" (atomic),
-                       "0" (newval));
-  return result == oldval;
-}
-#  elif GLIB_SIZEOF_VOID_P == 8 /* 64-bit system */
-gboolean
-g_atomic_pointer_compare_and_exchange (volatile gpointer G_GNUC_MAY_ALIAS *atomic, 
-                                      gpointer           oldval, 
-                                      gpointer           newval)
-{
-  gpointer result;
-  gpointer *a = atomic;
-  __asm__ __volatile__ ("casx [%4], %2, %0"
-                       : "=r" (result), "=m" (*a)
-                       : "r" (oldval), "m" (*a), "r" (a),
-                       "0" (newval));
-  return result == oldval;
-}
-#  else /* What's that */
-#    error "Your system has an unsupported pointer size"
-#  endif /* GLIB_SIZEOF_VOID_P */
-#  define G_ATOMIC_MEMORY_BARRIER                                      \
-  __asm__ __volatile__ ("membar #LoadLoad | #LoadStore"                        \
-                        " | #StoreLoad | #StoreStore" : : : "memory")
-
-# elif defined (G_ATOMIC_ALPHA)
-/* Adapted from CVS version 1.3 of glibc's sysdeps/alpha/bits/atomic.h
- */
-#  define ATOMIC_INT_CMP_XCHG(atomic, oldval, newval)                  \
-  ({                                                                   \
-     gint __result;                                                    \
-     gint __prev;                                                      \
-     __asm__ __volatile__ (                                            \
-        "       mb\n"                                                  \
-        "1:     ldl_l   %0,%2\n"                                       \
-        "       cmpeq   %0,%3,%1\n"                                    \
-        "       beq     %1,2f\n"                                       \
-        "       mov     %4,%1\n"                                       \
-        "       stl_c   %1,%2\n"                                       \
-        "       beq     %1,1b\n"                                       \
-        "       mb\n"                                                  \
-        "2:"                                                           \
-        : "=&r" (__prev),                                              \
-          "=&r" (__result)                                             \
-        : "m" (*(atomic)),                                             \
-          "Ir" (oldval),                                               \
-          "Ir" (newval)                                                        \
-        : "memory");                                                   \
-     __result != 0;                                                    \
-  })
-#  if GLIB_SIZEOF_VOID_P == 4 /* 32-bit system */
-gboolean
-g_atomic_pointer_compare_and_exchange (volatile gpointer G_GNUC_MAY_ALIAS *atomic, 
-                                      gpointer           oldval, 
-                                      gpointer           newval)
-{
-  gint result;
-  gpointer prev;
-  __asm__ __volatile__ (
-        "       mb\n"
-        "1:     ldl_l   %0,%2\n"
-        "       cmpeq   %0,%3,%1\n"
-        "       beq     %1,2f\n"
-        "       mov     %4,%1\n"
-        "       stl_c   %1,%2\n"
-        "       beq     %1,1b\n"
-        "       mb\n"
-        "2:"
-        : "=&r" (prev), 
-          "=&r" (result)
-        : "m" (*atomic),
-          "Ir" (oldval),
-          "Ir" (newval)
-        : "memory");
-  return result != 0;
-}
-#  elif GLIB_SIZEOF_VOID_P == 8 /* 64-bit system */
+/**
+ * g_atomic_int_compare_and_exchange:
+ * @atomic: a pointer to a #gint or #guint
+ * @oldval: the value to compare with
+ * @newval: the value to conditionally replace with
+ *
+ * Compares @atomic to @oldval and, if equal, sets it to @newval.  If
+ * @atomic was not equal to @oldval then no change occurs.
+ *
+ * This compare and exchange is done atomically.
+ *
+ * This call acts as a full compiler and hardware memory barrier.
+ *
+ * Returns: %TRUE if the exchange took place
+ *
+ * Since: 2.4
+ **/
 gboolean
-g_atomic_pointer_compare_and_exchange (volatile gpointer G_GNUC_MAY_ALIAS *atomic, 
-                                      gpointer           oldval, 
-                                      gpointer           newval)
+(g_atomic_int_compare_and_exchange) (volatile gint *atomic,
+                                     gint           oldval,
+                                     gint           newval)
 {
-  gint result;
-  gpointer prev;
-  __asm__ __volatile__ (
-        "       mb\n"
-        "1:     ldq_l   %0,%2\n"
-        "       cmpeq   %0,%3,%1\n"
-        "       beq     %1,2f\n"
-        "       mov     %4,%1\n"
-        "       stq_c   %1,%2\n"
-        "       beq     %1,1b\n"
-        "       mb\n"
-        "2:"
-        : "=&r" (prev), 
-          "=&r" (result)
-        : "m" (*atomic),
-          "Ir" (oldval),
-          "Ir" (newval)
-        : "memory");
-  return result != 0;
+  return g_atomic_int_compare_and_exchange (atomic, oldval, newval);
 }
-#  else /* What's that */
-#   error "Your system has an unsupported pointer size"
-#  endif /* GLIB_SIZEOF_VOID_P */
-#  define G_ATOMIC_MEMORY_BARRIER  __asm__ ("mb" : : : "memory")
-# elif defined (G_ATOMIC_X86_64)
-/* Adapted from CVS version 1.9 of glibc's sysdeps/x86_64/bits/atomic.h 
- */
+
+/**
+ * g_atomic_int_add:
+ * @atomic: a pointer to a #gint or #guint
+ * @val: the value to add
+ *
+ * Atomically adds @val to the value of @atomic.
+ *
+ * This call acts as a full compiler and hardware memory barrier.
+ *
+ * Returns: the value of @atomic before the add, signed
+ *
+ * Since: 2.4
+ **/
 gint
-g_atomic_int_exchange_and_add (volatile gint G_GNUC_MAY_ALIAS *atomic,
-                              gint           val)
+(g_atomic_int_add) (volatile gint *atomic,
+                    gint           val)
 {
-  gint result;
-
-  __asm__ __volatile__ ("lock; xaddl %0,%1"
-                        : "=r" (result), "=m" (*atomic) 
-                       : "0" (val), "m" (*atomic));
-  return result;
+  return g_atomic_int_add (atomic, val);
 }
-void
-g_atomic_int_add (volatile gint G_GNUC_MAY_ALIAS *atomic, 
-                 gint           val)
+
+/**
+ * g_atomic_int_and:
+ * @atomic: a pointer to a #gint or #guint
+ * @val: the value to 'and'
+ *
+ * Performs an atomic bitwise 'and' of the value of @atomic and @val,
+ * storing the result back in @atomic.
+ *
+ * This call acts as a full compiler and hardware memory barrier.
+ *
+ * Returns: the value of @atomic before the operation, unsigned
+ *
+ * Since: 2.30
+ **/
+guint
+(g_atomic_int_and) (volatile guint *atomic,
+                    guint           val)
 {
-  __asm__ __volatile__ ("lock; addl %1,%0"
-                       : "=m" (*atomic) 
-                       : "ir" (val), "m" (*atomic));
+  return g_atomic_int_and (atomic, val);
 }
 
-gboolean
-g_atomic_int_compare_and_exchange (volatile gint G_GNUC_MAY_ALIAS *atomic, 
-                                  gint           oldval, 
-                                  gint           newval)
+/**
+ * g_atomic_int_or:
+ * @atomic: a pointer to a #gint or #guint
+ * @val: the value to 'or'
+ *
+ * Performs an atomic bitwise 'or' of the value of @atomic and @val,
+ * storing the result back in @atomic.
+ *
+ * This call acts as a full compiler and hardware memory barrier.
+ *
+ * Returns: the value of @atomic before the operation, unsigned
+ *
+ * Since: 2.30
+ **/
+guint
+(g_atomic_int_or) (volatile guint *atomic,
+                   guint           val)
 {
-  gint result;
-  __asm__ __volatile__ ("lock; cmpxchgl %2, %1"
-                       : "=a" (result), "=m" (*atomic)
-                       : "r" (newval), "m" (*atomic), "0" (oldval)); 
-
-  return result == oldval;
+  return g_atomic_int_or (atomic, val);
 }
 
-gboolean
-g_atomic_pointer_compare_and_exchange (volatile gpointer G_GNUC_MAY_ALIAS *atomic, 
-                                      gpointer           oldval, 
-                                      gpointer           newval)
+/**
+ * g_atomic_int_xor:
+ * @atomic: a pointer to a #gint or #guint
+ * @val: the value to 'xor'
+ *
+ * Performs an atomic bitwise 'xor' of the value of @atomic and @val,
+ * storing the result back in @atomic.
+ *
+ * This call acts as a full compiler and hardware memory barrier.
+ *
+ * Returns: the value of @atomic before the operation, unsigned
+ *
+ * Since: 2.30
+ **/
+guint
+(g_atomic_int_xor) (volatile guint *atomic,
+                    guint           val)
 {
-  gpointer result;
-  __asm__ __volatile__ ("lock; cmpxchgq %q2, %1"
-                       : "=a" (result), "=m" (*atomic)
-                       : "r" (newval), "m" (*atomic), "0" (oldval)); 
-
-  return result == oldval;
+  return g_atomic_int_xor (atomic, val);
 }
 
-# elif defined (G_ATOMIC_POWERPC)
-/* Adapted from CVS version 1.16 of glibc's sysdeps/powerpc/bits/atomic.h 
- * and CVS version 1.4 of glibc's sysdeps/powerpc/powerpc32/bits/atomic.h 
- * and CVS version 1.7 of glibc's sysdeps/powerpc/powerpc64/bits/atomic.h 
- */
-#   ifdef __OPTIMIZE__
-/* Non-optimizing compile bails on the following two asm statements
- * for reasons unknown to the author */
-gint
-g_atomic_int_exchange_and_add (volatile gint G_GNUC_MAY_ALIAS *atomic, 
-                              gint           val)
+
+/**
+ * g_atomic_pointer_get:
+ * @atomic: a pointer to a #gpointer-sized value
+ *
+ * Gets the current value of @atomic.
+ *
+ * This call acts as a full compiler and hardware memory barrier (before
+ * the get).
+ *
+ * Returns: the value of the pointer
+ *
+ * Since: 2.4
+ **/
+gpointer
+(g_atomic_pointer_get) (volatile void *atomic)
 {
-  gint result, temp;
-#if ASM_NUMERIC_LABELS
-  __asm__ __volatile__ ("1:       lwarx   %0,0,%3\n"
-                       "         add     %1,%0,%4\n"
-                       "         stwcx.  %1,0,%3\n"
-                       "         bne-    1b"
-                       : "=&b" (result), "=&r" (temp), "=m" (*atomic)
-                       : "b" (atomic), "r" (val), "m" (*atomic)
-                       : "cr0", "memory");
-#else
-  __asm__ __volatile__ (".Lieaa%=:       lwarx   %0,0,%3\n"
-                       "         add     %1,%0,%4\n"
-                       "         stwcx.  %1,0,%3\n"
-                       "         bne-    .Lieaa%="
-                       : "=&b" (result), "=&r" (temp), "=m" (*atomic)
-                       : "b" (atomic), "r" (val), "m" (*atomic)
-                       : "cr0", "memory");
-#endif
-  return result;
+  return g_atomic_pointer_get ((volatile gpointer *) atomic);
 }
-/* The same as above, to save a function call repeated here */
+
+/**
+ * g_atomic_pointer_set:
+ * @atomic: a pointer to a #gpointer-sized value
+ * @newval: a new value to store
+ *
+ * Sets the value of @atomic to @newval.
+ *
+ * This call acts as a full compiler and hardware memory barrier (after
+ * the set).
+ *
+ * Since: 2.4
+ **/
 void
-g_atomic_int_add (volatile gint G_GNUC_MAY_ALIAS *atomic, 
-                 gint           val)
+(g_atomic_pointer_set) (volatile void *atomic,
+                        gpointer       newval)
 {
-  gint result, temp;  
-#if ASM_NUMERIC_LABELS
-  __asm__ __volatile__ ("1:       lwarx   %0,0,%3\n"
-                       "         add     %1,%0,%4\n"
-                       "         stwcx.  %1,0,%3\n"
-                       "         bne-    1b"
-                       : "=&b" (result), "=&r" (temp), "=m" (*atomic)
-                       : "b" (atomic), "r" (val), "m" (*atomic)
-                       : "cr0", "memory");
-#else
-  __asm__ __volatile__ (".Lia%=:       lwarx   %0,0,%3\n"
-                       "         add     %1,%0,%4\n"
-                       "         stwcx.  %1,0,%3\n"
-                       "         bne-    .Lia%="
-                       : "=&b" (result), "=&r" (temp), "=m" (*atomic)
-                       : "b" (atomic), "r" (val), "m" (*atomic)
-                       : "cr0", "memory");
-#endif
+  g_atomic_pointer_set ((volatile gpointer *) atomic, newval);
 }
-#   else /* !__OPTIMIZE__ */
-gint
-g_atomic_int_exchange_and_add (volatile gint G_GNUC_MAY_ALIAS *atomic, 
-                              gint           val)
-{
-  gint result;
-  do
-    result = *atomic;
-  while (!g_atomic_int_compare_and_exchange (atomic, result, result + val));
 
-  return result;
-}
-void
-g_atomic_int_add (volatile gint G_GNUC_MAY_ALIAS *atomic,
-                 gint           val)
+/**
+ * g_atomic_pointer_compare_and_exchange:
+ * @atomic: a pointer to a #gpointer-sized value
+ * @oldval: the value to compare with
+ * @newval: the value to conditionally replace with
+ *
+ * Compares @atomic to @oldval and, if equal, sets it to @newval.  If
+ * @atomic was not equal to @oldval then no change occurs.
+ *
+ * This compare and exchange is done atomically.
+ *
+ * This call acts as a full compiler and hardware memory barrier.
+ *
+ * Returns: %TRUE if the exchange took place
+ *
+ * Since: 2.4
+ **/
+gboolean
+(g_atomic_pointer_compare_and_exchange) (volatile void *atomic,
+                                         gpointer       oldval,
+                                         gpointer       newval)
 {
-  gint result;
-  do
-    result = *atomic;
-  while (!g_atomic_int_compare_and_exchange (atomic, result, result + val));
+  return g_atomic_pointer_compare_and_exchange ((volatile gpointer *) atomic,
+                                                oldval, newval);
 }
-#   endif /* !__OPTIMIZE__ */
 
-#   if GLIB_SIZEOF_VOID_P == 4 /* 32-bit system */
-gboolean
-g_atomic_int_compare_and_exchange (volatile gint G_GNUC_MAY_ALIAS *atomic, 
-                                  gint           oldval, 
-                                  gint           newval)
+/**
+ * g_atomic_pointer_add:
+ * @atomic: a pointer to a #gpointer-sized value
+ * @val: the value to add
+ *
+ * Atomically adds @val to the value of @atomic.
+ *
+ * This call acts as a full compiler and hardware memory barrier.
+ *
+ * Returns: the value of @atomic before the add, signed
+ *
+ * Since: 2.30
+ **/
+gssize
+(g_atomic_pointer_add) (volatile void *atomic,
+                        gssize         val)
 {
-  gint result;
-#if ASM_NUMERIC_LABELS
-  __asm__ __volatile__ ("sync\n"
-                       "1: lwarx   %0,0,%1\n"
-                       "   subf.   %0,%2,%0\n"
-                       "   bne     2f\n"
-                       "   stwcx.  %3,0,%1\n"
-                       "   bne-    1b\n"
-                       "2: isync"
-                       : "=&r" (result)
-                       : "b" (atomic), "r" (oldval), "r" (newval)
-                       : "cr0", "memory"); 
-#else
-  __asm__ __volatile__ ("sync\n"
-                       ".L1icae%=: lwarx   %0,0,%1\n"
-                       "   subf.   %0,%2,%0\n"
-                       "   bne     .L2icae%=\n"
-                       "   stwcx.  %3,0,%1\n"
-                       "   bne-    .L1icae%=\n"
-                       ".L2icae%=: isync"
-                       : "=&r" (result)
-                       : "b" (atomic), "r" (oldval), "r" (newval)
-                       : "cr0", "memory"); 
-#endif
-  return result == 0;
+  return g_atomic_pointer_add ((volatile gpointer *) atomic, val);
 }
 
-gboolean
-g_atomic_pointer_compare_and_exchange (volatile gpointer G_GNUC_MAY_ALIAS *atomic, 
-                                      gpointer           oldval, 
-                                      gpointer           newval)
+/**
+ * g_atomic_pointer_and:
+ * @atomic: a pointer to a #gpointer-sized value
+ * @val: the value to 'and'
+ *
+ * Performs an atomic bitwise 'and' of the value of @atomic and @val,
+ * storing the result back in @atomic.
+ *
+ * This call acts as a full compiler and hardware memory barrier.
+ *
+ * Returns: the value of @atomic before the operation, unsigned
+ *
+ * Since: 2.30
+ **/
+gsize
+(g_atomic_pointer_and) (volatile void *atomic,
+                        gsize          val)
 {
-  gpointer result;
-#if ASM_NUMERIC_LABELS
-  __asm__ __volatile__ ("sync\n"
-                       "1: lwarx   %0,0,%1\n"
-                       "   subf.   %0,%2,%0\n"
-                       "   bne     2f\n"
-                       "   stwcx.  %3,0,%1\n"
-                       "   bne-    1b\n"
-                       "2: isync"
-                       : "=&r" (result)
-                       : "b" (atomic), "r" (oldval), "r" (newval)
-                       : "cr0", "memory"); 
-#else
-  __asm__ __volatile__ ("sync\n"
-                       ".L1pcae%=: lwarx   %0,0,%1\n"
-                       "   subf.   %0,%2,%0\n"
-                       "   bne     .L2pcae%=\n"
-                       "   stwcx.  %3,0,%1\n"
-                       "   bne-    .L1pcae%=\n"
-                       ".L2pcae%=: isync"
-                       : "=&r" (result)
-                       : "b" (atomic), "r" (oldval), "r" (newval)
-                       : "cr0", "memory"); 
-#endif
-  return result == 0;
+  return g_atomic_pointer_and ((volatile gpointer *) atomic, val);
 }
-#   elif GLIB_SIZEOF_VOID_P == 8 /* 64-bit system */
-gboolean
-g_atomic_int_compare_and_exchange (volatile gint G_GNUC_MAY_ALIAS *atomic,
-                                  gint           oldval, 
-                                  gint           newval)
+
+/**
+ * g_atomic_pointer_or:
+ * @atomic: a pointer to a #gpointer-sized value
+ * @val: the value to 'or'
+ *
+ * Performs an atomic bitwise 'or' of the value of @atomic and @val,
+ * storing the result back in @atomic.
+ *
+ * This call acts as a full compiler and hardware memory barrier.
+ *
+ * Returns: the value of @atomic before the operation, unsigned
+ *
+ * Since: 2.30
+ **/
+gsize
+(g_atomic_pointer_or) (volatile void *atomic,
+                       gsize          val)
 {
-  gpointer result;
-#if ASM_NUMERIC_LABELS
-  __asm__ __volatile__ ("sync\n"
-                       "1: lwarx   %0,0,%1\n"
-                       "   extsw   %0,%0\n"
-                       "   subf.   %0,%2,%0\n"
-                       "   bne     2f\n"
-                       "   stwcx.  %3,0,%1\n"
-                       "   bne-    1b\n"
-                       "2: isync"
-                       : "=&r" (result)
-                       : "b" (atomic), "r" (oldval), "r" (newval)
-                       : "cr0", "memory"); 
-#else
-  __asm__ __volatile__ ("sync\n"
-                       ".L1icae%=: lwarx   %0,0,%1\n"
-                       "   extsw   %0,%0\n"
-                       "   subf.   %0,%2,%0\n"
-                       "   bne     .L2icae%=\n"
-                       "   stwcx.  %3,0,%1\n"
-                       "   bne-    .L1icae%=\n"
-                       ".L2icae%=: isync"
-                       : "=&r" (result)
-                       : "b" (atomic), "r" (oldval), "r" (newval)
-                       : "cr0", "memory"); 
-#endif
-  return result == 0;
+  return g_atomic_pointer_or ((volatile gpointer *) atomic, val);
 }
 
-gboolean
-g_atomic_pointer_compare_and_exchange (volatile gpointer G_GNUC_MAY_ALIAS *atomic, 
-                                      gpointer           oldval, 
-                                      gpointer           newval)
+/**
+ * g_atomic_pointer_xor:
+ * @atomic: a pointer to a #gpointer-sized value
+ * @val: the value to 'xor'
+ *
+ * Performs an atomic bitwise 'xor' of the value of @atomic and @val,
+ * storing the result back in @atomic.
+ *
+ * This call acts as a full compiler and hardware memory barrier.
+ *
+ * Returns: the value of @atomic before the operation, unsigned
+ *
+ * Since: 2.30
+ **/
+gsize
+(g_atomic_pointer_xor) (volatile void *atomic,
+                        gsize          val)
 {
-  gpointer result;
-#if ASM_NUMERIC_LABELS
-  __asm__ __volatile__ ("sync\n"
-                       "1: ldarx   %0,0,%1\n"
-                       "   subf.   %0,%2,%0\n"
-                       "   bne     2f\n"
-                       "   stdcx.  %3,0,%1\n"
-                       "   bne-    1b\n"
-                       "2: isync"
-                       : "=&r" (result)
-                       : "b" (atomic), "r" (oldval), "r" (newval)
-                       : "cr0", "memory"); 
-#else
-  __asm__ __volatile__ ("sync\n"
-                       ".L1pcae%=: ldarx   %0,0,%1\n"
-                       "   subf.   %0,%2,%0\n"
-                       "   bne     .L2pcae%=\n"
-                       "   stdcx.  %3,0,%1\n"
-                       "   bne-    .L1pcae%=\n"
-                       ".L2pcae%=: isync"
-                       : "=&r" (result)
-                       : "b" (atomic), "r" (oldval), "r" (newval)
-                       : "cr0", "memory"); 
-#endif
-  return result == 0;
+  return g_atomic_pointer_xor ((volatile gpointer *) atomic, val);
 }
-#  else /* What's that */
-#   error "Your system has an unsupported pointer size"
-#  endif /* GLIB_SIZEOF_VOID_P */
 
-#  define G_ATOMIC_MEMORY_BARRIER __asm__ ("sync" : : : "memory")
+#elif defined (G_PLATFORM_WIN32)
 
-# elif defined (G_ATOMIC_IA64)
-/* Adapted from CVS version 1.8 of glibc's sysdeps/ia64/bits/atomic.h
+/*
+ * http://msdn.microsoft.com/en-us/library/ms684122(v=vs.85).aspx
  */
 gint
-g_atomic_int_exchange_and_add (volatile gint G_GNUC_MAY_ALIAS *atomic,
-                              gint           val)
+(g_atomic_int_get) (volatile gint *atomic)
 {
-  return __sync_fetch_and_add (atomic, val);
+  MemoryBarrier ();
+  return *atomic;
 }
+
 void
-g_atomic_int_add (volatile gint G_GNUC_MAY_ALIAS *atomic, 
-                 gint val)
+(g_atomic_int_set) (volatile gint *atomic,
+                    gint           newval)
 {
-  __sync_fetch_and_add (atomic, val);
+  *atomic = newval;
+  MemoryBarrier ();
 }
 
-gboolean
-g_atomic_int_compare_and_exchange (volatile gint G_GNUC_MAY_ALIAS *atomic,
-                                  gint           oldval, 
-                                  gint           newval)
+void
+(g_atomic_int_inc) (volatile gint *atomic)
 {
-  return __sync_bool_compare_and_swap (atomic, oldval, newval);
+  InterlockedIncrement (atomic);
 }
 
 gboolean
-g_atomic_pointer_compare_and_exchange (volatile gpointer G_GNUC_MAY_ALIAS *atomic,
-                                      gpointer           oldval, 
-                                      gpointer           newval)
+(g_atomic_int_dec_and_test) (volatile gint *atomic)
 {
-  return __sync_bool_compare_and_swap ((long *)atomic, 
-                                      (long)oldval, (long)newval);
+  return InterlockedDecrement (atomic) == 0;
 }
 
-#  define G_ATOMIC_MEMORY_BARRIER __sync_synchronize ()
-# elif defined (G_ATOMIC_S390)
-/* Adapted from glibc's sysdeps/s390/bits/atomic.h
- */
-#  define ATOMIC_INT_CMP_XCHG(atomic, oldval, newval)                  \
-  ({                                                                   \
-     gint __result = oldval;                                   \
-     __asm__ __volatile__ ("cs %0, %2, %1"                             \
-                           : "+d" (__result), "=Q" (*(atomic))         \
-                           : "d" (newval), "m" (*(atomic)) : "cc" );   \
-     __result == oldval;                                               \
-  })
-
-#  if GLIB_SIZEOF_VOID_P == 4 /* 32-bit system */
 gboolean
-g_atomic_pointer_compare_and_exchange (volatile gpointer G_GNUC_MAY_ALIAS *atomic,
-                                      gpointer           oldval,
-                                      gpointer           newval)
-{
-  gpointer result = oldval;
-  __asm__ __volatile__ ("cs %0, %2, %1"
-                       : "+d" (result), "=Q" (*(atomic))
-                       : "d" (newval), "m" (*(atomic)) : "cc" );
-  return result == oldval;
-}
-#  elif GLIB_SIZEOF_VOID_P == 8 /* 64-bit system */
-gboolean
-g_atomic_pointer_compare_and_exchange (volatile gpointer G_GNUC_MAY_ALIAS *atomic,
-                                      gpointer           oldval,
-                                      gpointer           newval)
-{
-  gpointer result = oldval;
-  gpointer *a = atomic;
-  __asm__ __volatile__ ("csg %0, %2, %1"
-                       : "+d" (result), "=Q" (*a)
-                       : "d" ((long)(newval)), "m" (*a) : "cc" );
-  return result == oldval;
-}
-#  else /* What's that */
-#    error "Your system has an unsupported pointer size"
-#  endif /* GLIB_SIZEOF_VOID_P */
-# elif defined (G_ATOMIC_ARM)
-static volatile int atomic_spin = 0;
-
-static int atomic_spin_trylock (void)
+(g_atomic_int_compare_and_exchange) (volatile gint *atomic,
+                                     gint           oldval,
+                                     gint           newval)
 {
-  int result;
-
-  asm volatile (
-    "swp %0, %1, [%2]\n"
-    : "=&r,&r" (result)
-    : "r,0" (1), "r,r" (&atomic_spin)
-    : "memory");
-  if (result == 0)
-    return 0;
-  else
-    return -1;
-}
-
-static void atomic_spin_lock (void)
-{
-  while (atomic_spin_trylock())
-    sched_yield();
-}
-
-static void atomic_spin_unlock (void)
-{
-  atomic_spin = 0;
+  return InterlockedCompareExchange (atomic, newval, oldval) == oldval;
 }
 
 gint
-g_atomic_int_exchange_and_add (volatile gint G_GNUC_MAY_ALIAS *atomic, 
-                              gint           val)
+(g_atomic_int_add) (volatile gint *atomic,
+                    gint           val)
 {
-  gint result;
-  atomic_spin_lock();  
-  result = *atomic;
-  *atomic += val;
-  atomic_spin_unlock();
-
-  return result;
+  return InterlockedExchangeAdd (atomic, val);
 }
 
-void
-g_atomic_int_add (volatile gint G_GNUC_MAY_ALIAS *atomic,
-                 gint           val)
+guint
+(g_atomic_int_and) (volatile guint *atomic,
+                    guint           val)
 {
-  atomic_spin_lock();
-  *atomic += val;
-  atomic_spin_unlock();
+  return InterlockedAnd (atomic, val);
 }
 
-gboolean
-g_atomic_int_compare_and_exchange (volatile gint G_GNUC_MAY_ALIAS *atomic, 
-                                  gint           oldval, 
-                                  gint           newval)
+guint
+(g_atomic_int_or) (volatile guint *atomic,
+                   guint           val)
 {
-  gboolean result;
-
-  atomic_spin_lock();
-  if (*atomic == oldval)
-    {
-      result = TRUE;
-      *atomic = newval;
-    }
-  else
-    result = FALSE;
-  atomic_spin_unlock();
-
-  return result;
+  return InterlockedOr (atomic, val);
 }
 
-gboolean
-g_atomic_pointer_compare_and_exchange (volatile gpointer G_GNUC_MAY_ALIAS *atomic, 
-                                      gpointer           oldval, 
-                                      gpointer           newval)
+guint
+(g_atomic_int_xor) (volatile guint *atomic,
+                    guint           val)
 {
-  gboolean result;
-  atomic_spin_lock();
-  if (*atomic == oldval)
-    {
-      result = TRUE;
-      *atomic = newval;
-    }
-  else
-    result = FALSE;
-  atomic_spin_unlock();
-
-  return result;
+  return InterlockedXor (atomic, val);
 }
-# elif defined (G_ATOMIC_CRIS) || defined (G_ATOMIC_CRISV32)
-#  ifdef G_ATOMIC_CRIS
-#   define CRIS_ATOMIC_INT_CMP_XCHG(atomic, oldval, newval)            \
-  ({                                                                   \
-     gboolean __result;                                                        \
-     __asm__ __volatile__ ("\n"                                                \
-                           "0:\tclearf\n\t"                            \
-                           "cmp.d [%[Atomic]], %[OldVal]\n\t"          \
-                           "bne 1f\n\t"                                        \
-                           "ax\n\t"                                    \
-                           "move.d %[NewVal], [%[Atomic]]\n\t"         \
-                           "bwf 0b\n"                                  \
-                           "1:\tseq %[Result]"                         \
-                           : [Result] "=&r" (__result),                        \
-                                      "=m" (*(atomic))                 \
-                           : [Atomic] "r" (atomic),                    \
-                             [OldVal] "r" (oldval),                    \
-                             [NewVal] "r" (newval),                    \
-                                      "g" (*(gpointer*) (atomic))      \
-                           : "memory");                                        \
-     __result;                                                         \
-  })
-#  else
-#   define CRIS_ATOMIC_INT_CMP_XCHG(atomic, oldval, newval)            \
-  ({                                                                   \
-     gboolean __result;                                                        \
-     __asm__ __volatile__ ("\n"                                                \
-                           "0:\tclearf p\n\t"                          \
-                           "cmp.d [%[Atomic]], %[OldVal]\n\t"          \
-                           "bne 1f\n\t"                                        \
-                           "ax\n\t"                                    \
-                           "move.d %[NewVal], [%[Atomic]]\n\t"         \
-                           "bcs 0b\n"                                  \
-                           "1:\tseq %[Result]"                         \
-                           : [Result] "=&r" (__result),                        \
-                                      "=m" (*(atomic))                 \
-                           : [Atomic] "r" (atomic),                    \
-                             [OldVal] "r" (oldval),                    \
-                             [NewVal] "r" (newval),                    \
-                                      "g" (*(gpointer*) (atomic))      \
-                           : "memory");                                        \
-     __result;                                                         \
-  })
-#  endif
-
-#define CRIS_CACHELINE_SIZE 32
-#define CRIS_ATOMIC_BREAKS_CACHELINE(atomic) \
-  (((gulong)(atomic) & (CRIS_CACHELINE_SIZE - 1)) > (CRIS_CACHELINE_SIZE - sizeof (atomic)))
-
-gint     __g_atomic_int_exchange_and_add         (volatile gint   G_GNUC_MAY_ALIAS *atomic,
-                                                 gint             val);
-void     __g_atomic_int_add                      (volatile gint   G_GNUC_MAY_ALIAS *atomic,
-                                                 gint             val);
-gboolean __g_atomic_int_compare_and_exchange     (volatile gint   G_GNUC_MAY_ALIAS *atomic,
-                                                 gint             oldval,
-                                                 gint             newval);
-gboolean __g_atomic_pointer_compare_and_exchange (volatile gpointer G_GNUC_MAY_ALIAS *atomic,
-                                                 gpointer         oldval,
-                                                 gpointer         newval);
 
-gboolean
-g_atomic_pointer_compare_and_exchange (volatile gpointer G_GNUC_MAY_ALIAS *atomic,
-                                      gpointer           oldval,
-                                      gpointer           newval)
-{
-  if (G_UNLIKELY (CRIS_ATOMIC_BREAKS_CACHELINE (atomic)))
-    return __g_atomic_pointer_compare_and_exchange (atomic, oldval, newval);
-
-  return CRIS_ATOMIC_INT_CMP_XCHG (atomic, oldval, newval);
-}
 
-gboolean
-g_atomic_int_compare_and_exchange (volatile gint G_GNUC_MAY_ALIAS *atomic,
-                                  gint           oldval,
-                                  gint           newval)
+gpointer
+(g_atomic_pointer_get) (volatile void *atomic)
 {
-  if (G_UNLIKELY (CRIS_ATOMIC_BREAKS_CACHELINE (atomic)))
-    return __g_atomic_int_compare_and_exchange (atomic, oldval, newval);
+  volatile gpointer *ptr = atomic;
 
-  return CRIS_ATOMIC_INT_CMP_XCHG (atomic, oldval, newval);
+  MemoryBarrier ();
+  return *ptr;
 }
 
-gint
-g_atomic_int_exchange_and_add (volatile gint G_GNUC_MAY_ALIAS *atomic,
-                              gint           val)
+void
+(g_atomic_pointer_set) (volatile void *atomic,
+                        gpointer       newval)
 {
-  gint result;
-
-  if (G_UNLIKELY (CRIS_ATOMIC_BREAKS_CACHELINE (atomic)))
-    return __g_atomic_int_exchange_and_add (atomic, val);
+  volatile gpointer *ptr = atomic;
 
-  do
-    result = *atomic;
-  while (!CRIS_ATOMIC_INT_CMP_XCHG (atomic, result, result + val));
-
-  return result;
+  *ptr = newval;
+  MemoryBarrier ();
 }
 
-void
-g_atomic_int_add (volatile gint G_GNUC_MAY_ALIAS *atomic,
-                 gint           val)
+gboolean
+(g_atomic_pointer_compare_and_exchange) (volatile void *atomic,
+                                         gpointer       oldval,
+                                         gpointer       newval)
 {
-  gint result;
-
-  if (G_UNLIKELY (CRIS_ATOMIC_BREAKS_CACHELINE (atomic)))
-    return __g_atomic_int_add (atomic, val);
-
-  do
-    result = *atomic;
-  while (!CRIS_ATOMIC_INT_CMP_XCHG (atomic, result, result + val));
+  return InterlockedCompareExchangePointer (atomic, newval, oldval) == oldval;
 }
 
-/* We need the atomic mutex for atomic operations where the atomic variable
- * breaks the 32 byte cache line since the CRIS architecture does not support
- * atomic operations on such variables. Fortunately this should be rare.
- */
-#  define DEFINE_WITH_MUTEXES
-#  define g_atomic_int_exchange_and_add __g_atomic_int_exchange_and_add
-#  define g_atomic_int_add __g_atomic_int_add
-#  define g_atomic_int_compare_and_exchange __g_atomic_int_compare_and_exchange
-#  define g_atomic_pointer_compare_and_exchange __g_atomic_pointer_compare_and_exchange
-
-# else /* !G_ATOMIC_* */
-#  define DEFINE_WITH_MUTEXES
-# endif /* G_ATOMIC_* */
-#else /* !__GNUC__ */
-# ifdef G_PLATFORM_WIN32
-#  define DEFINE_WITH_WIN32_INTERLOCKED
-# else
-#  define DEFINE_WITH_MUTEXES
-# endif
-#endif /* __GNUC__ */
-
-#ifdef DEFINE_WITH_WIN32_INTERLOCKED
-# include <windows.h>
-/* Following indicates that InterlockedCompareExchangePointer is
- * declared in winbase.h (included by windows.h) and needs to be
- * commented out if not true. It is defined iff WINVER > 0x0400,
- * which is usually correct but can be wrong if WINVER is set before
- * windows.h is included.
- */
-# if WINVER > 0x0400
-#  define HAVE_INTERLOCKED_COMPARE_EXCHANGE_POINTER
-# endif
-
-gint32
-g_atomic_int_exchange_and_add (volatile gint32 G_GNUC_MAY_ALIAS *atomic,
-                              gint32           val)
+gssize
+(g_atomic_pointer_add) (volatile void *atomic,
+                        gssize         val)
 {
+#if GLIB_SIZEOF_VOID_P == 8
+  return InterlockedExchangeAdd64 (atomic, val);
+#else
   return InterlockedExchangeAdd (atomic, val);
+#endif
 }
 
-void     
-g_atomic_int_add (volatile gint32 G_GNUC_MAY_ALIAS *atomic, 
-                 gint32           val)
+gsize
+(g_atomic_pointer_and) (volatile void *atomic,
+                        gsize          val)
 {
-  InterlockedExchangeAdd (atomic, val);
+#if GLIB_SIZEOF_VOID_P == 8
+  return InterlockedAnd64 (atomic, val);
+#else
+  return InterlockedAnd (atomic, val);
+#endif
 }
 
-gboolean 
-g_atomic_int_compare_and_exchange (volatile gint32 G_GNUC_MAY_ALIAS *atomic,
-                                  gint32           oldval,
-                                  gint32           newval)
+gsize
+(g_atomic_pointer_or) (volatile void *atomic,
+                       gsize          val)
 {
-#ifndef HAVE_INTERLOCKED_COMPARE_EXCHANGE_POINTER
-  return (guint32) InterlockedCompareExchange ((PVOID*)atomic, 
-                                               (PVOID)newval, 
-                                               (PVOID)oldval) == oldval;
+#if GLIB_SIZEOF_VOID_P == 8
+  return InterlockedOr64 (atomic, val);
 #else
-  return InterlockedCompareExchange (atomic, 
-                                     newval, 
-                                     oldval) == oldval;
+  return InterlockedOr (atomic, val);
 #endif
 }
 
-gboolean 
-g_atomic_pointer_compare_and_exchange (volatile gpointer G_GNUC_MAY_ALIAS *atomic,
-                                      gpointer           oldval,
-                                      gpointer           newval)
+gsize
+(g_atomic_pointer_xor) (volatile void *atomic,
+                        gsize          val)
 {
-# ifdef HAVE_INTERLOCKED_COMPARE_EXCHANGE_POINTER
-  return InterlockedCompareExchangePointer (atomic, newval, oldval) == oldval;
-# else
-#  if GLIB_SIZEOF_VOID_P != 4 /* no 32-bit system */
-#   error "InterlockedCompareExchangePointer needed"
-#  else
-   return InterlockedCompareExchange (atomic, newval, oldval) == oldval;
-#  endif
-# endif
+#if GLIB_SIZEOF_VOID_P == 8
+  return InterlockedXor64 (atomic, val);
+#else
+  return InterlockedXor (atomic, val);
+#endif
 }
-#endif /* DEFINE_WITH_WIN32_INTERLOCKED */
 
-#ifdef DEFINE_WITH_MUTEXES
-/* We have to use the slow, but safe locking method */
-static GMutex *g_atomic_mutex; 
+#else
+
+#include "gthread.h"
+
+static GStaticMutex g_atomic_lock;
 
-/**
- * g_atomic_int_exchange_and_add:
- * @atomic: a pointer to an integer
- * @val: the value to add to *@atomic
- *
- * Atomically adds @val to the integer pointed to by @atomic.
- * It returns the value of *@atomic just before the addition
- * took place. Also acts as a memory barrier.
- *
- * Returns: the value of *@atomic before the addition.
- *
- * Since: 2.4
- */
 gint
-g_atomic_int_exchange_and_add (volatile gint G_GNUC_MAY_ALIAS *atomic, 
-                              gint           val)
+(g_atomic_int_get) (volatile gint *atomic)
 {
-  gint result;
-    
-  g_mutex_lock (g_atomic_mutex);
-  result = *atomic;
-  *atomic += val;
-  g_mutex_unlock (g_atomic_mutex);
-
-  return result;
+  gint value;
+
+  g_static_mutex_lock (&g_atomic_lock);
+  value = *atomic;
+  g_static_mutex_unlock (&g_atomic_lock);
+
+  return value;
 }
 
-/**
- * g_atomic_int_add:
- * @atomic: a pointer to an integer
- * @val: the value to add to *@atomic
- *
- * Atomically adds @val to the integer pointed to by @atomic.
- * Also acts as a memory barrier.
- *
- * Since: 2.4
- */
 void
-g_atomic_int_add (volatile gint G_GNUC_MAY_ALIAS *atomic,
-                 gint           val)
+(g_atomic_int_set) (volatile gint *atomic,
+                    gint           value)
 {
-  g_mutex_lock (g_atomic_mutex);
-  *atomic += val;
-  g_mutex_unlock (g_atomic_mutex);
+  g_static_mutex_lock (&g_atomic_lock);
+  *atomic = value;
+  g_static_mutex_unlock (&g_atomic_lock);
 }
 
-/**
- * g_atomic_int_compare_and_exchange:
- * @atomic: a pointer to an integer
- * @oldval: the assumed old value of *@atomic
- * @newval: the new value of *@atomic
- *
- * Compares @oldval with the integer pointed to by @atomic and
- * if they are equal, atomically exchanges *@atomic with @newval.
- * Also acts as a memory barrier.
- *
- * Returns: %TRUE, if *@atomic was equal @oldval. %FALSE otherwise.
- *
- * Since: 2.4
- */
-gboolean
-g_atomic_int_compare_and_exchange (volatile gint G_GNUC_MAY_ALIAS *atomic, 
-                                  gint           oldval, 
-                                  gint           newval)
+void
+(g_atomic_int_inc) (volatile gint *atomic)
 {
-  gboolean result;
-    
-  g_mutex_lock (g_atomic_mutex);
-  if (*atomic == oldval)
-    {
-      result = TRUE;
-      *atomic = newval;
-    }
-  else
-    result = FALSE;
-  g_mutex_unlock (g_atomic_mutex);
-
-  return result;
+  g_static_mutex_lock (&g_atomic_lock);
+  (*atomic)++;
+  g_static_mutex_unlock (&g_atomic_lock);
 }
 
-/**
- * g_atomic_pointer_compare_and_exchange:
- * @atomic: a pointer to a #gpointer
- * @oldval: the assumed old value of *@atomic
- * @newval: the new value of *@atomic
- *
- * Compares @oldval with the pointer pointed to by @atomic and
- * if they are equal, atomically exchanges *@atomic with @newval.
- * Also acts as a memory barrier.
- *
- * Returns: %TRUE, if *@atomic was equal @oldval. %FALSE otherwise.
- *
- * Since: 2.4
- */
 gboolean
-g_atomic_pointer_compare_and_exchange (volatile gpointer G_GNUC_MAY_ALIAS *atomic, 
-                                      gpointer           oldval, 
-                                      gpointer           newval)
+(g_atomic_int_dec_and_test) (volatile gint *atomic)
 {
-  gboolean result;
-    
-  g_mutex_lock (g_atomic_mutex);
-  if (*atomic == oldval)
-    {
-      result = TRUE;
-      *atomic = newval;
-    }
-  else
-    result = FALSE;
-  g_mutex_unlock (g_atomic_mutex);
-
-  return result;
-}
+  gboolean is_zero;
 
-#ifdef G_ATOMIC_OP_MEMORY_BARRIER_NEEDED
+  g_static_mutex_lock (&g_atomic_lock);
+  is_zero = --(*atomic) == 0;
+  g_static_mutex_unlock (&g_atomic_lock);
 
-/**
- * g_atomic_int_get:
- * @atomic: a pointer to an integer
- *
- * Reads the value of the integer pointed to by @atomic.
- * Also acts as a memory barrier.
- *
- * Returns: the value of *@atomic
- *
- * Since: 2.4
- */
-gint
-(g_atomic_int_get) (volatile gint G_GNUC_MAY_ALIAS *atomic)
+  return is_zero;
+}
+
+gboolean
+(g_atomic_int_compare_and_exchange) (volatile gint *atomic,
+                                     gint           oldval,
+                                     gint           newval)
 {
-  gint result;
+  gboolean success;
 
-  g_mutex_lock (g_atomic_mutex);
-  result = *atomic;
-  g_mutex_unlock (g_atomic_mutex);
+  g_static_mutex_lock (&g_atomic_lock);
 
-  return result;
-}
+  if ((success = (*atomic == oldval)))
+    *atomic = newval;
 
-/**
- * g_atomic_int_set:
- * @atomic: a pointer to an integer
- * @newval: the new value
- *
- * Sets the value of the integer pointed to by @atomic.
- * Also acts as a memory barrier.
- *
- * Since: 2.10
- */
-void
-(g_atomic_int_set) (volatile gint G_GNUC_MAY_ALIAS *atomic,
-                  gint           newval)
-{
-  g_mutex_lock (g_atomic_mutex);
-  *atomic = newval;
-  g_mutex_unlock (g_atomic_mutex);
+  g_static_mutex_unlock (&g_atomic_lock);
+
+  return success;
 }
 
-/**
- * g_atomic_pointer_get:
- * @atomic: a pointer to a #gpointer.
- *
- * Reads the value of the pointer pointed to by @atomic.
- * Also acts as a memory barrier.
- *
- * Returns: the value to add to *@atomic.
- *
- * Since: 2.4
- */
-gpointer
-(g_atomic_pointer_get) (volatile gpointer G_GNUC_MAY_ALIAS *atomic)
+gint
+(g_atomic_int_add) (volatile gint *atomic,
+                    gint           val)
 {
-  gpointer result;
+  gint oldval;
 
-  g_mutex_lock (g_atomic_mutex);
-  result = *atomic;
-  g_mutex_unlock (g_atomic_mutex);
+  g_static_mutex_lock (&g_atomic_lock);
+  oldval = *atomic;
+  *atomic = oldval + val;
+  g_static_mutex_unlock (&g_atomic_lock);
 
-  return result;
+  return oldval;
 }
 
-/**
- * g_atomic_pointer_set:
- * @atomic: a pointer to a #gpointer
- * @newval: the new value
- *
- * Sets the value of the pointer pointed to by @atomic.
- * Also acts as a memory barrier.
- *
- * Since: 2.10
- */
-void
-(g_atomic_pointer_set) (volatile gpointer G_GNUC_MAY_ALIAS *atomic,
-                      gpointer           newval)
+guint
+(g_atomic_int_and) (volatile guint *atomic,
+                    guint           val)
 {
-  g_mutex_lock (g_atomic_mutex);
-  *atomic = newval;
-  g_mutex_unlock (g_atomic_mutex);
+  guint oldval;
+
+  g_static_mutex_lock (&g_atomic_lock);
+  oldval = *atomic;
+  *atomic = oldval & val;
+  g_static_mutex_unlock (&g_atomic_lock);
+
+  return oldval;
 }
-#endif /* G_ATOMIC_OP_MEMORY_BARRIER_NEEDED */   
-#elif defined (G_ATOMIC_OP_MEMORY_BARRIER_NEEDED)
-gint
-(g_atomic_int_get) (volatile gint G_GNUC_MAY_ALIAS *atomic)
+
+guint
+(g_atomic_int_or) (volatile guint *atomic,
+                   guint           val)
 {
-  G_ATOMIC_MEMORY_BARRIER;
-  return *atomic;
+  guint oldval;
+
+  g_static_mutex_lock (&g_atomic_lock);
+  oldval = *atomic;
+  *atomic = oldval | val;
+  g_static_mutex_unlock (&g_atomic_lock);
+
+  return oldval;
 }
 
-void
-(g_atomic_int_set) (volatile gint G_GNUC_MAY_ALIAS *atomic,
-                  gint           newval)
+guint
+(g_atomic_int_xor) (volatile guint *atomic,
+                    guint           val)
 {
-  *atomic = newval;
-  G_ATOMIC_MEMORY_BARRIER; 
+  guint oldval;
+
+  g_static_mutex_lock (&g_atomic_lock);
+  oldval = *atomic;
+  *atomic = oldval ^ val;
+  g_static_mutex_unlock (&g_atomic_lock);
+
+  return oldval;
 }
 
+
 gpointer
-(g_atomic_pointer_get) (volatile gpointer G_GNUC_MAY_ALIAS *atomic)
+(g_atomic_pointer_get) (volatile void *atomic)
 {
-  G_ATOMIC_MEMORY_BARRIER;
-  return *atomic;
-}   
+  volatile gpointer *ptr = atomic;
+  gpointer value;
+
+  g_static_mutex_lock (&g_atomic_lock);
+  value = *ptr;
+  g_static_mutex_unlock (&g_atomic_lock);
+
+  return value;
+}
 
 void
-(g_atomic_pointer_set) (volatile gpointer G_GNUC_MAY_ALIAS *atomic,
-                      gpointer           newval)
+(g_atomic_pointer_set) (volatile void *atomic,
+                        gpointer       newval)
 {
-  *atomic = newval;
-  G_ATOMIC_MEMORY_BARRIER; 
+  volatile gpointer *ptr = atomic;
+
+  g_static_mutex_lock (&g_atomic_lock);
+  *ptr = newval;
+  g_static_mutex_unlock (&g_atomic_lock);
 }
-#endif /* DEFINE_WITH_MUTEXES || G_ATOMIC_OP_MEMORY_BARRIER_NEEDED */
 
-#ifdef ATOMIC_INT_CMP_XCHG
 gboolean
-g_atomic_int_compare_and_exchange (volatile gint G_GNUC_MAY_ALIAS *atomic,
-                                  gint           oldval,
-                                  gint           newval)
+(g_atomic_pointer_compare_and_exchange) (volatile void *atomic,
+                                         gpointer       oldval,
+                                         gpointer       newval)
 {
-  return ATOMIC_INT_CMP_XCHG (atomic, oldval, newval);
-}
+  volatile gpointer *ptr = atomic;
+  gboolean success;
 
-gint
-g_atomic_int_exchange_and_add (volatile gint G_GNUC_MAY_ALIAS *atomic,
-                              gint           val)
-{
-  gint result;
-  do
-    result = *atomic;
-  while (!ATOMIC_INT_CMP_XCHG (atomic, result, result + val));
+  g_static_mutex_lock (&g_atomic_lock);
 
-  return result;
-}
-void
-g_atomic_int_add (volatile gint G_GNUC_MAY_ALIAS *atomic,
-                 gint           val)
-{
-  gint result;
-  do
-    result = *atomic;
-  while (!ATOMIC_INT_CMP_XCHG (atomic, result, result + val));
+  if ((success = (*ptr == oldval)))
+    *ptr = newval;
+
+  g_static_mutex_unlock (&g_atomic_lock);
+
+  return success;
 }
-#endif /* ATOMIC_INT_CMP_XCHG */
 
-void 
-_g_atomic_thread_init (void)
+gssize
+(g_atomic_pointer_add) (volatile void *atomic,
+                        gssize         val)
 {
-#ifdef DEFINE_WITH_MUTEXES
-  g_atomic_mutex = g_mutex_new ();
-#endif /* DEFINE_WITH_MUTEXES */
+  volatile gssize *ptr = atomic;
+  gssize oldval;
+
+  g_static_mutex_lock (&g_atomic_lock);
+  oldval = *ptr;
+  *ptr = oldval + val;
+  g_static_mutex_unlock (&g_atomic_lock);
+
+  return oldval;
 }
 
-#ifndef G_ATOMIC_OP_MEMORY_BARRIER_NEEDED
-gint
-(g_atomic_int_get) (volatile gint G_GNUC_MAY_ALIAS *atomic)
+gsize
+(g_atomic_pointer_and) (volatile void *atomic,
+                        gsize          val)
 {
-  return g_atomic_int_get (atomic);
+  volatile gsize *ptr = atomic;
+  gsize oldval;
+
+  g_static_mutex_lock (&g_atomic_lock);
+  oldval = *ptr;
+  *ptr = oldval & val;
+  g_static_mutex_unlock (&g_atomic_lock);
+
+  return oldval;
 }
 
-void
-(g_atomic_int_set) (volatile gint G_GNUC_MAY_ALIAS *atomic,
-                   gint           newval)
+gsize
+(g_atomic_pointer_or) (volatile void *atomic,
+                       gsize          val)
 {
-  g_atomic_int_set (atomic, newval);
+  volatile gsize *ptr = atomic;
+  gsize oldval;
+
+  g_static_mutex_lock (&g_atomic_lock);
+  oldval = *ptr;
+  *ptr = oldval | val;
+  g_static_mutex_unlock (&g_atomic_lock);
+
+  return oldval;
 }
 
-gpointer
-(g_atomic_pointer_get) (volatile gpointer G_GNUC_MAY_ALIAS *atomic)
+gsize
+(g_atomic_pointer_xor) (volatile void *atomic,
+                        gsize          val)
 {
-  return g_atomic_pointer_get (atomic);
+  volatile gsize *ptr = atomic;
+  gsize oldval;
+
+  g_static_mutex_lock (&g_atomic_lock);
+  oldval = *ptr;
+  *ptr = oldval ^ val;
+  g_static_mutex_unlock (&g_atomic_lock);
+
+  return oldval;
 }
 
-void
-(g_atomic_pointer_set) (volatile gpointer G_GNUC_MAY_ALIAS *atomic,
-                       gpointer           newval)
+#endif
+
+/**
+ * g_atomic_int_exchange_and_add:
+ * @atomic: a pointer to a #gint
+ * @val: the value to add
+ *
+ * This function existed before g_atomic_int_add() returned the prior
+ * value of the integer (which it now does).  It is retained only for
+ * compatibility reasons.  Don't use this function in new code.
+ *
+ * Returns: the value of @atomic before the add, signed
+ * Since: 2.4
+ * Deprecated: 2.30: Use g_atomic_int_add() instead.
+ **/
+gint
+g_atomic_int_exchange_and_add (volatile gint *atomic,
+                               gint           val)
 {
-  g_atomic_pointer_set (atomic, newval);
+  return (g_atomic_int_add) (atomic, val);
 }
-#endif /* G_ATOMIC_OP_MEMORY_BARRIER_NEEDED */
index 544b6f15e5a57a6b7b24fb57793db493c2dee386..16b8e3dcbafb45fa61ac4c1f923c12022f3132a6 100644 (file)
@@ -1,30 +1,22 @@
-/* GLIB - Library of useful routines for C programming
- * Copyright (C) 1995-1997  Peter Mattis, Spencer Kimball and Josh MacDonald
- *
- * g_atomic_*: atomic operations.
- * Copyright (C) 2003 Sebastian Wilhelmi
+/*
+ * Copyright © 2011 Ryan Lortie
  *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
+ * This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * licence, or (at your option) any later version.
  *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  * Lesser General Public License for more details.
  *
  * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-/*
- * Modified by the GLib Team and others 1997-2000.  See the AUTHORS
- * file for a list of people on the GLib Team.  See the ChangeLog
- * files for a list of changes.  These files are distributed with
- * GLib at ftp://ftp.gtk.org/pub/gtk/.
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ * USA.
+ *
+ * Author: Ryan Lortie <desrt@desrt.ca>
  */
 
 #if defined(G_DISABLE_SINGLE_INCLUDES) && !defined (__GLIB_H_INSIDE__) && !defined (GLIB_COMPILATION)
 #ifndef __G_ATOMIC_H__
 #define __G_ATOMIC_H__
 
-#include <glib/gtypes.h>
+#include "glib/gtypes.h"
 
 G_BEGIN_DECLS
 
-gint     g_atomic_int_exchange_and_add         (volatile gint G_GNUC_MAY_ALIAS *atomic,
-                                                gint          val);
-void     g_atomic_int_add                      (volatile gint G_GNUC_MAY_ALIAS *atomic,
-                                                gint          val);
-gboolean g_atomic_int_compare_and_exchange     (volatile gint G_GNUC_MAY_ALIAS *atomic,
-                                                gint          oldval,
-                                                gint          newval);
-gboolean g_atomic_pointer_compare_and_exchange (volatile gpointer G_GNUC_MAY_ALIAS *atomic,
-                                                gpointer      oldval,
-                                                gpointer      newval);
-
-gint     g_atomic_int_get                      (volatile gint G_GNUC_MAY_ALIAS *atomic);
-void     g_atomic_int_set                      (volatile gint G_GNUC_MAY_ALIAS *atomic,
-                                                gint          newval);
-gpointer g_atomic_pointer_get                  (volatile gpointer G_GNUC_MAY_ALIAS *atomic);
-void     g_atomic_pointer_set                  (volatile gpointer G_GNUC_MAY_ALIAS *atomic,
-                                                gpointer      newval);
-
-#if defined(__GNUC__) && defined(G_ATOMIC_OP_USE_GCC_BUILTINS)
-
-#define g_atomic_int_exchange_and_add(atomic,val) \
-  __extension__ ({ G_STATIC_ASSERT_EXPR(sizeof (*(atomic)) == sizeof (gint)); \
-   __sync_fetch_and_add((atomic),(val)); })
-
-#define g_atomic_int_add(atomic,val) \
-  __extension__ ({ G_STATIC_ASSERT_EXPR(sizeof (*(atomic)) == sizeof (gint)); \
-   __sync_fetch_and_add((atomic),(val)); })
-
-#define g_atomic_int_compare_and_exchange(atomic,oldval,newval) \
-  __extension__ ({ G_STATIC_ASSERT_EXPR(sizeof (*(atomic)) == sizeof (gint)); \
-   __sync_bool_compare_and_swap((atomic),(oldval),(newval)); })
-
-#define g_atomic_int_get(atomic) \
-  __extension__ ({ G_STATIC_ASSERT_EXPR(sizeof (*(atomic)) == sizeof (gint)); \
-   __sync_synchronize(); *(atomic); })
+gint                    g_atomic_int_get                                (volatile gint  *atomic);
+void                    g_atomic_int_set                                (volatile gint  *atomic,
+                                                                         gint            newval);
+void                    g_atomic_int_inc                                (volatile gint  *atomic);
+gboolean                g_atomic_int_dec_and_test                       (volatile gint  *atomic);
+gboolean                g_atomic_int_compare_and_exchange               (volatile gint  *atomic,
+                                                                         gint            oldval,
+                                                                         gint            newval);
+gint                    g_atomic_int_add                                (volatile gint  *atomic,
+                                                                         gint            val);
+guint                   g_atomic_int_and                                (volatile guint *atomic,
+                                                                         guint           val);
+guint                   g_atomic_int_or                                 (volatile guint *atomic,
+                                                                         guint           val);
+guint                   g_atomic_int_xor                                (volatile guint *atomic,
+                                                                         guint           val);
+
+gpointer                g_atomic_pointer_get                            (volatile void  *atomic);
+void                    g_atomic_pointer_set                            (volatile void  *atomic,
+                                                                         gpointer        newval);
+gboolean                g_atomic_pointer_compare_and_exchange           (volatile void  *atomic,
+                                                                         gpointer        oldval,
+                                                                         gpointer        newval);
+gssize                  g_atomic_pointer_add                            (volatile void  *atomic,
+                                                                         gssize          val);
+gsize                   g_atomic_pointer_and                            (volatile void  *atomic,
+                                                                         gsize           val);
+gsize                   g_atomic_pointer_or                             (volatile void  *atomic,
+                                                                         gsize           val);
+gsize                   g_atomic_pointer_xor                            (volatile void  *atomic,
+                                                                         gsize           val);
+
+#ifndef G_DISABLE_DEPRECATED
+gint                    g_atomic_int_exchange_and_add                   (volatile gint  *atomic,
+                                                                         gint            val);
+#endif
 
-#define g_atomic_int_set(atomic,newval) \
-  __extension__ ({ G_STATIC_ASSERT_EXPR(sizeof (*(atomic)) == sizeof (gint)); \
-    *(atomic) = (newval); __sync_synchronize(); })
+G_END_DECLS
 
-#define g_atomic_pointer_compare_and_exchange(atomic,oldval,newval) \
-  __extension__ ({ G_STATIC_ASSERT_EXPR(sizeof (*(atomic)) == sizeof (gpointer)); \
-    __sync_bool_compare_and_swap((atomic),(oldval),(newval)); })
+#if defined(__GNUC__) && defined(G_ATOMIC_OP_USE_GCC_BUILTINS)
 
-#define g_atomic_pointer_get(atomic) \
-  __extension__ ({ G_STATIC_ASSERT_EXPR(sizeof (*(atomic)) == sizeof (gpointer)); \
-    __sync_synchronize(); *(atomic); })
-
-#define g_atomic_pointer_set(atomic,newval) \
-  __extension__ ({ G_STATIC_ASSERT_EXPR(sizeof (*(atomic)) == sizeof (gpointer)); \
-    *(atomic) = (newval); __sync_synchronize(); })
-
-#elif !defined(G_ATOMIC_OP_MEMORY_BARRIER_NEEDED)
-
-# define g_atomic_int_get(atomic)              ((gint)*(atomic))
-# define g_atomic_int_set(atomic, newval)      ((void) (*(atomic) = (newval)))
-# define g_atomic_pointer_get(atomic)          ((gpointer)*(atomic))
-# define g_atomic_pointer_set(atomic, newval)  ((void) (*(atomic) = (newval)))
-
-#else
-
-#define g_atomic_int_exchange_and_add(atomic,val) \
- (G_STATIC_ASSERT_EXPR(sizeof (*(atomic)) == sizeof (gint)), \
-  (g_atomic_int_exchange_and_add) ((volatile gint G_GNUC_MAY_ALIAS *) (volatile void *) (atomic), (val)))
-#define g_atomic_int_add(atomic,val) \
- (G_STATIC_ASSERT_EXPR(sizeof (*(atomic)) == sizeof (gint)), \
-  (g_atomic_int_add) ((volatile gint G_GNUC_MAY_ALIAS *) (volatile void *) (atomic), (val)))
-#define g_atomic_int_compare_and_exchange(atomic,oldval,newval) \
- (G_STATIC_ASSERT_EXPR(sizeof (*(atomic)) == sizeof (gint)), \
-  (g_atomic_int_compare_and_exchange) ((volatile gint G_GNUC_MAY_ALIAS *) (volatile void *) (atomic), (oldval), (newval)))
-#define g_atomic_pointer_compare_and_exchange(atomic,oldval,newval) \
- (G_STATIC_ASSERT_EXPR(sizeof (*(atomic)) == sizeof (gpointer)), \
-  (g_atomic_pointer_compare_and_exchange) ((volatile gpointer G_GNUC_MAY_ALIAS *) (volatile void *) (atomic), (oldval), (newval)))
 #define g_atomic_int_get(atomic) \
- (G_STATIC_ASSERT_EXPR(sizeof (*(atomic)) == sizeof (gint)), \
-  (g_atomic_int_get) ((volatile gint G_GNUC_MAY_ALIAS *) (volatile void *) (atomic)))
+  (__extension__ ({                                                          \
+    G_STATIC_ASSERT (sizeof *(atomic) == sizeof (gint));                     \
+    (void) (0 ? *(atomic) ^ *(atomic) : 0);                                  \
+    __sync_synchronize ();                                                   \
+    (gint) *(atomic);                                                        \
+  }))
 #define g_atomic_int_set(atomic, newval) \
- (G_STATIC_ASSERT_EXPR(sizeof (*(atomic)) == sizeof (gint)), \
-  (g_atomic_int_set) ((volatile gint G_GNUC_MAY_ALIAS *) (volatile void *) (atomic), (newval)))
+  (__extension__ ({                                                          \
+    G_STATIC_ASSERT (sizeof *(atomic) == sizeof (gint));                     \
+    (void) (0 ? *(atomic) ^ (newval) : 0);                                   \
+    *(atomic) = (newval);                                                    \
+    __sync_synchronize ();                                                   \
+  }))
+#define g_atomic_int_inc(atomic) \
+  (__extension__ ({                                                          \
+    G_STATIC_ASSERT (sizeof *(atomic) == sizeof (gint));                     \
+    (void) (0 ? *(atomic) ^ *(atomic) : 0);                                  \
+    (void) __sync_fetch_and_add ((atomic), 1);                               \
+  }))
+#define g_atomic_int_dec_and_test(atomic) \
+  (__extension__ ({                                                          \
+    G_STATIC_ASSERT (sizeof *(atomic) == sizeof (gint));                     \
+    (void) (0 ? *(atomic) ^ *(atomic) : 0);                                  \
+    __sync_fetch_and_sub ((atomic), 1) == 1;                                 \
+  }))
+#define g_atomic_int_compare_and_exchange(atomic, oldval, newval) \
+  (__extension__ ({                                                          \
+    G_STATIC_ASSERT (sizeof *(atomic) == sizeof (gint));                     \
+    (void) (0 ? *(atomic) ^ (newval) ^ (oldval) : 0);                        \
+    (gboolean) __sync_bool_compare_and_swap ((atomic), (oldval), (newval));  \
+  }))
+#define g_atomic_int_add(atomic, val) \
+  (__extension__ ({                                                          \
+    G_STATIC_ASSERT (sizeof *(atomic) == sizeof (gint));                     \
+    (void) (0 ? *(atomic) ^ (val) : 0);                                      \
+    (gint) __sync_fetch_and_add ((atomic), (val));                           \
+  }))
+#define g_atomic_int_and(atomic, val) \
+  (__extension__ ({                                                          \
+    G_STATIC_ASSERT (sizeof *(atomic) == sizeof (gint));                     \
+    (void) (0 ? *(atomic) ^ (val) : 0);                                      \
+    (guint) __sync_fetch_and_and ((atomic), (val));                          \
+  }))
+#define g_atomic_int_or(atomic, val) \
+  (__extension__ ({                                                          \
+    G_STATIC_ASSERT (sizeof *(atomic) == sizeof (gint));                     \
+    (void) (0 ? *(atomic) ^ (val) : 0);                                      \
+    (guint) __sync_fetch_and_or ((atomic), (val));                           \
+  }))
+#define g_atomic_int_xor(atomic, val) \
+  (__extension__ ({                                                          \
+    G_STATIC_ASSERT (sizeof *(atomic) == sizeof (gint));                     \
+    (void) (0 ? *(atomic) ^ (val) : 0);                                      \
+    (guint) __sync_fetch_and_xor ((atomic), (val));                          \
+  }))
+
 #define g_atomic_pointer_get(atomic) \
- (G_STATIC_ASSERT_EXPR(sizeof (*(atomic)) == sizeof (gpointer)), \
-  (g_atomic_pointer_get) ((volatile gpointer G_GNUC_MAY_ALIAS *) (volatile void *) (atomic)))
+  (__extension__ ({                                                          \
+    G_STATIC_ASSERT (sizeof *(atomic) == sizeof (gpointer));                 \
+    __sync_synchronize ();                                                   \
+    (gpointer) *(atomic);                                                    \
+  }))
 #define g_atomic_pointer_set(atomic, newval) \
- (G_STATIC_ASSERT_EXPR(sizeof (*(atomic)) == sizeof (gpointer)), \
-  (g_atomic_pointer_set) ((volatile gpointer G_GNUC_MAY_ALIAS *) (volatile void *) (atomic), (newval)))
-
-#endif /* G_ATOMIC_OP_MEMORY_BARRIER_NEEDED */
-
-/**
- * g_atomic_int_inc:
- * @atomic: a pointer to an integer.
- *
- * Atomically increments the integer pointed to by @atomic by 1.
- *
- * Since: 2.4
- */
-#define g_atomic_int_inc(atomic) (g_atomic_int_add ((atomic), 1))
+  (__extension__ ({                                                          \
+    G_STATIC_ASSERT (sizeof *(atomic) == sizeof (gpointer));                 \
+    (void) (0 ? (gpointer) *(atomic) : 0);                                   \
+    *(atomic) = (__typeof__ (*(atomic))) (gsize) (newval);                   \
+    __sync_synchronize ();                                                   \
+  }))
+#define g_atomic_pointer_compare_and_exchange(atomic, oldval, newval) \
+  (__extension__ ({                                                          \
+    G_STATIC_ASSERT (sizeof *(atomic) == sizeof (gpointer));                 \
+    (void) (0 ? (gpointer) *(atomic) : 0);                                   \
+    (gboolean) __sync_bool_compare_and_swap ((atomic), (oldval), (newval));  \
+  }))
+#define g_atomic_pointer_add(atomic, val) \
+  (__extension__ ({                                                          \
+    G_STATIC_ASSERT (sizeof *(atomic) == sizeof (gpointer));                 \
+    (void) (0 ? (gpointer) *(atomic) : 0);                                   \
+    (void) (0 ? (val) ^ (val) : 0);                                          \
+    (gssize) __sync_fetch_and_add ((atomic), (val));                         \
+  }))
+#define g_atomic_pointer_and(atomic, val) \
+  (__extension__ ({                                                          \
+    G_STATIC_ASSERT (sizeof *(atomic) == sizeof (gpointer));                 \
+    (void) (0 ? (gpointer) *(atomic) : 0);                                   \
+    (void) (0 ? (val) ^ (val) : 0);                                          \
+    (gsize) __sync_fetch_and_and ((atomic), (val));                          \
+  }))
+#define g_atomic_pointer_or(atomic, val) \
+  (__extension__ ({                                                          \
+    G_STATIC_ASSERT (sizeof *(atomic) == sizeof (gpointer));                 \
+    (void) (0 ? (gpointer) *(atomic) : 0);                                   \
+    (void) (0 ? (val) ^ (val) : 0);                                          \
+    (gsize) __sync_fetch_and_or ((atomic), (val));                           \
+  }))
+#define g_atomic_pointer_xor(atomic, val) \
+  (__extension__ ({                                                          \
+    G_STATIC_ASSERT (sizeof *(atomic) == sizeof (gpointer));                 \
+    (void) (0 ? (gpointer) *(atomic) : 0);                                   \
+    (void) (0 ? (val) ^ (val) : 0);                                          \
+    (gsize) __sync_fetch_and_xor ((atomic), (val));                          \
+  }))
+
+#else /* defined(__GNUC__) && defined(G_ATOMIC_OP_USE_GCC_BUILTINS) */
 
-/**
- * g_atomic_int_dec_and_test:
- * @atomic: a pointer to an integer
- *
- * Atomically decrements the integer pointed to by @atomic by 1.
- *
- * Returns: %TRUE if the integer pointed to by @atomic is 0
- *     after decrementing it
- *
- * Since: 2.4
- */
+#define g_atomic_int_get(atomic) \
+  (g_atomic_int_get ((gint *) (atomic)))
+#define g_atomic_int_set(atomic, newval) \
+  (g_atomic_int_set ((gint *) (atomic), (gint) (newval)))
+#define g_atomic_int_compare_and_exchange(atomic, oldval, newval) \
+  (g_atomic_int_compare_and_exchange ((gint *) (atomic), (oldval), (newval)))
+#define g_atomic_int_add(atomic, val) \
+  (g_atomic_int_add ((gint *) (atomic), (val)))
+#define g_atomic_int_and(atomic, val) \
+  (g_atomic_int_and ((gint *) (atomic), (val)))
+#define g_atomic_int_or(atomic, val) \
+  (g_atomic_int_or ((gint *) (atomic), (val)))
+#define g_atomic_int_xor(atomic, val) \
+  (g_atomic_int_xor ((gint *) (atomic), (val)))
+#define g_atomic_int_inc(atomic) \
+  (g_atomic_int_inc ((gint *) (atomic)))
 #define g_atomic_int_dec_and_test(atomic) \
-  (g_atomic_int_exchange_and_add ((atomic), -1) == 1)
+  (g_atomic_int_dec_and_test ((gint *) (atomic)))
 
-G_END_DECLS
+#define g_atomic_pointer_get(atomic) \
+  (g_atomic_pointer_get (atomic))
+#define g_atomic_pointer_set(atomic, newval) \
+  (g_atomic_pointer_set ((atomic), (gpointer) (newval)))
+#define g_atomic_pointer_compare_and_exchange(atomic, oldval, newval) \
+  (g_atomic_pointer_compare_and_exchange ((atomic), (gpointer) (oldval), (gpointer) (newval)))
+#define g_atomic_pointer_add(atomic, val) \
+  (g_atomic_pointer_add ((atomic), (gssize) (val)))
+#define g_atomic_pointer_and(atomic, val) \
+  (g_atomic_pointer_and ((atomic), (gsize) (val)))
+#define g_atomic_pointer_or(atomic, val) \
+  (g_atomic_pointer_or ((atomic), (gsize) (val)))
+#define g_atomic_pointer_xor(atomic, val) \
+  (g_atomic_pointer_xor ((atomic), (gsize) (val)))
+
+#endif /* defined(__GNUC__) && defined(G_ATOMIC_OP_USE_GCC_BUILTINS) */
 
 #endif /* __G_ATOMIC_H__ */
index f3ae0a95faed5753a4d03a7836cc0240fcaa71d4..c26bd91e8123c2e3d7435402e79947da2f413051 100644 (file)
@@ -69,13 +69,22 @@ g_async_queue_unref
 g_async_queue_ref_unlocked
 g_async_queue_unref_and_unlock
 g_atomic_int_add
+g_atomic_int_and
 g_atomic_int_compare_and_exchange
+g_atomic_int_dec_and_test
 g_atomic_int_exchange_and_add
-g_atomic_pointer_compare_and_exchange
 g_atomic_int_get
-g_atomic_pointer_get
+g_atomic_int_inc
+g_atomic_int_or
 g_atomic_int_set
+g_atomic_int_xor
+g_atomic_pointer_add
+g_atomic_pointer_and
+g_atomic_pointer_compare_and_exchange
+g_atomic_pointer_get
+g_atomic_pointer_or
 g_atomic_pointer_set
+g_atomic_pointer_xor
 g_on_error_query
 g_on_error_stack_trace
 g_base64_encode_step
index 61cc01f1d116ddbca4405835b1890c71ea526962..5a811ce0810bb07c2cbdee9ac79d2e220b65a712 100644 (file)
@@ -945,7 +945,6 @@ g_thread_init_glib (void)
   _g_messages_thread_init_nomessage ();
 
   /* we may run full-fledged initializers from here */
-  _g_atomic_thread_init ();
   _g_convert_thread_init ();
   _g_rand_thread_init ();
   _g_main_thread_init ();
index d6fac925357742806c6dac2fe9d5c24509be1414..bde519f5a417f558af81dadacfc4c004de2ecce3 100644 (file)
@@ -207,7 +207,7 @@ g_thread_pool_wait_for_new_pool (void)
            }
          else
            {
-             if (g_atomic_int_exchange_and_add (&kill_unused_threads, -1) > 0)
+             if (g_atomic_int_add (&kill_unused_threads, -1) > 0)
                {
                  pool = NULL;
                  break;
index e16baf02ecae79f32055b36cb9a57424279b5225..771e85346b3a13947ce5f0432b8edb2a8a71423b 100644 (file)
@@ -12,7 +12,6 @@ main (void)
   g_atomic_int_set (&u, 5);
   g_atomic_int_get (&u);
   g_atomic_int_compare_and_exchange (&u, 6, 7);
-  g_atomic_int_exchange_and_add (&u, 1);
   g_atomic_int_add (&u, 1);
   g_atomic_int_inc (&u);
   (void) g_atomic_int_dec_and_test (&u);
@@ -20,7 +19,6 @@ main (void)
   g_atomic_int_set (&s, 5);
   g_atomic_int_get (&s);
   g_atomic_int_compare_and_exchange (&s, 6, 7);
-  g_atomic_int_exchange_and_add (&s, 1);
   g_atomic_int_add (&s, 1);
   g_atomic_int_inc (&s);
   (void) g_atomic_int_dec_and_test (&s);
index ead9071952dc2ef738c9bad97282b4e97c2d2fba..33c978592d383f829323947883151f6aee976860 100644 (file)
@@ -2654,7 +2654,7 @@ g_object_ref (gpointer _object)
 #endif  /* G_ENABLE_DEBUG */
 
 
-  old_val = g_atomic_int_exchange_and_add ((int *)&object->ref_count, 1);
+  old_val = g_atomic_int_add (&object->ref_count, 1);
 
   if (old_val == 1 && OBJECT_HAS_TOGGLE_REF (object))
     toggle_refs_notify (object, FALSE);
@@ -2735,7 +2735,7 @@ g_object_unref (gpointer _object)
       g_datalist_id_set_data (&object->qdata, quark_weak_refs, NULL);
       
       /* decrement the last reference */
-      old_ref = g_atomic_int_exchange_and_add ((int *)&object->ref_count, -1);
+      old_ref = g_atomic_int_add (&object->ref_count, -1);
 
       TRACE (GOBJECT_OBJECT_UNREF(object,G_TYPE_FROM_INSTANCE(object),old_ref));