diff options
author | Fabrizio Fabbri <ffabbri4@bloomberg.net> | 2016-03-02 11:35:47 -0500 |
---|---|---|
committer | Ivan Maidanski <ivmai@mail.ru> | 2016-03-04 21:10:59 +0300 |
commit | f2471925f7d3c4b38f65a75bd22eca1f4fdb98a6 (patch) | |
tree | 0db05860217955a2a17b9497a39ffc58cd1f3ff9 | |
parent | c0ed77aa8ca564c7ee905dcf5dca032049a23967 (diff) | |
download | libatomic_ops-f2471925f7d3c4b38f65a75bd22eca1f4fdb98a6.tar.gz |
Initial ibmc/powerpc (xlc) support
* src/atomic_ops/sysdeps/ibmc/powerpc.h: Include
test_and_set_t_is_ao_t.h.
* src/atomic_ops/sysdeps/ibmc/powerpc.h (AO_test_and_set,
AO_fetch_compare_and_swap): Implement.
-rw-r--r-- | src/atomic_ops/sysdeps/ibmc/powerpc.h | 71 |
1 files changed, 63 insertions, 8 deletions
diff --git a/src/atomic_ops/sysdeps/ibmc/powerpc.h b/src/atomic_ops/sysdeps/ibmc/powerpc.h index e2d4027..a930b16 100644 --- a/src/atomic_ops/sysdeps/ibmc/powerpc.h +++ b/src/atomic_ops/sysdeps/ibmc/powerpc.h @@ -1,5 +1,4 @@ -/* FIXME. This is only a placeholder for the AIX compiler. */ -/* It doesn't work. Please send a patch. */ + /* Memory model documented at http://www-106.ibm.com/developerworks/ */ /* eserver/articles/archguide.html and (clearer) */ /* http://www-106.ibm.com/developerworks/eserver/articles/powerpc.html. */ @@ -16,6 +15,8 @@ #include "../all_aligned_atomic_load_store.h" +#include "../test_and_set_t_is_ao_t.h" + void AO_sync(void); #pragma mc_func AO_sync { "7c0004ac" } @@ -55,11 +56,41 @@ AO_store_release(volatile AO_t *addr, AO_t value) /* This is similar to the code in the garbage collector. Deleting */ /* this and having it synthesized from compare_and_swap would probably */ /* only cost us a load immediate instruction. */ -/*AO_INLINE AO_TS_VAL_t +AO_INLINE AO_TS_VAL_t AO_test_and_set(volatile AO_TS_t *addr) { -# error FIXME Implement me +#if defined(__powerpc64__) || defined(__ppc64__) || defined(__64BIT__) +/* Completely untested. And we should be using smaller objects anyway. */ + unsigned long oldval; + unsigned long temp = 1; /* locked value */ + + __asm__ __volatile__( + "1:ldarx %0,0,%1\n" /* load and reserve */ + "cmpdi %0, 0\n" /* if load is */ + "bne 2f\n" /* non-zero, return already set */ + "stdcx. %2,0,%1\n" /* else store conditional */ + "bne- 1b\n" /* retry if lost reservation */ + "2:\n" /* oldval is zero if we set */ + : "=&r"(oldval) + : "r"(addr), "r"(temp) + : "memory", "cr0"); +#else + int oldval; + int temp = 1; /* locked value */ + + __asm__ __volatile__( + "1:lwarx %0,0,%1\n" /* load and reserve */ + "cmpwi %0, 0\n" /* if load is */ + "bne 2f\n" /* non-zero, return already set */ + "stwcx. %2,0,%1\n" /* else store conditional */ + "bne- 1b\n" /* retry if lost reservation */ + "2:\n" /* oldval is zero if we set */ + : "=&r"(oldval) + : "r"(addr), "r"(temp) + : "memory", "cr0"); +#endif + return (AO_TS_VAL_t)oldval; } -#define AO_HAVE_test_and_set*/ +#define AO_HAVE_test_and_set AO_INLINE AO_TS_VAL_t AO_test_and_set_acquire(volatile AO_TS_t *addr) { @@ -87,12 +118,36 @@ AO_test_and_set_full(volatile AO_TS_t *addr) { #define AO_HAVE_test_and_set_full #endif /* !AO_PREFER_GENERALIZED */ -/*AO_INLINE AO_t +AO_INLINE AO_t AO_fetch_compare_and_swap(volatile AO_t *addr, AO_t old_val, AO_t new_val) { -# error FIXME Implement me + AO_t fetched_val; +# if defined(__powerpc64__) || defined(__ppc64__) || defined(__64BIT__) + __asm__ __volatile__( + "1:ldarx %0,0,%1\n" /* load and reserve */ + "cmpd %0, %3\n" /* if load is not equal to */ + "bne 2f\n" /* old_val, fail */ + "stdcx. %2,0,%1\n" /* else store conditional */ + "bne- 1b\n" /* retry if lost reservation */ + "2:\n" + : "=&r"(fetched_val) + : "r"(addr), "r"(new_val), "r"(old_val) + : "memory", "cr0"); +# else + __asm__ __volatile__( + "1:lwarx %0,0,%1\n" /* load and reserve */ + "cmpw %0, %3\n" /* if load is not equal to */ + "bne 2f\n" /* old_val, fail */ + "stwcx. %2,0,%1\n" /* else store conditional */ + "bne- 1b\n" /* retry if lost reservation */ + "2:\n" + : "=&r"(fetched_val) + : "r"(addr), "r"(new_val), "r"(old_val) + : "memory", "cr0"); +# endif + return fetched_val; } -#define AO_HAVE_fetch_compare_and_swap*/ +#define AO_HAVE_fetch_compare_and_swap AO_INLINE AO_t AO_fetch_compare_and_swap_acquire(volatile AO_t *addr, AO_t old_val, |