162306a36Sopenharmony_ci#!/bin/sh
262306a36Sopenharmony_ci# SPDX-License-Identifier: GPL-2.0
362306a36Sopenharmony_ci
462306a36Sopenharmony_ciATOMICDIR=$(dirname $0)
562306a36Sopenharmony_ci
662306a36Sopenharmony_ci. ${ATOMICDIR}/atomic-tbl.sh
762306a36Sopenharmony_ci
862306a36Sopenharmony_ci#gen_template_fallback(template, meta, pfx, name, sfx, order, atomic, int, args...)
962306a36Sopenharmony_cigen_template_fallback()
1062306a36Sopenharmony_ci{
1162306a36Sopenharmony_ci	local template="$1"; shift
1262306a36Sopenharmony_ci	local meta="$1"; shift
1362306a36Sopenharmony_ci	local pfx="$1"; shift
1462306a36Sopenharmony_ci	local name="$1"; shift
1562306a36Sopenharmony_ci	local sfx="$1"; shift
1662306a36Sopenharmony_ci	local order="$1"; shift
1762306a36Sopenharmony_ci	local atomic="$1"; shift
1862306a36Sopenharmony_ci	local int="$1"; shift
1962306a36Sopenharmony_ci
2062306a36Sopenharmony_ci	local ret="$(gen_ret_type "${meta}" "${int}")"
2162306a36Sopenharmony_ci	local retstmt="$(gen_ret_stmt "${meta}")"
2262306a36Sopenharmony_ci	local params="$(gen_params "${int}" "${atomic}" "$@")"
2362306a36Sopenharmony_ci	local args="$(gen_args "$@")"
2462306a36Sopenharmony_ci
2562306a36Sopenharmony_ci	. ${template}
2662306a36Sopenharmony_ci}
2762306a36Sopenharmony_ci
2862306a36Sopenharmony_ci#gen_order_fallback(meta, pfx, name, sfx, order, atomic, int, args...)
2962306a36Sopenharmony_cigen_order_fallback()
3062306a36Sopenharmony_ci{
3162306a36Sopenharmony_ci	local meta="$1"; shift
3262306a36Sopenharmony_ci	local pfx="$1"; shift
3362306a36Sopenharmony_ci	local name="$1"; shift
3462306a36Sopenharmony_ci	local sfx="$1"; shift
3562306a36Sopenharmony_ci	local order="$1"; shift
3662306a36Sopenharmony_ci
3762306a36Sopenharmony_ci	local tmpl_order=${order#_}
3862306a36Sopenharmony_ci	local tmpl="${ATOMICDIR}/fallbacks/${tmpl_order:-fence}"
3962306a36Sopenharmony_ci	gen_template_fallback "${tmpl}" "${meta}" "${pfx}" "${name}" "${sfx}" "${order}" "$@"
4062306a36Sopenharmony_ci}
4162306a36Sopenharmony_ci
4262306a36Sopenharmony_ci#gen_proto_fallback(meta, pfx, name, sfx, order, atomic, int, args...)
4362306a36Sopenharmony_cigen_proto_fallback()
4462306a36Sopenharmony_ci{
4562306a36Sopenharmony_ci	local meta="$1"; shift
4662306a36Sopenharmony_ci	local pfx="$1"; shift
4762306a36Sopenharmony_ci	local name="$1"; shift
4862306a36Sopenharmony_ci	local sfx="$1"; shift
4962306a36Sopenharmony_ci	local order="$1"; shift
5062306a36Sopenharmony_ci
5162306a36Sopenharmony_ci	local tmpl="$(find_fallback_template "${pfx}" "${name}" "${sfx}" "${order}")"
5262306a36Sopenharmony_ci	gen_template_fallback "${tmpl}" "${meta}" "${pfx}" "${name}" "${sfx}" "${order}" "$@"
5362306a36Sopenharmony_ci}
5462306a36Sopenharmony_ci
5562306a36Sopenharmony_ci#gen_proto_order_variant(meta, pfx, name, sfx, order, atomic, int, args...)
5662306a36Sopenharmony_cigen_proto_order_variant()
5762306a36Sopenharmony_ci{
5862306a36Sopenharmony_ci	local meta="$1"; shift
5962306a36Sopenharmony_ci	local pfx="$1"; shift
6062306a36Sopenharmony_ci	local name="$1"; shift
6162306a36Sopenharmony_ci	local sfx="$1"; shift
6262306a36Sopenharmony_ci	local order="$1"; shift
6362306a36Sopenharmony_ci	local atomic="$1"; shift
6462306a36Sopenharmony_ci	local int="$1"; shift
6562306a36Sopenharmony_ci
6662306a36Sopenharmony_ci	local atomicname="${atomic}_${pfx}${name}${sfx}${order}"
6762306a36Sopenharmony_ci	local basename="${atomic}_${pfx}${name}${sfx}"
6862306a36Sopenharmony_ci
6962306a36Sopenharmony_ci	local template="$(find_fallback_template "${pfx}" "${name}" "${sfx}" "${order}")"
7062306a36Sopenharmony_ci
7162306a36Sopenharmony_ci	local ret="$(gen_ret_type "${meta}" "${int}")"
7262306a36Sopenharmony_ci	local retstmt="$(gen_ret_stmt "${meta}")"
7362306a36Sopenharmony_ci	local params="$(gen_params "${int}" "${atomic}" "$@")"
7462306a36Sopenharmony_ci	local args="$(gen_args "$@")"
7562306a36Sopenharmony_ci
7662306a36Sopenharmony_ci	gen_kerneldoc "raw_" "${meta}" "${pfx}" "${name}" "${sfx}" "${order}" "${atomic}" "${int}" "$@"
7762306a36Sopenharmony_ci
7862306a36Sopenharmony_ci	printf "static __always_inline ${ret}\n"
7962306a36Sopenharmony_ci	printf "raw_${atomicname}(${params})\n"
8062306a36Sopenharmony_ci	printf "{\n"
8162306a36Sopenharmony_ci
8262306a36Sopenharmony_ci	# Where there is no possible fallback, this order variant is mandatory
8362306a36Sopenharmony_ci	# and must be provided by arch code. Add a comment to the header to
8462306a36Sopenharmony_ci	# make this obvious.
8562306a36Sopenharmony_ci	#
8662306a36Sopenharmony_ci	# Ideally we'd error on a missing definition, but arch code might
8762306a36Sopenharmony_ci	# define this order variant as a C function without a preprocessor
8862306a36Sopenharmony_ci	# symbol.
8962306a36Sopenharmony_ci	if [ -z ${template} ] && [ -z "${order}" ] && ! meta_has_relaxed "${meta}"; then
9062306a36Sopenharmony_ci		printf "\t${retstmt}arch_${atomicname}(${args});\n"
9162306a36Sopenharmony_ci		printf "}\n\n"
9262306a36Sopenharmony_ci		return
9362306a36Sopenharmony_ci	fi
9462306a36Sopenharmony_ci
9562306a36Sopenharmony_ci	printf "#if defined(arch_${atomicname})\n"
9662306a36Sopenharmony_ci	printf "\t${retstmt}arch_${atomicname}(${args});\n"
9762306a36Sopenharmony_ci
9862306a36Sopenharmony_ci	# Allow FULL/ACQUIRE/RELEASE ops to be defined in terms of RELAXED ops
9962306a36Sopenharmony_ci	if [ "${order}" != "_relaxed" ] && meta_has_relaxed "${meta}"; then
10062306a36Sopenharmony_ci		printf "#elif defined(arch_${basename}_relaxed)\n"
10162306a36Sopenharmony_ci		gen_order_fallback "${meta}" "${pfx}" "${name}" "${sfx}" "${order}" "${atomic}" "${int}" "$@"
10262306a36Sopenharmony_ci	fi
10362306a36Sopenharmony_ci
10462306a36Sopenharmony_ci	# Allow ACQUIRE/RELEASE/RELAXED ops to be defined in terms of FULL ops
10562306a36Sopenharmony_ci	if [ ! -z "${order}" ] && ! meta_is_implicitly_relaxed "${meta}"; then
10662306a36Sopenharmony_ci		printf "#elif defined(arch_${basename})\n"
10762306a36Sopenharmony_ci		printf "\t${retstmt}arch_${basename}(${args});\n"
10862306a36Sopenharmony_ci	fi
10962306a36Sopenharmony_ci
11062306a36Sopenharmony_ci	printf "#else\n"
11162306a36Sopenharmony_ci	if [ ! -z "${template}" ]; then
11262306a36Sopenharmony_ci		gen_proto_fallback "${meta}" "${pfx}" "${name}" "${sfx}" "${order}" "${atomic}" "${int}" "$@"
11362306a36Sopenharmony_ci	else
11462306a36Sopenharmony_ci		printf "#error \"Unable to define raw_${atomicname}\"\n"
11562306a36Sopenharmony_ci	fi
11662306a36Sopenharmony_ci
11762306a36Sopenharmony_ci	printf "#endif\n"
11862306a36Sopenharmony_ci	printf "}\n\n"
11962306a36Sopenharmony_ci}
12062306a36Sopenharmony_ci
12162306a36Sopenharmony_ci
12262306a36Sopenharmony_ci#gen_proto_order_variants(meta, pfx, name, sfx, atomic, int, args...)
12362306a36Sopenharmony_cigen_proto_order_variants()
12462306a36Sopenharmony_ci{
12562306a36Sopenharmony_ci	local meta="$1"; shift
12662306a36Sopenharmony_ci	local pfx="$1"; shift
12762306a36Sopenharmony_ci	local name="$1"; shift
12862306a36Sopenharmony_ci	local sfx="$1"; shift
12962306a36Sopenharmony_ci	local atomic="$1"
13062306a36Sopenharmony_ci
13162306a36Sopenharmony_ci	gen_proto_order_variant "${meta}" "${pfx}" "${name}" "${sfx}" "" "$@"
13262306a36Sopenharmony_ci
13362306a36Sopenharmony_ci	if meta_has_acquire "${meta}"; then
13462306a36Sopenharmony_ci		gen_proto_order_variant "${meta}" "${pfx}" "${name}" "${sfx}" "_acquire" "$@"
13562306a36Sopenharmony_ci	fi
13662306a36Sopenharmony_ci
13762306a36Sopenharmony_ci	if meta_has_release "${meta}"; then
13862306a36Sopenharmony_ci		gen_proto_order_variant "${meta}" "${pfx}" "${name}" "${sfx}" "_release" "$@"
13962306a36Sopenharmony_ci	fi
14062306a36Sopenharmony_ci
14162306a36Sopenharmony_ci	if meta_has_relaxed "${meta}"; then
14262306a36Sopenharmony_ci		gen_proto_order_variant "${meta}" "${pfx}" "${name}" "${sfx}" "_relaxed" "$@"
14362306a36Sopenharmony_ci	fi
14462306a36Sopenharmony_ci}
14562306a36Sopenharmony_ci
14662306a36Sopenharmony_ci#gen_basic_fallbacks(basename)
14762306a36Sopenharmony_cigen_basic_fallbacks()
14862306a36Sopenharmony_ci{
14962306a36Sopenharmony_ci	local basename="$1"; shift
15062306a36Sopenharmony_cicat << EOF
15162306a36Sopenharmony_ci#define raw_${basename}_acquire arch_${basename}
15262306a36Sopenharmony_ci#define raw_${basename}_release arch_${basename}
15362306a36Sopenharmony_ci#define raw_${basename}_relaxed arch_${basename}
15462306a36Sopenharmony_ciEOF
15562306a36Sopenharmony_ci}
15662306a36Sopenharmony_ci
15762306a36Sopenharmony_cigen_order_fallbacks()
15862306a36Sopenharmony_ci{
15962306a36Sopenharmony_ci	local xchg="$1"; shift
16062306a36Sopenharmony_ci
16162306a36Sopenharmony_cicat <<EOF
16262306a36Sopenharmony_ci
16362306a36Sopenharmony_ci#define raw_${xchg}_relaxed arch_${xchg}_relaxed
16462306a36Sopenharmony_ci
16562306a36Sopenharmony_ci#ifdef arch_${xchg}_acquire
16662306a36Sopenharmony_ci#define raw_${xchg}_acquire arch_${xchg}_acquire
16762306a36Sopenharmony_ci#else
16862306a36Sopenharmony_ci#define raw_${xchg}_acquire(...) \\
16962306a36Sopenharmony_ci	__atomic_op_acquire(arch_${xchg}, __VA_ARGS__)
17062306a36Sopenharmony_ci#endif
17162306a36Sopenharmony_ci
17262306a36Sopenharmony_ci#ifdef arch_${xchg}_release
17362306a36Sopenharmony_ci#define raw_${xchg}_release arch_${xchg}_release
17462306a36Sopenharmony_ci#else
17562306a36Sopenharmony_ci#define raw_${xchg}_release(...) \\
17662306a36Sopenharmony_ci	__atomic_op_release(arch_${xchg}, __VA_ARGS__)
17762306a36Sopenharmony_ci#endif
17862306a36Sopenharmony_ci
17962306a36Sopenharmony_ci#ifdef arch_${xchg}
18062306a36Sopenharmony_ci#define raw_${xchg} arch_${xchg}
18162306a36Sopenharmony_ci#else
18262306a36Sopenharmony_ci#define raw_${xchg}(...) \\
18362306a36Sopenharmony_ci	__atomic_op_fence(arch_${xchg}, __VA_ARGS__)
18462306a36Sopenharmony_ci#endif
18562306a36Sopenharmony_ci
18662306a36Sopenharmony_ciEOF
18762306a36Sopenharmony_ci}
18862306a36Sopenharmony_ci
18962306a36Sopenharmony_cigen_xchg_order_fallback()
19062306a36Sopenharmony_ci{
19162306a36Sopenharmony_ci	local xchg="$1"; shift
19262306a36Sopenharmony_ci	local order="$1"; shift
19362306a36Sopenharmony_ci	local forder="${order:-_fence}"
19462306a36Sopenharmony_ci
19562306a36Sopenharmony_ci	printf "#if defined(arch_${xchg}${order})\n"
19662306a36Sopenharmony_ci	printf "#define raw_${xchg}${order} arch_${xchg}${order}\n"
19762306a36Sopenharmony_ci
19862306a36Sopenharmony_ci	if [ "${order}" != "_relaxed" ]; then
19962306a36Sopenharmony_ci		printf "#elif defined(arch_${xchg}_relaxed)\n"
20062306a36Sopenharmony_ci		printf "#define raw_${xchg}${order}(...) \\\\\n"
20162306a36Sopenharmony_ci		printf "	__atomic_op${forder}(arch_${xchg}, __VA_ARGS__)\n"
20262306a36Sopenharmony_ci	fi
20362306a36Sopenharmony_ci
20462306a36Sopenharmony_ci	if [ ! -z "${order}" ]; then
20562306a36Sopenharmony_ci		printf "#elif defined(arch_${xchg})\n"
20662306a36Sopenharmony_ci		printf "#define raw_${xchg}${order} arch_${xchg}\n"
20762306a36Sopenharmony_ci	fi
20862306a36Sopenharmony_ci
20962306a36Sopenharmony_ci	printf "#else\n"
21062306a36Sopenharmony_ci	printf "extern void raw_${xchg}${order}_not_implemented(void);\n"
21162306a36Sopenharmony_ci	printf "#define raw_${xchg}${order}(...) raw_${xchg}${order}_not_implemented()\n"
21262306a36Sopenharmony_ci	printf "#endif\n\n"
21362306a36Sopenharmony_ci}
21462306a36Sopenharmony_ci
21562306a36Sopenharmony_cigen_xchg_fallbacks()
21662306a36Sopenharmony_ci{
21762306a36Sopenharmony_ci	local xchg="$1"; shift
21862306a36Sopenharmony_ci
21962306a36Sopenharmony_ci	for order in "" "_acquire" "_release" "_relaxed"; do
22062306a36Sopenharmony_ci		gen_xchg_order_fallback "${xchg}" "${order}"
22162306a36Sopenharmony_ci	done
22262306a36Sopenharmony_ci}
22362306a36Sopenharmony_ci
22462306a36Sopenharmony_cigen_try_cmpxchg_fallback()
22562306a36Sopenharmony_ci{
22662306a36Sopenharmony_ci	local cmpxchg="$1"; shift;
22762306a36Sopenharmony_ci	local order="$1"; shift;
22862306a36Sopenharmony_ci
22962306a36Sopenharmony_cicat <<EOF
23062306a36Sopenharmony_ci#define raw_try_${cmpxchg}${order}(_ptr, _oldp, _new) \\
23162306a36Sopenharmony_ci({ \\
23262306a36Sopenharmony_ci	typeof(*(_ptr)) *___op = (_oldp), ___o = *___op, ___r; \\
23362306a36Sopenharmony_ci	___r = raw_${cmpxchg}${order}((_ptr), ___o, (_new)); \\
23462306a36Sopenharmony_ci	if (unlikely(___r != ___o)) \\
23562306a36Sopenharmony_ci		*___op = ___r; \\
23662306a36Sopenharmony_ci	likely(___r == ___o); \\
23762306a36Sopenharmony_ci})
23862306a36Sopenharmony_ciEOF
23962306a36Sopenharmony_ci}
24062306a36Sopenharmony_ci
24162306a36Sopenharmony_cigen_try_cmpxchg_order_fallback()
24262306a36Sopenharmony_ci{
24362306a36Sopenharmony_ci	local cmpxchg="$1"; shift
24462306a36Sopenharmony_ci	local order="$1"; shift
24562306a36Sopenharmony_ci	local forder="${order:-_fence}"
24662306a36Sopenharmony_ci
24762306a36Sopenharmony_ci	printf "#if defined(arch_try_${cmpxchg}${order})\n"
24862306a36Sopenharmony_ci	printf "#define raw_try_${cmpxchg}${order} arch_try_${cmpxchg}${order}\n"
24962306a36Sopenharmony_ci
25062306a36Sopenharmony_ci	if [ "${order}" != "_relaxed" ]; then
25162306a36Sopenharmony_ci		printf "#elif defined(arch_try_${cmpxchg}_relaxed)\n"
25262306a36Sopenharmony_ci		printf "#define raw_try_${cmpxchg}${order}(...) \\\\\n"
25362306a36Sopenharmony_ci		printf "	__atomic_op${forder}(arch_try_${cmpxchg}, __VA_ARGS__)\n"
25462306a36Sopenharmony_ci	fi
25562306a36Sopenharmony_ci
25662306a36Sopenharmony_ci	if [ ! -z "${order}" ]; then
25762306a36Sopenharmony_ci		printf "#elif defined(arch_try_${cmpxchg})\n"
25862306a36Sopenharmony_ci		printf "#define raw_try_${cmpxchg}${order} arch_try_${cmpxchg}\n"
25962306a36Sopenharmony_ci	fi
26062306a36Sopenharmony_ci
26162306a36Sopenharmony_ci	printf "#else\n"
26262306a36Sopenharmony_ci	gen_try_cmpxchg_fallback "${cmpxchg}" "${order}"
26362306a36Sopenharmony_ci	printf "#endif\n\n"
26462306a36Sopenharmony_ci}
26562306a36Sopenharmony_ci
26662306a36Sopenharmony_cigen_try_cmpxchg_fallbacks()
26762306a36Sopenharmony_ci{
26862306a36Sopenharmony_ci	local cmpxchg="$1"; shift;
26962306a36Sopenharmony_ci
27062306a36Sopenharmony_ci	for order in "" "_acquire" "_release" "_relaxed"; do
27162306a36Sopenharmony_ci		gen_try_cmpxchg_order_fallback "${cmpxchg}" "${order}"
27262306a36Sopenharmony_ci	done
27362306a36Sopenharmony_ci}
27462306a36Sopenharmony_ci
27562306a36Sopenharmony_cigen_cmpxchg_local_fallbacks()
27662306a36Sopenharmony_ci{
27762306a36Sopenharmony_ci	local cmpxchg="$1"; shift
27862306a36Sopenharmony_ci
27962306a36Sopenharmony_ci	printf "#define raw_${cmpxchg} arch_${cmpxchg}\n\n"
28062306a36Sopenharmony_ci	printf "#ifdef arch_try_${cmpxchg}\n"
28162306a36Sopenharmony_ci	printf "#define raw_try_${cmpxchg} arch_try_${cmpxchg}\n"
28262306a36Sopenharmony_ci	printf "#else\n"
28362306a36Sopenharmony_ci	gen_try_cmpxchg_fallback "${cmpxchg}" ""
28462306a36Sopenharmony_ci	printf "#endif\n\n"
28562306a36Sopenharmony_ci}
28662306a36Sopenharmony_ci
28762306a36Sopenharmony_cicat << EOF
28862306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
28962306a36Sopenharmony_ci
29062306a36Sopenharmony_ci// Generated by $0
29162306a36Sopenharmony_ci// DO NOT MODIFY THIS FILE DIRECTLY
29262306a36Sopenharmony_ci
29362306a36Sopenharmony_ci#ifndef _LINUX_ATOMIC_FALLBACK_H
29462306a36Sopenharmony_ci#define _LINUX_ATOMIC_FALLBACK_H
29562306a36Sopenharmony_ci
29662306a36Sopenharmony_ci#include <linux/compiler.h>
29762306a36Sopenharmony_ci
29862306a36Sopenharmony_ciEOF
29962306a36Sopenharmony_ci
30062306a36Sopenharmony_cifor xchg in "xchg" "cmpxchg" "cmpxchg64" "cmpxchg128"; do
30162306a36Sopenharmony_ci	gen_xchg_fallbacks "${xchg}"
30262306a36Sopenharmony_cidone
30362306a36Sopenharmony_ci
30462306a36Sopenharmony_cifor cmpxchg in "cmpxchg" "cmpxchg64" "cmpxchg128"; do
30562306a36Sopenharmony_ci	gen_try_cmpxchg_fallbacks "${cmpxchg}"
30662306a36Sopenharmony_cidone
30762306a36Sopenharmony_ci
30862306a36Sopenharmony_cifor cmpxchg in "cmpxchg_local" "cmpxchg64_local" "cmpxchg128_local"; do
30962306a36Sopenharmony_ci	gen_cmpxchg_local_fallbacks "${cmpxchg}" ""
31062306a36Sopenharmony_cidone
31162306a36Sopenharmony_ci
31262306a36Sopenharmony_cifor cmpxchg in "sync_cmpxchg"; do
31362306a36Sopenharmony_ci	printf "#define raw_${cmpxchg} arch_${cmpxchg}\n\n"
31462306a36Sopenharmony_cidone
31562306a36Sopenharmony_ci
31662306a36Sopenharmony_cigrep '^[a-z]' "$1" | while read name meta args; do
31762306a36Sopenharmony_ci	gen_proto "${meta}" "${name}" "atomic" "int" ${args}
31862306a36Sopenharmony_cidone
31962306a36Sopenharmony_ci
32062306a36Sopenharmony_cicat <<EOF
32162306a36Sopenharmony_ci#ifdef CONFIG_GENERIC_ATOMIC64
32262306a36Sopenharmony_ci#include <asm-generic/atomic64.h>
32362306a36Sopenharmony_ci#endif
32462306a36Sopenharmony_ci
32562306a36Sopenharmony_ciEOF
32662306a36Sopenharmony_ci
32762306a36Sopenharmony_cigrep '^[a-z]' "$1" | while read name meta args; do
32862306a36Sopenharmony_ci	gen_proto "${meta}" "${name}" "atomic64" "s64" ${args}
32962306a36Sopenharmony_cidone
33062306a36Sopenharmony_ci
33162306a36Sopenharmony_cicat <<EOF
33262306a36Sopenharmony_ci#endif /* _LINUX_ATOMIC_FALLBACK_H */
33362306a36Sopenharmony_ciEOF
334