Added SILC Thread Queue API
[silc.git] / lib / silcutil / silcatomic.h
index 02a71ca9357d2a77ff0e6582b0b0aac7150b717c..77197fa0b37eb879b53ea39060d34af9548be5c1 100644 (file)
@@ -4,7 +4,7 @@
 
   Author: Pekka Riikonen <priikone@silcnet.org>
 
-  Copyright (C) 2006 Pekka Riikonen
+  Copyright (C) 2006 - 2007 Pekka Riikonen
 
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
  * simple operations with integers atomically.  This enables fast integer
  * additions and subtractions safely in multithreaded environment.  It is
  * especially suited for reference counters and similar and is much faster
- * than using locking.
+ * than using locking.  This interface supports 8, 16 and 32 bit integers
+ * and 32 or 64 bit pointers.
  *
- * If threads were not enabled when compiling the source code, the operations
- * are not atomic.  On some platforms this interface actually use mutual
- * exclusion lock instead of true atomic operations, leading into some
- * performace penalty.
+ * On some platforms this interface actually use mutual exclusion lock
+ * instead of true atomic operations, leading into some performace penalty.
+ * Also on some platforms the 8 and 16 bit integers are actually 32 bit
+ * integers.
+ *
+ * Fast operations are supported on: x86, x86_64, ia64, PPC
+ *
+ * EXAMPLE
+ *
+ * SilcAtomic32 refcnt;
+ *
+ * // Initialize atomic variable
+ * silc_atomic_init32(&refcnt, 0);
+ *
+ * // Increment referene counter by one
+ * silc_atomic_add_int32(&refcnt, 1);
+ *
+ * // Uninitialize atomic variable
+ * silc_atomic_uninit32(&refcnt);
  *
  ***/
 
 #ifndef SILCATOMIC_H
 #define SILCATOMIC_H
 
-/****s* silcutil/SilcAtomicAPI/SilcAtomic
+/* Use lock prefix only on true SMP systems */
+#ifdef SILC_SMP
+#define SILC_SMP_LOCK "lock; "
+#else
+#define SILC_SMP_LOCK
+#endif /* SILC_SMP */
+
+/****s* silcutil/SilcAtomicAPI/SilcAtomic32
+ *
+ * NAME
+ *
+ *    typedef struct { ... } SilcAtomic32;
+ *
+ * DESCRIPTION
+ *
+ *    The atomic operation structure given as argument to all atomic
+ *    operation functions.  It hols the actual 32-bit atomic variable.
+ *
+ * EXAMPLE
+ *
+ *    SilcAtomic32 refcnt;
+ *
+ *    // Initialize atomic variable
+ *    silc_atomic_init32(&refcnt, 0);
+ *
+ *    ...
+ *    // Increment referene counter
+ *    silc_atomic_add_int32(&refcnt, 1);
+ *    ...
+ *
+ *    // Uninitialize atomic variable
+ *    silc_atomic_uninit32(&refcnt);
+ *
+ ***/
+
+/****s* silcutil/SilcAtomicAPI/SilcAtomic16
+ *
+ * NAME
+ *
+ *    typedef struct { ... } SilcAtomic16;
+ *
+ * DESCRIPTION
+ *
+ *    The atomic operation structure given as argument to all atomic
+ *    operation functions.  It hols the actual 16-bit atomic variable.
+ *
+ * EXAMPLE
+ *
+ *    SilcAtomic16 refcnt;
+ *
+ *    // Initialize atomic variable
+ *    silc_atomic_init16(&refcnt, 0);
+ *
+ *    ...
+ *    // Increment referene counter
+ *    silc_atomic_add_int16(&refcnt, 1);
+ *    ...
+ *
+ *    // Uninitialize atomic variable
+ *    silc_atomic_uninit16(&refcnt);
+ *
+ ***/
+
+/****s* silcutil/SilcAtomicAPI/SilcAtomic8
  *
  * NAME
  *
- *    typedef struct { ... } SilcAtomic;
+ *    typedef struct { ... } SilcAtomic8;
  *
  * DESCRIPTION
  *
  *    The atomic operation structure given as argument to all atomic
- *    operation functions.  It hols the actual atomic variable.  On most
- *    platforms its size is 32 bits but on some platforms it may be
- *    larger.
+ *    operation functions.  It hols the actual 8-bit atomic variable.
  *
  * EXAMPLE
  *
- *    SilcAtomic refcnt;
+ *    SilcAtomic8 refcnt;
  *
  *    // Initialize atomic variable
- *    silc_atomic_init(&refcnt, 0);
+ *    silc_atomic_init8(&refcnt, 0);
  *
  *    ...
  *    // Increment referene counter
- *    silc_atomic_add_int(&refcnt, 1);
+ *    silc_atomic_add_int8(&refcnt, 1);
+ *    ...
+ *
+ *    // Uninitialize atomic variable
+ *    silc_atomic_uninit8(&refcnt);
+ *
+ ***/
+
+/****s* silcutil/SilcAtomicAPI/SilcAtomicPointer
+ *
+ * NAME
+ *
+ *    typedef struct { ... } SilcAtomicPointer;
+ *
+ * DESCRIPTION
+ *
+ *    The atomic operation structure given as argument to all atomic
+ *    operation functions.  It hols the actual pointer variable.
+ *
+ * EXAMPLE
+ *
+ *    SilcAtomicPointer ptr;
+ *
+ *    // Initialize atomic variable
+ *    silc_atomic_init_pointer(&ptr, NULL);
+ *
+ *    ...
+ *    // Set pointer
+ *    silc_atomic_set_pointer(&ptr, context);
  *    ...
  *
  *    // Uninitialize atomic variable
- *    silc_atomic_uninit(&refcnt);
+ *    silc_atomic_uninit_pointer(&ptr);
  *
  ***/
+
 #if !defined(SILC_THREADS) || defined(SILC_WIN32) || (defined(__GNUC__) &&  \
     (defined(SILC_I486) || defined(SILC_X86_64) || defined(SILC_IA64) ||    \
      defined(SILC_POWERPC)))
-typedef struct
-{
-  volatile SilcUInt32 value;
-} SilcAtomic;
+typedef struct {
+  SilcUInt32 value;
+} SilcAtomic32;
+typedef struct {
+  void *value;
+} SilcAtomicPointer;
 #else
 #define SILC_ATOMIC_MUTEX
