diff options
author | ed <ed@FreeBSD.org> | 2013-06-30 10:38:20 +0000 |
---|---|---|
committer | ed <ed@FreeBSD.org> | 2013-06-30 10:38:20 +0000 |
commit | 8d21a8da2cf6b3ab5834d56707c0e9820de6a71f (patch) | |
tree | a84efcd2f92262607ff64fc90eb4b1687b35c586 | |
parent | f288a4ea84db2f6313ae826c213b1032b0e0cd2d (diff) | |
download | FreeBSD-src-8d21a8da2cf6b3ab5834d56707c0e9820de6a71f.zip FreeBSD-src-8d21a8da2cf6b3ab5834d56707c0e9820de6a71f.tar.gz |
Make atomic_fetch_add() and atomic_fetch_sub() work for pointers with GCC 4.2.
According to the standard, atomic_fetch_*() has to behave identical to
regular arithmetic. This means that for pointer types, we have to apply
the stride when doing addition/subtraction.
The GCC documentation seems to imply this is done for __sync_*() as
well. Unfortunately, both tests and Googling seems to reveal this is not
really the case. Fix this by performing the multiplication with the
stride manually.
-rw-r--r-- | sys/sys/stdatomic.h | 8 |
1 files changed, 6 insertions, 2 deletions
diff --git a/sys/sys/stdatomic.h b/sys/sys/stdatomic.h index b9c2203..054ded6 100644 --- a/sys/sys/stdatomic.h +++ b/sys/sys/stdatomic.h @@ -281,6 +281,8 @@ typedef _Atomic(__uintmax_t) atomic_uintmax_t; #define atomic_store_explicit(object, desired, order) \ __atomic_store_n(&(object)->__val, desired, order) #else +#define __atomic_apply_stride(object, operand) \ + (((__typeof__((object)->__val))0) + (operand)) #define atomic_compare_exchange_strong_explicit(object, expected, \ desired, success, failure) __extension__ ({ \ __typeof__(expected) __ep = (expected); \ @@ -313,13 +315,15 @@ __extension__ ({ \ }) #endif #define atomic_fetch_add_explicit(object, operand, order) \ - ((void)(order), __sync_fetch_and_add(&(object)->__val, operand)) + ((void)(order), __sync_fetch_and_add(&(object)->__val, \ + __atomic_apply_stride(object, operand))) #define atomic_fetch_and_explicit(object, operand, order) \ ((void)(order), __sync_fetch_and_and(&(object)->__val, operand)) #define atomic_fetch_or_explicit(object, operand, order) \ ((void)(order), __sync_fetch_and_or(&(object)->__val, operand)) #define atomic_fetch_sub_explicit(object, operand, order) \ - ((void)(order), __sync_fetch_and_sub(&(object)->__val, operand)) + ((void)(order), __sync_fetch_and_sub(&(object)->__val, \ + __atomic_apply_stride(object, operand))) #define atomic_fetch_xor_explicit(object, operand, order) \ ((void)(order), __sync_fetch_and_xor(&(object)->__val, operand)) #define atomic_load_explicit(object, order) \ |