Home | History | Annotate | Line # | Download | only in sys
      1 /*	$NetBSD: atomic.h,v 1.27 2025/04/22 01:34:38 riastradh 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 
    134 ATOMIC_PROTO_ADD(32, uint32_t, uint32_t, int32_t);
    135 ATOMIC_PROTO_ADD(64, uint64_t, uint64_t, int64_t);
    136 ATOMIC_PROTO_ADD(int, unsigned int, unsigned int, int);
    137 ATOMIC_PROTO_ADD(long, unsigned long, unsigned long, long);
    138 ATOMIC_PROTO_ADD(ptr, void *, void, ssize_t);
    139 
    140 ATOMIC_PROTO_AND(32, uint32_t, uint32_t, uint32_t);
    141 ATOMIC_PROTO_AND(64, uint64_t, uint64_t, uint64_t);
    142 ATOMIC_PROTO_AND(uint, unsigned int, unsigned int, unsigned int);
    143 ATOMIC_PROTO_AND(ulong, unsigned long, unsigned long, unsigned long);
    144 
    145 ATOMIC_PROTO_OR(32, uint32_t, uint32_t, uint32_t);
    146 ATOMIC_PROTO_OR(64, uint64_t, uint64_t, uint64_t);
    147 ATOMIC_PROTO_OR(uint, unsigned int, unsigned int, unsigned int);
    148 ATOMIC_PROTO_OR(ulong, unsigned long, unsigned long, unsigned long);
    149 
    150 ATOMIC_PROTO_CAS(32, uint32_t, uint32_t, uint32_t);
    151 ATOMIC_PROTO_CAS(64, uint64_t, uint64_t, uint64_t);
    152 ATOMIC_PROTO_CAS(uint, unsigned int, unsigned int, unsigned int);
    153 ATOMIC_PROTO_CAS(ulong, unsigned long, unsigned long, unsigned long);
    154 ATOMIC_PROTO_CAS(ptr, void *, void, void *);
    155 
    156 ATOMIC_PROTO_SWAP(32, uint32_t, uint32_t, uint32_t);
    157 ATOMIC_PROTO_SWAP(64, uint64_t, uint64_t, uint64_t);
    158 ATOMIC_PROTO_SWAP(uint, unsigned int, unsigned int, unsigned int);
    159 ATOMIC_PROTO_SWAP(ulong, unsigned long, unsigned long, unsigned long);
    160 ATOMIC_PROTO_SWAP(ptr, void *, void, void *);
    161 
    162 ATOMIC_PROTO_DEC(32, uint32_t, uint32_t);
    163 ATOMIC_PROTO_DEC(64, uint64_t, uint64_t);
    164 ATOMIC_PROTO_DEC(uint, unsigned int, unsigned int);
    165 ATOMIC_PROTO_DEC(ulong, unsigned long, unsigned long);
    166 ATOMIC_PROTO_DEC(ptr, void *, void);
    167 
    168 ATOMIC_PROTO_INC(32, uint32_t, uint32_t);
    169 ATOMIC_PROTO_INC(64, uint64_t, uint64_t);
    170 ATOMIC_PROTO_INC(uint, unsigned int, unsigned int);
    171 ATOMIC_PROTO_INC(ulong, unsigned long, unsigned long);
    172 ATOMIC_PROTO_INC(ptr, void *, void);
    173 
    174 /*
    175  * These operations will be provided for userland, but may not be
    176  * implemented efficiently.
    177  */
    178 uint16_t	atomic_cas_16(volatile uint16_t *, uint16_t, uint16_t);
    179 uint8_t 	atomic_cas_8(volatile uint8_t *, uint8_t, uint8_t);
    180 
    181 /*
    182  * Memory barrier operations
    183  */
    184 void		membar_acquire(void);
    185 void		membar_release(void);
    186 void		membar_producer(void);
    187 void		membar_consumer(void);
    188 void		membar_sync(void);
    189 
    190 /*
    191  * Deprecated memory barriers
    192  */
    193 void		membar_enter(void);
    194 void		membar_exit(void);
    195 
    196 #ifdef	__HAVE_MEMBAR_DATADEP_CONSUMER
    197 void		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
    422 void kcsan_atomic_load(const volatile void *, void *, int);
    423 void 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
    489 static __inline __always_inline void
    490 __do_atomic_store(volatile void *p, const void *q, size_t size)
    491 {
    492 	volatile uint32_t *p32 = (volatile uint32_t *)((uintptr_t)p & ~3);
    493 
    494 	switch (size) {
    495 	case 1: {
    496 		uint8_t v;
    497 		unsigned s = 8 * ((uintptr_t)p & 3);
    498 		uint32_t o, n, m = ~(0xffU << s);
    499 
    500 		memcpy(&v, q, 1);
    501 		do {
    502 			o = atomic_load_relaxed(p32);
    503 			n = (o & m) | ((uint32_t)v << s);
    504 		} while (atomic_cas_32(p32, o, n) != o);
    505 		break;
    506 	}
    507 	case 2: {
    508 		uint16_t v;
    509 		unsigned s = 8 * (((uintptr_t)p & 2) >> 1);
    510 		uint32_t o, n, m = ~(0xffffU << s);
    511 
    512 		memcpy(&v, q, 2);
    513 		do {
    514 			o = atomic_load_relaxed(p32);
    515 			n = (o & m) | ((uint32_t)v << s);
    516 		} while (atomic_cas_32(p32, o, n) != o);
    517 		break;
    518 	}
    519 	case 4: {
    520 		uint32_t v;
    521 
    522 		memcpy(&v, q, 4);
    523 		(void)atomic_swap_32(p, v);
    524 		break;
    525 	}
    526 #ifdef __HAVE_ATOMIC64_LOADSTORE
    527 	case 8: {
    528 		uint64_t v;
    529 		memcpy(&v, q, 8);
    530 		(void)atomic_swap_64(p, v);
    531 		break;
    532 	}
    533 #endif
    534 	}
    535 }
    536 #endif	/* __HAVE_HASHLOCKED_ATOMICS */
    537 
    538 #else  /* __STDC_VERSION__ >= 201112L */
    539 
    540 /* C11 definitions, not yet available */
    541 
    542 #include <stdatomic.h>
    543 
    544 #define	atomic_load_relaxed(p)						      \
    545 	atomic_load_explicit((p), memory_order_relaxed)
    546 #if 0				/* memory_order_consume is not there yet */
    547 #define	atomic_load_consume(p)						      \
    548 	atomic_load_explicit((p), memory_order_consume)
    549 #else
    550 #define	atomic_load_consume(p)						      \
    551 ({									      \
    552 	const __typeof__(*(p)) __al_val = atomic_load_relaxed(p);	      \
    553 	membar_datadep_consumer();					      \
    554 	__al_val;							      \
    555 })
    556 #endif
    557 #define	atomic_load_acquire(p)						      \
    558 	atomic_load_explicit((p), memory_order_acquire)
    559 #define	atomic_store_relaxed(p, v)					      \
    560 	atomic_store_explicit((p), (v), memory_order_relaxed)
    561 #define	atomic_store_release(p, v)					      \
    562 	atomic_store_explicit((p), (v), memory_order_release)
    563 
    564 #endif	/* __STDC_VERSION__ */
    565 
    566 #endif	/* _KERNEL */
    567 
    568 #endif /* ! _SYS_ATOMIC_H_ */
    569