Author: Pekka Riikonen <priikone@silcnet.org>
- Copyright (C) 2006 - 2007 Pekka Riikonen
+ Copyright (C) 2006 - 2008 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
*/
-/****h* silcutil/SILC Atomic Operations Interface
+/****h* silcutil/Atomic Operations Interface
*
* DESCRIPTION
*
#define SILC_SMP_LOCK
#endif /* SILC_SMP */
-/****s* silcutil/SilcAtomicAPI/SilcAtomic32
+/****s* silcutil/SilcAtomic32
*
* NAME
*
*
***/
-/****s* silcutil/SilcAtomicAPI/SilcAtomic16
+/****s* silcutil/SilcAtomic16
*
* NAME
*
*
***/
-/****s* silcutil/SilcAtomicAPI/SilcAtomic8
+/****s* silcutil/SilcAtomic8
*
* NAME
*
*
***/
-/****s* silcutil/SilcAtomicAPI/SilcAtomicPointer
+/****s* silcutil/SilcAtomicPointer
*
* NAME
*
(defined(SILC_I486) || defined(SILC_X86_64) || defined(SILC_IA64) || \
defined(SILC_POWERPC)))
typedef struct {
- volatile SilcUInt32 value;
+ SilcUInt32 value;
} SilcAtomic32;
typedef struct {
- volatile void *value;
+ void *value;
} SilcAtomicPointer;
#else
#define SILC_ATOMIC_MUTEX
typedef struct {
SilcMutex lock;
- volatile SilcUInt32 value;
+ SilcUInt32 value;
} SilcAtomic32;
typedef struct {
SilcMutex lock;
- volatile void *value;
+ void *value;
} SilcAtomicPointer;
#endif
#if !defined(SILC_THREADS) || (defined(__GNUC__) && (defined(SILC_I486) || \
defined(SILC_X86_64)))
typedef struct {
- volatile SilcUInt16 value;
+ SilcUInt16 value;
} SilcAtomic16;
#elif defined(SILC_WIN32) || (defined(__GNUC__) && (defined(SILC_IA64) || \
defined(SILC_POWERPC)))
typedef struct {
- volatile SilcUInt32 value;
+ SilcUInt32 value;
} SilcAtomic16;
#else
typedef struct {
SilcMutex lock;
- volatile SilcUInt16 value;
+ SilcUInt16 value;
} SilcAtomic16;
#endif
#if !defined(SILC_THREADS) || (defined(__GNUC__) && (defined(SILC_I486) || \
defined(SILC_X86_64)))
typedef struct {
- volatile SilcUInt8 value;
+ SilcUInt8 value;
} SilcAtomic8;
#elif defined(SILC_WIN32) || (defined(__GNUC__) && (defined(SILC_IA64) || \
defined(SILC_POWERPC)))
typedef struct {
- volatile SilcUInt32 value;
+ SilcUInt32 value;
} SilcAtomic8;
#else
typedef struct {
SilcMutex lock;
- volatile SilcUInt8 value;
+ SilcUInt8 value;
} SilcAtomic8;
#endif
-/****f* silcutil/SilcAtomicAPI/silc_atomic_init32
+/****f* silcutil/silc_atomic_init32
*
* SYNOPSIS
*
*
***/
-/****f* silcutil/SilcAtomicAPI/silc_atomic_init16
+/****f* silcutil/silc_atomic_init16
*
* SYNOPSIS
*
*
***/
-/****f* silcutil/SilcAtomicAPI/silc_atomic_init8
+/****f* silcutil/silc_atomic_init8
*
* SYNOPSIS
*
*
***/
-/****f* silcutil/SilcAtomicAPI/silc_atomic_init_pointer
+/****f* silcutil/silc_atomic_init_pointer
*
* SYNOPSIS
*
#define SILC_ATOMIC_INIT(name, bits, type) \
SILC_ATOMIC_INIT_F(name, bits, type) \
{ \
- atomic->value = value; \
+ *(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) \
{ \
- atomic->value = value; \
+ *(type volatile *)&atomic->value = value; \
return TRUE; \
}
#endif /* SILC_ATOMIC_MUTEX */
SILC_ATOMIC_INIT(32, 32, SilcUInt32)
SILC_ATOMIC_INIT(_pointer, Pointer, void *)
-/****f* silcutil/SilcAtomicAPI/silc_atomic_uninit32
+/****f* silcutil/silc_atomic_uninit32
*
* SYNOPSIS
*
*
***/
-/****f* silcutil/SilcAtomicAPI/silc_atomic_uninit16
+/****f* silcutil/silc_atomic_uninit16
*
* SYNOPSIS
*
*
***/
-/****f* silcutil/SilcAtomicAPI/silc_atomic_uninit8
+/****f* silcutil/silc_atomic_uninit8
*
* SYNOPSIS
*
*
***/
-/****f* silcutil/SilcAtomicAPI/silc_atomic_uninit_pointer
+/****f* silcutil/silc_atomic_uninit_pointer
*
* SYNOPSIS
*
SILC_ATOMIC_UNINIT(32, 32)
SILC_ATOMIC_UNINIT(_pointer, Pointer)
-/****f* silcutil/SilcAtomicAPI/silc_atomic_set_int32
+/****f* silcutil/silc_atomic_set_int32
*
* SYNOPSIS
*
*
***/
-/****f* silcutil/SilcAtomicAPI/silc_atomic_set_int16
+/****f* silcutil/silc_atomic_set_int16
*
* SYNOPSIS
*
*
***/
-/****f* silcutil/SilcAtomicAPI/silc_atomic_set_int8
+/****f* silcutil/silc_atomic_set_int8
*
* SYNOPSIS
*
SILC_ATOMIC_SET_INT_F(bits) \
{ \
/* Windows */ \
- InterlockedExchange((LONG)&atomic->value, (LONG)value); \
+ InterlockedExchange((LONG *)&atomic->value, (LONG)value); \
}
#elif defined(__GNUC__) && (defined(SILC_I486) || defined(SILC_X86_64))
SILC_ATOMIC_SET_INT_F(bits) \
{ \
/* IA64, memory barrier needed */ \
- atomic->value = value; \
+ *(volatile SilcUInt##bits *)&atomic->value = value; \
__sync_synchronize(); \
}
SILC_ATOMIC_SET_INT_F(bits) \
{ \
/* PowerPC, memory barrier needed */ \
- atomic->value = value; \
+ *(volatile SilcUInt##bits *)&atomic->value = &value; \
__asm("sync" : : : "memory"); \
}
SILC_ATOMIC_SET_INT(16, "w", "w")
SILC_ATOMIC_SET_INT(32, "l", "")
-/****f* silcutil/SilcAtomicAPI/silc_atomic_set_pointer
+/****f* silcutil/silc_atomic_set_pointer
*
* SYNOPSIS
*
#if !defined(SILC_THREADS) || \
(defined(__GNUC__) && (defined(SILC_I486) || defined(SILC_X86_64)))
/* No threads, Windows, i486 or x86_64, no memory barrier needed */
- atomic->value = pointer;
+ *(void * volatile *)&atomic->value = pointer;
#elif defined(SILC_WIN32)
InterlockedExchangePointer(&atomic->value, pointer);
#elif defined(__GNUC__) && defined(SILC_IA64)
/* IA64, memory barrier needed */
- atomic->value = pointer;
+ *(void * volatile *)&atomic->value = pointer;
__sync_synchronize();
#elif defined(__GNUC__) && defined(SILC_POWERPC)
/* PowerPC, memory barrier needed */
- atomic->value = pointer;
+ *(void * volatile *)&atomic->value = pointer;
__asm("sync" : : : "memory");
#else
#endif
}
-/****f* silcutil/SilcAtomicAPI/silc_atomic_get_int32
+/****f* silcutil/silc_atomic_get_int32
*
* SYNOPSIS
*
*
***/
-/****f* silcutil/SilcAtomicAPI/silc_atomic_get_int16
+/****f* silcutil/silc_atomic_get_int16
*
* SYNOPSIS
*
*
***/
-/****f* silcutil/SilcAtomicAPI/silc_atomic_get_int8
+/****f* silcutil/silc_atomic_get_int8
*
* SYNOPSIS
*
SilcUInt##bits ret; \
\
/* No threads, Windows, i486 or x86_64, no memory barrier needed */ \
- ret = atomic->value; \
+ ret = *(volatile SilcUInt##bits *)&atomic->value; \
return ret; \
}
\
/* IA64, memory barrier needed */ \
__sync_synchronize(); \
- ret = atomic->value; \
+ ret = *(volatile SilcUInt##bits *)&atomic->value; \
return ret; \
}
\
/* PowerPC, memory barrier needed */ \
__asm("sync" : : : "memory"); \
- ret = atomic->value; \
+ ret = *(volatile SilcUInt##bits *)&atomic->value; \
return ret; \
}
SILC_ATOMIC_GET_INT(16)
SILC_ATOMIC_GET_INT(32)
-/****f* silcutil/SilcAtomicAPI/silc_atomic_get_pointer
+/****f* silcutil/silc_atomic_get_pointer
*
* SYNOPSIS
*
#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 *)atomic->value;
+ ret = (void *)*(void * volatile *)&atomic->value;
return ret;
#elif defined(__GNUC__) && defined(SILC_IA64)
/* IA64, memory barrier needed */
__sync_synchronize();
- ret = (void *)atomic->value;
+ ret = (void *)*(void * volatile *)&atomic->value;
return ret;
#elif defined(__GNUC__) && defined(SILC_POWERPC)
/* PowerPC, memory barrier needed */
__asm("sync" : : : "memory");
- ret = (void *)atomic->value;
+ ret = (void *)*(void * volatile *)&atomic->value;
return ret;
#else
#endif
}
-/****f* silcutil/SilcAtomicAPI/silc_atomic_add_int32
+/****f* silcutil/silc_atomic_add_int32
*
* SYNOPSIS
*
*
***/
-/****f* silcutil/SilcAtomicAPI/silc_atomic_add_int16
+/****f* silcutil/silc_atomic_add_int16
*
* SYNOPSIS
*
*
***/
-/****f* silcutil/SilcAtomicAPI/silc_atomic_add_int8
+/****f* silcutil/silc_atomic_add_int8
*
* SYNOPSIS
*
{ \
SilcUInt##bits ret; \
/* No atomic operations */ \
- ret = atomic->value; \
- atomic->value += value; \
+ ret = *(volatile SilcUInt##bits *)&atomic->value; \
+ *(volatile SilcUInt##bits *)&atomic->value += value; \
return ret + value; \
}
SilcUInt##bits ret; \
LONG val = value; \
/* Windows */ \
- ret = InterlockedExchangeAdd(&atomic->value, val); \
+ ret = InterlockedExchangeAdd((volatile SilcUInt##bits *)&atomic->value, \
+ val); \
return ret + value; \
}
SilcUInt##bits ret; \
/* GCC + i486 or x86_64 */ \
__asm __volatile(SILC_SMP_LOCK "xadd" bp " %0, %1" \
- : "=r" (ret), "+m" (atomic->value) \
- : "0" (value)); \
+ : "=r" (ret), "+m" (atomic->value) : "0" (value)); \
return ret + value; \
}
SILC_ATOMIC_ADD_INT_F(bits) \
{ \
SilcUInt##bits ret; \
- SilcInt32 val = value; \
+ SilcUInt32 val = value; \
/* GCC + IA64 (GCC builtin atomic operations) */ \
- ret = __sync_fetch_and_add(&atomic->value, val); \
+ ret = __sync_fetch_and_add((volatile SilcUInt32 *)&atomic->value, val); \
return ret + value; \
}
SILC_ATOMIC_ADD_INT_F(bits) \
{ \
SilcUInt32 ret; \
- SilcInt32 val = value; \
+ SilcUInt32 val = value; \
/* GCC + PowerPC (code adapted from IBM's documentation) */ \
__asm __volatile("0: lwarx %0, 0, %2\n" \
" add %0, %1, %0\n" \
SILC_ATOMIC_ADD_INT(16, "w")
SILC_ATOMIC_ADD_INT(32, "l")
-/****f* silcutil/SilcAtomicAPI/silc_atomic_sub_int32
+/****f* silcutil/silc_atomic_sub_int32
*
* SYNOPSIS
*
*
***/
-/****f* silcutil/SilcAtomicAPI/silc_atomic_sub_int16
+/****f* silcutil/silc_atomic_sub_int16
*
* SYNOPSIS
*
*
***/
-/****f* silcutil/SilcAtomicAPI/silc_atomic_sub_int8
+/****f* silcutil/silc_atomic_sub_int8
*
* SYNOPSIS
*
#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
+/****f* silcutil/silc_atomic_inc32
*
* SYNOPSIS
*
*
***/
-/****f* silcutil/SilcAtomicAPI/silc_atomic_inc16
+/****f* silcutil/silc_atomic_inc16
*
* SYNOPSIS
*
*
***/
-/****f* silcutil/SilcAtomicAPI/silc_atomic_inc8
+/****f* silcutil/silc_atomic_inc8
*
* SYNOPSIS
*
SILC_ATOMIC_INC_F(bits) \
{ \
/* Windows */ \
- InterlockedIncrement((LONG)&atomic->value); \
+ InterlockedIncrement((LONG *)&atomic->value); \
}
#elif defined(__GNUC__) && (defined(SILC_I486) || defined(SILC_X86_64))
SILC_ATOMIC_INC_F(bits) \
{ \
/* GCC + IA64 (GCC builtin atomic operations) */ \
- __sync_fetch_and_add(&atomic->value, 1); \
+ __sync_fetch_and_add((volatile SilcUInt##bits *)&atomic->value, 1); \
}
#elif defined(__GNUC__) && defined(SILC_POWERPC)
SILC_ATOMIC_INC(16, "w")
SILC_ATOMIC_INC(32, "l")
-/****f* silcutil/SilcAtomicAPI/silc_atomic_dec32
+/****f* silcutil/silc_atomic_dec32
*
* SYNOPSIS
*
*
***/
-/****f* silcutil/SilcAtomicAPI/silc_atomic_dec16
+/****f* silcutil/silc_atomic_dec16
*
* SYNOPSIS
*
*
***/
-/****f* silcutil/SilcAtomicAPI/silc_atomic_dec8
+/****f* silcutil/silc_atomic_dec8
*
* SYNOPSIS
*
SILC_ATOMIC_DEC_F(bits) \
{ \
/* Windows */ \
- InterlockedDecrement((LONG)&atomic->value); \
+ InterlockedDecrement((LONG *)&atomic->value); \
}
#elif defined(__GNUC__) && (defined(SILC_I486) || defined(SILC_X86_64))
SILC_ATOMIC_DEC_F(bits) \
{ \
/* GCC + IA64 (GCC builtin atomic operations) */ \
- __sync_fetch_and_sub(&atomic->value, 1); \
+ __sync_fetch_and_sub((volatile SilcUInt##bits *)&atomic->value, 1); \
}
#elif defined(__GNUC__) && defined(SILC_POWERPC)
SILC_ATOMIC_DEC(16, "w")
SILC_ATOMIC_DEC(32, "l")
-/****f* silcutil/SilcAtomicAPI/silc_atomic_cas32
+/****f* silcutil/silc_atomic_cas32
*
* SYNOPSIS
*
*
***/
-/****f* silcutil/SilcAtomicAPI/silc_atomic_cas16
+/****f* silcutil/silc_atomic_cas16
*
* SYNOPSIS
*
*
***/
-/****f* silcutil/SilcAtomicAPI/silc_atomic_cas8
+/****f* silcutil/silc_atomic_cas8
*
* SYNOPSIS
*
{ \
/* Windows */ \
LONG o = old_val, n = new_val; \
- return InterlockedCompareExchange(&atomic->value, n, o) == o; \
+ return InterlockedCompareExchange(&atomic->value, n, o) == o; \
}
#elif defined(__GNUC__) && (defined(SILC_I486) || defined(SILC_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)); \
+ : "r" (new_val), "m" (atomic->value), \
+ "0" (old_val)); \
return ret == (SilcUInt##bits)old_val; \
}
{ \
/* GCC + IA64 (GCC builtin atomic operations) */ \
SilcUInt32 o = old_val, n = new_val; \
- return __sync_bool_compare_and_swap(&atomic->value, o, n); \
+ return __sync_bool_compare_and_swap((volatile SilcUInt32 *)&atomic->value, \
+ o, n); \
}
#elif defined(__GNUC__) && defined(SILC_POWERPC)
SILC_ATOMIC_CAS(16, "w")
SILC_ATOMIC_CAS(32, "l")
-/****f* silcutil/SilcAtomicAPI/silc_atomic_cas_pointer
+/****f* silcutil/silc_atomic_cas_pointer
*
* SYNOPSIS
*