18d7e7a98SRuslan Bukin /*- 22183004eSRuslan Bukin * Copyright (c) 2015-2024 Ruslan Bukin <br@bsdpad.com> 38d7e7a98SRuslan Bukin * All rights reserved. 48d7e7a98SRuslan Bukin * 58d7e7a98SRuslan Bukin * Portions of this software were developed by SRI International and the 68d7e7a98SRuslan Bukin * University of Cambridge Computer Laboratory under DARPA/AFRL contract 78d7e7a98SRuslan Bukin * FA8750-10-C-0237 ("CTSRD"), as part of the DARPA CRASH research programme. 88d7e7a98SRuslan Bukin * 98d7e7a98SRuslan Bukin * Portions of this software were developed by the University of Cambridge 108d7e7a98SRuslan Bukin * Computer Laboratory as part of the CTSRD Project, with support from the 118d7e7a98SRuslan Bukin * UK Higher Education Innovation Fund (HEIF). 128d7e7a98SRuslan Bukin * 138d7e7a98SRuslan Bukin * Redistribution and use in source and binary forms, with or without 148d7e7a98SRuslan Bukin * modification, are permitted provided that the following conditions 158d7e7a98SRuslan Bukin * are met: 168d7e7a98SRuslan Bukin * 1. Redistributions of source code must retain the above copyright 178d7e7a98SRuslan Bukin * notice, this list of conditions and the following disclaimer. 188d7e7a98SRuslan Bukin * 2. Redistributions in binary form must reproduce the above copyright 198d7e7a98SRuslan Bukin * notice, this list of conditions and the following disclaimer in the 208d7e7a98SRuslan Bukin * documentation and/or other materials provided with the distribution. 218d7e7a98SRuslan Bukin * 228d7e7a98SRuslan Bukin * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 238d7e7a98SRuslan Bukin * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 248d7e7a98SRuslan Bukin * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 258d7e7a98SRuslan Bukin * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 268d7e7a98SRuslan Bukin * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 278d7e7a98SRuslan Bukin * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 288d7e7a98SRuslan Bukin * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 298d7e7a98SRuslan Bukin * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 308d7e7a98SRuslan Bukin * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 318d7e7a98SRuslan Bukin * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 328d7e7a98SRuslan Bukin * SUCH DAMAGE. 338d7e7a98SRuslan Bukin */ 348d7e7a98SRuslan Bukin 358d7e7a98SRuslan Bukin #ifndef _MACHINE_ATOMIC_H_ 368d7e7a98SRuslan Bukin #define _MACHINE_ATOMIC_H_ 378d7e7a98SRuslan Bukin 3830d4f9e8SKonstantin Belousov #include <sys/atomic_common.h> 3930d4f9e8SKonstantin Belousov 408d7e7a98SRuslan Bukin #define fence() __asm __volatile("fence" ::: "memory"); 418d7e7a98SRuslan Bukin #define mb() fence() 428d7e7a98SRuslan Bukin #define rmb() fence() 438d7e7a98SRuslan Bukin #define wmb() fence() 448d7e7a98SRuslan Bukin 4529a5f639SKyle Evans static __inline int atomic_cmpset_8(__volatile uint8_t *, uint8_t, uint8_t); 4629a5f639SKyle Evans static __inline int atomic_fcmpset_8(__volatile uint8_t *, uint8_t *, uint8_t); 4729a5f639SKyle Evans static __inline int atomic_cmpset_16(__volatile uint16_t *, uint16_t, uint16_t); 4829a5f639SKyle Evans static __inline int atomic_fcmpset_16(__volatile uint16_t *, uint16_t *, 4929a5f639SKyle Evans uint16_t); 5029a5f639SKyle Evans 518d7e7a98SRuslan Bukin #define ATOMIC_ACQ_REL(NAME, WIDTH) \ 528d7e7a98SRuslan Bukin static __inline void \ 538d7e7a98SRuslan Bukin atomic_##NAME##_acq_##WIDTH(__volatile uint##WIDTH##_t *p, uint##WIDTH##_t v)\ 548d7e7a98SRuslan Bukin { \ 558d7e7a98SRuslan Bukin atomic_##NAME##_##WIDTH(p, v); \ 568d7e7a98SRuslan Bukin fence(); \ 578d7e7a98SRuslan Bukin } \ 588d7e7a98SRuslan Bukin \ 598d7e7a98SRuslan Bukin static __inline void \ 608d7e7a98SRuslan Bukin atomic_##NAME##_rel_##WIDTH(__volatile uint##WIDTH##_t *p, uint##WIDTH##_t v)\ 618d7e7a98SRuslan Bukin { \ 628d7e7a98SRuslan Bukin fence(); \ 638d7e7a98SRuslan Bukin atomic_##NAME##_##WIDTH(p, v); \ 648d7e7a98SRuslan Bukin } 658d7e7a98SRuslan Bukin 6629a5f639SKyle Evans #define ATOMIC_CMPSET_ACQ_REL(WIDTH) \ 6729a5f639SKyle Evans static __inline int \ 6829a5f639SKyle Evans atomic_cmpset_acq_##WIDTH(__volatile uint##WIDTH##_t *p, \ 6929a5f639SKyle Evans uint##WIDTH##_t cmpval, uint##WIDTH##_t newval) \ 7029a5f639SKyle Evans { \ 7129a5f639SKyle Evans int retval; \ 7229a5f639SKyle Evans \ 7329a5f639SKyle Evans retval = atomic_cmpset_##WIDTH(p, cmpval, newval); \ 7429a5f639SKyle Evans fence(); \ 7529a5f639SKyle Evans return (retval); \ 7629a5f639SKyle Evans } \ 7729a5f639SKyle Evans \ 7829a5f639SKyle Evans static __inline int \ 7929a5f639SKyle Evans atomic_cmpset_rel_##WIDTH(__volatile uint##WIDTH##_t *p, \ 8029a5f639SKyle Evans uint##WIDTH##_t cmpval, uint##WIDTH##_t newval) \ 8129a5f639SKyle Evans { \ 8229a5f639SKyle Evans fence(); \ 8329a5f639SKyle Evans return (atomic_cmpset_##WIDTH(p, cmpval, newval)); \ 8429a5f639SKyle Evans } 8529a5f639SKyle Evans 8629a5f639SKyle Evans #define ATOMIC_FCMPSET_ACQ_REL(WIDTH) \ 8729a5f639SKyle Evans static __inline int \ 8829a5f639SKyle Evans atomic_fcmpset_acq_##WIDTH(__volatile uint##WIDTH##_t *p, \ 8929a5f639SKyle Evans uint##WIDTH##_t *cmpval, uint##WIDTH##_t newval) \ 9029a5f639SKyle Evans { \ 9129a5f639SKyle Evans int retval; \ 9229a5f639SKyle Evans \ 9329a5f639SKyle Evans retval = atomic_fcmpset_##WIDTH(p, cmpval, newval); \ 9429a5f639SKyle Evans fence(); \ 9529a5f639SKyle Evans return (retval); \ 9629a5f639SKyle Evans } \ 9729a5f639SKyle Evans \ 9829a5f639SKyle Evans static __inline int \ 9929a5f639SKyle Evans atomic_fcmpset_rel_##WIDTH(__volatile uint##WIDTH##_t *p, \ 10029a5f639SKyle Evans uint##WIDTH##_t *cmpval, uint##WIDTH##_t newval) \ 10129a5f639SKyle Evans { \ 10229a5f639SKyle Evans fence(); \ 10329a5f639SKyle Evans return (atomic_fcmpset_##WIDTH(p, cmpval, newval)); \ 10429a5f639SKyle Evans } 10529a5f639SKyle Evans 10629a5f639SKyle Evans ATOMIC_CMPSET_ACQ_REL(8); 10729a5f639SKyle Evans ATOMIC_FCMPSET_ACQ_REL(8); 10829a5f639SKyle Evans 10929a5f639SKyle Evans #define atomic_cmpset_char atomic_cmpset_8 11029a5f639SKyle Evans #define atomic_cmpset_acq_char atomic_cmpset_acq_8 11129a5f639SKyle Evans #define atomic_cmpset_rel_char atomic_cmpset_rel_8 11229a5f639SKyle Evans #define atomic_fcmpset_char atomic_fcmpset_8 11329a5f639SKyle Evans #define atomic_fcmpset_acq_char atomic_fcmpset_acq_8 11429a5f639SKyle Evans #define atomic_fcmpset_rel_char atomic_fcmpset_rel_8 11529a5f639SKyle Evans 11629a5f639SKyle Evans #define atomic_cmpset_short atomic_cmpset_16 11729a5f639SKyle Evans #define atomic_fcmpset_short atomic_fcmpset_16 1182183004eSRuslan Bukin 1192183004eSRuslan Bukin ATOMIC_CMPSET_ACQ_REL(16); 1202183004eSRuslan Bukin ATOMIC_FCMPSET_ACQ_REL(16); 1212183004eSRuslan Bukin 1222183004eSRuslan Bukin #define atomic_load_acq_16 atomic_load_acq_16 1232183004eSRuslan Bukin static __inline uint16_t 1245e9a82e8SOlivier Certner atomic_load_acq_16(const volatile uint16_t *p) 1252183004eSRuslan Bukin { 1262183004eSRuslan Bukin uint16_t ret; 1272183004eSRuslan Bukin 1282183004eSRuslan Bukin ret = *p; 1292183004eSRuslan Bukin 1302183004eSRuslan Bukin fence(); 1312183004eSRuslan Bukin 1322183004eSRuslan Bukin return (ret); 1332183004eSRuslan Bukin } 1342183004eSRuslan Bukin 1352183004eSRuslan Bukin static __inline void 1362183004eSRuslan Bukin atomic_store_rel_16(volatile uint16_t *p, uint16_t val) 1372183004eSRuslan Bukin { 1382183004eSRuslan Bukin 1392183004eSRuslan Bukin fence(); 1402183004eSRuslan Bukin 1412183004eSRuslan Bukin *p = val; 1422183004eSRuslan Bukin } 1432183004eSRuslan Bukin 1442183004eSRuslan Bukin #define atomic_cmpset_acq_short atomic_cmpset_acq_16 14529a5f639SKyle Evans #define atomic_fcmpset_acq_short atomic_fcmpset_acq_16 1462183004eSRuslan Bukin #define atomic_load_acq_short atomic_load_acq_16 1472183004eSRuslan Bukin 1482183004eSRuslan Bukin #define atomic_cmpset_rel_short atomic_cmpset_rel_16 14929a5f639SKyle Evans #define atomic_fcmpset_rel_short atomic_fcmpset_rel_16 1502183004eSRuslan Bukin #define atomic_store_rel_short atomic_store_rel_16 15129a5f639SKyle Evans 1528d7e7a98SRuslan Bukin static __inline void 1538d7e7a98SRuslan Bukin atomic_add_32(volatile uint32_t *p, uint32_t val) 1548d7e7a98SRuslan Bukin { 1558d7e7a98SRuslan Bukin 1568d7e7a98SRuslan Bukin __asm __volatile("amoadd.w zero, %1, %0" 1578d7e7a98SRuslan Bukin : "+A" (*p) 1588d7e7a98SRuslan Bukin : "r" (val) 1598d7e7a98SRuslan Bukin : "memory"); 1608d7e7a98SRuslan Bukin } 1618d7e7a98SRuslan Bukin 1628d7e7a98SRuslan Bukin static __inline void 1638d7e7a98SRuslan Bukin atomic_subtract_32(volatile uint32_t *p, uint32_t val) 1648d7e7a98SRuslan Bukin { 1658d7e7a98SRuslan Bukin 1668d7e7a98SRuslan Bukin __asm __volatile("amoadd.w zero, %1, %0" 1678d7e7a98SRuslan Bukin : "+A" (*p) 1688d7e7a98SRuslan Bukin : "r" (-val) 1698d7e7a98SRuslan Bukin : "memory"); 1708d7e7a98SRuslan Bukin } 1718d7e7a98SRuslan Bukin 1728d7e7a98SRuslan Bukin static __inline void 1738d7e7a98SRuslan Bukin atomic_set_32(volatile uint32_t *p, uint32_t val) 1748d7e7a98SRuslan Bukin { 1758d7e7a98SRuslan Bukin 1768d7e7a98SRuslan Bukin __asm __volatile("amoor.w zero, %1, %0" 1778d7e7a98SRuslan Bukin : "+A" (*p) 1788d7e7a98SRuslan Bukin : "r" (val) 1798d7e7a98SRuslan Bukin : "memory"); 1808d7e7a98SRuslan Bukin } 1818d7e7a98SRuslan Bukin 1828d7e7a98SRuslan Bukin static __inline void 1838d7e7a98SRuslan Bukin atomic_clear_32(volatile uint32_t *p, uint32_t val) 1848d7e7a98SRuslan Bukin { 1858d7e7a98SRuslan Bukin 1868d7e7a98SRuslan Bukin __asm __volatile("amoand.w zero, %1, %0" 1878d7e7a98SRuslan Bukin : "+A" (*p) 1888d7e7a98SRuslan Bukin : "r" (~val) 1898d7e7a98SRuslan Bukin : "memory"); 1908d7e7a98SRuslan Bukin } 1918d7e7a98SRuslan Bukin 1928d7e7a98SRuslan Bukin static __inline int 1938d7e7a98SRuslan Bukin atomic_cmpset_32(volatile uint32_t *p, uint32_t cmpval, uint32_t newval) 1948d7e7a98SRuslan Bukin { 1958d7e7a98SRuslan Bukin uint32_t tmp; 1968d7e7a98SRuslan Bukin int res; 1978d7e7a98SRuslan Bukin 1988d7e7a98SRuslan Bukin res = 0; 1998d7e7a98SRuslan Bukin 2008d7e7a98SRuslan Bukin __asm __volatile( 2018d7e7a98SRuslan Bukin "0:" 2028d7e7a98SRuslan Bukin "li %1, 1\n" /* Preset to fail */ 2038d7e7a98SRuslan Bukin "lr.w %0, %2\n" 2048d7e7a98SRuslan Bukin "bne %0, %z3, 1f\n" 2058d7e7a98SRuslan Bukin "sc.w %1, %z4, %2\n" 2068d7e7a98SRuslan Bukin "bnez %1, 0b\n" 2078d7e7a98SRuslan Bukin "1:" 2088d7e7a98SRuslan Bukin : "=&r" (tmp), "=&r" (res), "+A" (*p) 209b96562ebSJohn Baldwin : "rJ" ((long)(int32_t)cmpval), "rJ" (newval) 2108d7e7a98SRuslan Bukin : "memory"); 2118d7e7a98SRuslan Bukin 2128d7e7a98SRuslan Bukin return (!res); 2138d7e7a98SRuslan Bukin } 2148d7e7a98SRuslan Bukin 21543b595f6SRuslan Bukin static __inline int 21643b595f6SRuslan Bukin atomic_fcmpset_32(volatile uint32_t *p, uint32_t *cmpval, uint32_t newval) 21743b595f6SRuslan Bukin { 21843b595f6SRuslan Bukin uint32_t tmp; 21943b595f6SRuslan Bukin int res; 22043b595f6SRuslan Bukin 22143b595f6SRuslan Bukin res = 0; 22243b595f6SRuslan Bukin 22343b595f6SRuslan Bukin __asm __volatile( 22443b595f6SRuslan Bukin "0:" 22543b595f6SRuslan Bukin "li %1, 1\n" /* Preset to fail */ 22643b595f6SRuslan Bukin "lr.w %0, %2\n" /* Load old value */ 22743b595f6SRuslan Bukin "bne %0, %z4, 1f\n" /* Compare */ 22843b595f6SRuslan Bukin "sc.w %1, %z5, %2\n" /* Try to store new value */ 22943b595f6SRuslan Bukin "j 2f\n" 23043b595f6SRuslan Bukin "1:" 23143b595f6SRuslan Bukin "sw %0, %3\n" /* Save old value */ 23243b595f6SRuslan Bukin "2:" 23343b595f6SRuslan Bukin : "=&r" (tmp), "=&r" (res), "+A" (*p), "+A" (*cmpval) 234b96562ebSJohn Baldwin : "rJ" ((long)(int32_t)*cmpval), "rJ" (newval) 23543b595f6SRuslan Bukin : "memory"); 23643b595f6SRuslan Bukin 23743b595f6SRuslan Bukin return (!res); 23843b595f6SRuslan Bukin } 23943b595f6SRuslan Bukin 2408d7e7a98SRuslan Bukin static __inline uint32_t 2418d7e7a98SRuslan Bukin atomic_fetchadd_32(volatile uint32_t *p, uint32_t val) 2428d7e7a98SRuslan Bukin { 2438d7e7a98SRuslan Bukin uint32_t ret; 2448d7e7a98SRuslan Bukin 2458d7e7a98SRuslan Bukin __asm __volatile("amoadd.w %0, %2, %1" 2468d7e7a98SRuslan Bukin : "=&r" (ret), "+A" (*p) 2478d7e7a98SRuslan Bukin : "r" (val) 2488d7e7a98SRuslan Bukin : "memory"); 2498d7e7a98SRuslan Bukin 2508d7e7a98SRuslan Bukin return (ret); 2518d7e7a98SRuslan Bukin } 2528d7e7a98SRuslan Bukin 2538d7e7a98SRuslan Bukin static __inline uint32_t 2548d7e7a98SRuslan Bukin atomic_readandclear_32(volatile uint32_t *p) 2558d7e7a98SRuslan Bukin { 2568d7e7a98SRuslan Bukin uint32_t ret; 2578d7e7a98SRuslan Bukin uint32_t val; 2588d7e7a98SRuslan Bukin 2598d7e7a98SRuslan Bukin val = 0; 2608d7e7a98SRuslan Bukin 2618d7e7a98SRuslan Bukin __asm __volatile("amoswap.w %0, %2, %1" 2628d7e7a98SRuslan Bukin : "=&r"(ret), "+A" (*p) 2638d7e7a98SRuslan Bukin : "r" (val) 2648d7e7a98SRuslan Bukin : "memory"); 2658d7e7a98SRuslan Bukin 2668d7e7a98SRuslan Bukin return (ret); 2678d7e7a98SRuslan Bukin } 2688d7e7a98SRuslan Bukin 269a474e53dSJohn Baldwin static __inline int 270a474e53dSJohn Baldwin atomic_testandclear_32(volatile uint32_t *p, u_int val) 271a474e53dSJohn Baldwin { 272a474e53dSJohn Baldwin uint32_t mask, old; 273a474e53dSJohn Baldwin 274a474e53dSJohn Baldwin mask = 1u << (val & 31); 275a474e53dSJohn Baldwin __asm __volatile("amoand.w %0, %2, %1" 276a474e53dSJohn Baldwin : "=&r" (old), "+A" (*p) 277a474e53dSJohn Baldwin : "r" (~mask) 278a474e53dSJohn Baldwin : "memory"); 279a474e53dSJohn Baldwin 280a474e53dSJohn Baldwin return ((old & mask) != 0); 281a474e53dSJohn Baldwin } 282a474e53dSJohn Baldwin 283a474e53dSJohn Baldwin static __inline int 284a474e53dSJohn Baldwin atomic_testandset_32(volatile uint32_t *p, u_int val) 285a474e53dSJohn Baldwin { 286a474e53dSJohn Baldwin uint32_t mask, old; 287a474e53dSJohn Baldwin 288a474e53dSJohn Baldwin mask = 1u << (val & 31); 289a474e53dSJohn Baldwin __asm __volatile("amoor.w %0, %2, %1" 290a474e53dSJohn Baldwin : "=&r" (old), "+A" (*p) 291a474e53dSJohn Baldwin : "r" (mask) 292a474e53dSJohn Baldwin : "memory"); 293a474e53dSJohn Baldwin 294a474e53dSJohn Baldwin return ((old & mask) != 0); 295a474e53dSJohn Baldwin } 296a474e53dSJohn Baldwin 2978d7e7a98SRuslan Bukin #define atomic_add_int atomic_add_32 2988d7e7a98SRuslan Bukin #define atomic_clear_int atomic_clear_32 2998d7e7a98SRuslan Bukin #define atomic_cmpset_int atomic_cmpset_32 30043b595f6SRuslan Bukin #define atomic_fcmpset_int atomic_fcmpset_32 3018d7e7a98SRuslan Bukin #define atomic_fetchadd_int atomic_fetchadd_32 3028d7e7a98SRuslan Bukin #define atomic_readandclear_int atomic_readandclear_32 3038d7e7a98SRuslan Bukin #define atomic_set_int atomic_set_32 3048d7e7a98SRuslan Bukin #define atomic_subtract_int atomic_subtract_32 3058d7e7a98SRuslan Bukin 3068d7e7a98SRuslan Bukin ATOMIC_ACQ_REL(set, 32) 3078d7e7a98SRuslan Bukin ATOMIC_ACQ_REL(clear, 32) 3088d7e7a98SRuslan Bukin ATOMIC_ACQ_REL(add, 32) 3098d7e7a98SRuslan Bukin ATOMIC_ACQ_REL(subtract, 32) 3108d7e7a98SRuslan Bukin 31129a5f639SKyle Evans ATOMIC_CMPSET_ACQ_REL(32); 31229a5f639SKyle Evans ATOMIC_FCMPSET_ACQ_REL(32); 31343b595f6SRuslan Bukin 3148d7e7a98SRuslan Bukin static __inline uint32_t 3155e9a82e8SOlivier Certner atomic_load_acq_32(const volatile uint32_t *p) 3168d7e7a98SRuslan Bukin { 3178d7e7a98SRuslan Bukin uint32_t ret; 3188d7e7a98SRuslan Bukin 3198d7e7a98SRuslan Bukin ret = *p; 3208d7e7a98SRuslan Bukin 3218d7e7a98SRuslan Bukin fence(); 3228d7e7a98SRuslan Bukin 3238d7e7a98SRuslan Bukin return (ret); 3248d7e7a98SRuslan Bukin } 3258d7e7a98SRuslan Bukin 3268d7e7a98SRuslan Bukin static __inline void 3278d7e7a98SRuslan Bukin atomic_store_rel_32(volatile uint32_t *p, uint32_t val) 3288d7e7a98SRuslan Bukin { 3298d7e7a98SRuslan Bukin 3308d7e7a98SRuslan Bukin fence(); 3318d7e7a98SRuslan Bukin 3328d7e7a98SRuslan Bukin *p = val; 3338d7e7a98SRuslan Bukin } 3348d7e7a98SRuslan Bukin 3358d7e7a98SRuslan Bukin #define atomic_add_acq_int atomic_add_acq_32 3368d7e7a98SRuslan Bukin #define atomic_clear_acq_int atomic_clear_acq_32 3378d7e7a98SRuslan Bukin #define atomic_cmpset_acq_int atomic_cmpset_acq_32 33843b595f6SRuslan Bukin #define atomic_fcmpset_acq_int atomic_fcmpset_acq_32 3398d7e7a98SRuslan Bukin #define atomic_load_acq_int atomic_load_acq_32 3408d7e7a98SRuslan Bukin #define atomic_set_acq_int atomic_set_acq_32 3418d7e7a98SRuslan Bukin #define atomic_subtract_acq_int atomic_subtract_acq_32 3428d7e7a98SRuslan Bukin 3438d7e7a98SRuslan Bukin #define atomic_add_rel_int atomic_add_rel_32 3440d3b3beeSMitchell Horne #define atomic_clear_rel_int atomic_clear_rel_32 3458d7e7a98SRuslan Bukin #define atomic_cmpset_rel_int atomic_cmpset_rel_32 34643b595f6SRuslan Bukin #define atomic_fcmpset_rel_int atomic_fcmpset_rel_32 3478d7e7a98SRuslan Bukin #define atomic_set_rel_int atomic_set_rel_32 3488d7e7a98SRuslan Bukin #define atomic_subtract_rel_int atomic_subtract_rel_32 3498d7e7a98SRuslan Bukin #define atomic_store_rel_int atomic_store_rel_32 3508d7e7a98SRuslan Bukin 3518d7e7a98SRuslan Bukin static __inline void 3528d7e7a98SRuslan Bukin atomic_add_64(volatile uint64_t *p, uint64_t val) 3538d7e7a98SRuslan Bukin { 3548d7e7a98SRuslan Bukin 3558d7e7a98SRuslan Bukin __asm __volatile("amoadd.d zero, %1, %0" 3568d7e7a98SRuslan Bukin : "+A" (*p) 3578d7e7a98SRuslan Bukin : "r" (val) 3588d7e7a98SRuslan Bukin : "memory"); 3598d7e7a98SRuslan Bukin } 3608d7e7a98SRuslan Bukin 3618d7e7a98SRuslan Bukin static __inline void 3628d7e7a98SRuslan Bukin atomic_subtract_64(volatile uint64_t *p, uint64_t val) 3638d7e7a98SRuslan Bukin { 3648d7e7a98SRuslan Bukin 3658d7e7a98SRuslan Bukin __asm __volatile("amoadd.d zero, %1, %0" 3668d7e7a98SRuslan Bukin : "+A" (*p) 3678d7e7a98SRuslan Bukin : "r" (-val) 3688d7e7a98SRuslan Bukin : "memory"); 3698d7e7a98SRuslan Bukin } 3708d7e7a98SRuslan Bukin 3718d7e7a98SRuslan Bukin static __inline void 3728d7e7a98SRuslan Bukin atomic_set_64(volatile uint64_t *p, uint64_t val) 3738d7e7a98SRuslan Bukin { 3748d7e7a98SRuslan Bukin 3758d7e7a98SRuslan Bukin __asm __volatile("amoor.d zero, %1, %0" 3768d7e7a98SRuslan Bukin : "+A" (*p) 3778d7e7a98SRuslan Bukin : "r" (val) 3788d7e7a98SRuslan Bukin : "memory"); 3798d7e7a98SRuslan Bukin } 3808d7e7a98SRuslan Bukin 3818d7e7a98SRuslan Bukin static __inline void 3828d7e7a98SRuslan Bukin atomic_clear_64(volatile uint64_t *p, uint64_t val) 3838d7e7a98SRuslan Bukin { 3848d7e7a98SRuslan Bukin 3858d7e7a98SRuslan Bukin __asm __volatile("amoand.d zero, %1, %0" 3868d7e7a98SRuslan Bukin : "+A" (*p) 3878d7e7a98SRuslan Bukin : "r" (~val) 3888d7e7a98SRuslan Bukin : "memory"); 3898d7e7a98SRuslan Bukin } 3908d7e7a98SRuslan Bukin 3918d7e7a98SRuslan Bukin static __inline int 3928d7e7a98SRuslan Bukin atomic_cmpset_64(volatile uint64_t *p, uint64_t cmpval, uint64_t newval) 3938d7e7a98SRuslan Bukin { 3948d7e7a98SRuslan Bukin uint64_t tmp; 3958d7e7a98SRuslan Bukin int res; 3968d7e7a98SRuslan Bukin 3978d7e7a98SRuslan Bukin res = 0; 3988d7e7a98SRuslan Bukin 3998d7e7a98SRuslan Bukin __asm __volatile( 4008d7e7a98SRuslan Bukin "0:" 4018d7e7a98SRuslan Bukin "li %1, 1\n" /* Preset to fail */ 4028d7e7a98SRuslan Bukin "lr.d %0, %2\n" 4038d7e7a98SRuslan Bukin "bne %0, %z3, 1f\n" 4048d7e7a98SRuslan Bukin "sc.d %1, %z4, %2\n" 4058d7e7a98SRuslan Bukin "bnez %1, 0b\n" 4068d7e7a98SRuslan Bukin "1:" 4078d7e7a98SRuslan Bukin : "=&r" (tmp), "=&r" (res), "+A" (*p) 4088d7e7a98SRuslan Bukin : "rJ" (cmpval), "rJ" (newval) 4098d7e7a98SRuslan Bukin : "memory"); 4108d7e7a98SRuslan Bukin 4118d7e7a98SRuslan Bukin return (!res); 4128d7e7a98SRuslan Bukin } 4138d7e7a98SRuslan Bukin 41443b595f6SRuslan Bukin static __inline int 41543b595f6SRuslan Bukin atomic_fcmpset_64(volatile uint64_t *p, uint64_t *cmpval, uint64_t newval) 41643b595f6SRuslan Bukin { 41743b595f6SRuslan Bukin uint64_t tmp; 41843b595f6SRuslan Bukin int res; 41943b595f6SRuslan Bukin 42043b595f6SRuslan Bukin res = 0; 42143b595f6SRuslan Bukin 42243b595f6SRuslan Bukin __asm __volatile( 42343b595f6SRuslan Bukin "0:" 42443b595f6SRuslan Bukin "li %1, 1\n" /* Preset to fail */ 42543b595f6SRuslan Bukin "lr.d %0, %2\n" /* Load old value */ 42643b595f6SRuslan Bukin "bne %0, %z4, 1f\n" /* Compare */ 42743b595f6SRuslan Bukin "sc.d %1, %z5, %2\n" /* Try to store new value */ 42843b595f6SRuslan Bukin "j 2f\n" 42943b595f6SRuslan Bukin "1:" 43043b595f6SRuslan Bukin "sd %0, %3\n" /* Save old value */ 43143b595f6SRuslan Bukin "2:" 43243b595f6SRuslan Bukin : "=&r" (tmp), "=&r" (res), "+A" (*p), "+A" (*cmpval) 43343b595f6SRuslan Bukin : "rJ" (*cmpval), "rJ" (newval) 43443b595f6SRuslan Bukin : "memory"); 43543b595f6SRuslan Bukin 43643b595f6SRuslan Bukin return (!res); 43743b595f6SRuslan Bukin } 43843b595f6SRuslan Bukin 4398d7e7a98SRuslan Bukin static __inline uint64_t 4408d7e7a98SRuslan Bukin atomic_fetchadd_64(volatile uint64_t *p, uint64_t val) 4418d7e7a98SRuslan Bukin { 4428d7e7a98SRuslan Bukin uint64_t ret; 4438d7e7a98SRuslan Bukin 4448d7e7a98SRuslan Bukin __asm __volatile("amoadd.d %0, %2, %1" 4458d7e7a98SRuslan Bukin : "=&r" (ret), "+A" (*p) 4468d7e7a98SRuslan Bukin : "r" (val) 4478d7e7a98SRuslan Bukin : "memory"); 4488d7e7a98SRuslan Bukin 4498d7e7a98SRuslan Bukin return (ret); 4508d7e7a98SRuslan Bukin } 4518d7e7a98SRuslan Bukin 4528d7e7a98SRuslan Bukin static __inline uint64_t 4538d7e7a98SRuslan Bukin atomic_readandclear_64(volatile uint64_t *p) 4548d7e7a98SRuslan Bukin { 4558d7e7a98SRuslan Bukin uint64_t ret; 4568d7e7a98SRuslan Bukin uint64_t val; 4578d7e7a98SRuslan Bukin 4588d7e7a98SRuslan Bukin val = 0; 4598d7e7a98SRuslan Bukin 4608d7e7a98SRuslan Bukin __asm __volatile("amoswap.d %0, %2, %1" 4618d7e7a98SRuslan Bukin : "=&r"(ret), "+A" (*p) 4628d7e7a98SRuslan Bukin : "r" (val) 4638d7e7a98SRuslan Bukin : "memory"); 4648d7e7a98SRuslan Bukin 4658d7e7a98SRuslan Bukin return (ret); 4668d7e7a98SRuslan Bukin } 4678d7e7a98SRuslan Bukin 468a474e53dSJohn Baldwin static __inline int 469a474e53dSJohn Baldwin atomic_testandclear_64(volatile uint64_t *p, u_int val) 470a474e53dSJohn Baldwin { 471a474e53dSJohn Baldwin uint64_t mask, old; 472a474e53dSJohn Baldwin 473a474e53dSJohn Baldwin mask = 1ul << (val & 63); 474a474e53dSJohn Baldwin __asm __volatile("amoand.d %0, %2, %1" 475a474e53dSJohn Baldwin : "=&r" (old), "+A" (*p) 476a474e53dSJohn Baldwin : "r" (~mask) 477a474e53dSJohn Baldwin : "memory"); 478a474e53dSJohn Baldwin 479a474e53dSJohn Baldwin return ((old & mask) != 0); 480a474e53dSJohn Baldwin } 481a474e53dSJohn Baldwin 482a474e53dSJohn Baldwin static __inline int 483a474e53dSJohn Baldwin atomic_testandset_64(volatile uint64_t *p, u_int val) 484a474e53dSJohn Baldwin { 485a474e53dSJohn Baldwin uint64_t mask, old; 486a474e53dSJohn Baldwin 487a474e53dSJohn Baldwin mask = 1ul << (val & 63); 488a474e53dSJohn Baldwin __asm __volatile("amoor.d %0, %2, %1" 489a474e53dSJohn Baldwin : "=&r" (old), "+A" (*p) 490a474e53dSJohn Baldwin : "r" (mask) 491a474e53dSJohn Baldwin : "memory"); 492a474e53dSJohn Baldwin 493a474e53dSJohn Baldwin return ((old & mask) != 0); 494a474e53dSJohn Baldwin } 495a474e53dSJohn Baldwin 496a474e53dSJohn Baldwin static __inline int 497a474e53dSJohn Baldwin atomic_testandset_acq_64(volatile uint64_t *p, u_int val) 498a474e53dSJohn Baldwin { 499a474e53dSJohn Baldwin uint64_t mask, old; 500a474e53dSJohn Baldwin 501a474e53dSJohn Baldwin mask = 1ul << (val & 63); 502a474e53dSJohn Baldwin __asm __volatile("amoor.d.aq %0, %2, %1" 503a474e53dSJohn Baldwin : "=&r" (old), "+A" (*p) 504a474e53dSJohn Baldwin : "r" (mask) 505a474e53dSJohn Baldwin : "memory"); 506a474e53dSJohn Baldwin 507a474e53dSJohn Baldwin return ((old & mask) != 0); 508a474e53dSJohn Baldwin } 509a474e53dSJohn Baldwin 5105fe191b0SRuslan Bukin static __inline uint32_t 5115fe191b0SRuslan Bukin atomic_swap_32(volatile uint32_t *p, uint32_t val) 5125fe191b0SRuslan Bukin { 5135fe191b0SRuslan Bukin uint32_t old; 5145fe191b0SRuslan Bukin 5155fe191b0SRuslan Bukin __asm __volatile("amoswap.w %0, %2, %1" 5165fe191b0SRuslan Bukin : "=&r"(old), "+A" (*p) 5175fe191b0SRuslan Bukin : "r" (val) 5185fe191b0SRuslan Bukin : "memory"); 5195fe191b0SRuslan Bukin 5205fe191b0SRuslan Bukin return (old); 5215fe191b0SRuslan Bukin } 5225fe191b0SRuslan Bukin 5238d7e7a98SRuslan Bukin static __inline uint64_t 5248d7e7a98SRuslan Bukin atomic_swap_64(volatile uint64_t *p, uint64_t val) 5258d7e7a98SRuslan Bukin { 5268d7e7a98SRuslan Bukin uint64_t old; 5278d7e7a98SRuslan Bukin 5288d7e7a98SRuslan Bukin __asm __volatile("amoswap.d %0, %2, %1" 5298d7e7a98SRuslan Bukin : "=&r"(old), "+A" (*p) 5308d7e7a98SRuslan Bukin : "r" (val) 5318d7e7a98SRuslan Bukin : "memory"); 5328d7e7a98SRuslan Bukin 5338d7e7a98SRuslan Bukin return (old); 5348d7e7a98SRuslan Bukin } 5358d7e7a98SRuslan Bukin 53613a10f34SMarius Strobl #define atomic_swap_int atomic_swap_32 53713a10f34SMarius Strobl 5388d7e7a98SRuslan Bukin #define atomic_add_long atomic_add_64 5398d7e7a98SRuslan Bukin #define atomic_clear_long atomic_clear_64 5408d7e7a98SRuslan Bukin #define atomic_cmpset_long atomic_cmpset_64 54143b595f6SRuslan Bukin #define atomic_fcmpset_long atomic_fcmpset_64 5428d7e7a98SRuslan Bukin #define atomic_fetchadd_long atomic_fetchadd_64 5438d7e7a98SRuslan Bukin #define atomic_readandclear_long atomic_readandclear_64 5448d7e7a98SRuslan Bukin #define atomic_set_long atomic_set_64 5458d7e7a98SRuslan Bukin #define atomic_subtract_long atomic_subtract_64 54613a10f34SMarius Strobl #define atomic_swap_long atomic_swap_64 547a474e53dSJohn Baldwin #define atomic_testandclear_long atomic_testandclear_64 548a474e53dSJohn Baldwin #define atomic_testandset_long atomic_testandset_64 549a474e53dSJohn Baldwin #define atomic_testandset_acq_long atomic_testandset_acq_64 5508d7e7a98SRuslan Bukin 5518d7e7a98SRuslan Bukin #define atomic_add_ptr atomic_add_64 5528d7e7a98SRuslan Bukin #define atomic_clear_ptr atomic_clear_64 5538d7e7a98SRuslan Bukin #define atomic_cmpset_ptr atomic_cmpset_64 55443b595f6SRuslan Bukin #define atomic_fcmpset_ptr atomic_fcmpset_64 5558d7e7a98SRuslan Bukin #define atomic_fetchadd_ptr atomic_fetchadd_64 5568d7e7a98SRuslan Bukin #define atomic_readandclear_ptr atomic_readandclear_64 5578d7e7a98SRuslan Bukin #define atomic_set_ptr atomic_set_64 5588d7e7a98SRuslan Bukin #define atomic_subtract_ptr atomic_subtract_64 55913a10f34SMarius Strobl #define atomic_swap_ptr atomic_swap_64 560a80b9ee1SJohn Baldwin #define atomic_testandclear_ptr atomic_testandclear_64 561a80b9ee1SJohn Baldwin #define atomic_testandset_ptr atomic_testandset_64 5628d7e7a98SRuslan Bukin 5638d7e7a98SRuslan Bukin ATOMIC_ACQ_REL(set, 64) 5648d7e7a98SRuslan Bukin ATOMIC_ACQ_REL(clear, 64) 5658d7e7a98SRuslan Bukin ATOMIC_ACQ_REL(add, 64) 5668d7e7a98SRuslan Bukin ATOMIC_ACQ_REL(subtract, 64) 5678d7e7a98SRuslan Bukin 56829a5f639SKyle Evans ATOMIC_CMPSET_ACQ_REL(64); 56929a5f639SKyle Evans ATOMIC_FCMPSET_ACQ_REL(64); 57043b595f6SRuslan Bukin 5718d7e7a98SRuslan Bukin static __inline uint64_t 572*ac2156c1SOlivier Certner atomic_load_acq_64(const volatile uint64_t *p) 5738d7e7a98SRuslan Bukin { 5748d7e7a98SRuslan Bukin uint64_t ret; 5758d7e7a98SRuslan Bukin 5768d7e7a98SRuslan Bukin ret = *p; 5778d7e7a98SRuslan Bukin 5788d7e7a98SRuslan Bukin fence(); 5798d7e7a98SRuslan Bukin 5808d7e7a98SRuslan Bukin return (ret); 5818d7e7a98SRuslan Bukin } 5828d7e7a98SRuslan Bukin 5838d7e7a98SRuslan Bukin static __inline void 5848d7e7a98SRuslan Bukin atomic_store_rel_64(volatile uint64_t *p, uint64_t val) 5858d7e7a98SRuslan Bukin { 5868d7e7a98SRuslan Bukin 5878d7e7a98SRuslan Bukin fence(); 5888d7e7a98SRuslan Bukin 5898d7e7a98SRuslan Bukin *p = val; 5908d7e7a98SRuslan Bukin } 5918d7e7a98SRuslan Bukin 5928d7e7a98SRuslan Bukin #define atomic_add_acq_long atomic_add_acq_64 5930d3b3beeSMitchell Horne #define atomic_clear_acq_long atomic_clear_acq_64 5948d7e7a98SRuslan Bukin #define atomic_cmpset_acq_long atomic_cmpset_acq_64 59543b595f6SRuslan Bukin #define atomic_fcmpset_acq_long atomic_fcmpset_acq_64 5968d7e7a98SRuslan Bukin #define atomic_load_acq_long atomic_load_acq_64 5978d7e7a98SRuslan Bukin #define atomic_set_acq_long atomic_set_acq_64 5988d7e7a98SRuslan Bukin #define atomic_subtract_acq_long atomic_subtract_acq_64 5998d7e7a98SRuslan Bukin 6008d7e7a98SRuslan Bukin #define atomic_add_acq_ptr atomic_add_acq_64 6010d3b3beeSMitchell Horne #define atomic_clear_acq_ptr atomic_clear_acq_64 6028d7e7a98SRuslan Bukin #define atomic_cmpset_acq_ptr atomic_cmpset_acq_64 60343b595f6SRuslan Bukin #define atomic_fcmpset_acq_ptr atomic_fcmpset_acq_64 6048d7e7a98SRuslan Bukin #define atomic_load_acq_ptr atomic_load_acq_64 6058d7e7a98SRuslan Bukin #define atomic_set_acq_ptr atomic_set_acq_64 6068d7e7a98SRuslan Bukin #define atomic_subtract_acq_ptr atomic_subtract_acq_64 6078d7e7a98SRuslan Bukin 6085c118142SRuslan Bukin #undef ATOMIC_ACQ_REL 6095c118142SRuslan Bukin 6108d7e7a98SRuslan Bukin static __inline void 6118d7e7a98SRuslan Bukin atomic_thread_fence_acq(void) 6128d7e7a98SRuslan Bukin { 6138d7e7a98SRuslan Bukin 6148d7e7a98SRuslan Bukin fence(); 6158d7e7a98SRuslan Bukin } 6168d7e7a98SRuslan Bukin 6178d7e7a98SRuslan Bukin static __inline void 6188d7e7a98SRuslan Bukin atomic_thread_fence_rel(void) 6198d7e7a98SRuslan Bukin { 6208d7e7a98SRuslan Bukin 6218d7e7a98SRuslan Bukin fence(); 6228d7e7a98SRuslan Bukin } 6238d7e7a98SRuslan Bukin 6248d7e7a98SRuslan Bukin static __inline void 6258d7e7a98SRuslan Bukin atomic_thread_fence_acq_rel(void) 6268d7e7a98SRuslan Bukin { 6278d7e7a98SRuslan Bukin 6288d7e7a98SRuslan Bukin fence(); 6298d7e7a98SRuslan Bukin } 6308d7e7a98SRuslan Bukin 6318d7e7a98SRuslan Bukin static __inline void 6328d7e7a98SRuslan Bukin atomic_thread_fence_seq_cst(void) 6338d7e7a98SRuslan Bukin { 6348d7e7a98SRuslan Bukin 6358d7e7a98SRuslan Bukin fence(); 6368d7e7a98SRuslan Bukin } 6378d7e7a98SRuslan Bukin 6388d7e7a98SRuslan Bukin #define atomic_add_rel_long atomic_add_rel_64 6398d7e7a98SRuslan Bukin #define atomic_clear_rel_long atomic_clear_rel_64 6408d7e7a98SRuslan Bukin 6418d7e7a98SRuslan Bukin #define atomic_add_rel_long atomic_add_rel_64 6428d7e7a98SRuslan Bukin #define atomic_clear_rel_long atomic_clear_rel_64 6438d7e7a98SRuslan Bukin #define atomic_cmpset_rel_long atomic_cmpset_rel_64 64443b595f6SRuslan Bukin #define atomic_fcmpset_rel_long atomic_fcmpset_rel_64 6458d7e7a98SRuslan Bukin #define atomic_set_rel_long atomic_set_rel_64 6468d7e7a98SRuslan Bukin #define atomic_subtract_rel_long atomic_subtract_rel_64 6478d7e7a98SRuslan Bukin #define atomic_store_rel_long atomic_store_rel_64 6488d7e7a98SRuslan Bukin 6498d7e7a98SRuslan Bukin #define atomic_add_rel_ptr atomic_add_rel_64 6508d7e7a98SRuslan Bukin #define atomic_clear_rel_ptr atomic_clear_rel_64 6518d7e7a98SRuslan Bukin #define atomic_cmpset_rel_ptr atomic_cmpset_rel_64 65243b595f6SRuslan Bukin #define atomic_fcmpset_rel_ptr atomic_fcmpset_rel_64 6538d7e7a98SRuslan Bukin #define atomic_set_rel_ptr atomic_set_rel_64 6548d7e7a98SRuslan Bukin #define atomic_subtract_rel_ptr atomic_subtract_rel_64 6558d7e7a98SRuslan Bukin #define atomic_store_rel_ptr atomic_store_rel_64 6568d7e7a98SRuslan Bukin 65729a5f639SKyle Evans #include <sys/_atomic_subword.h> 65829a5f639SKyle Evans 6598d7e7a98SRuslan Bukin #endif /* _MACHINE_ATOMIC_H_ */ 660