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
This commit is contained in:
John David Anglin 2005-12-28 17:13:56 +00:00 committed by John David Anglin
parent 3eb046081b
commit 3779973b0b
2 changed files with 52 additions and 15 deletions

View 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

View 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