summaryrefslogtreecommitdiff
path: root/atomic/unix/ppc.c
diff options
context:
space:
mode:
Diffstat (limited to 'atomic/unix/ppc.c')
-rw-r--r--atomic/unix/ppc.c31
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 */