1// Low-level functions for atomic operations: PA-RISC version  -*- C++ -*-
2
3// Copyright (C) 2002-2020 Free Software Foundation, Inc.
4//
5// This file is part of the GNU ISO C++ Library.  This library is free
6// software; you can redistribute it and/or modify it under the
7// terms of the GNU General Public License as published by the
8// Free Software Foundation; either version 3, or (at your option)
9// any later version.
10
11// This library is distributed in the hope that it will be useful,
12// but WITHOUT ANY WARRANTY; without even the implied warranty of
13// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14// GNU General Public License for more details.
15
16// Under Section 7 of GPL version 3, you are granted additional
17// permissions described in the GCC Runtime Library Exception, version
18// 3.1, as published by the Free Software Foundation.
19
20// You should have received a copy of the GNU General Public License and
21// a copy of the GCC Runtime Library Exception along with this program;
22// see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
23// <http://www.gnu.org/licenses/>.
24
25#include <bits/c++config.h>
26#include <ext/atomicity.h>
27
28namespace __gnu_cxx _GLIBCXX_VISIBILITY(default)
29{
30_GLIBCXX_BEGIN_NAMESPACE_VERSION
31
32  template<int _Inst>
33    struct _Atomicity_lock
34    {
35      static volatile int _S_atomicity_lock;
36    };
37
38  template<int _Inst>
39  volatile int
40  _Atomicity_lock<_Inst>::_S_atomicity_lock __attribute__ ((aligned (16))) = 1;
41
42  // Because of the lack of weak support when using the hpux som
43  // linker, we explicitly instantiate the atomicity lock.
44  template volatile int _Atomicity_lock<0>::_S_atomicity_lock;
45
46  int
47  __attribute__ ((__unused__))
48  __exchange_and_add(volatile _Atomic_word* __mem, int __val) throw ()
49  {
50    _Atomic_word result;
51    int tmp;
52    volatile int& lock = _Atomicity_lock<0>::_S_atomicity_lock;
53
54    __asm__ __volatile__ ("ldcw 0(%1),%0\n\t"
55			  "cmpib,<>,n 0,%0,.+20\n\t"
56			  "ldw 0(%1),%0\n\t"
57			  "cmpib,= 0,%0,.-4\n\t"
58			  "nop\n\t"
59			  "b,n .-20"
60			  : "=&r" (tmp)
61			  : "r" (&lock)
62			  : "memory");
63
64    result = *__mem;
65    *__mem = result + __val;
66    __asm__ __volatile__ ("stw %1,0(%0)"
67			  : : "r" (&lock), "r" (tmp) : "memory");
68    return result;
69  }
70
71  void
72  __attribute__ ((__unused__))
73  __atomic_add(volatile _Atomic_word* __mem, int __val) throw ()
74  {
75    int tmp;
76    volatile int& lock = _Atomicity_lock<0>::_S_atomicity_lock;
77
78    __asm__ __volatile__ ("ldcw 0(%1),%0\n\t"
79			  "cmpib,<>,n 0,%0,.+20\n\t"
80			  "ldw 0(%1),%0\n\t"
81			  "cmpib,= 0,%0,.-4\n\t"
82			  "nop\n\t"
83			  "b,n .-20"
84			  : "=&r" (tmp)
85			  : "r" (&lock)
86			  : "memory");
87
88    *__mem += __val;
89    __asm__ __volatile__ ("stw %1,0(%0)"
90			  : : "r" (&lock), "r" (tmp) : "memory");
91  }
92
93_GLIBCXX_END_NAMESPACE_VERSION
94} // namespace
95