1 /* Low-level functions for atomic operations. Mips version. 2 Copyright (C) 2005-2022 Free Software Foundation, Inc. 3 This file is part of the GNU C Library. 4 5 The GNU C Library is free software; you can redistribute it and/or 6 modify it under the terms of the GNU Lesser General Public 7 License as published by the Free Software Foundation; either 8 version 2.1 of the License, or (at your option) any later version. 9 10 The GNU C Library is distributed in the hope that it will be useful, 11 but WITHOUT ANY WARRANTY; without even the implied warranty of 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 Lesser General Public License for more details. 14 15 You should have received a copy of the GNU Lesser General Public 16 License along with the GNU C Library. If not, see 17 <https://www.gnu.org/licenses/>. */ 18 19 #ifndef _MIPS_ATOMIC_MACHINE_H 20 #define _MIPS_ATOMIC_MACHINE_H 1 21 22 #include <sgidefs.h> 23 24 #if _MIPS_SIM == _ABIO32 && __mips < 2 25 #define MIPS_PUSH_MIPS2 ".set mips2\n\t" 26 #else 27 #define MIPS_PUSH_MIPS2 28 #endif 29 30 #if _MIPS_SIM == _ABIO32 || _MIPS_SIM == _ABIN32 31 #define __HAVE_64B_ATOMICS 0 32 #else 33 #define __HAVE_64B_ATOMICS 1 34 #endif 35 36 /* See the comments in <sys/asm.h> about the use of the sync instruction. */ 37 #ifndef MIPS_SYNC 38 # define MIPS_SYNC sync 39 #endif 40 41 #define MIPS_SYNC_STR_2(X) #X 42 #define MIPS_SYNC_STR_1(X) MIPS_SYNC_STR_2(X) 43 #define MIPS_SYNC_STR MIPS_SYNC_STR_1(MIPS_SYNC) 44 45 #define USE_ATOMIC_COMPILER_BUILTINS 1 46 47 /* MIPS is an LL/SC machine. However, XLP has a direct atomic exchange 48 instruction which will be used by __atomic_exchange_n. */ 49 #ifdef _MIPS_ARCH_XLP 50 # define ATOMIC_EXCHANGE_USES_CAS 0 51 #else 52 # define ATOMIC_EXCHANGE_USES_CAS 1 53 #endif 54 55 /* Compare and exchange. 56 For all "bool" routines, we return FALSE if exchange succesful. */ 57 58 #define __arch_compare_and_exchange_bool_8_int(mem, newval, oldval, model) \ 59 (abort (), 0) 60 61 #define __arch_compare_and_exchange_bool_16_int(mem, newval, oldval, model) \ 62 (abort (), 0) 63 64 #define __arch_compare_and_exchange_bool_32_int(mem, newval, oldval, model) \ 65 ({ \ 66 typeof (*mem) __oldval = (oldval); \ 67 !__atomic_compare_exchange_n (mem, (void *) &__oldval, newval, 0, \ 68 model, __ATOMIC_RELAXED); \ 69 }) 70 71 #define __arch_compare_and_exchange_val_8_int(mem, newval, oldval, model) \ 72 (abort (), (typeof(*mem)) 0) 73 74 #define __arch_compare_and_exchange_val_16_int(mem, newval, oldval, model) \ 75 (abort (), (typeof(*mem)) 0) 76 77 #define __arch_compare_and_exchange_val_32_int(mem, newval, oldval, model) \ 78 ({ \ 79 typeof (*mem) __oldval = (oldval); \ 80 __atomic_compare_exchange_n (mem, (void *) &__oldval, newval, 0, \ 81 model, __ATOMIC_RELAXED); \ 82 __oldval; \ 83 }) 84 85 #if _MIPS_SIM == _ABIO32 86 /* We can't do an atomic 64-bit operation in O32. */ 87 # define __arch_compare_and_exchange_bool_64_int(mem, newval, oldval, model) \ 88 (abort (), 0) 89 # define __arch_compare_and_exchange_val_64_int(mem, newval, oldval, model) \ 90 (abort (), (typeof(*mem)) 0) 91 #else 92 # define __arch_compare_and_exchange_bool_64_int(mem, newval, oldval, model) \ 93 __arch_compare_and_exchange_bool_32_int (mem, newval, oldval, model) 94 # define __arch_compare_and_exchange_val_64_int(mem, newval, oldval, model) \ 95 __arch_compare_and_exchange_val_32_int (mem, newval, oldval, model) 96 #endif 97 98 /* Compare and exchange with "acquire" semantics, ie barrier after. */ 99 100 #define atomic_compare_and_exchange_bool_acq(mem, new, old) \ 101 __atomic_bool_bysize (__arch_compare_and_exchange_bool, int, \ 102 mem, new, old, __ATOMIC_ACQUIRE) 103 104 #define atomic_compare_and_exchange_val_acq(mem, new, old) \ 105 __atomic_val_bysize (__arch_compare_and_exchange_val, int, \ 106 mem, new, old, __ATOMIC_ACQUIRE) 107 108 /* Compare and exchange with "release" semantics, ie barrier before. */ 109 110 #define atomic_compare_and_exchange_val_rel(mem, new, old) \ 111 __atomic_val_bysize (__arch_compare_and_exchange_val, int, \ 112 mem, new, old, __ATOMIC_RELEASE) 113 114 115 /* Atomic exchange (without compare). */ 116 117 #define __arch_exchange_8_int(mem, newval, model) \ 118 (abort (), (typeof(*mem)) 0) 119 120 #define __arch_exchange_16_int(mem, newval, model) \ 121 (abort (), (typeof(*mem)) 0) 122 123 #define __arch_exchange_32_int(mem, newval, model) \ 124 __atomic_exchange_n (mem, newval, model) 125 126 #if _MIPS_SIM == _ABIO32 127 /* We can't do an atomic 64-bit operation in O32. */ 128 # define __arch_exchange_64_int(mem, newval, model) \ 129 (abort (), (typeof(*mem)) 0) 130 #else 131 # define __arch_exchange_64_int(mem, newval, model) \ 132 __atomic_exchange_n (mem, newval, model) 133 #endif 134 135 #define atomic_exchange_acq(mem, value) \ 136 __atomic_val_bysize (__arch_exchange, int, mem, value, __ATOMIC_ACQUIRE) 137 138 #define atomic_exchange_rel(mem, value) \ 139 __atomic_val_bysize (__arch_exchange, int, mem, value, __ATOMIC_RELEASE) 140 141 142 /* Atomically add value and return the previous (unincremented) value. */ 143 144 #define __arch_exchange_and_add_8_int(mem, value, model) \ 145 (abort (), (typeof(*mem)) 0) 146 147 #define __arch_exchange_and_add_16_int(mem, value, model) \ 148 (abort (), (typeof(*mem)) 0) 149 150 #define __arch_exchange_and_add_32_int(mem, value, model) \ 151 __atomic_fetch_add (mem, value, model) 152 153 #if _MIPS_SIM == _ABIO32 154 /* We can't do an atomic 64-bit operation in O32. */ 155 # define __arch_exchange_and_add_64_int(mem, value, model) \ 156 (abort (), (typeof(*mem)) 0) 157 #else 158 # define __arch_exchange_and_add_64_int(mem, value, model) \ 159 __atomic_fetch_add (mem, value, model) 160 #endif 161 162 #define atomic_exchange_and_add_acq(mem, value) \ 163 __atomic_val_bysize (__arch_exchange_and_add, int, mem, value, \ 164 __ATOMIC_ACQUIRE) 165 166 #define atomic_exchange_and_add_rel(mem, value) \ 167 __atomic_val_bysize (__arch_exchange_and_add, int, mem, value, \ 168 __ATOMIC_RELEASE) 169 170 /* TODO: More atomic operations could be implemented efficiently; only the 171 basic requirements are done. */ 172 173 #ifdef __mips16 174 # define atomic_full_barrier() __sync_synchronize () 175 176 #else /* !__mips16 */ 177 # define atomic_full_barrier() \ 178 __asm__ __volatile__ (".set push\n\t" \ 179 MIPS_PUSH_MIPS2 \ 180 MIPS_SYNC_STR "\n\t" \ 181 ".set pop" : : : "memory") 182 #endif /* !__mips16 */ 183 184 #endif /* atomic-machine.h */ 185