1/* -*- mode: C++; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2// vim: ft=cpp:expandtab:ts=8:sw=4:softtabstop=4:
3#ident "$Id$"
4/*======
5This file is part of PerconaFT.
6
7
8Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved.
9
10 PerconaFT is free software: you can redistribute it and/or modify
11 it under the terms of the GNU General Public License, version 2,
12 as published by the Free Software Foundation.
13
14 PerconaFT is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with PerconaFT. If not, see <http://www.gnu.org/licenses/>.
21
22----------------------------------------
23
24 PerconaFT is free software: you can redistribute it and/or modify
25 it under the terms of the GNU Affero General Public License, version 3,
26 as published by the Free Software Foundation.
27
28 PerconaFT is distributed in the hope that it will be useful,
29 but WITHOUT ANY WARRANTY; without even the implied warranty of
30 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
31 GNU Affero General Public License for more details.
32
33 You should have received a copy of the GNU Affero General Public License
34 along with PerconaFT. If not, see <http://www.gnu.org/licenses/>.
35======= */
36
37#ident "Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved."
38
39#pragma once
40
41#include <portability/toku_config.h>
42#include <toku_assert.h>
43
44#include <stdbool.h>
45#include <stdint.h>
46#include <stddef.h>
47
48__attribute__((const, always_inline))
49static inline intptr_t which_cache_line(intptr_t addr) {
50 static const size_t assumed_cache_line_size = 64;
51 return addr / assumed_cache_line_size;
52}
53template <typename T> __attribute__((const, always_inline))
54static inline bool crosses_boundary(T *addr, size_t width) {
55 const intptr_t int_addr = reinterpret_cast<intptr_t>(addr);
56 const intptr_t last_byte = int_addr + width - 1;
57 return which_cache_line(int_addr) != which_cache_line(last_byte);
58}
59
60template <typename T, typename U> __attribute__((always_inline))
61static inline T toku_sync_fetch_and_add(T *addr, U diff) {
62 paranoid_invariant(!crosses_boundary(addr, sizeof *addr));
63 return __sync_fetch_and_add(addr, diff);
64}
65template <typename T, typename U> __attribute__((always_inline))
66static inline T toku_sync_add_and_fetch(T *addr, U diff) {
67 paranoid_invariant(!crosses_boundary(addr, sizeof *addr));
68 return __sync_add_and_fetch(addr, diff);
69}
70template <typename T, typename U> __attribute__((always_inline))
71static inline T toku_sync_fetch_and_sub(T *addr, U diff) {
72 paranoid_invariant(!crosses_boundary(addr, sizeof *addr));
73 return __sync_fetch_and_sub(addr, diff);
74}
75template <typename T, typename U> __attribute__((always_inline))
76static inline T toku_sync_sub_and_fetch(T *addr, U diff) {
77 paranoid_invariant(!crosses_boundary(addr, sizeof *addr));
78 return __sync_sub_and_fetch(addr, diff);
79}
80template <typename T, typename U, typename V> __attribute__((always_inline))
81static inline T toku_sync_val_compare_and_swap(T *addr, U oldval, V newval) {
82 paranoid_invariant(!crosses_boundary(addr, sizeof *addr));
83 return __sync_val_compare_and_swap(addr, oldval, newval);
84}
85template <typename T, typename U, typename V> __attribute__((always_inline))
86static inline bool toku_sync_bool_compare_and_swap(T *addr, U oldval, V newval) {
87 paranoid_invariant(!crosses_boundary(addr, sizeof *addr));
88 return __sync_bool_compare_and_swap(addr, oldval, newval);
89}
90
91// in case you include this but not toku_portability.h
92#pragma GCC poison __sync_fetch_and_add
93#pragma GCC poison __sync_fetch_and_sub
94#pragma GCC poison __sync_fetch_and_or
95#pragma GCC poison __sync_fetch_and_and
96#pragma GCC poison __sync_fetch_and_xor
97#pragma GCC poison __sync_fetch_and_nand
98#pragma GCC poison __sync_add_and_fetch
99#pragma GCC poison __sync_sub_and_fetch
100#pragma GCC poison __sync_or_and_fetch
101#pragma GCC poison __sync_and_and_fetch
102#pragma GCC poison __sync_xor_and_fetch
103#pragma GCC poison __sync_nand_and_fetch
104#pragma GCC poison __sync_bool_compare_and_swap
105#pragma GCC poison __sync_val_compare_and_swap
106#pragma GCC poison __sync_synchronize
107#pragma GCC poison __sync_lock_test_and_set
108#pragma GCC poison __sync_release
109