diff options
author | danglin <danglin@138bc75d-0d04-0410-961f-82ee72b054a4> | 2005-12-28 17:13:56 +0000 |
---|---|---|
committer | danglin <danglin@138bc75d-0d04-0410-961f-82ee72b054a4> | 2005-12-28 17:13:56 +0000 |
commit | 328eb802880e7a7d81d9a413aa73a88f2b6eed60 (patch) | |
tree | 43fb807f36566e859f3fd6271273ce6af4baa761 /libjava/sysdep | |
parent | aa4936de1f3d71964fc6f9822ebdef4d66153b5d (diff) | |
download | gcc-328eb802880e7a7d81d9a413aa73a88f2b6eed60.tar.gz |
* sysdep/pa/locks.h (compare_and_swap): Add ldcw semaphore to make
operation atomic.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@109110 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'libjava/sysdep')
-rw-r--r-- | libjava/sysdep/pa/locks.h | 62 |
1 files changed, 47 insertions, 15 deletions
diff --git a/libjava/sysdep/pa/locks.h b/libjava/sysdep/pa/locks.h index 3f24afc5669..4edc2d71626 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 |