Commit | Line | Data |
---|---|---|
e4d1eb09 PB |
1 | #ifndef _URCU_ARCH_GENERIC_H |
2 | #define _URCU_ARCH_GENERIC_H | |
3 | ||
4 | /* | |
5 | * arch_generic.h: common definitions for multiple architectures. | |
6 | * | |
7 | * Copyright (c) 2010 Paolo Bonzini <pbonzini@redhat.com> | |
8 | * | |
9 | * This library is free software; you can redistribute it and/or | |
10 | * modify it under the terms of the GNU Lesser General Public | |
11 | * License as published by the Free Software Foundation; either | |
12 | * version 2.1 of the License, or (at your option) any later version. | |
05dd4b94 | 13 | * |
e4d1eb09 PB |
14 | * This library 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 GNU | |
17 | * Lesser General Public License for more details. | |
18 | * | |
19 | * You should have received a copy of the GNU Lesser General Public | |
20 | * License along with this library; if not, write to the Free Software | |
21 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |
22 | */ | |
23 | ||
24 | #include <urcu/compiler.h> | |
25 | #include <urcu/config.h> | |
999991c6 | 26 | #include <urcu/syscall-compat.h> |
e4d1eb09 PB |
27 | |
28 | #ifdef __cplusplus | |
29 | extern "C" { | |
30 | #endif | |
31 | ||
06f22bdb DG |
32 | #ifndef CAA_CACHE_LINE_SIZE |
33 | #define CAA_CACHE_LINE_SIZE 64 | |
e4d1eb09 PB |
34 | #endif |
35 | ||
5481ddb3 | 36 | #if !defined(cmm_mc) && !defined(cmm_rmc) && !defined(cmm_wmc) |
e4d1eb09 PB |
37 | #define CONFIG_HAVE_MEM_COHERENCY |
38 | /* | |
5481ddb3 | 39 | * Architectures with cache coherency must _not_ define cmm_mc/cmm_rmc/cmm_wmc. |
e4d1eb09 | 40 | * |
d0bbd9c2 MD |
41 | * For them, cmm_mc/cmm_rmc/cmm_wmc are implemented with a simple |
42 | * compiler barrier; in addition, we provide defaults for cmm_mb (using | |
43 | * GCC builtins) as well as cmm_rmb and cmm_wmb (defaulting to cmm_mb). | |
e4d1eb09 PB |
44 | */ |
45 | ||
5481ddb3 DG |
46 | #ifndef cmm_mb |
47 | #define cmm_mb() __sync_synchronize() | |
e4d1eb09 PB |
48 | #endif |
49 | ||
5481ddb3 DG |
50 | #ifndef cmm_rmb |
51 | #define cmm_rmb() cmm_mb() | |
e4d1eb09 PB |
52 | #endif |
53 | ||
5481ddb3 DG |
54 | #ifndef cmm_wmb |
55 | #define cmm_wmb() cmm_mb() | |
e4d1eb09 PB |
56 | #endif |
57 | ||
5481ddb3 DG |
58 | #define cmm_mc() cmm_barrier() |
59 | #define cmm_rmc() cmm_barrier() | |
60 | #define cmm_wmc() cmm_barrier() | |
e4d1eb09 PB |
61 | #else |
62 | /* | |
63 | * Architectures without cache coherency need something like the following: | |
64 | * | |
67ecffc0 | 65 | * #define cmm_mc() arch_cache_flush() |
5481ddb3 DG |
66 | * #define cmm_rmc() arch_cache_flush_read() |
67 | * #define cmm_wmc() arch_cache_flush_write() | |
e4d1eb09 | 68 | * |
d0bbd9c2 MD |
69 | * Of these, only cmm_mc is mandatory. cmm_rmc and cmm_wmc default to |
70 | * cmm_mc. cmm_mb/cmm_rmb/cmm_wmb use these definitions by default: | |
e4d1eb09 | 71 | * |
d0bbd9c2 | 72 | * #define cmm_mb() cmm_mc() |
5481ddb3 DG |
73 | * #define cmm_rmb() cmm_rmc() |
74 | * #define cmm_wmb() cmm_wmc() | |
e4d1eb09 PB |
75 | */ |
76 | ||
5481ddb3 DG |
77 | #ifndef cmm_mb |
78 | #define cmm_mb() cmm_mc() | |
e4d1eb09 PB |
79 | #endif |
80 | ||
5481ddb3 DG |
81 | #ifndef cmm_rmb |
82 | #define cmm_rmb() cmm_rmc() | |
e4d1eb09 PB |
83 | #endif |
84 | ||
5481ddb3 DG |
85 | #ifndef cmm_wmb |
86 | #define cmm_wmb() cmm_wmc() | |
e4d1eb09 PB |
87 | #endif |
88 | ||
5481ddb3 DG |
89 | #ifndef cmm_rmc |
90 | #define cmm_rmc() cmm_mc() | |
e4d1eb09 PB |
91 | #endif |
92 | ||
5481ddb3 DG |
93 | #ifndef cmm_wmc |
94 | #define cmm_wmc() cmm_mc() | |
e4d1eb09 PB |
95 | #endif |
96 | #endif | |
97 | ||
98 | /* Nop everywhere except on alpha. */ | |
5481ddb3 DG |
99 | #ifndef cmm_read_barrier_depends |
100 | #define cmm_read_barrier_depends() | |
e4d1eb09 PB |
101 | #endif |
102 | ||
103 | #ifdef CONFIG_RCU_SMP | |
0bd48ad3 | 104 | #ifndef cmm_smp_mb |
5481ddb3 | 105 | #define cmm_smp_mb() cmm_mb() |
0bd48ad3 PB |
106 | #endif |
107 | #ifndef cmm_smp_rmb | |
5481ddb3 | 108 | #define cmm_smp_rmb() cmm_rmb() |
0bd48ad3 PB |
109 | #endif |
110 | #ifndef cmm_smp_wmb | |
5481ddb3 | 111 | #define cmm_smp_wmb() cmm_wmb() |
0bd48ad3 PB |
112 | #endif |
113 | #ifndef cmm_smp_mc | |
5481ddb3 | 114 | #define cmm_smp_mc() cmm_mc() |
0bd48ad3 PB |
115 | #endif |
116 | #ifndef cmm_smp_rmc | |
5481ddb3 | 117 | #define cmm_smp_rmc() cmm_rmc() |
0bd48ad3 PB |
118 | #endif |
119 | #ifndef cmm_smp_wmc | |
5481ddb3 | 120 | #define cmm_smp_wmc() cmm_wmc() |
0bd48ad3 PB |
121 | #endif |
122 | #ifndef cmm_smp_read_barrier_depends | |
5481ddb3 | 123 | #define cmm_smp_read_barrier_depends() cmm_read_barrier_depends() |
0bd48ad3 | 124 | #endif |
e4d1eb09 | 125 | #else |
0bd48ad3 | 126 | #ifndef cmm_smp_mb |
5481ddb3 | 127 | #define cmm_smp_mb() cmm_barrier() |
0bd48ad3 PB |
128 | #endif |
129 | #ifndef cmm_smp_rmb | |
5481ddb3 | 130 | #define cmm_smp_rmb() cmm_barrier() |
0bd48ad3 PB |
131 | #endif |
132 | #ifndef cmm_smp_wmb | |
5481ddb3 | 133 | #define cmm_smp_wmb() cmm_barrier() |
0bd48ad3 PB |
134 | #endif |
135 | #ifndef cmm_smp_mc | |
5481ddb3 | 136 | #define cmm_smp_mc() cmm_barrier() |
0bd48ad3 PB |
137 | #endif |
138 | #ifndef cmm_smp_rmc | |
5481ddb3 | 139 | #define cmm_smp_rmc() cmm_barrier() |
0bd48ad3 PB |
140 | #endif |
141 | #ifndef cmm_smp_wmc | |
5481ddb3 | 142 | #define cmm_smp_wmc() cmm_barrier() |
0bd48ad3 PB |
143 | #endif |
144 | #ifndef cmm_smp_read_barrier_depends | |
5481ddb3 | 145 | #define cmm_smp_read_barrier_depends() |
e4d1eb09 | 146 | #endif |
0bd48ad3 | 147 | #endif |
e4d1eb09 | 148 | |
06f22bdb DG |
149 | #ifndef caa_cpu_relax |
150 | #define caa_cpu_relax() cmm_barrier() | |
e4d1eb09 PB |
151 | #endif |
152 | ||
f8c43f45 MD |
153 | #ifndef HAS_CAA_GET_CYCLES |
154 | #define HAS_CAA_GET_CYCLES | |
f8c43f45 | 155 | |
a0307b90 MD |
156 | #ifdef CONFIG_RCU_HAVE_CLOCK_GETTIME |
157 | ||
3fa18286 MD |
158 | #include <time.h> |
159 | #include <stdint.h> | |
160 | ||
161 | typedef uint64_t caa_cycles_t; | |
162 | ||
163 | static inline caa_cycles_t caa_get_cycles (void) | |
f8c43f45 | 164 | { |
3fa18286 | 165 | struct timespec ts; |
f8c43f45 | 166 | |
3fa18286 MD |
167 | if (caa_unlikely(clock_gettime(CLOCK_MONOTONIC, &ts))) |
168 | return -1ULL; | |
169 | return ((uint64_t) ts.tv_sec * 1000000000ULL) + ts.tv_nsec; | |
f8c43f45 | 170 | } |
a0307b90 MD |
171 | |
172 | #elif defined(__APPLE__) | |
173 | ||
174 | #include <mach/mach.h> | |
175 | #include <mach/clock.h> | |
176 | #include <mach/mach_time.h> | |
177 | #include <time.h> | |
178 | #include <stdint.h> | |
179 | ||
180 | typedef uint64_t caa_cycles_t; | |
181 | ||
182 | static inline caa_cycles_t caa_get_cycles (void) | |
183 | { | |
184 | mach_timespec_t ts = { 0, 0 }; | |
185 | static clock_serv_t clock_service; | |
186 | ||
187 | if (caa_unlikely(!clock_service)) { | |
188 | if (host_get_clock_service(mach_host_self(), | |
189 | SYSTEM_CLOCK, &clock_service)) | |
190 | return -1ULL; | |
191 | } | |
192 | if (caa_unlikely(clock_get_time(clock_service, &ts))) | |
193 | return -1ULL; | |
194 | return ((uint64_t) ts.tv_sec * 1000000000ULL) + ts.tv_nsec; | |
195 | } | |
196 | ||
197 | #else | |
198 | ||
199 | #error caa_get_cycles() not implemented for this platform. | |
200 | ||
201 | #endif | |
202 | ||
f8c43f45 MD |
203 | #endif /* HAS_CAA_GET_CYCLES */ |
204 | ||
e4d1eb09 PB |
205 | #ifdef __cplusplus |
206 | } | |
207 | #endif | |
208 | ||
209 | #endif /* _URCU_ARCH_GENERIC_H */ |