aboutsummaryrefslogtreecommitdiffstats
path: root/include/atomic.h
diff options
context:
space:
mode:
authorChris Robinson <[email protected]>2014-05-14 02:47:07 -0700
committerChris Robinson <[email protected]>2014-05-14 02:47:07 -0700
commit1d2504d12e996a4c1e8fe9785901db9a9e3b4d7c (patch)
tree51895ba97192cee1fccab44a838e4fa43d81a984 /include/atomic.h
parent4454ae25c753388c529b937ae2ce0f47f06d16c4 (diff)
Make RefCount a non-integer type
It should only be accessed through the appropriate functions to ensure proper atomicity.
Diffstat (limited to 'include/atomic.h')
-rw-r--r--include/atomic.h54
1 files changed, 35 insertions, 19 deletions
diff --git a/include/atomic.h b/include/atomic.h
index 2fc6ee18..e8a9d3f4 100644
--- a/include/atomic.h
+++ b/include/atomic.h
@@ -5,14 +5,24 @@
typedef void *volatile XchgPtr;
-typedef unsigned int RefCount;
+
+typedef unsigned int uint;
+typedef union {
+ uint value;
+} RefCount;
+
+#define STATIC_REFCOUNT_INIT(V) {(V)}
#if defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 1)) && !defined(__QNXNTO__)
-inline RefCount IncrementRef(volatile RefCount *ptr)
-{ return __sync_add_and_fetch(ptr, 1); }
-inline RefCount DecrementRef(volatile RefCount *ptr)
-{ return __sync_sub_and_fetch(ptr, 1); }
+inline void InitRef(volatile RefCount *ptr, uint value)
+{ ptr->value = value; }
+inline uint ReadRef(volatile RefCount *ptr)
+{ __sync_synchronize(); return ptr->value; }
+inline uint IncrementRef(volatile RefCount *ptr)
+{ return __sync_add_and_fetch(&ptr->value, 1); }
+inline uint DecrementRef(volatile RefCount *ptr)
+{ return __sync_sub_and_fetch(&ptr->value, 1); }
inline int ExchangeInt(volatile int *ptr, int newval)
{ return __sync_lock_test_and_set(ptr, newval); }
@@ -25,7 +35,7 @@ inline void *CompExchangePtr(XchgPtr *ptr, void *oldval, void *newval)
#elif defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
-inline unsigned int xaddl(volatile unsigned int *dest, int incr)
+inline uint xaddl(volatile uint *dest, int incr)
{
unsigned int ret;
__asm__ __volatile__("lock; xaddl %0,(%1)"
@@ -35,10 +45,14 @@ inline unsigned int xaddl(volatile unsigned int *dest, int incr)
return ret;
}
-inline RefCount IncrementRef(volatile RefCount *ptr)
-{ return xaddl(ptr, 1)+1; }
-inline RefCount DecrementRef(volatile RefCount *ptr)
-{ return xaddl(ptr, -1)-1; }
+inline void InitRef(volatile RefCount *ptr, uint value)
+{ ptr->value = value; }
+inline uint ReadRef(volatile RefCount *ptr)
+{ __asm__ __volatile__("" ::: "memory"); return ptr->value; }
+inline uint IncrementRef(volatile RefCount *ptr)
+{ return xaddl(&ptr->value, 1)+1; }
+inline uint DecrementRef(volatile RefCount *ptr)
+{ return xaddl(&ptr->value, -1)-1; }
inline int ExchangeInt(volatile int *dest, int newval)
{
@@ -94,27 +108,29 @@ inline void *CompExchangePtr(XchgPtr *dest, void *oldval, void *newval)
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
-static_assert(sizeof(LONG)==sizeof(RefCount), "sizeof LONG does not match sizeof RefCount");
+static_assert(sizeof(LONG)==sizeof(uint), "sizeof LONG does not match sizeof uint");
-inline RefCount IncrementRef(volatile RefCount *ptr)
+inline void InitRef(volatile RefCount *ptr, uint value)
+{ ptr->value = value; }
+inline uint ReadRef(volatile RefCount *ptr)
+{ _ReadBarrier(); return ptr->value; }
+inline uint IncrementRef(volatile RefCount *ptr)
{
union {
- volatile RefCount *u;
+ volatile uint *u;
volatile LONG *l;
- } u = { ptr };
+ } u = { &ptr->value };
return InterlockedIncrement(u.l);
}
-inline RefCount DecrementRef(volatile RefCount *ptr)
+inline uint DecrementRef(volatile RefCount *ptr)
{
union {
- volatile RefCount *u;
+ volatile uint *u;
volatile LONG *l;
- } u = { ptr };
+ } u = { &ptr->value };
return InterlockedDecrement(u.l);
}
-static_assert(sizeof(LONG)==sizeof(int), "sizeof LONG does not match sizeof int");
-
inline int ExchangeInt(volatile int *ptr, int newval)
{
union {