summaryrefslogtreecommitdiff
path: root/glib/gatomic.h
diff options
context:
space:
mode:
authorSebastian Wilhelmi <seppi@seppi.de>2004-02-29 16:48:37 +0000
committerSebastian Wilhelmi <wilhelmi@src.gnome.org>2004-02-29 16:48:37 +0000
commit769f36db47c3e81225fd6625b5251b50a0aedb8a (patch)
tree6419cccdbe485f995da7f0f76fc1c61baa92bbbf /glib/gatomic.h
parentfe2efd06a08c1a035339b1a6e46446a9a02958b1 (diff)
downloadglib-769f36db47c3e81225fd6625b5251b50a0aedb8a.tar.gz
Moved the assembler functions from gatomic.h to gatomic.c, which makes for
2004-02-29 Sebastian Wilhelmi <seppi@seppi.de> * configure.in, glib/gatomic.c, glib/gatomic.h: Moved the assembler functions from gatomic.h to gatomic.c, which makes for better maintainability. Also use gint instead of gint32 to be able to use reference counting for ABI-fixed structures with gint/guint. * glib/gthread.h: Adapted accordingly. * tests/atomic-test.c: Updated to test for G_MAXINT and G_MININT.
Diffstat (limited to 'glib/gatomic.h')
-rw-r--r--glib/gatomic.h517
1 files changed, 17 insertions, 500 deletions
diff --git a/glib/gatomic.h b/glib/gatomic.h
index aeab3b84a..069fc1743 100644
--- a/glib/gatomic.h
+++ b/glib/gatomic.h
@@ -1,7 +1,7 @@
/* GLIB - Library of useful routines for C programming
* Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
*
- * GAtomic: atomic integer operation.
+ * g_atomic_*: atomic operations.
* Copyright (C) 2003 Sebastian Wilhelmi
*
* This library is free software; you can redistribute it and/or
@@ -34,507 +34,24 @@
G_BEGIN_DECLS
-#ifdef G_THREADS_ENABLED
-
-gint32 g_atomic_int_exchange_and_add_fallback (gint32 *atomic,
- gint32 val);
-void g_atomic_int_add_fallback (gint32 *atomic,
- gint32 val);
-gboolean g_atomic_int_compare_and_exchange_fallback (gint32 *atomic,
- gint32 oldval,
- gint32 newval);
-gboolean g_atomic_pointer_compare_and_exchange_fallback (gpointer *atomic,
- gpointer oldval,
- gpointer newval);
-
-# if defined (__GNUC__)
-# if defined (G_ATOMIC_INLINED_IMPLEMENTATION_I486)
-/* Adapted from CVS version 1.10 of glibc's sysdeps/i386/i486/bits/atomic.h
- */
-static inline gint32
-g_atomic_int_exchange_and_add (gint32 *atomic,
- gint32 val)
-{
- gint32 result;
-
- __asm__ __volatile__ ("lock; xaddl %0,%1"
- : "=r" (result), "=m" (*atomic)
- : "0" (val), "m" (*atomic));
- return result;
-}
-
-static inline void
-g_atomic_int_add (gint32 *atomic,
- gint32 val)
-{
- __asm__ __volatile__ ("lock; addl %1,%0"
- : "=m" (*atomic)
- : "ir" (val), "m" (*atomic));
-}
-
-static inline gboolean
-g_atomic_int_compare_and_exchange (gint32 *atomic,
- gint32 oldval,
- gint32 newval)
-{
- gint32 result;
-
- __asm __volatile ("lock; cmpxchgl %2, %1"
- : "=a" (result), "=m" (*atomic)
- : "r" (newval), "m" (*atomic), "0" (oldval));
-
- return result == oldval;
-}
-
-/* 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 */
-
-static inline gboolean
-g_atomic_pointer_compare_and_exchange (gpointer *atomic,
- gpointer oldval,
- gpointer newval)
-{
- gpointer result;
-
- __asm __volatile ("lock; cmpxchgl %2, %1"
- : "=a" (result), "=m" (*atomic)
- : "r" (newval), "m" (*atomic), "0" (oldval));
-
- return result == oldval;
-}
-
-# define G_ATOMIC_MEMORY_BARRIER() /* Not needed */
-
-# elif defined(G_ATOMIC_INLINED_IMPLEMENTATION_SPARCV9) \
- && (defined(__sparcv8) || defined(__sparcv9) || defined(__sparc_v9__))
-/* Adapted from CVS version 1.3 of glibc's sysdeps/sparc/sparc64/bits/atomic.h
- */
-/* Why the test for __sparcv8, wheras really the sparcv9 architecture
- * is required for the folowing assembler instructions? On
- * sparc-solaris the only difference detectable at compile time
- * between no -m and -mcpu=v9 is __sparcv8.
- *
- * However, in case -mcpu=v8 is set, the assembler will fail. This
- * should be rare however, as there are only very few v8-not-v9
- * machines still out there (and we can't do better).
- */
-static inline gboolean
-g_atomic_int_compare_and_exchange (gint32 *atomic,
- gint32 oldval,
- gint32 newval)
-{
- gint32 result;
- __asm __volatile ("cas [%4], %2, %0"
- : "=r" (result), "=m" (*atomic)
- : "r" (oldval), "m" (*atomic), "r" (atomic),
- "0" (newval));
- return result != 0;
-}
-
-# if GLIB_SIZEOF_VOID_P == 4 /* 32-bit system */
-static inline gboolean
-g_atomic_pointer_compare_and_exchange (gpointer *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 != 0;
-}
-# elif GLIB_SIZEOF_VOID_P == 8 /* 64-bit system */
-static inline gboolean
-g_atomic_pointer_compare_and_exchange (gpointer *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 != 0;
-}
-# else /* What's that */
-# error "Your system has an unsupported pointer size"
-# endif /* GLIB_SIZEOF_VOID_P */
-static inline gint32
-g_atomic_int_exchange_and_add (gint32 *atomic,
- gint32 val)
-{
- gint32 result;
- do
- result = *atomic;
- while (!g_atomic_int_compare_and_exchange (atomic, result, result + val));
-
- return result;
-}
-
-static inline void
-g_atomic_int_add (gint32 *atomic,
- gint32 val)
-{
- g_atomic_int_exchange_and_add (atomic, val);
-}
-
-# define G_ATOMIC_MEMORY_BARRIER() \
- __asm __volatile ("membar #LoadLoad | #LoadStore" \
- " | #StoreLoad | #StoreStore" : : : "memory")
-
-# elif defined(G_ATOMIC_INLINED_IMPLEMENTATION_ALPHA)
-/* Adapted from CVS version 1.3 of glibc's sysdeps/alpha/bits/atomic.h
- */
-static inline gboolean
-g_atomic_int_compare_and_exchange (gint32 *atomic,
- gint32 oldval,
- gint32 newval)
-{
- gint32 result;
- gint32 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" ((gint64)oldval),
- "Ir" (newval)
- : "memory");
- return result != 0;
-}
-# if GLIB_SIZEOF_VOID_P == 4 /* 32-bit system */
-static inline gboolean
-g_atomic_pointer_compare_and_exchange (gpointer *atomic,
- gpointer oldval,
- gpointer newval)
-{
- gint32 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" ((gint64)oldval),
- "Ir" (newval)
- : "memory");
- return result != 0;
-}
-# elif GLIB_SIZEOF_VOID_P == 8 /* 64-bit system */
-static inline gboolean
-g_atomic_pointer_compare_and_exchange (gpointer *atomic,
- gpointer oldval,
- gpointer newval)
-{
- gint32 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" ((gint64)oldval),
- "Ir" (newval)
- : "memory");
- return result != 0;
-}
-# else /* What's that */
-# error "Your system has an unsupported pointer size"
-# endif /* GLIB_SIZEOF_VOID_P */
-static inline gint32
-g_atomic_int_exchange_and_add (gint32 *atomic,
- gint32 val)
-{
- gint32 result;
- do
- result = *atomic;
- while (!g_atomic_int_compare_and_exchange (atomic, result, result + val));
-
- return result;
-}
-
-static inline void
-g_atomic_int_add (gint32 *atomic,
- gint32 val)
-{
- g_atomic_int_exchange_and_add (atomic, val);
-}
-
-# define G_ATOMIC_MEMORY_BARRIER() __asm ("mb" : : : "memory")
-
-# elif defined(G_ATOMIC_INLINED_IMPLEMENTATION_X86_64)
-/* Adapted from CVS version 1.9 of glibc's sysdeps/x86_64/bits/atomic.h
- */
-static inline gint32
-g_atomic_int_exchange_and_add (gint32 *atomic,
- gint32 val)
-{
- gint32 result;
-
- __asm__ __volatile__ ("lock; xaddl %0,%1"
- : "=r" (result), "=m" (*atomic)
- : "0" (val), "m" (*atomic));
- return result;
-}
-
-static inline void
-g_atomic_int_add (gint32 *atomic,
- gint32 val)
-{
- __asm__ __volatile__ ("lock; addl %1,%0"
- : "=m" (*atomic)
- : "ir" (val), "m" (*atomic));
-}
-
-static inline gboolean
-g_atomic_int_compare_and_exchange (gint32 *atomic,
- gint32 oldval,
- gint32 newval)
-{
- gint32 result;
-
- __asm __volatile ("lock; cmpxchgl %2, %1"
- : "=a" (result), "=m" (*atomic)
- : "r" (newval), "m" (*atomic), "0" (oldval));
-
- return result == oldval;
-}
-
-static inline gboolean
-g_atomic_pointer_compare_and_exchange (gpointer *atomic,
- gpointer oldval,
- gpointer newval)
-{
- gpointer result;
-
- __asm __volatile ("lock; cmpxchgq %q2, %1"
- : "=a" (result), "=m" (*atomic)
- : "r" (newval), "m" (*atomic), "0" (oldval));
-
- return result == oldval;
-}
-
-# define G_ATOMIC_MEMORY_BARRIER() /* Not needed */
-
-# elif defined(G_ATOMIC_INLINED_IMPLEMENTATION_POWERPC)
-/* Adapted from CVS version 1.12 of glibc's sysdeps/powerpc/bits/atomic.h
- * and CVS version 1.3 of glibc's sysdeps/powerpc/powerpc32/bits/atomic.h
- * and CVS version 1.2 of glibc's sysdeps/powerpc/powerpc64/bits/atomic.h
- */
-static inline gint32
-g_atomic_int_exchange_and_add (gint32 *atomic,
- gint32 val)
-{
- gint32 result, temp;
- __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), "2" (*atomic)
- : "cr0", "memory");
- return result;
-}
-
-static inline void
-g_atomic_int_add (gint32 *atomic,
- gint32 val)
-{
- g_atomic_int_exchange_and_add (atomic, val);
-}
-
-# if GLIB_SIZEOF_VOID_P == 4 /* 32-bit system */
-static inline gboolean
-g_atomic_int_compare_and_exchange (gint32 *atomic,
- gint32 oldval,
- gint32 newval)
-{
- gint32 result;
- __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");
- return result == 0;
-}
-
-static inline gboolean
-g_atomic_pointer_compare_and_exchange (gpointer *atomic,
- gpointer oldval,
- gpointer newval)
-{
- gpointer result;
- __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");
- return result == 0;
-}
-# elif GLIB_SIZEOF_VOID_P == 8 /* 64-bit system */
-static inline gboolean
-g_atomic_int_compare_and_exchange (gint32 *atomic,
- gint32 oldval,
- gint32 newval)
-{
- __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");
- return result == 0;
-}
-
-static inline gboolean
-g_atomic_pointer_compare_and_exchange (gpointer *atomic,
- gpointer oldval,
- gpointer newval)
-{
- gpointer result;
- __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");
- return result == 0;
-}
-# 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_ATOMIC_INLINED_IMPLEMENTATION_IA64)
-/* Adapted from CVS version 1.8 of glibc's sysdeps/ia64/bits/atomic.h
- */
-static inline gint32
-g_atomic_int_exchange_and_add (gint32 *atomic,
- gint32 val)
-{
- return __sync_fetch_and_add_si (atomic, val);
-}
-
-static inline void
-g_atomic_int_add (gint32 *atomic,
- gint32 val)
-{
- __sync_fetch_and_add_si (atomic, val);
-}
-
-static inline gboolean
-g_atomic_int_compare_and_exchange (gint32 *atomic,
- gint32 oldval,
- gint32 newval)
-{
- return __sync_bool_compare_and_exchange_si (atomic, oldval, newval);
-}
-
-static inline gboolean
-g_atomic_pointer_compare_and_exchange (gpointer *atomic,
- gpointer oldval,
- gpointer newval)
-{
- return __sync_bool_compare_and_exchange_di ((long *)atomic,
- (long)oldval, (long)newval);
-}
-
-# define G_ATOMIC_MEMORY_BARRIER() __sync_synchronize ()
-
-# else /* !G_ATOMIC_INLINED_IMPLEMENTATION_... */
-# define G_ATOMIC_USE_FALLBACK_IMPLEMENTATION
-# endif /* G_ATOMIC_INLINED_IMPLEMENTATION_... */
-# else /* !__GNU__ */
-# define G_ATOMIC_USE_FALLBACK_IMPLEMENTATION
-# endif /* __GNUC__ */
-# ifdef G_ATOMIC_USE_FALLBACK_IMPLEMENTATION
-# define g_atomic_int_exchange_and_add \
- g_atomic_int_exchange_and_add_fallback
-# define g_atomic_int_add \
- g_atomic_int_add_fallback
-# define g_atomic_int_compare_and_exchange \
- g_atomic_int_compare_and_exchange_fallback
-# define g_atomic_pointer_compare_and_exchange \
- g_atomic_pointer_compare_and_exchange_fallback
-# define g_atomic_int_get \
- g_atomic_int_get_fallback
-# define g_atomic_pointer_get \
- g_atomic_pointer_get_fallback
-# else /* !G_ATOMIC_USE_FALLBACK_IMPLEMENTATION */
-static inline gint32
-g_atomic_int_get (gint32 *atomic)
-{
- gint32 result = *atomic;
- G_ATOMIC_MEMORY_BARRIER ();
- return result;
-}
-
-static inline gpointer
-g_atomic_pointer_get (gpointer *atomic)
-{
- gpointer result = *atomic;
- G_ATOMIC_MEMORY_BARRIER ();
- return result;
-}
-# endif /* G_ATOMIC_USE_FALLBACK_IMPLEMENTATION */
-#else /* !G_THREADS_ENABLED */
-gint32 g_atomic_int_exchange_and_add (gint32 *atomic, gint32 val);
-# define g_atomic_int_add(atomic, val) (void)(*(atomic) += (val))
-# define g_atomic_int_compare_and_exchange(atomic, oldval, newval) \
- (*(atomic) == (oldval) ? (*(atomic) = (newval), TRUE) : FALSE)
-# define g_atomic_pointer_compare_and_exchange(atomic, oldval, newval) \
- (*(atomic) == (oldval) ? (*(atomic) = (newval), TRUE) : FALSE)
+gint g_atomic_int_exchange_and_add (gint *atomic,
+ gint val);
+void g_atomic_int_add (gint *atomic,
+ gint val);
+gboolean g_atomic_int_compare_and_exchange (gint *atomic,
+ gint oldval,
+ gint newval);
+gboolean g_atomic_pointer_compare_and_exchange (gpointer *atomic,
+ gpointer oldval,
+ gpointer newval);
+
+#ifdef G_ATOMIC_OP_MEMORY_BARRIER_NEEDED
+gint g_atomic_int_get (gint *atomic);
+gpointer g_atomic_pointer_get (gpointer *atomic);
+#else /* !G_ATOMIC_OP_MEMORY_BARRIER_NEEDED */
# define g_atomic_int_get(atomic) (*(atomic))
# define g_atomic_pointer_get(atomic) (*(atomic))
-# define G_ATOMIC_MEMORY_BARRIER() /* Not needed */
-#endif /* G_THREADS_ENABLED */
+#endif /* G_ATOMIC_OP_MEMORY_BARRIER_NEEDED */
#define g_atomic_int_inc(atomic) (g_atomic_int_add ((atomic), 1))
#define g_atomic_int_dec_and_test(atomic) \