1#!/bin/sh 2# SPDX-License-Identifier: GPL-2.0 3 4ATOMICDIR=$(dirname $0) 5 6. ${ATOMICDIR}/atomic-tbl.sh 7 8#gen_template_fallback(template, meta, pfx, name, sfx, order, atomic, int, args...) 9gen_template_fallback() 10{ 11 local template="$1"; shift 12 local meta="$1"; shift 13 local pfx="$1"; shift 14 local name="$1"; shift 15 local sfx="$1"; shift 16 local order="$1"; shift 17 local atomic="$1"; shift 18 local int="$1"; shift 19 20 local ret="$(gen_ret_type "${meta}" "${int}")" 21 local retstmt="$(gen_ret_stmt "${meta}")" 22 local params="$(gen_params "${int}" "${atomic}" "$@")" 23 local args="$(gen_args "$@")" 24 25 . ${template} 26} 27 28#gen_order_fallback(meta, pfx, name, sfx, order, atomic, int, args...) 29gen_order_fallback() 30{ 31 local meta="$1"; shift 32 local pfx="$1"; shift 33 local name="$1"; shift 34 local sfx="$1"; shift 35 local order="$1"; shift 36 37 local tmpl_order=${order#_} 38 local tmpl="${ATOMICDIR}/fallbacks/${tmpl_order:-fence}" 39 gen_template_fallback "${tmpl}" "${meta}" "${pfx}" "${name}" "${sfx}" "${order}" "$@" 40} 41 42#gen_proto_fallback(meta, pfx, name, sfx, order, atomic, int, args...) 43gen_proto_fallback() 44{ 45 local meta="$1"; shift 46 local pfx="$1"; shift 47 local name="$1"; shift 48 local sfx="$1"; shift 49 local order="$1"; shift 50 51 local tmpl="$(find_fallback_template "${pfx}" "${name}" "${sfx}" "${order}")" 52 gen_template_fallback "${tmpl}" "${meta}" "${pfx}" "${name}" "${sfx}" "${order}" "$@" 53} 54 55#gen_proto_order_variant(meta, pfx, name, sfx, order, atomic, int, args...) 56gen_proto_order_variant() 57{ 58 local meta="$1"; shift 59 local pfx="$1"; shift 60 local name="$1"; shift 61 local sfx="$1"; shift 62 local order="$1"; shift 63 local atomic="$1"; shift 64 local int="$1"; shift 65 66 local atomicname="${atomic}_${pfx}${name}${sfx}${order}" 67 local basename="${atomic}_${pfx}${name}${sfx}" 68 69 local template="$(find_fallback_template "${pfx}" "${name}" "${sfx}" "${order}")" 70 71 local ret="$(gen_ret_type "${meta}" "${int}")" 72 local retstmt="$(gen_ret_stmt "${meta}")" 73 local params="$(gen_params "${int}" "${atomic}" "$@")" 74 local args="$(gen_args "$@")" 75 76 gen_kerneldoc "raw_" "${meta}" "${pfx}" "${name}" "${sfx}" "${order}" "${atomic}" "${int}" "$@" 77 78 printf "static __always_inline ${ret}\n" 79 printf "raw_${atomicname}(${params})\n" 80 printf "{\n" 81 82 # Where there is no possible fallback, this order variant is mandatory 83 # and must be provided by arch code. Add a comment to the header to 84 # make this obvious. 85 # 86 # Ideally we'd error on a missing definition, but arch code might 87 # define this order variant as a C function without a preprocessor 88 # symbol. 89 if [ -z ${template} ] && [ -z "${order}" ] && ! meta_has_relaxed "${meta}"; then 90 printf "\t${retstmt}arch_${atomicname}(${args});\n" 91 printf "}\n\n" 92 return 93 fi 94 95 printf "#if defined(arch_${atomicname})\n" 96 printf "\t${retstmt}arch_${atomicname}(${args});\n" 97 98 # Allow FULL/ACQUIRE/RELEASE ops to be defined in terms of RELAXED ops 99 if [ "${order}" != "_relaxed" ] && meta_has_relaxed "${meta}"; then 100 printf "#elif defined(arch_${basename}_relaxed)\n" 101 gen_order_fallback "${meta}" "${pfx}" "${name}" "${sfx}" "${order}" "${atomic}" "${int}" "$@" 102 fi 103 104 # Allow ACQUIRE/RELEASE/RELAXED ops to be defined in terms of FULL ops 105 if [ ! -z "${order}" ] && ! meta_is_implicitly_relaxed "${meta}"; then 106 printf "#elif defined(arch_${basename})\n" 107 printf "\t${retstmt}arch_${basename}(${args});\n" 108 fi 109 110 printf "#else\n" 111 if [ ! -z "${template}" ]; then 112 gen_proto_fallback "${meta}" "${pfx}" "${name}" "${sfx}" "${order}" "${atomic}" "${int}" "$@" 113 else 114 printf "#error \"Unable to define raw_${atomicname}\"\n" 115 fi 116 117 printf "#endif\n" 118 printf "}\n\n" 119} 120 121 122#gen_proto_order_variants(meta, pfx, name, sfx, atomic, int, args...) 123gen_proto_order_variants() 124{ 125 local meta="$1"; shift 126 local pfx="$1"; shift 127 local name="$1"; shift 128 local sfx="$1"; shift 129 local atomic="$1" 130 131 gen_proto_order_variant "${meta}" "${pfx}" "${name}" "${sfx}" "" "$@" 132 133 if meta_has_acquire "${meta}"; then 134 gen_proto_order_variant "${meta}" "${pfx}" "${name}" "${sfx}" "_acquire" "$@" 135 fi 136 137 if meta_has_release "${meta}"; then 138 gen_proto_order_variant "${meta}" "${pfx}" "${name}" "${sfx}" "_release" "$@" 139 fi 140 141 if meta_has_relaxed "${meta}"; then 142 gen_proto_order_variant "${meta}" "${pfx}" "${name}" "${sfx}" "_relaxed" "$@" 143 fi 144} 145 146#gen_basic_fallbacks(basename) 147gen_basic_fallbacks() 148{ 149 local basename="$1"; shift 150cat << EOF 151#define raw_${basename}_acquire arch_${basename} 152#define raw_${basename}_release arch_${basename} 153#define raw_${basename}_relaxed arch_${basename} 154EOF 155} 156 157gen_order_fallbacks() 158{ 159 local xchg="$1"; shift 160 161cat <<EOF 162 163#define raw_${xchg}_relaxed arch_${xchg}_relaxed 164 165#ifdef arch_${xchg}_acquire 166#define raw_${xchg}_acquire arch_${xchg}_acquire 167#else 168#define raw_${xchg}_acquire(...) \\ 169 __atomic_op_acquire(arch_${xchg}, __VA_ARGS__) 170#endif 171 172#ifdef arch_${xchg}_release 173#define raw_${xchg}_release arch_${xchg}_release 174#else 175#define raw_${xchg}_release(...) \\ 176 __atomic_op_release(arch_${xchg}, __VA_ARGS__) 177#endif 178 179#ifdef arch_${xchg} 180#define raw_${xchg} arch_${xchg} 181#else 182#define raw_${xchg}(...) \\ 183 __atomic_op_fence(arch_${xchg}, __VA_ARGS__) 184#endif 185 186EOF 187} 188 189gen_xchg_order_fallback() 190{ 191 local xchg="$1"; shift 192 local order="$1"; shift 193 local forder="${order:-_fence}" 194 195 printf "#if defined(arch_${xchg}${order})\n" 196 printf "#define raw_${xchg}${order} arch_${xchg}${order}\n" 197 198 if [ "${order}" != "_relaxed" ]; then 199 printf "#elif defined(arch_${xchg}_relaxed)\n" 200 printf "#define raw_${xchg}${order}(...) \\\\\n" 201 printf " __atomic_op${forder}(arch_${xchg}, __VA_ARGS__)\n" 202 fi 203 204 if [ ! -z "${order}" ]; then 205 printf "#elif defined(arch_${xchg})\n" 206 printf "#define raw_${xchg}${order} arch_${xchg}\n" 207 fi 208 209 printf "#else\n" 210 printf "extern void raw_${xchg}${order}_not_implemented(void);\n" 211 printf "#define raw_${xchg}${order}(...) raw_${xchg}${order}_not_implemented()\n" 212 printf "#endif\n\n" 213} 214 215gen_xchg_fallbacks() 216{ 217 local xchg="$1"; shift 218 219 for order in "" "_acquire" "_release" "_relaxed"; do 220 gen_xchg_order_fallback "${xchg}" "${order}" 221 done 222} 223 224gen_try_cmpxchg_fallback() 225{ 226 local cmpxchg="$1"; shift; 227 local order="$1"; shift; 228 229cat <<EOF 230#define raw_try_${cmpxchg}${order}(_ptr, _oldp, _new) \\ 231({ \\ 232 typeof(*(_ptr)) *___op = (_oldp), ___o = *___op, ___r; \\ 233 ___r = raw_${cmpxchg}${order}((_ptr), ___o, (_new)); \\ 234 if (unlikely(___r != ___o)) \\ 235 *___op = ___r; \\ 236 likely(___r == ___o); \\ 237}) 238EOF 239} 240 241gen_try_cmpxchg_order_fallback() 242{ 243 local cmpxchg="$1"; shift 244 local order="$1"; shift 245 local forder="${order:-_fence}" 246 247 printf "#if defined(arch_try_${cmpxchg}${order})\n" 248 printf "#define raw_try_${cmpxchg}${order} arch_try_${cmpxchg}${order}\n" 249 250 if [ "${order}" != "_relaxed" ]; then 251 printf "#elif defined(arch_try_${cmpxchg}_relaxed)\n" 252 printf "#define raw_try_${cmpxchg}${order}(...) \\\\\n" 253 printf " __atomic_op${forder}(arch_try_${cmpxchg}, __VA_ARGS__)\n" 254 fi 255 256 if [ ! -z "${order}" ]; then 257 printf "#elif defined(arch_try_${cmpxchg})\n" 258 printf "#define raw_try_${cmpxchg}${order} arch_try_${cmpxchg}\n" 259 fi 260 261 printf "#else\n" 262 gen_try_cmpxchg_fallback "${cmpxchg}" "${order}" 263 printf "#endif\n\n" 264} 265 266gen_try_cmpxchg_fallbacks() 267{ 268 local cmpxchg="$1"; shift; 269 270 for order in "" "_acquire" "_release" "_relaxed"; do 271 gen_try_cmpxchg_order_fallback "${cmpxchg}" "${order}" 272 done 273} 274 275gen_cmpxchg_local_fallbacks() 276{ 277 local cmpxchg="$1"; shift 278 279 printf "#define raw_${cmpxchg} arch_${cmpxchg}\n\n" 280 printf "#ifdef arch_try_${cmpxchg}\n" 281 printf "#define raw_try_${cmpxchg} arch_try_${cmpxchg}\n" 282 printf "#else\n" 283 gen_try_cmpxchg_fallback "${cmpxchg}" "" 284 printf "#endif\n\n" 285} 286 287cat << EOF 288// SPDX-License-Identifier: GPL-2.0 289 290// Generated by $0 291// DO NOT MODIFY THIS FILE DIRECTLY 292 293#ifndef _LINUX_ATOMIC_FALLBACK_H 294#define _LINUX_ATOMIC_FALLBACK_H 295 296#include <linux/compiler.h> 297 298EOF 299 300for xchg in "xchg" "cmpxchg" "cmpxchg64" "cmpxchg128"; do 301 gen_xchg_fallbacks "${xchg}" 302done 303 304for cmpxchg in "cmpxchg" "cmpxchg64" "cmpxchg128"; do 305 gen_try_cmpxchg_fallbacks "${cmpxchg}" 306done 307 308for cmpxchg in "cmpxchg_local" "cmpxchg64_local" "cmpxchg128_local"; do 309 gen_cmpxchg_local_fallbacks "${cmpxchg}" "" 310done 311 312for cmpxchg in "sync_cmpxchg"; do 313 printf "#define raw_${cmpxchg} arch_${cmpxchg}\n\n" 314done 315 316grep '^[a-z]' "$1" | while read name meta args; do 317 gen_proto "${meta}" "${name}" "atomic" "int" ${args} 318done 319 320cat <<EOF 321#ifdef CONFIG_GENERIC_ATOMIC64 322#include <asm-generic/atomic64.h> 323#endif 324 325EOF 326 327grep '^[a-z]' "$1" | while read name meta args; do 328 gen_proto "${meta}" "${name}" "atomic64" "s64" ${args} 329done 330 331cat <<EOF 332#endif /* _LINUX_ATOMIC_FALLBACK_H */ 333EOF 334