diff options
author | Chris Robinson <[email protected]> | 2014-05-27 15:48:15 -0700 |
---|---|---|
committer | Chris Robinson <[email protected]> | 2014-05-27 15:48:15 -0700 |
commit | 73614f228eda86e9dc074540989a11a4fd7fb9e9 (patch) | |
tree | f06a99caeba3556be3275ad69f4abcd2e4f1d2ff | |
parent | fd62868c17ce1b7c0a68c6615c0392b09c3661cd (diff) |
Add methods to exchange and compare-exchange RefCount values
-rw-r--r-- | common/atomic.c | 2 | ||||
-rw-r--r-- | include/atomic.h | 38 |
2 files changed, 40 insertions, 0 deletions
diff --git a/common/atomic.c b/common/atomic.c index 95b8f835..634587e4 100644 --- a/common/atomic.c +++ b/common/atomic.c @@ -8,6 +8,8 @@ extern inline void InitRef(volatile RefCount *ptr, uint value); extern inline uint ReadRef(volatile RefCount *ptr); extern inline uint IncrementRef(volatile RefCount *ptr); extern inline uint DecrementRef(volatile RefCount *ptr); +extern inline uint ExchangeRef(volatile RefCount *ptr, uint newval); +extern inline uint CompExchangeRef(volatile RefCount *ptr, uint oldval, uint newval); extern inline int ExchangeInt(volatile int *ptr, int newval); extern inline void *ExchangePtr(XchgPtr *ptr, void *newval); extern inline int CompExchangeInt(volatile int *ptr, int oldval, int newval); diff --git a/include/atomic.h b/include/atomic.h index e8a9d3f4..87a02f7b 100644 --- a/include/atomic.h +++ b/include/atomic.h @@ -23,6 +23,10 @@ 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 uint ExchangeRef(volatile RefCount *ptr, uint newval) +{ return __sync_lock_test_and_set(&ptr->value, newval); } +inline uint CompExchangeRef(volatile RefCount *ptr, uint oldval, uint newval) +{ return __sync_val_compare_and_swap(&ptr->value, oldval, newval); } inline int ExchangeInt(volatile int *ptr, int newval) { return __sync_lock_test_and_set(ptr, newval); } @@ -53,6 +57,24 @@ 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 uint ExchangeRef(volatile RefCount *ptr, uint newval) +{ + int ret; + __asm__ __volatile__("lock; xchgl %0,(%1)" + : "=r" (ret) + : "r" (&ptr->value), "0" (newval) + : "memory"); + return ret; +} +inline uint CompExchangeRef(volatile RefCount *ptr, uint oldval, uint newval) +{ + int ret; + __asm__ __volatile__("lock; cmpxchgl %2,(%1)" + : "=a" (ret) + : "r" (&ptr->value), "r" (newval), "0" (oldval) + : "memory"); + return ret; +} inline int ExchangeInt(volatile int *dest, int newval) { @@ -130,6 +152,22 @@ inline uint DecrementRef(volatile RefCount *ptr) } u = { &ptr->value }; return InterlockedDecrement(u.l); } +inline uint ExchangeRef(volatile RefCount *ptr, uint newval) +{ + union { + volatile uint *i; + volatile LONG *l; + } u = { &ptr->value }; + return InterlockedExchange(u.l, newval); +} +inline uint CompExchangeRef(volatile RefCount *ptr, uint oldval, uint newval) +{ + union { + volatile uint *i; + volatile LONG *l; + } u = { &ptr->value }; + return InterlockedCompareExchange(u.l, newval, oldval); +} inline int ExchangeInt(volatile int *ptr, int newval) { |