changeset in /hg/icedtea6: ARM atomic primitives.

Andrew Haley aph at redhat.com
Wed Apr 16 08:46:41 PDT 2008


changeset 82d528d417a5 in /hg/icedtea6
details: http://icedtea.classpath.org/hg/icedtea6?cmd=changeset;node=82d528d417a5
description:
	ARM atomic primitives.

diffstat:

1 file changed, 56 insertions(+), 15 deletions(-)
ports/hotspot/src/os_cpu/linux_zero/vm/atomic_linux_zero.inline.hpp |   71 +++++++---

diffs (88 lines):

diff -r 3f3dd2815005 -r 82d528d417a5 ports/hotspot/src/os_cpu/linux_zero/vm/atomic_linux_zero.inline.hpp
--- a/ports/hotspot/src/os_cpu/linux_zero/vm/atomic_linux_zero.inline.hpp	Wed Apr 16 10:34:20 2008 -0400
+++ b/ports/hotspot/src/os_cpu/linux_zero/vm/atomic_linux_zero.inline.hpp	Wed Apr 16 16:46:37 2008 +0100
@@ -26,28 +26,69 @@
 // Implementation of class atomic
 
 #ifdef ARM
+
+/*
+ * __kernel_cmpxchg
+ *
+ * Atomically store newval in *ptr if *ptr is equal to oldval for user space.
+ * Return zero if *ptr was changed or non-zero if no exchange happened.
+ * The C flag is also set if *ptr was changed to allow for assembly
+ * optimization in the calling code.
+ *
+ */
+
 typedef int (__kernel_cmpxchg_t)(int oldval, int newval, volatile int *ptr);
 #define __kernel_cmpxchg (*(__kernel_cmpxchg_t *) 0xffff0fc0)
 
+
+
+/* Perform an atomic compare and swap: if the current value of `*PTR'
+   is OLDVAL, then write NEWVAL into `*PTR'.  Return the contents of
+   `*PTR' before the operation.*/
 static inline int arm_compare_and_swap(volatile int *ptr,
                                        int oldval,
-                                       int newval) {
-  int old = *ptr;
-  __kernel_cmpxchg(oldval, newval, (volatile int*) ptr);
-  return old;
-}
-
-static inline int arm_add_and_fetch(volatile int *dest, int add_value)
-{
-  arm_compare_and_swap(dest, *dest, *dest + add_value);
-  return *dest;
-}
-
+                                       int newval) 
+{
+  for (;;)
+    {
+      int prev = *ptr;
+      if (prev != oldval)
+	return prev;
+
+      if (__kernel_cmpxchg (prev, newval, ptr) == 0)
+	// Success.
+	return prev;
+
+      // We failed even though prev == oldval.  Try again.
+    }
+}
+
+/* Atomically add an int to memory.  */
+static inline int arm_add_and_fetch(volatile int *ptr, int add_value)
+{
+  for (;;)
+    {
+      // Loop until a __kernel_cmpxchg succeeds.
+
+      int prev = *ptr;
+
+      if (__kernel_cmpxchg (prev, prev + add_value, ptr) == 0)
+	return prev + add_value;
+    }
+}
+
+/* Atomically write VALUE into `*PTR' and returns the previous
+   contents of `*PTR'.  */
 static inline int arm_lock_test_and_set(volatile int *ptr, int newval)
 {
-  int old = *ptr;
-  arm_compare_and_swap(ptr, *ptr, newval);
-  return old;
+  for (;;)
+    {
+      // Loop until a __kernel_cmpxchg succeeds.
+      int prev = *ptr;
+
+      if (__kernel_cmpxchg (prev, newval, ptr) == 0)
+	return prev;
+    }
 }
 #endif // ARM
 



More information about the distro-pkg-dev mailing list