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