atomicity.h revision 117397
1254721Semaste/* Low-level functions for atomic operations.  PA-RISC version. -*- C++ -*-
2254721Semaste   Copyright 2002 Free Software Foundation, Inc.
3353358Sdim   This file is part of the GNU C Library.
4353358Sdim
5353358Sdim   The GNU C Library is free software; you can redistribute it and/or
6254721Semaste   modify it under the terms of the GNU Library General Public License as
7254721Semaste   published by the Free Software Foundation; either version 2 of the
8254721Semaste   License, or (at your option) any later version.
9254721Semaste
10254721Semaste   The GNU C Library is distributed in the hope that it will be useful,
11254721Semaste   but WITHOUT ANY WARRANTY; without even the implied warranty of
12254721Semaste   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13254721Semaste   Library General Public License for more details.
14254721Semaste
15314564Sdim   You should have received a copy of the GNU Library General Public
16360784Sdim   License along with the GNU C Library; see the file COPYING.LIB.  If not,
17314564Sdim   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18314564Sdim   Boston, MA 02111-1307, USA.  */
19314564Sdim
20254721Semaste#ifndef _BITS_ATOMICITY_H
21254721Semaste#define _BITS_ATOMICITY_H	1
22353358Sdim
23254721Semastetypedef int _Atomic_word;
24341825Sdim
25341825Sdimtemplate <int __inst>
26341825Sdimstruct __Atomicity_lock
27254721Semaste{
28254721Semaste  static volatile int _S_atomicity_lock;
29254721Semaste};
30254721Semaste
31353358Sdimtemplate <int __inst>
32353358Sdimvolatile int
33360784Sdim__Atomicity_lock<__inst>::_S_atomicity_lock __attribute__ ((aligned (16))) = 1;
34360784Sdim
35254721Semaste/* Because of the lack of weak support when using the hpux
36314564Sdim   som linker, we explicitly instantiate the atomicity lock
37341825Sdim   in src/misc-inst.cc when _GLIBCPP_INST_ATOMICITY_LOCK
38254721Semaste   is defined.  */
39314564Sdim#ifndef _GLIBCPP_INST_ATOMICITY_LOCK
40314564Sdimtemplate volatile int __Atomicity_lock<0>::_S_atomicity_lock;
41314564Sdim#endif
42254721Semaste
43314564Sdimstatic inline int
44276479Sdim__attribute__ ((__unused__))
45314564Sdim__exchange_and_add (volatile _Atomic_word* __mem, int __val)
46314564Sdim{
47321369Sdim  _Atomic_word result;
48353358Sdim  int tmp;
49353358Sdim  volatile int& lock = __Atomicity_lock<0>::_S_atomicity_lock;
50353358Sdim
51276479Sdim  __asm__ __volatile__ ("ldcw 0(%1),%0\n\t"
52360784Sdim			"cmpib,<>,n 0,%0,.+20\n\t"
53360784Sdim			"ldw 0(%1),%0\n\t"
54353358Sdim			"cmpib,= 0,%0,.-4\n\t"
55321369Sdim			"nop\n\t"
56321369Sdim			"b,n .-20"
57321369Sdim			: "=&r" (tmp)
58321369Sdim			: "r" (&lock));
59321369Sdim
60321369Sdim  result = *__mem;
61353358Sdim  *__mem = result + __val;
62321369Sdim  /* Reset lock with PA 2.0 "ordered" store.  */
63321369Sdim  __asm__ __volatile__ ("stw,ma %1,0(%0)"
64321369Sdim			: : "r" (&lock), "r" (tmp) : "memory");
65321369Sdim  return result;
66321369Sdim}
67353358Sdim
68321369Sdimstatic inline void
69321369Sdim__attribute__ ((__unused__))
70321369Sdim__atomic_add (_Atomic_word* __mem, int __val)
71321369Sdim{
72353358Sdim  int tmp;
73321369Sdim  volatile int& lock = __Atomicity_lock<0>::_S_atomicity_lock;
74321369Sdim
75321369Sdim  __asm__ __volatile__ ("ldcw 0(%1),%0\n\t"
76321369Sdim			"cmpib,<>,n 0,%0,.+20\n\t"
77321369Sdim			"ldw 0(%1),%0\n\t"
78321369Sdim			"cmpib,= 0,%0,.-4\n\t"
79353358Sdim			"nop\n\t"
80254721Semaste			"b,n .-20"
81314564Sdim			: "=&r" (tmp)
82254721Semaste			: "r" (&lock));
83254721Semaste
84314564Sdim  *__mem += __val;
85314564Sdim  /* Reset lock with PA 2.0 "ordered" store.  */
86321369Sdim  __asm__ __volatile__ ("stw,ma %1,0(%0)"
87321369Sdim			: : "r" (&lock), "r" (tmp) : "memory");
88321369Sdim}
89321369Sdim
90360784Sdim#endif
91360784Sdim