]> git.ipfire.org Git - thirdparty/gcc.git/blame - libstdc++-v3/src/atomic.cc
[multiple changes]
[thirdparty/gcc.git] / libstdc++-v3 / src / atomic.cc
CommitLineData
d466a7e2
BK
1// Support for atomic operations -*- C++ -*-
2
3// Copyright (C) 2008
4// Free Software Foundation, Inc.
5//
6// This file is part of the GNU ISO C++ Library. This library is free
7// software; you can redistribute it and/or modify it under the
8// terms of the GNU General Public License as published by the
9// Free Software Foundation; either version 2, or (at your option)
10// any later version.
11
12// This library is distributed in the hope that it will be useful,
13// but WITHOUT ANY WARRANTY; without even the implied warranty of
14// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15// GNU General Public License for more details.
16
17// You should have received a copy of the GNU General Public License
18// along with this library; see the file COPYING. If not, write to
19// the Free Software Foundation, 51 Franklin Street, Fifth Floor,
20// Boston, MA 02110-1301, USA.
21
22// As a special exception, you may use this file as part of a free software
23// library without restriction. Specifically, if other files instantiate
24// templates or use macros or inline functions from this file, or you compile
25// this file and link it with other files to produce an executable, this
26// file does not by itself cause the resulting executable to be covered by
27// the GNU General Public License. This exception does not however
28// invalidate any other reasons why the executable file might be covered by
29// the GNU General Public License.
30
31#include <stdint.h>
32#include <cstdatomic>
33
34#define LOGSIZE 4
35
36namespace
37{
38 atomic_flag volatile __atomic_flag_anon_table__[ 1 << LOGSIZE ] =
39 {
40 ATOMIC_FLAG_INIT, ATOMIC_FLAG_INIT, ATOMIC_FLAG_INIT, ATOMIC_FLAG_INIT,
41 ATOMIC_FLAG_INIT, ATOMIC_FLAG_INIT, ATOMIC_FLAG_INIT, ATOMIC_FLAG_INIT,
42 ATOMIC_FLAG_INIT, ATOMIC_FLAG_INIT, ATOMIC_FLAG_INIT, ATOMIC_FLAG_INIT,
43 ATOMIC_FLAG_INIT, ATOMIC_FLAG_INIT, ATOMIC_FLAG_INIT, ATOMIC_FLAG_INIT,
44 };
45} // anonymous namespace
46
47namespace std
48{
49 extern "C" {
50
51 const atomic_flag atomic_global_fence_compatibility = ATOMIC_FLAG_INIT;
52
53 bool
54 atomic_flag_test_and_set_explicit(volatile atomic_flag* __a,
55 memory_order __x)
56 {
57#ifdef _GLIBCXX_ATOMIC_BUILTINS
58 if (__x >= memory_order_acq_rel)
59 __sync_synchronize();
60 return __sync_lock_test_and_set(&(__a->_M_base._M_b), 1);
61#else
62 bool result = __a->_M_base._M_b;
63 __a->_M_base._M_b = true;
64 return result;
65#endif
66 }
67
68 bool
69 atomic_flag_test_and_set(volatile atomic_flag* __a)
70 { return atomic_flag_test_and_set_explicit(__a, memory_order_seq_cst); }
71
72 void
73 atomic_flag_clear_explicit(volatile atomic_flag* __a, memory_order __x)
74 {
75#ifdef _GLIBCXX_ATOMIC_BUILTINS
76 __sync_lock_release(&(__a->_M_base._M_b));
77 if (__x >= memory_order_acq_rel)
78 __sync_synchronize();
79#else
80 __a->_M_base._M_b = false;
81#endif
82 }
83
84 void
85 atomic_flag_clear(volatile atomic_flag* __a)
86 { atomic_flag_clear_explicit(__a, memory_order_seq_cst); }
87
88 void
89 atomic_flag_fence(const volatile atomic_flag*, memory_order)
90 {
91#ifdef _GLIBCXX_ATOMIC_BUILTINS
92 __sync_synchronize();
93#endif
94 }
95
96 void
97 __atomic_flag_wait_explicit(volatile atomic_flag* __a, memory_order __x)
98 {
99 while (atomic_flag_test_and_set_explicit(__a, __x))
100 { };
101 }
102
103 volatile atomic_flag*
104 __atomic_flag_for_address(const volatile void* __z)
105 {
106 uintptr_t __u = reinterpret_cast<uintptr_t>(__z);
107 __u += (__u >> 2) + (__u << 4);
108 __u += (__u >> 7) + (__u << 5);
109 __u += (__u >> 17) + (__u << 13);
110 if (sizeof(uintptr_t) > 4) __u += (__u >> 31);
111 __u &= ~((~uintptr_t(0)) << LOGSIZE);
112 return __atomic_flag_anon_table__ + __u;
113 }
114
115 } // extern "C"
116} // namespace std