* sysdep/pa/locks.h (compare_and_swap): Add ldcw semaphore to make
authordanglin <danglin@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 28 Dec 2005 17:13:56 +0000 (17:13 +0000)
committerdanglin <danglin@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 28 Dec 2005 17:13:56 +0000 (17:13 +0000)
operation atomic.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@109110 138bc75d-0d04-0410-961f-82ee72b054a4

libjava/ChangeLog
libjava/sysdep/pa/locks.h

index 09821fe..cff2e26 100644 (file)
@@ -1,3 +1,8 @@
+2005-12-28  John David Anglin  <dave.anglin@nrc-cnrc.gc.ca>
+
+       * sysdep/pa/locks.h (compare_and_swap): Add ldcw semaphore to make
+       operation atomic.
+
 2005-12-22  Andrew Haley  <aph@redhat.com>
 
        PR java/25535
index 3f24afc..4edc2d7 100644 (file)
@@ -1,6 +1,6 @@
-// locks.h - Thread synchronization primitives. PARISC implementation.
+// locks.h - Thread synchronization primitives. PA-RISC implementation.
 
-/* Copyright (C) 2002  Free Software Foundation
+/* Copyright (C) 2002, 2005  Free Software Foundation
 
    This file is part of libgcj.
 
@@ -11,30 +11,62 @@ details.  */
 #ifndef __SYSDEP_LOCKS_H__
 #define __SYSDEP_LOCKS_H__
 
-typedef size_t obj_addr_t;     /* Integer type big enough for object   */
-                               /* address.                             */
+// Integer type big enough for object address.
+typedef size_t obj_addr_t;
 
-// Atomically replace *addr by new_val if it was initially equal to old.
-// Return true if the comparison succeeded.
+template<int _Inst>
+  struct _pa_jv_cas_lock
+  {
+    static volatile int _S_pa_jv_cas_lock;
+  };
+
+template<int _Inst>
+volatile int
+_pa_jv_cas_lock<_Inst>::_S_pa_jv_cas_lock __attribute__ ((aligned (16))) = 1;
+
+// Because of the lack of weak support when using the hpux som
+// linker, we explicitly instantiate the atomicity lock.
+template volatile int _pa_jv_cas_lock<0>::_S_pa_jv_cas_lock;
+
+// Atomically replace *addr by new_val if it was initially equal to old_val.
+// Return true if the comparison is successful.
 // Assumed to have acquire semantics, i.e. later memory operations
 // cannot execute before the compare_and_swap finishes.
+// The following implementation is atomic but it can deadlock
+// (e.g., if a thread dies holding the lock).
 inline static bool
+__attribute__ ((__unused__))
 compare_and_swap(volatile obj_addr_t *addr,
-                obj_addr_t old,
+                obj_addr_t old_val,
                 obj_addr_t new_val) 
 {
-  /* FIXME: not atomic */
-  obj_addr_t prev;
+  bool result;
+  int tmp;
+  volatile int& lock = _pa_jv_cas_lock<0>::_S_pa_jv_cas_lock;
 
-  if ((prev = *addr) == old)
-    {
-      *addr = new_val;
-      return true;
-    }
+  __asm__ __volatile__ ("ldcw 0(%1),%0\n\t"
+                       "cmpib,<>,n 0,%0,.+20\n\t"
+                       "ldw 0(%1),%0\n\t"
+                       "cmpib,= 0,%0,.-4\n\t"
+                       "nop\n\t"
+                       "b,n .-20"
+                       : "=&r" (tmp)
+                       : "r" (&lock)
+                       : "memory");
+
+  if (*addr != old_val)
+    result = false;
   else
     {
-      return false;
+      *addr = new_val;
+      result = true;
     }
+
+  /* Reset lock with PA 2.0 "ordered" store.  */
+  __asm__ __volatile__ ("stw,ma %1,0(%0)"
+                       : : "r" (&lock), "r" (tmp) : "memory");
+
+  return result;
 }
 
 // Set *addr to new_val with release semantics, i.e. making sure