master
1/* $NetBSD: atomic.h,v 1.26 2022/07/31 11:28:46 martin Exp $ */
2
3/*-
4 * Copyright (c) 2007, 2008 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Jason R. Thorpe.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
30 */
31
32#ifndef _SYS_ATOMIC_H_
33#define _SYS_ATOMIC_H_
34
35#include <sys/types.h>
36#if !defined(_KERNEL) && !defined(_STANDALONE)
37#include <stdint.h>
38#endif
39
40#if defined(_KERNEL) && defined(_KERNEL_OPT)
41#include "opt_kasan.h"
42#include "opt_kcsan.h"
43#include "opt_kmsan.h"
44#endif
45
46#if defined(KASAN)
47#define ATOMIC_PROTO_ADD(name, tret, targ1, targ2) \
48 void kasan_atomic_add_##name(volatile targ1 *, targ2); \
49 tret kasan_atomic_add_##name##_nv(volatile targ1 *, targ2)
50#define ATOMIC_PROTO_AND(name, tret, targ1, targ2) \
51 void kasan_atomic_and_##name(volatile targ1 *, targ2); \
52 tret kasan_atomic_and_##name##_nv(volatile targ1 *, targ2)
53#define ATOMIC_PROTO_OR(name, tret, targ1, targ2) \
54 void kasan_atomic_or_##name(volatile targ1 *, targ2); \
55 tret kasan_atomic_or_##name##_nv(volatile targ1 *, targ2)
56#define ATOMIC_PROTO_CAS(name, tret, targ1, targ2) \
57 tret kasan_atomic_cas_##name(volatile targ1 *, targ2, targ2); \
58 tret kasan_atomic_cas_##name##_ni(volatile targ1 *, targ2, targ2)
59#define ATOMIC_PROTO_SWAP(name, tret, targ1, targ2) \
60 tret kasan_atomic_swap_##name(volatile targ1 *, targ2)
61#define ATOMIC_PROTO_DEC(name, tret, targ1) \
62 void kasan_atomic_dec_##name(volatile targ1 *); \
63 tret kasan_atomic_dec_##name##_nv(volatile targ1 *)
64#define ATOMIC_PROTO_INC(name, tret, targ1) \
65 void kasan_atomic_inc_##name(volatile targ1 *); \
66 tret kasan_atomic_inc_##name##_nv(volatile targ1 *)
67#elif defined(KCSAN)
68#define ATOMIC_PROTO_ADD(name, tret, targ1, targ2) \
69 void kcsan_atomic_add_##name(volatile targ1 *, targ2); \
70 tret kcsan_atomic_add_##name##_nv(volatile targ1 *, targ2)
71#define ATOMIC_PROTO_AND(name, tret, targ1, targ2) \
72 void kcsan_atomic_and_##name(volatile targ1 *, targ2); \
73 tret kcsan_atomic_and_##name##_nv(volatile targ1 *, targ2)
74#define ATOMIC_PROTO_OR(name, tret, targ1, targ2) \
75 void kcsan_atomic_or_##name(volatile targ1 *, targ2); \
76 tret kcsan_atomic_or_##name##_nv(volatile targ1 *, targ2)
77#define ATOMIC_PROTO_CAS(name, tret, targ1, targ2) \
78 tret kcsan_atomic_cas_##name(volatile targ1 *, targ2, targ2); \
79 tret kcsan_atomic_cas_##name##_ni(volatile targ1 *, targ2, targ2)
80#define ATOMIC_PROTO_SWAP(name, tret, targ1, targ2) \
81 tret kcsan_atomic_swap_##name(volatile targ1 *, targ2)
82#define ATOMIC_PROTO_DEC(name, tret, targ1) \
83 void kcsan_atomic_dec_##name(volatile targ1 *); \
84 tret kcsan_atomic_dec_##name##_nv(volatile targ1 *)
85#define ATOMIC_PROTO_INC(name, tret, targ1) \
86 void kcsan_atomic_inc_##name(volatile targ1 *); \
87 tret kcsan_atomic_inc_##name##_nv(volatile targ1 *)
88#elif defined(KMSAN)
89#define ATOMIC_PROTO_ADD(name, tret, targ1, targ2) \
90 void kmsan_atomic_add_##name(volatile targ1 *, targ2); \
91 tret kmsan_atomic_add_##name##_nv(volatile targ1 *, targ2)
92#define ATOMIC_PROTO_AND(name, tret, targ1, targ2) \
93 void kmsan_atomic_and_##name(volatile targ1 *, targ2); \
94 tret kmsan_atomic_and_##name##_nv(volatile targ1 *, targ2)
95#define ATOMIC_PROTO_OR(name, tret, targ1, targ2) \
96 void kmsan_atomic_or_##name(volatile targ1 *, targ2); \
97 tret kmsan_atomic_or_##name##_nv(volatile targ1 *, targ2)
98#define ATOMIC_PROTO_CAS(name, tret, targ1, targ2) \
99 tret kmsan_atomic_cas_##name(volatile targ1 *, targ2, targ2); \
100 tret kmsan_atomic_cas_##name##_ni(volatile targ1 *, targ2, targ2)
101#define ATOMIC_PROTO_SWAP(name, tret, targ1, targ2) \
102 tret kmsan_atomic_swap_##name(volatile targ1 *, targ2)
103#define ATOMIC_PROTO_DEC(name, tret, targ1) \
104 void kmsan_atomic_dec_##name(volatile targ1 *); \
105 tret kmsan_atomic_dec_##name##_nv(volatile targ1 *)
106#define ATOMIC_PROTO_INC(name, tret, targ1) \
107 void kmsan_atomic_inc_##name(volatile targ1 *); \
108 tret kmsan_atomic_inc_##name##_nv(volatile targ1 *)
109#else
110#define ATOMIC_PROTO_ADD(name, tret, targ1, targ2) \
111 void atomic_add_##name(volatile targ1 *, targ2); \
112 tret atomic_add_##name##_nv(volatile targ1 *, targ2)
113#define ATOMIC_PROTO_AND(name, tret, targ1, targ2) \
114 void atomic_and_##name(volatile targ1 *, targ2); \
115 tret atomic_and_##name##_nv(volatile targ1 *, targ2)
116#define ATOMIC_PROTO_OR(name, tret, targ1, targ2) \
117 void atomic_or_##name(volatile targ1 *, targ2); \
118 tret atomic_or_##name##_nv(volatile targ1 *, targ2)
119#define ATOMIC_PROTO_CAS(name, tret, targ1, targ2) \
120 tret atomic_cas_##name(volatile targ1 *, targ2, targ2); \
121 tret atomic_cas_##name##_ni(volatile targ1 *, targ2, targ2)
122#define ATOMIC_PROTO_SWAP(name, tret, targ1, targ2) \
123 tret atomic_swap_##name(volatile targ1 *, targ2)
124#define ATOMIC_PROTO_DEC(name, tret, targ1) \
125 void atomic_dec_##name(volatile targ1 *); \
126 tret atomic_dec_##name##_nv(volatile targ1 *)
127#define ATOMIC_PROTO_INC(name, tret, targ1) \
128 void atomic_inc_##name(volatile targ1 *); \
129 tret atomic_inc_##name##_nv(volatile targ1 *)
130#endif
131
132__BEGIN_DECLS
133
134ATOMIC_PROTO_ADD(32, uint32_t, uint32_t, int32_t);
135ATOMIC_PROTO_ADD(64, uint64_t, uint64_t, int64_t);
136ATOMIC_PROTO_ADD(int, unsigned int, unsigned int, int);
137ATOMIC_PROTO_ADD(long, unsigned long, unsigned long, long);
138ATOMIC_PROTO_ADD(ptr, void *, void, ssize_t);
139
140ATOMIC_PROTO_AND(32, uint32_t, uint32_t, uint32_t);
141ATOMIC_PROTO_AND(64, uint64_t, uint64_t, uint64_t);
142ATOMIC_PROTO_AND(uint, unsigned int, unsigned int, unsigned int);
143ATOMIC_PROTO_AND(ulong, unsigned long, unsigned long, unsigned long);
144
145ATOMIC_PROTO_OR(32, uint32_t, uint32_t, uint32_t);
146ATOMIC_PROTO_OR(64, uint64_t, uint64_t, uint64_t);
147ATOMIC_PROTO_OR(uint, unsigned int, unsigned int, unsigned int);
148ATOMIC_PROTO_OR(ulong, unsigned long, unsigned long, unsigned long);
149
150ATOMIC_PROTO_CAS(32, uint32_t, uint32_t, uint32_t);
151ATOMIC_PROTO_CAS(64, uint64_t, uint64_t, uint64_t);
152ATOMIC_PROTO_CAS(uint, unsigned int, unsigned int, unsigned int);
153ATOMIC_PROTO_CAS(ulong, unsigned long, unsigned long, unsigned long);
154ATOMIC_PROTO_CAS(ptr, void *, void, void *);
155
156ATOMIC_PROTO_SWAP(32, uint32_t, uint32_t, uint32_t);
157ATOMIC_PROTO_SWAP(64, uint64_t, uint64_t, uint64_t);
158ATOMIC_PROTO_SWAP(uint, unsigned int, unsigned int, unsigned int);
159ATOMIC_PROTO_SWAP(ulong, unsigned long, unsigned long, unsigned long);
160ATOMIC_PROTO_SWAP(ptr, void *, void, void *);
161
162ATOMIC_PROTO_DEC(32, uint32_t, uint32_t);
163ATOMIC_PROTO_DEC(64, uint64_t, uint64_t);
164ATOMIC_PROTO_DEC(uint, unsigned int, unsigned int);
165ATOMIC_PROTO_DEC(ulong, unsigned long, unsigned long);
166ATOMIC_PROTO_DEC(ptr, void *, void);
167
168ATOMIC_PROTO_INC(32, uint32_t, uint32_t);
169ATOMIC_PROTO_INC(64, uint64_t, uint64_t);
170ATOMIC_PROTO_INC(uint, unsigned int, unsigned int);
171ATOMIC_PROTO_INC(ulong, unsigned long, unsigned long);
172ATOMIC_PROTO_INC(ptr, void *, void);
173
174/*
175 * These operations will be provided for userland, but may not be
176 * implemented efficiently.
177 */
178uint16_t atomic_cas_16(volatile uint16_t *, uint16_t, uint16_t);
179uint8_t atomic_cas_8(volatile uint8_t *, uint8_t, uint8_t);
180
181/*
182 * Memory barrier operations
183 */
184void membar_acquire(void);
185void membar_release(void);
186void membar_producer(void);
187void membar_consumer(void);
188void membar_sync(void);
189
190/*
191 * Deprecated memory barriers
192 */
193void membar_enter(void);
194void membar_exit(void);
195
196#ifdef __HAVE_MEMBAR_DATADEP_CONSUMER
197void membar_datadep_consumer(void);
198#else
199#define membar_datadep_consumer() ((void)0)
200#endif
201
202__END_DECLS
203
204#if defined(KASAN)
205#define atomic_add_32 kasan_atomic_add_32
206#define atomic_add_int kasan_atomic_add_int
207#define atomic_add_long kasan_atomic_add_long
208#define atomic_add_ptr kasan_atomic_add_ptr
209#define atomic_add_64 kasan_atomic_add_64
210#define atomic_add_32_nv kasan_atomic_add_32_nv
211#define atomic_add_int_nv kasan_atomic_add_int_nv
212#define atomic_add_long_nv kasan_atomic_add_long_nv
213#define atomic_add_ptr_nv kasan_atomic_add_ptr_nv
214#define atomic_add_64_nv kasan_atomic_add_64_nv
215#define atomic_and_32 kasan_atomic_and_32
216#define atomic_and_uint kasan_atomic_and_uint
217#define atomic_and_ulong kasan_atomic_and_ulong
218#define atomic_and_64 kasan_atomic_and_64
219#define atomic_and_32_nv kasan_atomic_and_32_nv
220#define atomic_and_uint_nv kasan_atomic_and_uint_nv
221#define atomic_and_ulong_nv kasan_atomic_and_ulong_nv
222#define atomic_and_64_nv kasan_atomic_and_64_nv
223#define atomic_or_32 kasan_atomic_or_32
224#define atomic_or_uint kasan_atomic_or_uint
225#define atomic_or_ulong kasan_atomic_or_ulong
226#define atomic_or_64 kasan_atomic_or_64
227#define atomic_or_32_nv kasan_atomic_or_32_nv
228#define atomic_or_uint_nv kasan_atomic_or_uint_nv
229#define atomic_or_ulong_nv kasan_atomic_or_ulong_nv
230#define atomic_or_64_nv kasan_atomic_or_64_nv
231#define atomic_cas_32 kasan_atomic_cas_32
232#define atomic_cas_uint kasan_atomic_cas_uint
233#define atomic_cas_ulong kasan_atomic_cas_ulong
234#define atomic_cas_ptr kasan_atomic_cas_ptr
235#define atomic_cas_64 kasan_atomic_cas_64
236#define atomic_cas_32_ni kasan_atomic_cas_32_ni
237#define atomic_cas_uint_ni kasan_atomic_cas_uint_ni
238#define atomic_cas_ulong_ni kasan_atomic_cas_ulong_ni
239#define atomic_cas_ptr_ni kasan_atomic_cas_ptr_ni
240#define atomic_cas_64_ni kasan_atomic_cas_64_ni
241#define atomic_swap_32 kasan_atomic_swap_32
242#define atomic_swap_uint kasan_atomic_swap_uint
243#define atomic_swap_ulong kasan_atomic_swap_ulong
244#define atomic_swap_ptr kasan_atomic_swap_ptr
245#define atomic_swap_64 kasan_atomic_swap_64
246#define atomic_dec_32 kasan_atomic_dec_32
247#define atomic_dec_uint kasan_atomic_dec_uint
248#define atomic_dec_ulong kasan_atomic_dec_ulong
249#define atomic_dec_ptr kasan_atomic_dec_ptr
250#define atomic_dec_64 kasan_atomic_dec_64
251#define atomic_dec_32_nv kasan_atomic_dec_32_nv
252#define atomic_dec_uint_nv kasan_atomic_dec_uint_nv
253#define atomic_dec_ulong_nv kasan_atomic_dec_ulong_nv
254#define atomic_dec_ptr_nv kasan_atomic_dec_ptr_nv
255#define atomic_dec_64_nv kasan_atomic_dec_64_nv
256#define atomic_inc_32 kasan_atomic_inc_32
257#define atomic_inc_uint kasan_atomic_inc_uint
258#define atomic_inc_ulong kasan_atomic_inc_ulong
259#define atomic_inc_ptr kasan_atomic_inc_ptr
260#define atomic_inc_64 kasan_atomic_inc_64
261#define atomic_inc_32_nv kasan_atomic_inc_32_nv
262#define atomic_inc_uint_nv kasan_atomic_inc_uint_nv
263#define atomic_inc_ulong_nv kasan_atomic_inc_ulong_nv
264#define atomic_inc_ptr_nv kasan_atomic_inc_ptr_nv
265#define atomic_inc_64_nv kasan_atomic_inc_64_nv
266#elif defined(KCSAN)
267#define atomic_add_32 kcsan_atomic_add_32
268#define atomic_add_int kcsan_atomic_add_int
269#define atomic_add_long kcsan_atomic_add_long
270#define atomic_add_ptr kcsan_atomic_add_ptr
271#define atomic_add_64 kcsan_atomic_add_64
272#define atomic_add_32_nv kcsan_atomic_add_32_nv
273#define atomic_add_int_nv kcsan_atomic_add_int_nv
274#define atomic_add_long_nv kcsan_atomic_add_long_nv
275#define atomic_add_ptr_nv kcsan_atomic_add_ptr_nv
276#define atomic_add_64_nv kcsan_atomic_add_64_nv
277#define atomic_and_32 kcsan_atomic_and_32
278#define atomic_and_uint kcsan_atomic_and_uint
279#define atomic_and_ulong kcsan_atomic_and_ulong
280#define atomic_and_64 kcsan_atomic_and_64
281#define atomic_and_32_nv kcsan_atomic_and_32_nv
282#define atomic_and_uint_nv kcsan_atomic_and_uint_nv
283#define atomic_and_ulong_nv kcsan_atomic_and_ulong_nv
284#define atomic_and_64_nv kcsan_atomic_and_64_nv
285#define atomic_or_32 kcsan_atomic_or_32
286#define atomic_or_uint kcsan_atomic_or_uint
287#define atomic_or_ulong kcsan_atomic_or_ulong
288#define atomic_or_64 kcsan_atomic_or_64
289#define atomic_or_32_nv kcsan_atomic_or_32_nv
290#define atomic_or_uint_nv kcsan_atomic_or_uint_nv
291#define atomic_or_ulong_nv kcsan_atomic_or_ulong_nv
292#define atomic_or_64_nv kcsan_atomic_or_64_nv
293#define atomic_cas_32 kcsan_atomic_cas_32
294#define atomic_cas_uint kcsan_atomic_cas_uint
295#define atomic_cas_ulong kcsan_atomic_cas_ulong
296#define atomic_cas_ptr kcsan_atomic_cas_ptr
297#define atomic_cas_64 kcsan_atomic_cas_64
298#define atomic_cas_32_ni kcsan_atomic_cas_32_ni
299#define atomic_cas_uint_ni kcsan_atomic_cas_uint_ni
300#define atomic_cas_ulong_ni kcsan_atomic_cas_ulong_ni
301#define atomic_cas_ptr_ni kcsan_atomic_cas_ptr_ni
302#define atomic_cas_64_ni kcsan_atomic_cas_64_ni
303#define atomic_swap_32 kcsan_atomic_swap_32
304#define atomic_swap_uint kcsan_atomic_swap_uint
305#define atomic_swap_ulong kcsan_atomic_swap_ulong
306#define atomic_swap_ptr kcsan_atomic_swap_ptr
307#define atomic_swap_64 kcsan_atomic_swap_64
308#define atomic_dec_32 kcsan_atomic_dec_32
309#define atomic_dec_uint kcsan_atomic_dec_uint
310#define atomic_dec_ulong kcsan_atomic_dec_ulong
311#define atomic_dec_ptr kcsan_atomic_dec_ptr
312#define atomic_dec_64 kcsan_atomic_dec_64
313#define atomic_dec_32_nv kcsan_atomic_dec_32_nv
314#define atomic_dec_uint_nv kcsan_atomic_dec_uint_nv
315#define atomic_dec_ulong_nv kcsan_atomic_dec_ulong_nv
316#define atomic_dec_ptr_nv kcsan_atomic_dec_ptr_nv
317#define atomic_dec_64_nv kcsan_atomic_dec_64_nv
318#define atomic_inc_32 kcsan_atomic_inc_32
319#define atomic_inc_uint kcsan_atomic_inc_uint
320#define atomic_inc_ulong kcsan_atomic_inc_ulong
321#define atomic_inc_ptr kcsan_atomic_inc_ptr
322#define atomic_inc_64 kcsan_atomic_inc_64
323#define atomic_inc_32_nv kcsan_atomic_inc_32_nv
324#define atomic_inc_uint_nv kcsan_atomic_inc_uint_nv
325#define atomic_inc_ulong_nv kcsan_atomic_inc_ulong_nv
326#define atomic_inc_ptr_nv kcsan_atomic_inc_ptr_nv
327#define atomic_inc_64_nv kcsan_atomic_inc_64_nv
328#elif defined(KMSAN)
329#define atomic_add_32 kmsan_atomic_add_32
330#define atomic_add_int kmsan_atomic_add_int
331#define atomic_add_long kmsan_atomic_add_long
332#define atomic_add_ptr kmsan_atomic_add_ptr
333#define atomic_add_64 kmsan_atomic_add_64
334#define atomic_add_32_nv kmsan_atomic_add_32_nv
335#define atomic_add_int_nv kmsan_atomic_add_int_nv
336#define atomic_add_long_nv kmsan_atomic_add_long_nv
337#define atomic_add_ptr_nv kmsan_atomic_add_ptr_nv
338#define atomic_add_64_nv kmsan_atomic_add_64_nv
339#define atomic_and_32 kmsan_atomic_and_32
340#define atomic_and_uint kmsan_atomic_and_uint
341#define atomic_and_ulong kmsan_atomic_and_ulong
342#define atomic_and_64 kmsan_atomic_and_64
343#define atomic_and_32_nv kmsan_atomic_and_32_nv
344#define atomic_and_uint_nv kmsan_atomic_and_uint_nv
345#define atomic_and_ulong_nv kmsan_atomic_and_ulong_nv
346#define atomic_and_64_nv kmsan_atomic_and_64_nv
347#define atomic_or_32 kmsan_atomic_or_32
348#define atomic_or_uint kmsan_atomic_or_uint
349#define atomic_or_ulong kmsan_atomic_or_ulong
350#define atomic_or_64 kmsan_atomic_or_64
351#define atomic_or_32_nv kmsan_atomic_or_32_nv
352#define atomic_or_uint_nv kmsan_atomic_or_uint_nv
353#define atomic_or_ulong_nv kmsan_atomic_or_ulong_nv
354#define atomic_or_64_nv kmsan_atomic_or_64_nv
355#define atomic_cas_32 kmsan_atomic_cas_32
356#define atomic_cas_uint kmsan_atomic_cas_uint
357#define atomic_cas_ulong kmsan_atomic_cas_ulong
358#define atomic_cas_ptr kmsan_atomic_cas_ptr
359#define atomic_cas_64 kmsan_atomic_cas_64
360#define atomic_cas_32_ni kmsan_atomic_cas_32_ni
361#define atomic_cas_uint_ni kmsan_atomic_cas_uint_ni
362#define atomic_cas_ulong_ni kmsan_atomic_cas_ulong_ni
363#define atomic_cas_ptr_ni kmsan_atomic_cas_ptr_ni
364#define atomic_cas_64_ni kmsan_atomic_cas_64_ni
365#define atomic_swap_32 kmsan_atomic_swap_32
366#define atomic_swap_uint kmsan_atomic_swap_uint
367#define atomic_swap_ulong kmsan_atomic_swap_ulong
368#define atomic_swap_ptr kmsan_atomic_swap_ptr
369#define atomic_swap_64 kmsan_atomic_swap_64
370#define atomic_dec_32 kmsan_atomic_dec_32
371#define atomic_dec_uint kmsan_atomic_dec_uint
372#define atomic_dec_ulong kmsan_atomic_dec_ulong
373#define atomic_dec_ptr kmsan_atomic_dec_ptr
374#define atomic_dec_64 kmsan_atomic_dec_64
375#define atomic_dec_32_nv kmsan_atomic_dec_32_nv
376#define atomic_dec_uint_nv kmsan_atomic_dec_uint_nv
377#define atomic_dec_ulong_nv kmsan_atomic_dec_ulong_nv
378#define atomic_dec_ptr_nv kmsan_atomic_dec_ptr_nv
379#define atomic_dec_64_nv kmsan_atomic_dec_64_nv
380#define atomic_inc_32 kmsan_atomic_inc_32
381#define atomic_inc_uint kmsan_atomic_inc_uint
382#define atomic_inc_ulong kmsan_atomic_inc_ulong
383#define atomic_inc_ptr kmsan_atomic_inc_ptr
384#define atomic_inc_64 kmsan_atomic_inc_64
385#define atomic_inc_32_nv kmsan_atomic_inc_32_nv
386#define atomic_inc_uint_nv kmsan_atomic_inc_uint_nv
387#define atomic_inc_ulong_nv kmsan_atomic_inc_ulong_nv
388#define atomic_inc_ptr_nv kmsan_atomic_inc_ptr_nv
389#define atomic_inc_64_nv kmsan_atomic_inc_64_nv
390#endif
391
392#ifdef _KERNEL
393
394#if 1 // XXX: __STDC_VERSION__ < 201112L
395
396/* Pre-C11 definitions */
397
398#include <sys/cdefs.h>
399
400#include <lib/libkern/libkern.h>
401
402#ifdef _LP64
403#define __HAVE_ATOMIC64_LOADSTORE 1
404#define __ATOMIC_SIZE_MAX 8
405#else
406#define __ATOMIC_SIZE_MAX 4
407#endif
408
409/*
410 * We assume that access to an aligned pointer to a volatile object of
411 * at most __ATOMIC_SIZE_MAX bytes is guaranteed to be atomic. This is
412 * an assumption that may be wrong, but we hope it won't be wrong
413 * before we just adopt the C11 atomic API.
414 */
415#define __ATOMIC_PTR_CHECK(p) do \
416{ \
417 CTASSERT(sizeof(*(p)) <= __ATOMIC_SIZE_MAX); \
418 KASSERT(((uintptr_t)(p) & (sizeof(*(p)) - 1)) == 0); \
419} while (0)
420
421#ifdef KCSAN
422void kcsan_atomic_load(const volatile void *, void *, int);
423void kcsan_atomic_store(volatile void *, const void *, int);
424#define __BEGIN_ATOMIC_LOAD(p, v) \
425 union { __typeof__(*(p)) __al_val; char __al_buf[1]; } v; \
426 kcsan_atomic_load(p, v.__al_buf, sizeof(v.__al_val))
427#define __END_ATOMIC_LOAD(v) \
428 (v).__al_val
429#define __DO_ATOMIC_STORE(p, v) \
430 kcsan_atomic_store(p, __UNVOLATILE(&v), sizeof(v))
431#else
432#define __BEGIN_ATOMIC_LOAD(p, v) \
433 __typeof__(*(p)) v = *(p)
434#define __END_ATOMIC_LOAD(v) \
435 v
436#ifdef __HAVE_HASHLOCKED_ATOMICS
437#define __DO_ATOMIC_STORE(p, v) \
438 __do_atomic_store(p, __UNVOLATILE(&v), sizeof(v))
439#else /* !__HAVE_HASHLOCKED_ATOMICS */
440#define __DO_ATOMIC_STORE(p, v) \
441 *p = v
442#endif
443#endif
444
445#define atomic_load_relaxed(p) \
446({ \
447 const volatile __typeof__(*(p)) *__al_ptr = (p); \
448 __ATOMIC_PTR_CHECK(__al_ptr); \
449 __BEGIN_ATOMIC_LOAD(__al_ptr, __al_val); \
450 __END_ATOMIC_LOAD(__al_val); \
451})
452
453#define atomic_load_consume(p) \
454({ \
455 const volatile __typeof__(*(p)) *__al_ptr = (p); \
456 __ATOMIC_PTR_CHECK(__al_ptr); \
457 __BEGIN_ATOMIC_LOAD(__al_ptr, __al_val); \
458 membar_datadep_consumer(); \
459 __END_ATOMIC_LOAD(__al_val); \
460})
461
462#define atomic_load_acquire(p) \
463({ \
464 const volatile __typeof__(*(p)) *__al_ptr = (p); \
465 __ATOMIC_PTR_CHECK(__al_ptr); \
466 __BEGIN_ATOMIC_LOAD(__al_ptr, __al_val); \
467 membar_acquire(); \
468 __END_ATOMIC_LOAD(__al_val); \
469})
470
471#define atomic_store_relaxed(p,v) \
472({ \
473 volatile __typeof__(*(p)) *__as_ptr = (p); \
474 __typeof__(*(p)) __as_val = (v); \
475 __ATOMIC_PTR_CHECK(__as_ptr); \
476 __DO_ATOMIC_STORE(__as_ptr, __as_val); \
477})
478
479#define atomic_store_release(p,v) \
480({ \
481 volatile __typeof__(*(p)) *__as_ptr = (p); \
482 __typeof__(*(p)) __as_val = (v); \
483 __ATOMIC_PTR_CHECK(__as_ptr); \
484 membar_release(); \
485 __DO_ATOMIC_STORE(__as_ptr, __as_val); \
486})
487
488#ifdef __HAVE_HASHLOCKED_ATOMICS
489static __inline __always_inline void
490__do_atomic_store(volatile void *p, const void *q, size_t size)
491{
492 switch (size) {
493 case 1: {
494 uint8_t v;
495 unsigned s = 8 * ((uintptr_t)p & 3);
496 uint32_t o, n, m = ~(0xffU << s);
497 memcpy(&v, q, 1);
498 do {
499 o = atomic_load_relaxed((const volatile uint32_t *)p);
500 n = (o & m) | ((uint32_t)v << s);
501 } while (atomic_cas_32((volatile uint32_t *)p, o, n) != o);
502 break;
503 }
504 case 2: {
505 uint16_t v;
506 unsigned s = 8 * (((uintptr_t)p & 2) >> 1);
507 uint32_t o, n, m = ~(0xffffU << s);
508 memcpy(&v, q, 2);
509 do {
510 o = atomic_load_relaxed((const volatile uint32_t *)p);
511 n = (o & m) | ((uint32_t)v << s);
512 } while (atomic_cas_32((volatile uint32_t *)p, o, n) != o);
513 break;
514 }
515 case 4: {
516 uint32_t v;
517 memcpy(&v, q, 4);
518 (void)atomic_swap_32(p, v);
519 break;
520 }
521#ifdef __HAVE_ATOMIC64_LOADSTORE
522 case 8: {
523 uint64_t v;
524 memcpy(&v, q, 8);
525 (void)atomic_swap_64(p, v);
526 break;
527 }
528#endif
529 }
530}
531#endif /* __HAVE_HASHLOCKED_ATOMICS */
532
533#else /* __STDC_VERSION__ >= 201112L */
534
535/* C11 definitions, not yet available */
536
537#include <stdatomic.h>
538
539#define atomic_load_relaxed(p) \
540 atomic_load_explicit((p), memory_order_relaxed)
541#if 0 /* memory_order_consume is not there yet */
542#define atomic_load_consume(p) \
543 atomic_load_explicit((p), memory_order_consume)
544#else
545#define atomic_load_consume(p) \
546({ \
547 const __typeof__(*(p)) __al_val = atomic_load_relaxed(p); \
548 membar_datadep_consumer(); \
549 __al_val; \
550})
551#endif
552#define atomic_load_acquire(p) \
553 atomic_load_explicit((p), memory_order_acquire)
554#define atomic_store_relaxed(p, v) \
555 atomic_store_explicit((p), (v), memory_order_relaxed)
556#define atomic_store_release(p, v) \
557 atomic_store_explicit((p), (v), memory_order_release)
558
559#endif /* __STDC_VERSION__ */
560
561#endif /* _KERNEL */
562
563#endif /* ! _SYS_ATOMIC_H_ */