aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn David Anglin <dave.anglin@nrc-cnrc.gc.ca>2005-12-28 17:13:56 +0000
committerJohn David Anglin <danglin@gcc.gnu.org>2005-12-28 17:13:56 +0000
commit3779973b0b163d0323aa679f9ec81c8caae5c427 (patch)
tree43fb807f36566e859f3fd6271273ce6af4baa761
parent3eb046081bda6816fa9a59efa63cb2a1db7f4595 (diff)
downloadgcc-3779973b0b163d0323aa679f9ec81c8caae5c427.zip
gcc-3779973b0b163d0323aa679f9ec81c8caae5c427.tar.gz
gcc-3779973b0b163d0323aa679f9ec81c8caae5c427.tar.bz2
locks.h (compare_and_swap): Add ldcw semaphore to make operation atomic.
* sysdep/pa/locks.h (compare_and_swap): Add ldcw semaphore to make operation atomic. From-SVN: r109110
-rw-r--r--libjava/ChangeLog5
-rw-r--r--libjava/sysdep/pa/locks.h62
2 files changed, 52 insertions, 15 deletions
diff --git a/libjava/ChangeLog b/libjava/ChangeLog
index 09821fe..cff2e26 100644
--- a/libjava/ChangeLog
+++ b/libjava/ChangeLog
@@ -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
diff --git a/libjava/sysdep/pa/locks.h b/libjava/sysdep/pa/locks.h
index 3f24afc..4edc2d7 100644
--- a/libjava/sysdep/pa/locks.h
+++ b/libjava/sysdep/pa/locks.h
@@ -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