-typedef struct
-{
-  volatile SilcUInt32 value;
+typedef struct {
+  SilcMutex lock;
+  SilcUInt32 value;
+} SilcAtomic32;
+typedef struct {
+  SilcMutex lock;
+  void *value;
+} SilcAtomicPointer;
+#endif
+
+#if !defined(SILC_THREADS) || (defined(__GNUC__) && (defined(SILC_I486) ||  \
+                                                    defined(SILC_X86_64)))
+typedef struct {
+  SilcUInt16 value;
+} SilcAtomic16;
+#elif defined(SILC_WIN32) || (defined(__GNUC__) && (defined(SILC_IA64) ||   \
+                                                   defined(SILC_POWERPC)))
+typedef struct {
+  SilcUInt32 value;
+} SilcAtomic16;
+#else
+typedef struct {
+  SilcMutex lock;
+  SilcUInt16 value;
+} SilcAtomic16;
+#endif
+
+#if !defined(SILC_THREADS) || (defined(__GNUC__) && (defined(SILC_I486) ||  \
+                                                    defined(SILC_X86_64)))
+typedef struct {
+  SilcUInt8 value;
+} SilcAtomic8;
+#elif defined(SILC_WIN32) || (defined(__GNUC__) && (defined(SILC_IA64) ||   \
+                                                   defined(SILC_POWERPC)))
+typedef struct {
+  SilcUInt32 value;
+} SilcAtomic8;
+#else
+typedef struct {
   SilcMutex lock;
-} SilcAtomic;
+  SilcUInt8 value;
+} SilcAtomic8;
 #endif
 
-/****f* silcutil/SilcAtomicAPI/silc_atomic_init
+/****f* silcutil/SilcAtomicAPI/silc_atomic_init32
  *
  * SYNOPSIS
  *
  *    static inline
- *    SilcBool silc_atomic_init(SilcAtomic *atomic, int value);
+ *    SilcBool silc_atomic_init32(SilcAtomic32 *atomic, SilcUInt32 value);
  *
  * DESCRIPTION
  *
  *    Initializes the atomic variable `atomic', and sets the `value' as its
  *    inital value.  Returns FALSE on error.  To uninitialize call the
- *    silc_atomic_uninit function.
+ *    silc_atomic_uninit32 function.
  *
  ***/
 
-static inline
-SilcBool silc_atomic_init(SilcAtomic *atomic, int value)
-{
-  atomic->value = value;
+/****f* silcutil/SilcAtomicAPI/silc_atomic_init16
+ *
+ * SYNOPSIS
+ *
+ *    static inline
+ *    SilcBool silc_atomic_init16(SilcAtomic16 *atomic, SilcUInt16 value);
+ *
+ * DESCRIPTION
+ *
+ *    Initializes the atomic variable `atomic', and sets the `value' as its
+ *    inital value.  Returns FALSE on error.  To uninitialize call the
+ *    silc_atomic_uninit32 function.
+ *
+ ***/
+
+/****f* silcutil/SilcAtomicAPI/silc_atomic_init8
+ *
+ * SYNOPSIS
+ *
+ *    static inline
+ *    SilcBool silc_atomic_init8(SilcAtomic8 *atomic, SilcUInt8 value);
+ *
+ * DESCRIPTION
+ *
+ *    Initializes the atomic variable `atomic', and sets the `value' as its
+ *    inital value.  Returns FALSE on error.  To uninitialize call the
+ *    silc_atomic_uninit8 function.
+ *
+ ***/
+
+/****f* silcutil/SilcAtomicAPI/silc_atomic_init_pointer
+ *
+ * SYNOPSIS
+ *
+ *    static inline
+ *    SilcBool silc_atomic_init_pointer(SilcAtomicPointer *atomic,
+ *                                      void *pointer);
+ *
+ * DESCRIPTION
+ *
+ *    Initializes the atomic pointer variable `atomic', and sets the `pointer'
+ *    as its inital pointer.  Returns FALSE on error.  To uninitialize call
+ *    the silc_atomic_uninit_pointer function.
+ *
+ ***/
+
+#define SILC_ATOMIC_INIT_F(name, bits, type)                           \
+static inline                                                          \
+SilcBool silc_atomic_init##name(SilcAtomic##bits *atomic, type value)
 
 #if defined(SILC_ATOMIC_MUTEX)
-  if (!silc_mutex_alloc(&atomic->lock))
-    return FALSE;
+#define SILC_ATOMIC_INIT(name, bits, type)                             \
+SILC_ATOMIC_INIT_F(name, bits, type)                                   \
+{                                                                      \
+  *(type volatile *)&atomic->value = value;                            \
+  return silc_mutex_alloc(&atomic->lock);                              \
+}
+#else
+#define SILC_ATOMIC_INIT(name, bits, type)                             \
+SILC_ATOMIC_INIT_F(name, bits, type)                                   \
+{                                                                      \
+  *(type volatile *)&atomic->value = value;                            \
+  return TRUE;                                                         \
+}
 #endif /* SILC_ATOMIC_MUTEX */
 
-  return TRUE;
-}
+SILC_ATOMIC_INIT(8, 8, SilcUInt8)
+SILC_ATOMIC_INIT(16, 16, SilcUInt16)
+SILC_ATOMIC_INIT(32, 32, SilcUInt32)
+SILC_ATOMIC_INIT(_pointer, Pointer, void *)
 
-/****f* silcutil/SilcAtomicAPI/silc_atomic_uninit
+/****f* silcutil/SilcAtomicAPI/silc_atomic_uninit32
  *
  * SYNOPSIS
  *
  *    static inline
- *    void silc_atomic_uninit(SilcAtomic *atomic);
+ *    void silc_atomic_uninit32(SilcAtomic32 *atomic);
  *
  * DESCRIPTION
  *
@@ -124,102 +327,246 @@ SilcBool silc_atomic_init(SilcAtomic *atomic, int value)
  *
  ***/
 
