diff options
Diffstat (limited to 'atomic/unix/ppc.c')
-rw-r--r-- | atomic/unix/ppc.c | 31 |
1 files changed, 31 insertions, 0 deletions
diff --git a/atomic/unix/ppc.c b/atomic/unix/ppc.c index 149347eae..d7673d5ee 100644 --- a/atomic/unix/ppc.c +++ b/atomic/unix/ppc.c @@ -175,4 +175,35 @@ APR_DECLARE(void*) apr_atomic_casptr(volatile void **mem, void *with, const void return prev; } +APR_DECLARE(void*) apr_atomic_xchgptr(volatile void **mem, void *with) +{ + void *prev; +#if APR_SIZEOF_VOIDP == 4 + asm volatile (PPC_SYNC + "loop_%=:\n" /* lost reservation */ + " lwarx %0,0,%1\n" /* load and reserve */ + PPC405_ERR77_SYNC /* ppc405 Erratum 77 */ + " stwcx. %2,0,%1\n" /* store new value */ + " bne- loop_%=\n" /* loop if lost */ + " isync\n" /* memory barrier */ + : "=&r" (prev) + : "b" (mem), "r" (with) + : "cc", "memory"); +#elif APR_SIZEOF_VOIDP == 8 + asm volatile (PPC_SYNC + "loop_%=:\n" /* lost reservation */ + " ldarx %0,0,%1\n" /* load and reserve */ + PPC405_ERR77_SYNC /* ppc405 Erratum 77 */ + " stdcx. %2,0,%1\n" /* store new value */ + " bne- loop_%=\n" /* loop if lost */ + " isync\n" /* memory barrier */ + : "=&r" (prev) + : "b" (mem), "r" (with) + : "cc", "memory"); +#else +#error APR_SIZEOF_VOIDP value not supported +#endif + return prev; +} + #endif /* USE_ATOMICS_PPC */ |