libfoedus-core
FOEDUS Core Library
raw_atomics.hpp
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2014-2015, Hewlett-Packard Development Company, LP.
3  * This program is free software; you can redistribute it and/or modify it
4  * under the terms of the GNU General Public License as published by the Free
5  * Software Foundation; either version 2 of the License, or (at your option)
6  * any later version.
7  *
8  * This program is distributed in the hope that it will be useful, but WITHOUT
9  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
11  * more details. You should have received a copy of the GNU General Public
12  * License along with this program; if not, write to the Free Software
13  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
14  *
15  * HP designates this particular file as subject to the "Classpath" exception
16  * as provided by HP in the LICENSE.txt file that accompanied this code.
17  */
18 #ifndef FOEDUS_ASSORTED_RAW_ATOMICS_HPP_
19 #define FOEDUS_ASSORTED_RAW_ATOMICS_HPP_
20 
21 #include <stdint.h>
22 
40 namespace foedus {
41 namespace assorted {
42 
48 template <typename T>
49 inline bool raw_atomic_compare_exchange_strong(T* target, T* expected, T desired) {
50  // Use newer builtin instead of __sync_val_compare_and_swap
51  return ::__atomic_compare_exchange_n(
52  target,
53  expected,
54  desired,
55  false,
56  __ATOMIC_SEQ_CST,
57  __ATOMIC_SEQ_CST);
58  // T expected_val = *expected;
59  // T old_val = ::__sync_val_compare_and_swap(target, expected_val, desired);
60  // if (old_val == expected_val) {
61  // return true;
62  // } else {
63  // *expected = old_val;
64  // return false;
65  // }
66 }
67 
73 template <typename T>
74 inline bool raw_atomic_compare_exchange_weak(T* target, T* expected, T desired) {
75  return ::__atomic_compare_exchange_n(
76  target,
77  expected,
78  desired,
79  true, // weak
80  __ATOMIC_SEQ_CST,
81  __ATOMIC_SEQ_CST);
82 }
83 
100  uint64_t *ptr,
101  const uint64_t *old_value,
102  const uint64_t *new_value);
103 
109  uint64_t *ptr,
110  const uint64_t *old_value,
111  const uint64_t *new_value) {
112  if (ptr[0] != old_value[0] || ptr[1] != old_value[1]) {
113  return false; // this comparison is fast but not atomic, thus 'weak'
114  } else {
115  return raw_atomic_compare_exchange_strong_uint128(ptr, old_value, new_value);
116  }
117 }
118 
129 template <typename T>
130 inline T raw_atomic_exchange(T* target, T desired) {
131  return ::__atomic_exchange_n(target, desired, __ATOMIC_SEQ_CST);
132  // Note: We must NOT use __sync_lock_test_and_set, which is only acquire-barrier for some
133  // reason. We instead use GCC/Clang's __atomic_exchange() builtin.
134  // return ::__sync_lock_test_and_set(target, desired);
135  // see https://gcc.gnu.org/onlinedocs/gcc-4.4.3/gcc/Atomic-Builtins.html
136  // and https://bugzilla.mozilla.org/show_bug.cgi?id=873799
137 
138  // BTW, __atomic_exchange_n/__ATOMIC_SEQ_CST demands a C++11-capable version of gcc/clang,
139  // but FOEDUS anyway relies on C++11. It just allows the linked program to be
140  // compiled without std=c++11. So, nothing lost.
141 }
142 
149 template <typename T>
150 inline T raw_atomic_fetch_add(T* target, T addendum) {
151  return ::__atomic_fetch_add(target, addendum, __ATOMIC_SEQ_CST);
152  // Just to align with above, use __atomic_fetch_add rather than __sync_fetch_and_add.
153  // It's equivalent.
154  // return ::__sync_fetch_and_add(target, addendum);
155 }
156 
163 template <typename T>
164 inline T raw_atomic_fetch_and_bitwise_and(T* target, T operand) {
165  return ::__atomic_fetch_and(target, operand, __ATOMIC_SEQ_CST);
166 }
173 template <typename T>
174 inline T raw_atomic_fetch_and_bitwise_or(T* target, T operand) {
175  return ::__atomic_fetch_or(target, operand, __ATOMIC_SEQ_CST);
176 }
183 template <typename T>
184 inline T raw_atomic_fetch_and_bitwise_xor(T* target, T operand) {
185  return ::__atomic_fetch_xor(target, operand, __ATOMIC_SEQ_CST);
186 }
187 } // namespace assorted
188 } // namespace foedus
189 
190 #endif // FOEDUS_ASSORTED_RAW_ATOMICS_HPP_
T raw_atomic_exchange(T *target, T desired)
Atomic Swap for raw primitive types rather than std::atomic.
Root package of FOEDUS (Fast Optimistic Engine for Data Unification Services).
Definition: assert_nd.hpp:44
T raw_atomic_fetch_and_bitwise_and(T *target, T operand)
Atomic fetch-bitwise-and for raw primitive types rather than std::atomic.
T raw_atomic_fetch_and_bitwise_or(T *target, T operand)
Atomic fetch-bitwise-or for raw primitive types rather than std::atomic.
T raw_atomic_fetch_and_bitwise_xor(T *target, T operand)
Atomic fetch-bitwise-xor for raw primitive types rather than std::atomic
T raw_atomic_fetch_add(T *target, T addendum)
Atomic fetch-add for raw primitive types rather than std::atomic.
bool raw_atomic_compare_exchange_strong(T *target, T *expected, T desired)
Atomic CAS.
Definition: raw_atomics.hpp:49
bool raw_atomic_compare_exchange_weak(T *target, T *expected, T desired)
Weak version of raw_atomic_compare_exchange_strong().
Definition: raw_atomics.hpp:74
bool raw_atomic_compare_exchange_strong_uint128(uint64_t *ptr, const uint64_t *old_value, const uint64_t *new_value)
Atomic 128-bit CAS, which is not in the standard yet.
Definition: raw_atomics.cpp:25
bool raw_atomic_compare_exchange_weak_uint128(uint64_t *ptr, const uint64_t *old_value, const uint64_t *new_value)
Weak version of raw_atomic_compare_exchange_strong_uint128().