-static inline
-void silc_atomic_uninit(SilcAtomic *atomic)
-{
-  atomic->value = 0;
+/****f* silcutil/SilcAtomicAPI/silc_atomic_uninit16
+ *
+ * SYNOPSIS
+ *
+ *    static inline
+ *    void silc_atomic_uninit16(SilcAtomic16 *atomic);
+ *
+ * DESCRIPTION
+ *
+ *    Uninitializes the atomic variable `atomic'.  This should alwyas be
+ *    called after the atomic variable is not used anymore.
+ *
+ ***/
+
+/****f* silcutil/SilcAtomicAPI/silc_atomic_uninit8
+ *
+ * SYNOPSIS
+ *
+ *    static inline
+ *    void silc_atomic_uninit8(SilcAtomic8 *atomic);
+ *
+ * DESCRIPTION
+ *
+ *    Uninitializes the atomic variable `atomic'.  This should alwyas be
+ *    called after the atomic variable is not used anymore.
+ *
+ ***/
+
+/****f* silcutil/SilcAtomicAPI/silc_atomic_uninit_pointer
+ *
+ * SYNOPSIS
+ *
+ *    static inline
+ *    void silc_atomic_uninit_pointer(SilcAtomicPointer *atomic);
+ *
+ * DESCRIPTION
+ *
+ *    Uninitializes the atomic variable `atomic'.  This should alwyas be
+ *    called after the atomic variable is not used anymore.
+ *
+ ***/
+
+#define SILC_ATOMIC_UNINIT_F(bits, t)                                  \
+static inline void silc_atomic_uninit##bits(SilcAtomic##t *atomic)
+
 #if defined(SILC_ATOMIC_MUTEX)
-  silc_mutex_free(atomic->lock);
-#endif /* SILC_ATOMIC_MUTEX */
+#define SILC_ATOMIC_UNINIT(bits, t)                                    \
+SILC_ATOMIC_UNINIT_F(bits, t)                                          \
+{                                                                      \
+  silc_mutex_free(atomic->lock);                                       \
+}
+#else
+#define SILC_ATOMIC_UNINIT(bits, t)                                    \
+SILC_ATOMIC_UNINIT_F(bits, t)                                          \
+{                                                                      \
+  memset(atomic, 0, sizeof(*atomic));                                  \
 }
+#endif /* SILC_ATOMIC_MUTEX */
 
-/****f* silcutil/SilcAtomicAPI/silc_atomic_add_int
+SILC_ATOMIC_UNINIT(8, 8)
+SILC_ATOMIC_UNINIT(16, 16)
+SILC_ATOMIC_UNINIT(32, 32)
+SILC_ATOMIC_UNINIT(_pointer, Pointer)
+
+/****f* silcutil/SilcAtomicAPI/silc_atomic_set_int32
  *
  * SYNOPSIS
  *
  *    static inline
- *    SilcUInt32 silc_atomic_add_int(SilcAtomic *atomic, int value);
+ *    void silc_atomic_set_int32(SilcAtomic32 *atomic, SilcUInt32 value);
  *
  * DESCRIPTION
  *
- *    Atomically adds `value' to 32-bit integer.  Returns the value after
- *    addition.
+ *    Atomically sets `value' to 32-bit integer.
  *
  ***/
 
-static inline
-SilcUInt32 silc_atomic_add_int(SilcAtomic *atomic, int value)
-{
-  SilcUInt32 ret;
+/****f* silcutil/SilcAtomicAPI/silc_atomic_set_int16
+ *
+ * SYNOPSIS
+ *
+ *    static inline
+ *    void silc_atomic_set_int16(SilcAtomic16 *atomic, SilcUInt16 value);
+ *
+ * DESCRIPTION
+ *
+ *    Atomically sets `value' to 16-bit integer.
+ *
+ ***/
+
+/****f* silcutil/SilcAtomicAPI/silc_atomic_set_int8
+ *
+ * SYNOPSIS
+ *
+ *    static inline
+ *    void silc_atomic_set_int8(SilcAtomic8 *atomic, SilcUInt8 value);
+ *
+ * DESCRIPTION
+ *
+ *    Atomically sets `value' to 8-bit integer.
+ *
+ ***/
+
+#define SILC_ATOMIC_SET_INT_F(bits)                                    \
+static inline void silc_atomic_set_int##bits(SilcAtomic##bits *atomic, \
+                                            SilcUInt##bits value)
 
 #if !defined(SILC_THREADS)
-  /* No atomic operations */
-  ret = atomic->value;
-  atomic->value += value;
+#define SILC_ATOMIC_SET_INT(bits, bp, bp2)                             \
+SILC_ATOMIC_SET_INT_F(bits)                                            \
+{                                                                      \
+  /* No atomic operations */                                           \
+  atomic->value = value;                                               \
+}
 
 #elif defined(SILC_WIN32)
-  /* Windows */
-  ret = InterlockedExchangeAdd(&atomic->value, (LONG)value);
+#define SILC_ATOMIC_SET_INT(bits, bp, bp2)                             \
+SILC_ATOMIC_SET_INT_F(bits)                                            \
+{                                                                      \
+  /* Windows */                                                                \
+  InterlockedExchange((LONG *)&atomic->value, (LONG)value);            \
+}
 
 #elif defined(__GNUC__) && (defined(SILC_I486) || defined(SILC_X86_64))
-  /* GCC + i486 or x86_64 */
-  __asm __volatile("lock; xaddl %0, %1"
-                  : "=r" (ret), "+m" (atomic->value)
-                  : "0" (value));
+#define SILC_ATOMIC_SET_INT(bits, bp, bp2)                             \
+SILC_ATOMIC_SET_INT_F(bits)                                            \
+{                                                                      \
+  /* GCC + i486 or x86_64 */                                           \
+  __asm __volatile("xchg" bp " %" bp2 "0, %1"                          \
+                  : "=r" (value)                                       \
+                  : "m" (atomic->value), "0" (value));                 \
+}
 
 #elif defined(__GNUC__) && defined(SILC_IA64)
-  /* GCC + IA64 (GCC builtin atomic operations) */
-  ret = __sync_fetch_and_add(&atomic->value, value);
+#define SILC_ATOMIC_SET_INT(bits, bp, bp2)                             \
+SILC_ATOMIC_SET_INT_F(bits)                                            \
+{                                                                      \
+  /* IA64, memory barrier needed */                                    \
+  *(volatile SilcUInt##bits *)&atomic->value = value;                  \
+  __sync_synchronize();                                                        \
+}
 
 #elif defined(__GNUC__) && defined(SILC_POWERPC)
-  /* GCC + PowerPC (code adapted from IBM's documentation) */
-  /* XXX Hmm.. should I sync and isync this?... */
-  __asm __volatile("0: lwarx  %0,  0, %2\n"
-                  "   add    %0, %1, %0\n"
-                  "   stwcx. %0,  0, %2\n"
-                  "   bne-   0b"
-                  : "=&r" (ret)
-                  : "r" (value), "r" (&atomic->value)
-                  : "cc");
-  return ret;
+#define SILC_ATOMIC_SET_INT(bits, bp, bp2)                             \
+SILC_ATOMIC_SET_INT_F(bits)                                            \
+{                                                                      \
+  /* PowerPC, memory barrier needed */                                 \
+  *(volatile SilcUInt##bits *)&atomic->value = &value;                 \
+  __asm("sync" : : : "memory");                                                \
+}
+
+#else /* SILC_ATOMIC_MUTEX */
+#define SILC_ATOMIC_SET_INT(bits, bp, bp2)                             \
+SILC_ATOMIC_SET_INT_F(bits)                                            \
+{                                                                      \
+  /* Mutex */                                                          \
+  silc_mutex_lock(atomic->lock);                                       \
+  atomic->value = value;                                               \
+  silc_mutex_unlock(atomic->lock);                                     \
+}
+#endif /* !SILC_THREADS */
+
+SILC_ATOMIC_SET_INT(8, "b", "b")
+SILC_ATOMIC_SET_INT(16, "w", "w")
+SILC_ATOMIC_SET_INT(32, "l", "")
+
+/****f* silcutil/SilcAtomicAPI/silc_atomic_set_pointer
+ *
+ * SYNOPSIS
+ *
+ *    static inline
+ *    void silc_atomic_set_pointer(SilcAtomicPointer *atomic, void *pointer);
+ *
+ * DESCRIPTION
+ *
+ *    Atomically sets `pointer' to the atomic variable.
+ *
+ ***/
+
+static inline
+void silc_atomic_set_pointer(SilcAtomicPointer *atomic, void *pointer)
+{
+#if !defined(SILC_THREADS) ||                   \
+     (defined(__GNUC__) && (defined(SILC_I486) || defined(SILC_X86_64)))
+  /* No threads, Windows, i486 or x86_64, no memory barrier needed */
+  *(void * volatile *)&atomic->value = pointer;
+
+#elif defined(SILC_WIN32)
+  InterlockedExchangePointer(&atomic->value, pointer);
+
+#elif defined(__GNUC__) && defined(SILC_IA64)
+  /* IA64, memory barrier needed */
+  *(void * volatile *)&atomic->value = pointer;
+  __sync_synchronize();
+
+#elif defined(__GNUC__) && defined(SILC_POWERPC)
+  /* PowerPC, memory barrier needed */
+  *(void * volatile *)&atomic->value = pointer;
+  __asm("sync" : : : "memory");
 
 #else
   /* Mutex */
   silc_mutex_lock(atomic->lock);
-  ret = atomic->value;
-  atomic->value += value;
+  atomic->value = pointer;
   silc_mutex_unlock(atomic->lock);
 #endif
-
-  return ret + value;
 }
 
-/****f* silcutil/SilcAtomicAPI/silc_atomic_sub_int
+/****f* silcutil/SilcAtomicAPI/silc_atomic_get_int32
  *
  * SYNOPSIS
  *
  *    static inline
- *    SilcUInt32 silc_atomic_sub_int(SilcAtomic *atomic, int value);
+ *    SilcUInt32 silc_atomic_get_int32(SilcAtomic32 *atomic);
  *
  * DESCRIPTION
  *
- *    Atomically subtracts `value' from 32-bit integer.  Returns the value
- *    after subtraction.
+ *    Returns the current value of the atomic variable.
  *
  ***/
 
-static inline
-SilcUInt32 silc_atomic_sub_int(SilcAtomic *atomic, int value)
-{
-  return silc_atomic_add_int(atomic, -value);
-}
+/****f* silcutil/SilcAtomicAPI/silc_atomic_get_int16
+ *
+ * SYNOPSIS
+ *
+ *    static inline
+ *    SilcUInt32 silc_atomic_get_int16(SilcAtomic16 *atomic);
+ *
+ * DESCRIPTION
+ *
+ *    Returns the current value of the atomic variable.
+ *
+ ***/
 
-/****f* silcutil/SilcAtomicAPI/silc_atomic_get_int
+/****f* silcutil/SilcAtomicAPI/silc_atomic_get_int8
  *
  * SYNOPSIS
  *
  *    static inline
- *    SilcUInt32 silc_atomic_get_int(SilcAtomic *atomic);
+ *    SilcUInt32 silc_atomic_get_int8(SilcAtomic8 *atomic);
  *
  * DESCRIPTION
  *
@@ -227,36 +574,692 @@ SilcUInt32 silc_atomic_sub_int(SilcAtomic *atomic, int value)
  *
  ***/
 
-static inline
-SilcUInt32 silc_atomic_get_int(SilcAtomic *atomic)
-{
-  SilcUInt32 ret;
+#define SILC_ATOMIC_GET_INT_F(bits)                                    \
+static inline                                                          \
+SilcUInt##bits silc_atomic_get_int##bits(SilcAtomic##bits *atomic)
 
-#if !defined(SILC_THREADS) || defined(SILC_WIN32) ||                    \
+#if !defined(SILC_THREADS) || defined(SILC_WIN32) ||                   \
      (defined(__GNUC__) && (defined(SILC_I486) || defined(SILC_X86_64)))
-  /* No threads, Windows, i486 or x86_64, no memory barrier needed */
-  ret = atomic->value;
-  return ret;
+#define SILC_ATOMIC_GET_INT(bits)                                      \
+SILC_ATOMIC_GET_INT_F(bits)                                            \
+{                                                                      \
+  SilcUInt##bits ret;                                                  \
+                                                                       \
+  /* No threads, Windows, i486 or x86_64, no memory barrier needed */  \
+  ret = *(volatile SilcUInt##bits *)&atomic->value;                    \
+  return ret;                                                          \
+}
 
 #elif defined(__GNUC__) && defined(SILC_IA64)
-  /* IA64, memory barrier needed */
-  __sync_synchronize();
-  ret = atomic->value;
-  return ret;
+#define SILC_ATOMIC_GET_INT(bits)                                      \
+SILC_ATOMIC_GET_INT_F(bits)                                            \
+{                                                                      \
+  SilcUInt##bits ret;                                                  \
+                                                                       \
+  /* IA64, memory barrier needed */                                    \
+  __sync_synchronize();                                                        \
+  ret = *(volatile SilcUInt##bits *)&atomic->value;                    \
+  return ret;                                                          \
+}
 
 #elif defined(__GNUC__) && defined(SILC_POWERPC)
-  /* PowerPC, memory barrier needed */
+#define SILC_ATOMIC_GET_INT(bits)                                      \
+SILC_ATOMIC_GET_INT_F(bits)                                            \
+{                                                                      \
+  SilcUInt##bits ret;                                                  \
+                                                                       \
+  /* PowerPC, memory barrier needed */                                 \
+  __asm("sync" : : : "memory");                                                \
+  ret = *(volatile SilcUInt##bits *)&atomic->value;                    \
+  return ret;                                                          \
+}
+
+#else /* SILC_ATOMIC_MUTEX */
+#define SILC_ATOMIC_GET_INT(bits)                                      \
+SILC_ATOMIC_GET_INT_F(bits)                                            \
+{                                                                      \
+  SilcUInt##bits ret;                                                  \
+                                                                       \
+  /* Mutex */                                                          \
+  silc_mutex_lock(atomic->lock);                                       \
+  ret = atomic->value;                                                 \
+  silc_mutex_unlock(atomic->lock);                                     \
+  return ret;                                                          \
+}
+#endif /* !SILC_THREADS */
+
+SILC_ATOMIC_GET_INT(8)
+SILC_ATOMIC_GET_INT(16)
+SILC_ATOMIC_GET_INT(32)
+
+/****f* silcutil/SilcAtomicAPI/silc_atomic_get_pointer
+ *
+ * SYNOPSIS
+ *
+ *    static inline
+ *    SilcUInt8 silc_atomic_get_pointer(SilcAtomicPointer *atomic)
+ *
+ * DESCRIPTION
+ *
+ *    Returns the current pointer value of the atomic variable.
+ *
+ ***/
+
+static inline
+void *silc_atomic_get_pointer(SilcAtomicPointer *atomic)
+{
+  void *ret;
+
+#if !defined(SILC_THREADS) || defined(SILC_WIN32) ||                    \
+     (defined(__GNUC__) && (defined(SILC_I486) || defined(SILC_X86_64)))
+  /* No threads, Windows, i486 or x86_64, no memory barrier needed */
+  ret = (void *)*(void * volatile *)&atomic->value;
+  return ret;
+
+#elif defined(__GNUC__) && defined(SILC_IA64)
+  /* IA64, memory barrier needed */
+  __sync_synchronize();
+  ret = (void *)*(void * volatile *)&atomic->value;
+  return ret;
+
+#elif defined(__GNUC__) && defined(SILC_POWERPC)
+  /* PowerPC, memory barrier needed */
   __asm("sync" : : : "memory");
-  ret = atomic->value;
+  ret = (void *)*(void * volatile *)&atomic->value;
   return ret;
 
 #else
   /* Mutex */
   silc_mutex_lock(atomic->lock);
-  ret = atomic->value;
+  ret = (void *)atomic->value;
   silc_mutex_unlock(atomic->lock);
   return ret;
 #endif
 }
 
+/****f* silcutil/SilcAtomicAPI/silc_atomic_add_int32
+ *
+ * SYNOPSIS
+ *
+ *    static inline
+ *    SilcUInt32 silc_atomic_add_int32(SilcAtomic32 *atomic, SilcInt32 value);
+ *
+ * DESCRIPTION
+ *
+ *    Atomically adds `value' to 32-bit integer.  Returns the value after
+ *    addition.
+ *
+ ***/
+
+/****f* silcutil/SilcAtomicAPI/silc_atomic_add_int16
+ *
+ * SYNOPSIS
+ *
+ *    static inline
+ *    SilcUInt16 silc_atomic_add_int16(SilcAtomic16 *atomic, SilcInt16 value);
+ *
+ * DESCRIPTION
+ *
+ *    Atomically adds `value' to 16-bit integer.  Returns the value after
+ *    addition.
+ *
+ ***/
+
+/****f* silcutil/SilcAtomicAPI/silc_atomic_add_int8
+ *
+ * SYNOPSIS
+ *
+ *    static inline
+ *    SilcUInt8 silc_atomic_add_int8(SilcAtomic8 *atomic, SilcInt8 value);
+ *
+ * DESCRIPTION
+ *
+ *    Atomically adds `value' to 8-bit integer.  Returns the value after
+ *    addition.
+ *
+ ***/
+
+#define SILC_ATOMIC_ADD_INT_F(bits)                                    \
+static inline                                                          \
+SilcUInt##bits silc_atomic_add_int##bits(SilcAtomic##bits *atomic,     \
+                                        SilcInt##bits value)
+
+#if !defined(SILC_THREADS)
+#define SILC_ATOMIC_ADD_INT(bits, bp)                                  \
+SILC_ATOMIC_ADD_INT_F(bits)                                            \
+{                                                                      \
+  SilcUInt##bits ret;                                                  \
+  /* No atomic operations */                                           \
+  ret = *(volatile SilcUInt##bits *)&atomic->value;                    \
+  *(volatile SilcUInt##bits *)&atomic->value += value;                 \
+  return ret + value;                                                  \
+}
+
+#elif defined(SILC_WIN32)
+#define SILC_ATOMIC_ADD_INT(bits, bp)                                  \
+SILC_ATOMIC_ADD_INT_F(bits)                                            \
+{                                                                      \
+  SilcUInt##bits ret;                                                  \
+  LONG val = value;                                                    \
+  /* Windows */                                                                \
+  ret = InterlockedExchangeAdd((volatile SilcUInt##bits *)&atomic->value, \
+                              val);                                    \
+  return ret + value;                                                  \
+}
+
+#elif defined(__GNUC__) && (defined(SILC_I486) || defined(SILC_X86_64))
+#define SILC_ATOMIC_ADD_INT(bits, bp)                                  \
+SILC_ATOMIC_ADD_INT_F(bits)                                            \
+{                                                                      \
+  SilcUInt##bits ret;                                                  \
+  /* GCC + i486 or x86_64 */                                           \
+  __asm __volatile(SILC_SMP_LOCK "xadd" bp " %0, %1"                   \
+                  : "=r" (ret), "+m" (atomic->value) : "0" (value));   \
+  return ret + value;                                                  \
+}
+
+#elif defined(__GNUC__) && defined(SILC_IA64)
+#define SILC_ATOMIC_ADD_INT(bits, bp)                                  \
+SILC_ATOMIC_ADD_INT_F(bits)                                            \
+{                                                                      \
+  SilcUInt##bits ret;                                                  \
+  SilcUInt32 val = value;                                              \
+  /* GCC + IA64 (GCC builtin atomic operations) */                     \
+  ret = __sync_fetch_and_add((volatile SilcUInt32 *)&atomic->value, val); \
+  return ret + value;                                                  \
+}
+
+#elif defined(__GNUC__) && defined(SILC_POWERPC)
+#define SILC_ATOMIC_ADD_INT(bits, bp)                                  \
+SILC_ATOMIC_ADD_INT_F(bits)                                            \
+{                                                                      \
+  SilcUInt32 ret;                                                      \
+  SilcUInt32 val = value;                                              \
+  /* GCC + PowerPC (code adapted from IBM's documentation) */          \
+  __asm __volatile("0: lwarx  %0,  0, %2\n"                            \
+                  "   add    %0, %1, %0\n"                             \
+                  "   stwcx. %0,  0, %2\n"                             \
+                  "   bne-   0b"                                       \
+                  : "=&r" (ret)                                        \
+                  : "r" (val), "r" (&atomic->value)                    \
+                  : "cc");                                             \
+  return ret;                                                          \
+}
+
+#else /* SILC_ATOMIC_MUTEX */
+#define SILC_ATOMIC_ADD_INT(bits, bp)                                  \
+SILC_ATOMIC_ADD_INT_F(bits)                                            \
+{                                                                      \
+  SilcUInt##bits ret;                                                  \
+  /* Mutex */                                                          \
+  silc_mutex_lock(atomic->lock);                                       \
+  ret = atomic->value;                                                 \
+  atomic->value += value;                                              \
+  silc_mutex_unlock(atomic->lock);                                     \
+  return ret + value;                                                  \
+}
+#endif /* !SILC_THREADS */
+
+SILC_ATOMIC_ADD_INT(8, "b")
+SILC_ATOMIC_ADD_INT(16, "w")
+SILC_ATOMIC_ADD_INT(32, "l")
+
+/****f* silcutil/SilcAtomicAPI/silc_atomic_sub_int32
+ *
+ * SYNOPSIS
+ *
+ *    static inline
+ *    SilcUInt32 silc_atomic_sub_int32(SilcAtomic32 *atomic, SilcInt32 value);
+ *
+ * DESCRIPTION
+ *
+ *    Atomically subtracts `value' from 32-bit integer.  Returns the value
+ *    after subtraction.
+ *
+ ***/
+
+/****f* silcutil/SilcAtomicAPI/silc_atomic_sub_int16
+ *
+ * SYNOPSIS
+ *
+ *    static inline
+ *    SilcUInt16 silc_atomic_sub_int16(SilcAtomic16 *atomic, SilcInt16 value);
+ *
+ * DESCRIPTION
+ *
+ *    Atomically subtracts `value' from 16-bit integer.  Returns the value
+ *    after subtraction.
+ *
+ ***/
+
+/****f* silcutil/SilcAtomicAPI/silc_atomic_sub_int8
+ *
+ * SYNOPSIS
+ *
+ *    static inline
+ *    SilcUInt8 silc_atomic_sub_int8(SilcAtomic8 *atomic, SilcInt8 value);
+ *
+ * DESCRIPTION
+ *
+ *    Atomically subtracts `value' from 8-bit integer.  Returns the value
+ *    after subtraction.
+ *
+ ***/
+
+#define silc_atomic_sub_int8(a, v) silc_atomic_add_int8(a, (-v))
+#define silc_atomic_sub_int16(a, v) silc_atomic_add_int16(a, (-v))
+#define silc_atomic_sub_int32(a, v) silc_atomic_add_int32(a, (-v))
+
+/****f* silcutil/SilcAtomicAPI/silc_atomic_inc32
+ *
+ * SYNOPSIS
+ *
+ *    static inline
+ *    void silc_atomic_inc32(SilcAtomic32 *atomic);
+ *
+ * DESCRIPTION
+ *
+ *    Atomically increments 32-bit integer by one.
+ *
+ ***/
+
+/****f* silcutil/SilcAtomicAPI/silc_atomic_inc16
+ *
+ * SYNOPSIS
+ *
+ *    static inline
+ *    void silc_atomic_inc16(SilcAtomic16 *atomic);
+ *
+ * DESCRIPTION
+ *
+ *    Atomically increments 16-bit integer by one.
+ *
+ ***/
+
+/****f* silcutil/SilcAtomicAPI/silc_atomic_inc8
+ *
+ * SYNOPSIS
+ *
+ *    static inline
+ *    void silc_atomic_inc8(SilcAtomic8 *atomic);
+ *
+ * DESCRIPTION
+ *
+ *    Atomically increments 8-bit integer by one.
+ *
+ ***/
+
+#define SILC_ATOMIC_INC_F(bits)                                                \
+static inline void silc_atomic_inc##bits(SilcAtomic##bits *atomic)
+
+#if !defined(SILC_THREADS)
+#define SILC_ATOMIC_INC(bits, bp)                                      \
+SILC_ATOMIC_INC_F(bits)                                                        \
+{                                                                      \
+  /* No atomic operations */                                           \
+  ++atomic->value;                                                     \
+}
+
+#elif defined(SILC_WIN32)
+#define SILC_ATOMIC_INC(bits, bp)                                      \
+SILC_ATOMIC_INC_F(bits)                                                        \
+{                                                                      \
+  /* Windows */                                                                \
+  InterlockedIncrement((LONG *)&atomic->value);                                \
+}
+
+#elif defined(__GNUC__) && (defined(SILC_I486) || defined(SILC_X86_64))
+#define SILC_ATOMIC_INC(bits, bp)                                      \
+SILC_ATOMIC_INC_F(bits)                                                        \
+{                                                                      \
+  /* GCC + i486 or x86_64 */                                           \
+  __asm __volatile(SILC_SMP_LOCK "inc" bp " %0"                                \
+                  : "+m" (atomic->value));                             \
+}
+
+#elif defined(__GNUC__) && defined(SILC_IA64)
+#define SILC_ATOMIC_INC(bits, bp)                                      \
+SILC_ATOMIC_INC_F(bits)                                                        \
+{                                                                      \
+  /* GCC + IA64 (GCC builtin atomic operations) */                     \
+  __sync_fetch_and_add((volatile SilcUInt##bits *)&atomic->value, 1);  \
+}
+
+#elif defined(__GNUC__) && defined(SILC_POWERPC)
+#define SILC_ATOMIC_INC(bits, bp)                                      \
+SILC_ATOMIC_INC_F(bits)                                                        \
+{                                                                      \
+  SilcUInt32 ret;                                                      \
+  SilcInt32 val = 1;                                                   \
+  /* GCC + PowerPC (code adapted from IBM's documentation) */          \
+  __asm __volatile("0: lwarx  %0,  0, %2\n"                            \
+                  "   add    %0, %1, %0\n"                             \
+                  "   stwcx. %0,  0, %2\n"                             \
+                  "   bne-   0b"                                       \
+                  : "=&r" (ret)                                        \
+                  : "r" (val), "r" (&atomic->value)                    \
+                  : "cc");                                             \
+}
+
+#else /* SILC_ATOMIC_MUTEX */
+#define SILC_ATOMIC_INC(bits, bp)                                      \
+SILC_ATOMIC_INC_F(bits)                                                        \
+{                                                                      \
+  /* Mutex */                                                          \
+  silc_mutex_lock(atomic->lock);                                       \
+  ++atomic->value;                                                     \
+  silc_mutex_unlock(atomic->lock);                                     \
+}
+#endif /* !SILC_THREADS */
+
+SILC_ATOMIC_INC(8, "b")
+SILC_ATOMIC_INC(16, "w")
+SILC_ATOMIC_INC(32, "l")
+
+/****f* silcutil/SilcAtomicAPI/silc_atomic_dec32
+ *
+ * SYNOPSIS
+ *
+ *    static inline
+ *    void silc_atomic_dec32(SilcAtomic32 *atomic);
+ *
+ * DESCRIPTION
+ *
+ *    Atomically decrements 32-bit integer by one.
+ *
+ ***/
+
+/****f* silcutil/SilcAtomicAPI/silc_atomic_dec16
+ *
+ * SYNOPSIS
+ *
+ *    static inline
+ *    void silc_atomic_dec16(SilcAtomic16 *atomic);
+ *
+ * DESCRIPTION
+ *
+ *    Atomically decrements 16-bit integer by one.
+ *
+ ***/
+
+/****f* silcutil/SilcAtomicAPI/silc_atomic_dec8
+ *
+ * SYNOPSIS
+ *
+ *    static inline
+ *    void silc_atomic_dec8(SilcAtomic8 *atomic);
+ *
+ * DESCRIPTION
+ *
+ *    Atomically decrements 8-bit integer by one.
+ *
+ ***/
+
+#define SILC_ATOMIC_DEC_F(bits)                                                \
+static inline void silc_atomic_dec##bits(SilcAtomic##bits *atomic)
+
+#if !defined(SILC_THREADS)
+#define SILC_ATOMIC_DEC(bits, bp)                                      \
+SILC_ATOMIC_DEC_F(bits)                                                        \
+{                                                                      \
+  /* No atomic operations */                                           \
+  --atomic->value;                                                     \
+}
+
+#elif defined(SILC_WIN32)
+#define SILC_ATOMIC_DEC(bits, bp)                                      \
+SILC_ATOMIC_DEC_F(bits)                                                        \
+{                                                                      \
+  /* Windows */                                                                \
+  InterlockedDecrement((LONG *)&atomic->value);                                \
+}
+
+#elif defined(__GNUC__) && (defined(SILC_I486) || defined(SILC_X86_64))
+#define SILC_ATOMIC_DEC(bits, bp)                                      \
+SILC_ATOMIC_DEC_F(bits)                                                        \
+{                                                                      \
+  /* GCC + i486 or x86_64 */                                           \
+  __asm __volatile(SILC_SMP_LOCK "dec" bp " %0"                                \
+                  : "+m" (atomic->value));                             \
+}
+
+#elif defined(__GNUC__) && defined(SILC_IA64)
+#define SILC_ATOMIC_DEC(bits, bp)                                      \
+SILC_ATOMIC_DEC_F(bits)                                                        \
+{                                                                      \
+  /* GCC + IA64 (GCC builtin atomic operations) */                     \
+  __sync_fetch_and_sub((volatile SilcUInt##bits *)&atomic->value, 1);  \
+}
+
+#elif defined(__GNUC__) && defined(SILC_POWERPC)
+#define SILC_ATOMIC_DEC(bits, bp)                                      \
+SILC_ATOMIC_DEC_F(bits)                                                        \
+{                                                                      \
+  SilcUInt32 ret;                                                      \
+  SilcInt32 val = -1;                                                  \
+  /* GCC + PowerPC (code adapted from IBM's documentation) */          \
+  __asm __volatile("0: lwarx  %0,  0, %2\n"                            \
+                  "   add    %0, %1, %0\n"                             \
+                  "   stwcx. %0,  0, %2\n"                             \
+                  "   bne-   0b"                                       \
+                  : "=&r" (ret)                                        \
+                  : "r" (val), "r" (&atomic->value)                    \
+                  : "cc");                                             \
+}
+
+#else /* SILC_ATOMIC_MUTEX */
+#define SILC_ATOMIC_DEC(bits, bp)                                      \
+SILC_ATOMIC_DEC_F(bits)                                                        \
+{                                                                      \
+  /* Mutex */                                                          \
+  silc_mutex_lock(atomic->lock);                                       \
+  --atomic->value;                                                     \
+  silc_mutex_unlock(atomic->lock);                                     \
+}
+#endif /* !SILC_THREADS */
+
+SILC_ATOMIC_DEC(8, "b")
+SILC_ATOMIC_DEC(16, "w")
+SILC_ATOMIC_DEC(32, "l")
+
+/****f* silcutil/SilcAtomicAPI/silc_atomic_cas32
+ *
+ * SYNOPSIS
+ *
+ *    static inline
+ *    SilcBool silc_atomic_cas32(SilcAtomic32 *atomic, SilcUInt32 old_val,
+ *                               SilcUInt32 new_val)
+ *
+ * DESCRIPTION
+ *
+ *    Performs compare and swap (CAS).  Atomically compares if the variable
+ *    `atomic' has the value `old_val' and in that case swaps it with the
+ *    value `new_val'.  Returns TRUE if the old value was same and it was
+ *    swapped and FALSE if it differed and was not swapped.
+ *
+ ***/
+
+/****f* silcutil/SilcAtomicAPI/silc_atomic_cas16
+ *
+ * SYNOPSIS
+ *
+ *    static inline
+ *    SilcBool silc_atomic_cas16(SilcAtomic16 *atomic, SilcUInt16 old_val,
+ *                               SilcUInt16 new_val)
+ *
+ * DESCRIPTION
+ *
+ *    Performs compare and swap (CAS).  Atomically compares if the variable
+ *    `atomic' has the value `old_val' and in that case swaps it with the
+ *    value `new_val'.  Returns TRUE if the old value was same and it was
+ *    swapped and FALSE if it differed and was not swapped.
+ *
+ ***/
+
+/****f* silcutil/SilcAtomicAPI/silc_atomic_cas8
+ *
+ * SYNOPSIS
+ *
+ *    static inline
+ *    SilcBool silc_atomic_cas8(SilcAtomic8 *atomic, SilcUInt8 old_val,
+ *                              SilcUInt8 new_val)
+ *
+ * DESCRIPTION
+ *
+ *    Performs compare and swap (CAS).  Atomically compares if the variable
+ *    `atomic' has the value `old_val' and in that case swaps it with the
+ *    value `new_val'.  Returns TRUE if the old value was same and it was
+ *    swapped and FALSE if it differed and was not swapped.
+ *
+ ***/
+
+#define SILC_ATOMIC_CAS_F(bits)                                                \
+static inline SilcBool silc_atomic_cas##bits(SilcAtomic##bits *atomic,  \
+                                            SilcInt##bits old_val,     \
+                                            SilcInt##bits new_val)
+
+#if !defined(SILC_THREADS)
+#define SILC_ATOMIC_CAS(bits, bp)                                      \
+SILC_ATOMIC_CAS_F(bits)                                                        \
+{                                                                      \
+  /* No atomic operations */                                           \
+  if (atomic->value == (SilcUInt##bits)old_val) {                      \
+    atomic->value = new_val;                                           \
+    return TRUE;                                                       \
+  }                                                                    \
+  return FALSE;                                                                \
+}
+
+#elif defined(SILC_WIN32)
+#define SILC_ATOMIC_CAS(bits, bp)                                      \
+SILC_ATOMIC_CAS_F(bits)                                                        \
+{                                                                      \
+  /* Windows */                                                                \
+  LONG o = old_val, n = new_val;                                       \
+  return InterlockedCompareExchange(&atomic->value, n, o) == o;        \
+}
+
+#elif defined(__GNUC__) && (defined(SILC_I486) || defined(SILC_X86_64))
+#define SILC_ATOMIC_CAS(bits, bp)                                      \
+SILC_ATOMIC_CAS_F(bits)                                                        \
+{                                                                      \
+  /* GCC + i486 or x86_64 */                                           \
+  SilcUInt##bits ret;                                                  \
+  __asm __volatile(SILC_SMP_LOCK "cmpxchg" bp " %2, %1"                        \
+                  : "=a" (ret), "=m" (atomic->value)                   \
+                  : "r" (new_val), "m" (atomic->value),                \
+                  "0" (old_val));                                      \
+  return ret == (SilcUInt##bits)old_val;                               \
+}
+
+#elif defined(__GNUC__) && defined(SILC_IA64)
+#define SILC_ATOMIC_CAS(bits, bp)                                      \
+SILC_ATOMIC_CAS_F(bits)                                                        \
+{                                                                      \
+  /* GCC + IA64 (GCC builtin atomic operations) */                     \
+  SilcUInt32 o = old_val, n = new_val;                                 \
+  return __sync_bool_compare_and_swap((volatile SilcUInt32 *)&atomic->value, \
+                                     o, n);                            \
+}
+
+#elif defined(__GNUC__) && defined(SILC_POWERPC)
+#define SILC_ATOMIC_CAS(bits, bp)                                      \
+SILC_ATOMIC_CAS_F(bits)                                                        \
+{                                                                      \
+  /* GCC + PowerPC */                                                  \
+  /* XXX TODO */                                                       \
+}
+
+#else /* SILC_ATOMIC_MUTEX */
+#define SILC_ATOMIC_CAS(bits, bp)                                      \
+SILC_ATOMIC_CAS_F(bits)                                                        \
+{                                                                      \
+  /* Mutex */                                                          \
+  silc_mutex_lock(atomic->lock);                                       \
+  if (atomic->value == (SilcUInt##bits)old_val) {                      \
+    atomic->value = new_val;                                           \
+    silc_mutex_unlock(atomic->lock);                                   \
+    return TRUE;                                                       \
+  }                                                                    \
+  silc_mutex_unlock(atomic->lock);                                     \
+  return FALSE;                                                                \
+}
+#endif /* !SILC_THREADS */
+
+SILC_ATOMIC_CAS(8, "b")
+SILC_ATOMIC_CAS(16, "w")
+SILC_ATOMIC_CAS(32, "l")
+
+/****f* silcutil/SilcAtomicAPI/silc_atomic_cas_pointer
+ *
+ * SYNOPSIS
+ *
+ *    static inline
+ *    SilcBool silc_atomic_cas_pointer(SilcAtomicPointer *atomic,
+ *                                     void *old_ptr, void *new_ptr);
+ *
+ * DESCRIPTION
+ *
+ *    Performs compare and swap (CAS).  Atomically compares if the variable
+ *    `atomic' has the pointer `old_ptr' and in that case swaps it with the
+ *    pointer `new_ptr'.  Returns TRUE if the old pointer was same and it was
+ *    swapped and FALSE if it differed and was not swapped.
+ *
+ ***/
+
+static inline
+SilcBool silc_atomic_cas_pointer(SilcAtomicPointer *atomic, void *old_val,
+                                void *new_val)
+{
+#if !defined(SILC_THREADS)
+  /* No atomic operations */
+  if (atomic->value == old_val) {
+    atomic->value = new_val;
+    return TRUE;
+  }
+  return FALSE;
+
+#elif defined(SILC_WIN32)
+  /* Windows */
+  return InterlockedCompareExchangePointer(&atomic->value, new_val, old_val)
+    == old_val;
+
+#elif defined(__GNUC__) && defined(SILC_I486)
+  /* GCC + i486 */
+  void *ret;
+  __asm __volatile(SILC_SMP_LOCK "cmpxchgl %2, %1"
+                  : "=a" (ret), "=m" (atomic->value)
+                  : "c" (new_val), "m" (atomic->value), "0" (old_val));
+  return ret == old_val;
+
+#elif defined(__GNUC__) && defined(SILC_X86_64)
+  /* GCC + x86_64 */
+  void *ret;
+  __asm __volatile(SILC_SMP_LOCK "cmpxchgq %q2, %1"
+                  : "=a" (ret), "=m" (atomic->value)
+                  : "c" (new_val), "m" (atomic->value), "0" (old_val));
+  return ret == old_val;
+
+#elif defined(__GNUC__) && defined(SILC_IA64)
+  /* GCC + IA64 (GCC builtin atomic operations) */
+  return  __sync_bool_compare_and_swap((long *)&atomic->value, (long)old_val,
+                                      (long)new_val);
+
+#elif defined(__GNUC__) && defined(SILC_POWERPC)
+  /* GCC + PowerPC */
+  /* XXX TODO */
+
+#else
+  /* Mutex */
+  silc_mutex_lock(atomic->lock);
+  if (atomic->value == old_val) {
+    atomic->value = new_val;
+    silc_mutex_unlock(atomic->lock);
+    return TRUE;
+  }
+  silc_mutex_unlock(atomic->lock);
+  return FALSE;
+#endif
+}
+
 #endif /* SILCATOMIC_H */