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