diff options
Diffstat (limited to 'scripts/atomic')
50 files changed, 757 insertions, 396 deletions
diff --git a/scripts/atomic/atomic-tbl.sh b/scripts/atomic/atomic-tbl.sh index 81d5c32039dd..608ff39ebd8c 100755 --- a/scripts/atomic/atomic-tbl.sh +++ b/scripts/atomic/atomic-tbl.sh @@ -36,9 +36,16 @@ meta_has_relaxed() meta_in "$1" "BFIR" } -#find_fallback_template(pfx, name, sfx, order) -find_fallback_template() +#meta_is_implicitly_relaxed(meta) +meta_is_implicitly_relaxed() { + meta_in "$1" "vls" +} + +#find_template(tmpltype, pfx, name, sfx, order) +find_template() +{ + local tmpltype="$1"; shift local pfx="$1"; shift local name="$1"; shift local sfx="$1"; shift @@ -52,8 +59,8 @@ find_fallback_template() # # Start at the most specific, and fall back to the most general. Once # we find a specific fallback, don't bother looking for more. - for base in "${pfx}${name}${sfx}${order}" "${name}"; do - file="${ATOMICDIR}/fallbacks/${base}" + for base in "${pfx}${name}${sfx}${order}" "${pfx}${name}${sfx}" "${name}"; do + file="${ATOMICDIR}/${tmpltype}/${base}" if [ -f "${file}" ]; then printf "${file}" @@ -62,6 +69,18 @@ find_fallback_template() done } +#find_fallback_template(pfx, name, sfx, order) +find_fallback_template() +{ + find_template "fallbacks" "$@" +} + +#find_kerneldoc_template(pfx, name, sfx, order) +find_kerneldoc_template() +{ + find_template "kerneldoc" "$@" +} + #gen_ret_type(meta, int) gen_ret_type() { local meta="$1"; shift @@ -142,6 +161,91 @@ gen_args() done } +#gen_desc_return(meta) +gen_desc_return() +{ + local meta="$1"; shift + + case "${meta}" in + [v]) + printf "Return: Nothing." + ;; + [Ff]) + printf "Return: The original value of @v." + ;; + [R]) + printf "Return: The updated value of @v." + ;; + [l]) + printf "Return: The value of @v." + ;; + esac +} + +#gen_template_kerneldoc(template, class, meta, pfx, name, sfx, order, atomic, int, args...) +gen_template_kerneldoc() +{ + local template="$1"; shift + local class="$1"; shift + local meta="$1"; shift + local pfx="$1"; shift + local name="$1"; shift + local sfx="$1"; shift + local order="$1"; shift + local atomic="$1"; shift + local int="$1"; shift + + local atomicname="${atomic}_${pfx}${name}${sfx}${order}" + + local ret="$(gen_ret_type "${meta}" "${int}")" + local retstmt="$(gen_ret_stmt "${meta}")" + local params="$(gen_params "${int}" "${atomic}" "$@")" + local args="$(gen_args "$@")" + local desc_order="" + local desc_instrumentation="" + local desc_return="" + + if [ ! -z "${order}" ]; then + desc_order="${order##_}" + elif meta_is_implicitly_relaxed "${meta}"; then + desc_order="relaxed" + else + desc_order="full" + fi + + if [ -z "${class}" ]; then + desc_noinstr="Unsafe to use in noinstr code; use raw_${atomicname}() there." + else + desc_noinstr="Safe to use in noinstr code; prefer ${atomicname}() elsewhere." + fi + + desc_return="$(gen_desc_return "${meta}")" + + . ${template} +} + +#gen_kerneldoc(class, meta, pfx, name, sfx, order, atomic, int, args...) +gen_kerneldoc() +{ + local class="$1"; shift + local meta="$1"; shift + local pfx="$1"; shift + local name="$1"; shift + local sfx="$1"; shift + local order="$1"; shift + + local atomicname="${atomic}_${pfx}${name}${sfx}${order}" + + local tmpl="$(find_kerneldoc_template "${pfx}" "${name}" "${sfx}" "${order}")" + if [ -z "${tmpl}" ]; then + printf "/*\n" + printf " * No kerneldoc available for ${class}${atomicname}\n" + printf " */\n" + else + gen_template_kerneldoc "${tmpl}" "${class}" "${meta}" "${pfx}" "${name}" "${sfx}" "${order}" "$@" + fi +} + #gen_proto_order_variants(meta, pfx, name, sfx, ...) gen_proto_order_variants() { diff --git a/scripts/atomic/atomics.tbl b/scripts/atomic/atomics.tbl index fbee2f6190d9..903946cbf1b3 100755..100644 --- a/scripts/atomic/atomics.tbl +++ b/scripts/atomic/atomics.tbl @@ -27,13 +27,13 @@ and vF i v andnot vF i v or vF i v xor vF i v -xchg I v i +xchg I v i:new cmpxchg I v i:old i:new try_cmpxchg B v p:old i:new sub_and_test b i v dec_and_test b v inc_and_test b v -add_negative b i v +add_negative B i v add_unless fb v i:a i:u inc_not_zero b v inc_unless_negative b v diff --git a/scripts/atomic/check-atomics.sh b/scripts/atomic/check-atomics.sh deleted file mode 100755 index 8378c63a1e09..000000000000 --- a/scripts/atomic/check-atomics.sh +++ /dev/null @@ -1,33 +0,0 @@ -#!/bin/sh -# SPDX-License-Identifier: GPL-2.0 -# -# Check if atomic headers are up-to-date - -ATOMICDIR=$(dirname $0) -ATOMICTBL=${ATOMICDIR}/atomics.tbl -LINUXDIR=${ATOMICDIR}/../.. - -echo '' | sha1sum - > /dev/null 2>&1 -if [ $? -ne 0 ]; then - printf "sha1sum not available, skipping atomic header checks.\n" - exit 0 -fi - -cat <<EOF | -asm-generic/atomic-instrumented.h -asm-generic/atomic-long.h -linux/atomic-fallback.h -EOF -while read header; do - OLDSUM="$(tail -n 1 ${LINUXDIR}/include/${header})" - OLDSUM="${OLDSUM#// }" - - NEWSUM="$(sed '$d' ${LINUXDIR}/include/${header} | sha1sum)" - NEWSUM="${NEWSUM%% *}" - - if [ "${OLDSUM}" != "${NEWSUM}" ]; then - printf "warning: generated include/${header} has been modified.\n" - fi -done - -exit 0 diff --git a/scripts/atomic/fallbacks/acquire b/scripts/atomic/fallbacks/acquire index 59c00529dc7c..4da0cab3604e 100755 --- a/scripts/atomic/fallbacks/acquire +++ b/scripts/atomic/fallbacks/acquire @@ -1,9 +1,5 @@ cat <<EOF -static __always_inline ${ret} -${arch}${atomic}_${pfx}${name}${sfx}_acquire(${params}) -{ - ${ret} ret = ${arch}${atomic}_${pfx}${name}${sfx}_relaxed(${args}); + ${ret} ret = arch_${atomic}_${pfx}${name}${sfx}_relaxed(${args}); __atomic_acquire_fence(); return ret; -} EOF diff --git a/scripts/atomic/fallbacks/add_negative b/scripts/atomic/fallbacks/add_negative index a66635bceefb..1d3d4ab3a9d2 100755 --- a/scripts/atomic/fallbacks/add_negative +++ b/scripts/atomic/fallbacks/add_negative @@ -1,16 +1,3 @@ cat <<EOF -/** - * ${arch}${atomic}_add_negative - add and test if negative - * @i: integer value to add - * @v: pointer of type ${atomic}_t - * - * Atomically adds @i to @v and returns true - * if the result is negative, or false when - * result is greater than or equal to zero. - */ -static __always_inline bool -${arch}${atomic}_add_negative(${int} i, ${atomic}_t *v) -{ - return ${arch}${atomic}_add_return(i, v) < 0; -} + return raw_${atomic}_add_return${order}(i, v) < 0; EOF diff --git a/scripts/atomic/fallbacks/add_unless b/scripts/atomic/fallbacks/add_unless index 2ff598a3f9ec..95ecb2b7405b 100755 --- a/scripts/atomic/fallbacks/add_unless +++ b/scripts/atomic/fallbacks/add_unless @@ -1,16 +1,3 @@ cat << EOF -/** - * ${arch}${atomic}_add_unless - add unless the number is already a given value - * @v: pointer of type ${atomic}_t - * @a: the amount to add to v... - * @u: ...unless v is equal to u. - * - * Atomically adds @a to @v, if @v was not already @u. - * Returns true if the addition was done. - */ -static __always_inline bool -${arch}${atomic}_add_unless(${atomic}_t *v, ${int} a, ${int} u) -{ - return ${arch}${atomic}_fetch_add_unless(v, a, u) != u; -} + return raw_${atomic}_fetch_add_unless(v, a, u) != u; EOF diff --git a/scripts/atomic/fallbacks/andnot b/scripts/atomic/fallbacks/andnot index 3f18663dcefb..66760457e67a 100755 --- a/scripts/atomic/fallbacks/andnot +++ b/scripts/atomic/fallbacks/andnot @@ -1,7 +1,3 @@ cat <<EOF -static __always_inline ${ret} -${arch}${atomic}_${pfx}andnot${sfx}${order}(${int} i, ${atomic}_t *v) -{ - ${retstmt}${arch}${atomic}_${pfx}and${sfx}${order}(~i, v); -} + ${retstmt}raw_${atomic}_${pfx}and${sfx}${order}(~i, v); EOF diff --git a/scripts/atomic/fallbacks/cmpxchg b/scripts/atomic/fallbacks/cmpxchg new file mode 100644 index 000000000000..1c8507f62e04 --- /dev/null +++ b/scripts/atomic/fallbacks/cmpxchg @@ -0,0 +1,3 @@ +cat <<EOF + return raw_cmpxchg${order}(&v->counter, old, new); +EOF diff --git a/scripts/atomic/fallbacks/dec b/scripts/atomic/fallbacks/dec index e2e01f0574bb..60d286d40300 100755 --- a/scripts/atomic/fallbacks/dec +++ b/scripts/atomic/fallbacks/dec @@ -1,7 +1,3 @@ cat <<EOF -static __always_inline ${ret} -${arch}${atomic}_${pfx}dec${sfx}${order}(${atomic}_t *v) -{ - ${retstmt}${arch}${atomic}_${pfx}sub${sfx}${order}(1, v); -} + ${retstmt}raw_${atomic}_${pfx}sub${sfx}${order}(1, v); EOF diff --git a/scripts/atomic/fallbacks/dec_and_test b/scripts/atomic/fallbacks/dec_and_test index e8a5e492eb5f..3a0278e0ddd7 100755 --- a/scripts/atomic/fallbacks/dec_and_test +++ b/scripts/atomic/fallbacks/dec_and_test @@ -1,15 +1,3 @@ cat <<EOF -/** - * ${arch}${atomic}_dec_and_test - decrement and test - * @v: pointer of type ${atomic}_t - * - * Atomically decrements @v by 1 and - * returns true if the result is 0, or false for all other - * cases. - */ -static __always_inline bool -${arch}${atomic}_dec_and_test(${atomic}_t *v) -{ - return ${arch}${atomic}_dec_return(v) == 0; -} + return raw_${atomic}_dec_return(v) == 0; EOF diff --git a/scripts/atomic/fallbacks/dec_if_positive b/scripts/atomic/fallbacks/dec_if_positive index 527adec89c37..f65c11b4b85b 100755 --- a/scripts/atomic/fallbacks/dec_if_positive +++ b/scripts/atomic/fallbacks/dec_if_positive @@ -1,15 +1,11 @@ cat <<EOF -static __always_inline ${ret} -${arch}${atomic}_dec_if_positive(${atomic}_t *v) -{ - ${int} dec, c = ${arch}${atomic}_read(v); + ${int} dec, c = raw_${atomic}_read(v); do { dec = c - 1; if (unlikely(dec < 0)) break; - } while (!${arch}${atomic}_try_cmpxchg(v, &c, dec)); + } while (!raw_${atomic}_try_cmpxchg(v, &c, dec)); return dec; -} EOF diff --git a/scripts/atomic/fallbacks/dec_unless_positive b/scripts/atomic/fallbacks/dec_unless_positive index dcab6848ca1e..d025361d7b85 100755 --- a/scripts/atomic/fallbacks/dec_unless_positive +++ b/scripts/atomic/fallbacks/dec_unless_positive @@ -1,14 +1,10 @@ cat <<EOF -static __always_inline bool -${arch}${atomic}_dec_unless_positive(${atomic}_t *v) -{ - ${int} c = ${arch}${atomic}_read(v); + ${int} c = raw_${atomic}_read(v); do { if (unlikely(c > 0)) return false; - } while (!${arch}${atomic}_try_cmpxchg(v, &c, c - 1)); + } while (!raw_${atomic}_try_cmpxchg(v, &c, c - 1)); return true; -} EOF diff --git a/scripts/atomic/fallbacks/fence b/scripts/atomic/fallbacks/fence index 3764fc8ce945..40d5b397658f 100755 --- a/scripts/atomic/fallbacks/fence +++ b/scripts/atomic/fallbacks/fence @@ -1,11 +1,7 @@ cat <<EOF -static __always_inline ${ret} -${arch}${atomic}_${pfx}${name}${sfx}(${params}) -{ ${ret} ret; __atomic_pre_full_fence(); - ret = ${arch}${atomic}_${pfx}${name}${sfx}_relaxed(${args}); + ret = arch_${atomic}_${pfx}${name}${sfx}_relaxed(${args}); __atomic_post_full_fence(); return ret; -} EOF diff --git a/scripts/atomic/fallbacks/fetch_add_unless b/scripts/atomic/fallbacks/fetch_add_unless index 0e0b9aef1515..8db7e9e17fac 100755 --- a/scripts/atomic/fallbacks/fetch_add_unless +++ b/scripts/atomic/fallbacks/fetch_add_unless @@ -1,23 +1,10 @@ cat << EOF -/** - * ${arch}${atomic}_fetch_add_unless - add unless the number is already a given value - * @v: pointer of type ${atomic}_t - * @a: the amount to add to v... - * @u: ...unless v is equal to u. - * - * Atomically adds @a to @v, so long as @v was not already @u. - * Returns original value of @v - */ -static __always_inline ${int} -${arch}${atomic}_fetch_add_unless(${atomic}_t *v, ${int} a, ${int} u) -{ - ${int} c = ${arch}${atomic}_read(v); + ${int} c = raw_${atomic}_read(v); do { if (unlikely(c == u)) break; - } while (!${arch}${atomic}_try_cmpxchg(v, &c, c + a)); + } while (!raw_${atomic}_try_cmpxchg(v, &c, c + a)); return c; -} EOF diff --git a/scripts/atomic/fallbacks/inc b/scripts/atomic/fallbacks/inc index 15ec62946e8c..56c770f5919c 100755 --- a/scripts/atomic/fallbacks/inc +++ b/scripts/atomic/fallbacks/inc @@ -1,7 +1,3 @@ cat <<EOF -static __always_inline ${ret} -${arch}${atomic}_${pfx}inc${sfx}${order}(${atomic}_t *v) -{ - ${retstmt}${arch}${atomic}_${pfx}add${sfx}${order}(1, v); -} + ${retstmt}raw_${atomic}_${pfx}add${sfx}${order}(1, v); EOF diff --git a/scripts/atomic/fallbacks/inc_and_test b/scripts/atomic/fallbacks/inc_and_test index cecc8322a21f..7d16a10f2257 100755 --- a/scripts/atomic/fallbacks/inc_and_test +++ b/scripts/atomic/fallbacks/inc_and_test @@ -1,15 +1,3 @@ cat <<EOF -/** - * ${arch}${atomic}_inc_and_test - increment and test - * @v: pointer of type ${atomic}_t - * - * Atomically increments @v by 1 - * and returns true if the result is zero, or false for all - * other cases. - */ -static __always_inline bool -${arch}${atomic}_inc_and_test(${atomic}_t *v) -{ - return ${arch}${atomic}_inc_return(v) == 0; -} + return raw_${atomic}_inc_return(v) == 0; EOF diff --git a/scripts/atomic/fallbacks/inc_not_zero b/scripts/atomic/fallbacks/inc_not_zero index 50f2d4d48279..1fcef1e55bc9 100755 --- a/scripts/atomic/fallbacks/inc_not_zero +++ b/scripts/atomic/fallbacks/inc_not_zero @@ -1,14 +1,3 @@ cat <<EOF -/** - * ${arch}${atomic}_inc_not_zero - increment unless the number is zero - * @v: pointer of type ${atomic}_t - * - * Atomically increments @v by 1, if @v is non-zero. - * Returns true if the increment was done. - */ -static __always_inline bool -${arch}${atomic}_inc_not_zero(${atomic}_t *v) -{ - return ${arch}${atomic}_add_unless(v, 1, 0); -} + return raw_${atomic}_add_unless(v, 1, 0); EOF diff --git a/scripts/atomic/fallbacks/inc_unless_negative b/scripts/atomic/fallbacks/inc_unless_negative index 87629e0d4a80..7b4b09868842 100755 --- a/scripts/atomic/fallbacks/inc_unless_negative +++ b/scripts/atomic/fallbacks/inc_unless_negative @@ -1,14 +1,10 @@ cat <<EOF -static __always_inline bool -${arch}${atomic}_inc_unless_negative(${atomic}_t *v) -{ - ${int} c = ${arch}${atomic}_read(v); + ${int} c = raw_${atomic}_read(v); do { if (unlikely(c < 0)) return false; - } while (!${arch}${atomic}_try_cmpxchg(v, &c, c + 1)); + } while (!raw_${atomic}_try_cmpxchg(v, &c, c + 1)); return true; -} EOF diff --git a/scripts/atomic/fallbacks/read_acquire b/scripts/atomic/fallbacks/read_acquire index 341a88dccaa7..e319862d2f1a 100755 --- a/scripts/atomic/fallbacks/read_acquire +++ b/scripts/atomic/fallbacks/read_acquire @@ -1,7 +1,12 @@ cat <<EOF -static __always_inline ${ret} -${arch}${atomic}_read_acquire(const ${atomic}_t *v) -{ - return smp_load_acquire(&(v)->counter); -} + ${int} ret; + + if (__native_word(${atomic}_t)) { + ret = smp_load_acquire(&(v)->counter); + } else { + ret = raw_${atomic}_read(v); + __atomic_acquire_fence(); + } + + return ret; EOF diff --git a/scripts/atomic/fallbacks/release b/scripts/atomic/fallbacks/release index f8906d537c0f..1e6daf57b4ba 100755 --- a/scripts/atomic/fallbacks/release +++ b/scripts/atomic/fallbacks/release @@ -1,8 +1,4 @@ cat <<EOF -static __always_inline ${ret} -${arch}${atomic}_${pfx}${name}${sfx}_release(${params}) -{ __atomic_release_fence(); - ${retstmt}${arch}${atomic}_${pfx}${name}${sfx}_relaxed(${args}); -} + ${retstmt}arch_${atomic}_${pfx}${name}${sfx}_relaxed(${args}); EOF diff --git a/scripts/atomic/fallbacks/set_release b/scripts/atomic/fallbacks/set_release index 76068272d5f5..16a374ae6bb1 100755 --- a/scripts/atomic/fallbacks/set_release +++ b/scripts/atomic/fallbacks/set_release @@ -1,7 +1,8 @@ cat <<EOF -static __always_inline void -${arch}${atomic}_set_release(${atomic}_t *v, ${int} i) -{ - smp_store_release(&(v)->counter, i); -} + if (__native_word(${atomic}_t)) { + smp_store_release(&(v)->counter, i); + } else { + __atomic_release_fence(); + raw_${atomic}_set(v, i); + } EOF diff --git a/scripts/atomic/fallbacks/sub_and_test b/scripts/atomic/fallbacks/sub_and_test index c580f4c2136e..d1f746fe0ca4 100755 --- a/scripts/atomic/fallbacks/sub_and_test +++ b/scripts/atomic/fallbacks/sub_and_test @@ -1,16 +1,3 @@ cat <<EOF -/** - * ${arch}${atomic}_sub_and_test - subtract value from variable and test result - * @i: integer value to subtract - * @v: pointer of type ${atomic}_t - * - * Atomically subtracts @i from @v and returns - * true if the result is zero, or false for all - * other cases. - */ -static __always_inline bool -${arch}${atomic}_sub_and_test(${int} i, ${atomic}_t *v) -{ - return ${arch}${atomic}_sub_return(i, v) == 0; -} + return raw_${atomic}_sub_return(i, v) == 0; EOF diff --git a/scripts/atomic/fallbacks/try_cmpxchg b/scripts/atomic/fallbacks/try_cmpxchg index 06db0f738e45..d4da82092baf 100755 --- a/scripts/atomic/fallbacks/try_cmpxchg +++ b/scripts/atomic/fallbacks/try_cmpxchg @@ -1,11 +1,7 @@ cat <<EOF -static __always_inline bool -${arch}${atomic}_try_cmpxchg${order}(${atomic}_t *v, ${int} *old, ${int} new) -{ ${int} r, o = *old; - r = ${arch}${atomic}_cmpxchg${order}(v, o, new); + r = raw_${atomic}_cmpxchg${order}(v, o, new); if (unlikely(r != o)) *old = r; return likely(r == o); -} EOF diff --git a/scripts/atomic/fallbacks/xchg b/scripts/atomic/fallbacks/xchg new file mode 100644 index 000000000000..e4def1e0d092 --- /dev/null +++ b/scripts/atomic/fallbacks/xchg @@ -0,0 +1,3 @@ +cat <<EOF + return raw_xchg${order}(&v->counter, new); +EOF diff --git a/scripts/atomic/gen-atomic-fallback.sh b/scripts/atomic/gen-atomic-fallback.sh index 693dfa1de430..f80d69cfeb1f 100755 --- a/scripts/atomic/gen-atomic-fallback.sh +++ b/scripts/atomic/gen-atomic-fallback.sh @@ -2,11 +2,10 @@ # SPDX-License-Identifier: GPL-2.0 ATOMICDIR=$(dirname $0) -ARCH=$2 . ${ATOMICDIR}/atomic-tbl.sh -#gen_template_fallback(template, meta, pfx, name, sfx, order, arch, atomic, int, args...) +#gen_template_fallback(template, meta, pfx, name, sfx, order, atomic, int, args...) gen_template_fallback() { local template="$1"; shift @@ -15,27 +14,19 @@ gen_template_fallback() local name="$1"; shift local sfx="$1"; shift local order="$1"; shift - local arch="$1"; shift local atomic="$1"; shift local int="$1"; shift - local atomicname="${arch}${atomic}_${pfx}${name}${sfx}${order}" - local ret="$(gen_ret_type "${meta}" "${int}")" local retstmt="$(gen_ret_stmt "${meta}")" local params="$(gen_params "${int}" "${atomic}" "$@")" local args="$(gen_args "$@")" - if [ ! -z "${template}" ]; then - printf "#ifndef ${atomicname}\n" - . ${template} - printf "#define ${atomicname} ${atomicname}\n" - printf "#endif\n\n" - fi + . ${template} } -#gen_proto_fallback(meta, pfx, name, sfx, order, arch, atomic, int, args...) -gen_proto_fallback() +#gen_order_fallback(meta, pfx, name, sfx, order, atomic, int, args...) +gen_order_fallback() { local meta="$1"; shift local pfx="$1"; shift @@ -43,137 +34,259 @@ gen_proto_fallback() local sfx="$1"; shift local order="$1"; shift - local tmpl="$(find_fallback_template "${pfx}" "${name}" "${sfx}" "${order}")" + local tmpl_order=${order#_} + local tmpl="${ATOMICDIR}/fallbacks/${tmpl_order:-fence}" gen_template_fallback "${tmpl}" "${meta}" "${pfx}" "${name}" "${sfx}" "${order}" "$@" } -#gen_basic_fallbacks(basename) -gen_basic_fallbacks() -{ - local basename="$1"; shift -cat << EOF -#define ${basename}_acquire ${basename} -#define ${basename}_release ${basename} -#define ${basename}_relaxed ${basename} -EOF -} - -gen_proto_order_variant() +#gen_proto_fallback(meta, pfx, name, sfx, order, atomic, int, args...) +gen_proto_fallback() { local meta="$1"; shift local pfx="$1"; shift local name="$1"; shift local sfx="$1"; shift local order="$1"; shift - local arch="$1" - local atomic="$2" - local basename="${arch}${atomic}_${pfx}${name}${sfx}" - - printf "#define arch_${basename}${order} ${basename}${order}\n" + local tmpl="$(find_fallback_template "${pfx}" "${name}" "${sfx}" "${order}")" + gen_template_fallback "${tmpl}" "${meta}" "${pfx}" "${name}" "${sfx}" "${order}" "$@" } -#gen_proto_order_variants(meta, pfx, name, sfx, arch, atomic, int, args...) -gen_proto_order_variants() +#gen_proto_order_variant(meta, pfx, name, sfx, order, atomic, int, args...) +gen_proto_order_variant() { local meta="$1"; shift local pfx="$1"; shift local name="$1"; shift local sfx="$1"; shift - local arch="$1" - local atomic="$2" + local order="$1"; shift + local atomic="$1"; shift + local int="$1"; shift - local basename="${arch}${atomic}_${pfx}${name}${sfx}" + local atomicname="${atomic}_${pfx}${name}${sfx}${order}" + local basename="${atomic}_${pfx}${name}${sfx}" local template="$(find_fallback_template "${pfx}" "${name}" "${sfx}" "${order}")" - if [ -z "$arch" ]; then - gen_proto_order_variant "${meta}" "${pfx}" "${name}" "${sfx}" "" "$@" - - if meta_has_acquire "${meta}"; then - gen_proto_order_variant "${meta}" "${pfx}" "${name}" "${sfx}" "_acquire" "$@" - fi - if meta_has_release "${meta}"; then - gen_proto_order_variant "${meta}" "${pfx}" "${name}" "${sfx}" "_release" "$@" - fi - if meta_has_relaxed "${meta}"; then - gen_proto_order_variant "${meta}" "${pfx}" "${name}" "${sfx}" "_relaxed" "$@" - fi + local ret="$(gen_ret_type "${meta}" "${int}")" + local retstmt="$(gen_ret_stmt "${meta}")" + local params="$(gen_params "${int}" "${atomic}" "$@")" + local args="$(gen_args "$@")" - echo "" + gen_kerneldoc "raw_" "${meta}" "${pfx}" "${name}" "${sfx}" "${order}" "${atomic}" "${int}" "$@" + + printf "static __always_inline ${ret}\n" + printf "raw_${atomicname}(${params})\n" + printf "{\n" + + # Where there is no possible fallback, this order variant is mandatory + # and must be provided by arch code. Add a comment to the header to + # make this obvious. + # + # Ideally we'd error on a missing definition, but arch code might + # define this order variant as a C function without a preprocessor + # symbol. + if [ -z ${template} ] && [ -z "${order}" ] && ! meta_has_relaxed "${meta}"; then + printf "\t${retstmt}arch_${atomicname}(${args});\n" + printf "}\n\n" + return fi - # If we don't have relaxed atomics, then we don't bother with ordering fallbacks - # read_acquire and set_release need to be templated, though - if ! meta_has_relaxed "${meta}"; then - gen_proto_fallback "${meta}" "${pfx}" "${name}" "${sfx}" "" "$@" - - if meta_has_acquire "${meta}"; then - gen_proto_fallback "${meta}" "${pfx}" "${name}" "${sfx}" "_acquire" "$@" - fi + printf "#if defined(arch_${atomicname})\n" + printf "\t${retstmt}arch_${atomicname}(${args});\n" - if meta_has_release "${meta}"; then - gen_proto_fallback "${meta}" "${pfx}" "${name}" "${sfx}" "_release" "$@" - fi - - return + # Allow FULL/ACQUIRE/RELEASE ops to be defined in terms of RELAXED ops + if [ "${order}" != "_relaxed" ] && meta_has_relaxed "${meta}"; then + printf "#elif defined(arch_${basename}_relaxed)\n" + gen_order_fallback "${meta}" "${pfx}" "${name}" "${sfx}" "${order}" "${atomic}" "${int}" "$@" fi - printf "#ifndef ${basename}_relaxed\n" + # Allow ACQUIRE/RELEASE/RELAXED ops to be defined in terms of FULL ops + if [ ! -z "${order}" ] && ! meta_is_implicitly_relaxed "${meta}"; then + printf "#elif defined(arch_${basename})\n" + printf "\t${retstmt}arch_${basename}(${args});\n" + fi + printf "#else\n" if [ ! -z "${template}" ]; then - printf "#ifdef ${basename}\n" + gen_proto_fallback "${meta}" "${pfx}" "${name}" "${sfx}" "${order}" "${atomic}" "${int}" "$@" + else + printf "#error \"Unable to define raw_${atomicname}\"\n" fi - gen_basic_fallbacks "${basename}" + printf "#endif\n" + printf "}\n\n" +} - if [ ! -z "${template}" ]; then - printf "#endif /* ${arch}${atomic}_${pfx}${name}${sfx} */\n\n" - gen_proto_fallback "${meta}" "${pfx}" "${name}" "${sfx}" "" "$@" - gen_proto_fallback "${meta}" "${pfx}" "${name}" "${sfx}" "_acquire" "$@" - gen_proto_fallback "${meta}" "${pfx}" "${name}" "${sfx}" "_release" "$@" - gen_proto_fallback "${meta}" "${pfx}" "${name}" "${sfx}" "_relaxed" "$@" + +#gen_proto_order_variants(meta, pfx, name, sfx, atomic, int, args...) +gen_proto_order_variants() +{ + local meta="$1"; shift + local pfx="$1"; shift + local name="$1"; shift + local sfx="$1"; shift + local atomic="$1" + + gen_proto_order_variant "${meta}" "${pfx}" "${name}" "${sfx}" "" "$@" + + if meta_has_acquire "${meta}"; then + gen_proto_order_variant "${meta}" "${pfx}" "${name}" "${sfx}" "_acquire" "$@" fi - printf "#else /* ${basename}_relaxed */\n\n" + if meta_has_release "${meta}"; then + gen_proto_order_variant "${meta}" "${pfx}" "${name}" "${sfx}" "_release" "$@" + fi - gen_template_fallback "${ATOMICDIR}/fallbacks/acquire" "${meta}" "${pfx}" "${name}" "${sfx}" "_acquire" "$@" - gen_template_fallback "${ATOMICDIR}/fallbacks/release" "${meta}" "${pfx}" "${name}" "${sfx}" "_release" "$@" - gen_template_fallback "${ATOMICDIR}/fallbacks/fence" "${meta}" "${pfx}" "${name}" "${sfx}" "" "$@" + if meta_has_relaxed "${meta}"; then + gen_proto_order_variant "${meta}" "${pfx}" "${name}" "${sfx}" "_relaxed" "$@" + fi +} - printf "#endif /* ${basename}_relaxed */\n\n" +#gen_basic_fallbacks(basename) +gen_basic_fallbacks() +{ + local basename="$1"; shift +cat << EOF +#define raw_${basename}_acquire arch_${basename} +#define raw_${basename}_release arch_${basename} +#define raw_${basename}_relaxed arch_${basename} +EOF } -gen_xchg_fallbacks() +gen_order_fallbacks() { local xchg="$1"; shift + cat <<EOF -#ifndef ${xchg}_relaxed -#define ${xchg}_relaxed ${xchg} -#define ${xchg}_acquire ${xchg} -#define ${xchg}_release ${xchg} -#else /* ${xchg}_relaxed */ - -#ifndef ${xchg}_acquire -#define ${xchg}_acquire(...) \\ - __atomic_op_acquire(${xchg}, __VA_ARGS__) + +#define raw_${xchg}_relaxed arch_${xchg}_relaxed + +#ifdef arch_${xchg}_acquire +#define raw_${xchg}_acquire arch_${xchg}_acquire +#else +#define raw_${xchg}_acquire(...) \\ + __atomic_op_acquire(arch_${xchg}, __VA_ARGS__) #endif -#ifndef ${xchg}_release -#define ${xchg}_release(...) \\ - __atomic_op_release(${xchg}, __VA_ARGS__) +#ifdef arch_${xchg}_release +#define raw_${xchg}_release arch_${xchg}_release +#else +#define raw_${xchg}_release(...) \\ + __atomic_op_release(arch_${xchg}, __VA_ARGS__) #endif -#ifndef ${xchg} -#define ${xchg}(...) \\ - __atomic_op_fence(${xchg}, __VA_ARGS__) +#ifdef arch_${xchg} +#define raw_${xchg} arch_${xchg} +#else +#define raw_${xchg}(...) \\ + __atomic_op_fence(arch_${xchg}, __VA_ARGS__) #endif -#endif /* ${xchg}_relaxed */ +EOF +} + +gen_xchg_order_fallback() +{ + local xchg="$1"; shift + local order="$1"; shift + local forder="${order:-_fence}" + + printf "#if defined(arch_${xchg}${order})\n" + printf "#define raw_${xchg}${order} arch_${xchg}${order}\n" + if [ "${order}" != "_relaxed" ]; then + printf "#elif defined(arch_${xchg}_relaxed)\n" + printf "#define raw_${xchg}${order}(...) \\\\\n" + printf " __atomic_op${forder}(arch_${xchg}, __VA_ARGS__)\n" + fi + + if [ ! -z "${order}" ]; then + printf "#elif defined(arch_${xchg})\n" + printf "#define raw_${xchg}${order} arch_${xchg}\n" + fi + + printf "#else\n" + printf "extern void raw_${xchg}${order}_not_implemented(void);\n" + printf "#define raw_${xchg}${order}(...) raw_${xchg}${order}_not_implemented()\n" + printf "#endif\n\n" +} + +gen_xchg_fallbacks() +{ + local xchg="$1"; shift + + for order in "" "_acquire" "_release" "_relaxed"; do + gen_xchg_order_fallback "${xchg}" "${order}" + done +} + +gen_try_cmpxchg_fallback() +{ + local prefix="$1"; shift + local cmpxchg="$1"; shift; + local suffix="$1"; shift; + +cat <<EOF +#define raw_${prefix}try_${cmpxchg}${suffix}(_ptr, _oldp, _new) \\ +({ \\ + typeof(*(_ptr)) *___op = (_oldp), ___o = *___op, ___r; \\ + ___r = raw_${prefix}${cmpxchg}${suffix}((_ptr), ___o, (_new)); \\ + if (unlikely(___r != ___o)) \\ + *___op = ___r; \\ + likely(___r == ___o); \\ +}) EOF } +gen_try_cmpxchg_order_fallback() +{ + local cmpxchg="$1"; shift + local order="$1"; shift + local forder="${order:-_fence}" + + printf "#if defined(arch_try_${cmpxchg}${order})\n" + printf "#define raw_try_${cmpxchg}${order} arch_try_${cmpxchg}${order}\n" + + if [ "${order}" != "_relaxed" ]; then + printf "#elif defined(arch_try_${cmpxchg}_relaxed)\n" + printf "#define raw_try_${cmpxchg}${order}(...) \\\\\n" + printf " __atomic_op${forder}(arch_try_${cmpxchg}, __VA_ARGS__)\n" + fi + + if [ ! -z "${order}" ]; then + printf "#elif defined(arch_try_${cmpxchg})\n" + printf "#define raw_try_${cmpxchg}${order} arch_try_${cmpxchg}\n" + fi + + printf "#else\n" + gen_try_cmpxchg_fallback "" "${cmpxchg}" "${order}" + printf "#endif\n\n" +} + +gen_try_cmpxchg_order_fallbacks() +{ + local cmpxchg="$1"; shift; + + for order in "" "_acquire" "_release" "_relaxed"; do + gen_try_cmpxchg_order_fallback "${cmpxchg}" "${order}" + done +} + +gen_def_and_try_cmpxchg_fallback() +{ + local prefix="$1"; shift + local cmpxchg="$1"; shift + local suffix="$1"; shift + + printf "#define raw_${prefix}${cmpxchg}${suffix} arch_${prefix}${cmpxchg}${suffix}\n\n" + printf "#ifdef arch_${prefix}try_${cmpxchg}${suffix}\n" + printf "#define raw_${prefix}try_${cmpxchg}${suffix} arch_${prefix}try_${cmpxchg}${suffix}\n" + printf "#else\n" + gen_try_cmpxchg_fallback "${prefix}" "${cmpxchg}" "${suffix}" + printf "#endif\n\n" +} + cat << EOF // SPDX-License-Identifier: GPL-2.0 @@ -187,12 +300,24 @@ cat << EOF EOF -for xchg in "${ARCH}xchg" "${ARCH}cmpxchg" "${ARCH}cmpxchg64"; do +for xchg in "xchg" "cmpxchg" "cmpxchg64" "cmpxchg128"; do gen_xchg_fallbacks "${xchg}" done +for cmpxchg in "cmpxchg" "cmpxchg64" "cmpxchg128"; do + gen_try_cmpxchg_order_fallbacks "${cmpxchg}" +done + +for cmpxchg in "cmpxchg" "cmpxchg64" "cmpxchg128"; do + gen_def_and_try_cmpxchg_fallback "" "${cmpxchg}" "_local" +done + +for cmpxchg in "cmpxchg"; do + gen_def_and_try_cmpxchg_fallback "sync_" "${cmpxchg}" "" +done + grep '^[a-z]' "$1" | while read name meta args; do - gen_proto "${meta}" "${name}" "${ARCH}" "atomic" "int" ${args} + gen_proto "${meta}" "${name}" "atomic" "int" ${args} done cat <<EOF @@ -203,7 +328,7 @@ cat <<EOF EOF grep '^[a-z]' "$1" | while read name meta args; do - gen_proto "${meta}" "${name}" "${ARCH}" "atomic64" "s64" ${args} + gen_proto "${meta}" "${name}" "atomic64" "s64" ${args} done cat <<EOF diff --git a/scripts/atomic/gen-atomic-instrumented.sh b/scripts/atomic/gen-atomic-instrumented.sh index 6afadf73da17..592f3ec89b5f 100755 --- a/scripts/atomic/gen-atomic-instrumented.sh +++ b/scripts/atomic/gen-atomic-instrumented.sh @@ -5,9 +5,10 @@ ATOMICDIR=$(dirname $0) . ${ATOMICDIR}/atomic-tbl.sh -#gen_param_check(arg) +#gen_param_check(meta, arg) gen_param_check() { + local meta="$1"; shift local arg="$1"; shift local type="${arg%%:*}" local name="$(gen_param_name "${arg}")" @@ -17,47 +18,35 @@ gen_param_check() i) return;; esac - # We don't write to constant parameters - [ ${type#c} != ${type} ] && rw="read" + if [ ${type#c} != ${type} ]; then + # We don't write to constant parameters. + rw="read" + elif [ "${meta}" != "s" ]; then + # An atomic RMW: if this parameter is not a constant, and this atomic is + # not just a 's'tore, this parameter is both read from and written to. + rw="read_write" + fi printf "\tinstrument_atomic_${rw}(${name}, sizeof(*${name}));\n" } -#gen_param_check(arg...) +#gen_params_checks(meta, arg...) gen_params_checks() { - while [ "$#" -gt 0 ]; do - gen_param_check "$1" - shift; - done -} - -# gen_guard(meta, atomic, pfx, name, sfx, order) -gen_guard() -{ local meta="$1"; shift - local atomic="$1"; shift - local pfx="$1"; shift - local name="$1"; shift - local sfx="$1"; shift local order="$1"; shift - local atomicname="arch_${atomic}_${pfx}${name}${sfx}${order}" - - local template="$(find_fallback_template "${pfx}" "${name}" "${sfx}" "${order}")" - - # We definitely need a preprocessor symbol for this atomic if it is an - # ordering variant, or if there's a generic fallback. - if [ ! -z "${order}" ] || [ ! -z "${template}" ]; then - printf "defined(${atomicname})" - return + if [ "${order}" = "_release" ]; then + printf "\tkcsan_release();\n" + elif [ -z "${order}" ] && ! meta_in "$meta" "slv"; then + # RMW with return value is fully ordered + printf "\tkcsan_mb();\n" fi - # If this is a base variant, but a relaxed variant *may* exist, then we - # only have a preprocessor symbol if the relaxed variant isn't defined - if meta_has_relaxed "${meta}"; then - printf "!defined(${atomicname}_relaxed) || defined(${atomicname})" - fi + while [ "$#" -gt 0 ]; do + gen_param_check "$meta" "$1" + shift; + done } #gen_proto_order_variant(meta, pfx, name, sfx, order, atomic, int, arg...) @@ -73,57 +62,70 @@ gen_proto_order_variant() local atomicname="${atomic}_${pfx}${name}${sfx}${order}" - local guard="$(gen_guard "${meta}" "${atomic}" "${pfx}" "${name}" "${sfx}" "${order}")" - local ret="$(gen_ret_type "${meta}" "${int}")" local params="$(gen_params "${int}" "${atomic}" "$@")" - local checks="$(gen_params_checks "$@")" + local checks="$(gen_params_checks "${meta}" "${order}" "$@")" local args="$(gen_args "$@")" local retstmt="$(gen_ret_stmt "${meta}")" - [ ! -z "${guard}" ] && printf "#if ${guard}\n" + gen_kerneldoc "" "${meta}" "${pfx}" "${name}" "${sfx}" "${order}" "${atomic}" "${int}" "$@" cat <<EOF static __always_inline ${ret} ${atomicname}(${params}) { ${checks} - ${retstmt}arch_${atomicname}(${args}); + ${retstmt}raw_${atomicname}(${args}); } -#define ${atomicname} ${atomicname} EOF - [ ! -z "${guard}" ] && printf "#endif\n" - printf "\n" } gen_xchg() { local xchg="$1"; shift - local mult="$1"; shift + local order="$1"; shift + kcsan_barrier="" + if [ "${xchg%_local}" = "${xchg}" ]; then + case "$order" in + _release) kcsan_barrier="kcsan_release()" ;; + "") kcsan_barrier="kcsan_mb()" ;; + esac + fi + + if [ "${xchg%${xchg#try_cmpxchg}}" = "try_cmpxchg" ] ; then + +cat <<EOF +#define ${xchg}${order}(ptr, oldp, ...) \\ +({ \\ + typeof(ptr) __ai_ptr = (ptr); \\ + typeof(oldp) __ai_oldp = (oldp); \\ +EOF +[ -n "$kcsan_barrier" ] && printf "\t${kcsan_barrier}; \\\\\n" cat <<EOF -#define ${xchg}(ptr, ...) \\ -({ \\ - typeof(ptr) __ai_ptr = (ptr); \\ - instrument_atomic_write(__ai_ptr, ${mult}sizeof(*__ai_ptr)); \\ - arch_${xchg}(__ai_ptr, __VA_ARGS__); \\ + instrument_atomic_read_write(__ai_ptr, sizeof(*__ai_ptr)); \\ + instrument_read_write(__ai_oldp, sizeof(*__ai_oldp)); \\ + raw_${xchg}${order}(__ai_ptr, __ai_oldp, __VA_ARGS__); \\ }) EOF -} -gen_optional_xchg() -{ - local name="$1"; shift - local sfx="$1"; shift - local guard="defined(arch_${name}${sfx})" + else - [ -z "${sfx}" ] && guard="!defined(arch_${name}_relaxed) || defined(arch_${name})" +cat <<EOF +#define ${xchg}${order}(ptr, ...) \\ +({ \\ + typeof(ptr) __ai_ptr = (ptr); \\ +EOF +[ -n "$kcsan_barrier" ] && printf "\t${kcsan_barrier}; \\\\\n" +cat <<EOF + instrument_atomic_read_write(__ai_ptr, sizeof(*__ai_ptr)); \\ + raw_${xchg}${order}(__ai_ptr, __VA_ARGS__); \\ +}) +EOF - printf "#if ${guard}\n" - gen_xchg "${name}${sfx}" "" - printf "#endif\n\n" + fi } cat << EOF @@ -133,18 +135,13 @@ cat << EOF // DO NOT MODIFY THIS FILE DIRECTLY /* - * This file provides wrappers with KASAN instrumentation for atomic operations. - * To use this functionality an arch's atomic.h file needs to define all - * atomic operations with arch_ prefix (e.g. arch_atomic_read()) and include - * this file at the end. This file provides atomic_read() that forwards to - * arch_atomic_read() for actual atomic operation. - * Note: if an arch atomic operation is implemented by means of other atomic - * operations (e.g. atomic_read()/atomic_cmpxchg() loop), then it needs to use - * arch_ variants (i.e. arch_atomic_read()/arch_atomic_cmpxchg()) to avoid - * double instrumentation. + * This file provoides atomic operations with explicit instrumentation (e.g. + * KASAN, KCSAN), which should be used unless it is necessary to avoid + * instrumentation. Where it is necessary to aovid instrumenation, the + * raw_atomic*() operations should be used. */ -#ifndef _ASM_GENERIC_ATOMIC_INSTRUMENTED_H -#define _ASM_GENERIC_ATOMIC_INSTRUMENTED_H +#ifndef _LINUX_ATOMIC_INSTRUMENTED_H +#define _LINUX_ATOMIC_INSTRUMENTED_H #include <linux/build_bug.h> #include <linux/compiler.h> @@ -160,24 +157,25 @@ grep '^[a-z]' "$1" | while read name meta args; do gen_proto "${meta}" "${name}" "atomic64" "s64" ${args} done -for xchg in "xchg" "cmpxchg" "cmpxchg64"; do +grep '^[a-z]' "$1" | while read name meta args; do + gen_proto "${meta}" "${name}" "atomic_long" "long" ${args} +done + + +for xchg in "xchg" "cmpxchg" "cmpxchg64" "cmpxchg128" "try_cmpxchg" "try_cmpxchg64" "try_cmpxchg128"; do for order in "" "_acquire" "_release" "_relaxed"; do - gen_optional_xchg "${xchg}" "${order}" + gen_xchg "${xchg}" "${order}" + printf "\n" done done -for xchg in "cmpxchg_local" "cmpxchg64_local" "sync_cmpxchg"; do +for xchg in "cmpxchg_local" "cmpxchg64_local" "cmpxchg128_local" "sync_cmpxchg" \ + "try_cmpxchg_local" "try_cmpxchg64_local" "try_cmpxchg128_local" "sync_try_cmpxchg"; do gen_xchg "${xchg}" "" printf "\n" done -gen_xchg "cmpxchg_double" "2 * " - -printf "\n\n" - -gen_xchg "cmpxchg_double_local" "2 * " - cat <<EOF -#endif /* _ASM_GENERIC_ATOMIC_INSTRUMENTED_H */ +#endif /* _LINUX_ATOMIC_INSTRUMENTED_H */ EOF diff --git a/scripts/atomic/gen-atomic-long.sh b/scripts/atomic/gen-atomic-long.sh index e318d3f92e53..9826be3ba986 100755 --- a/scripts/atomic/gen-atomic-long.sh +++ b/scripts/atomic/gen-atomic-long.sh @@ -32,24 +32,34 @@ gen_args_cast() done } -#gen_proto_order_variant(meta, pfx, name, sfx, order, atomic, int, arg...) +#gen_proto_order_variant(meta, pfx, name, sfx, order, arg...) gen_proto_order_variant() { local meta="$1"; shift - local name="$1$2$3$4"; shift; shift; shift; shift - local atomic="$1"; shift - local int="$1"; shift + local pfx="$1"; shift + local name="$1"; shift + local sfx="$1"; shift + local order="$1"; shift + + local atomicname="${pfx}${name}${sfx}${order}" local ret="$(gen_ret_type "${meta}" "long")" local params="$(gen_params "long" "atomic_long" "$@")" - local argscast="$(gen_args_cast "${int}" "${atomic}" "$@")" + local argscast_32="$(gen_args_cast "int" "atomic" "$@")" + local argscast_64="$(gen_args_cast "s64" "atomic64" "$@")" local retstmt="$(gen_ret_stmt "${meta}")" + gen_kerneldoc "raw_" "${meta}" "${pfx}" "${name}" "${sfx}" "${order}" "atomic_long" "long" "$@" + cat <<EOF static __always_inline ${ret} -atomic_long_${name}(${params}) +raw_atomic_long_${atomicname}(${params}) { - ${retstmt}${atomic}_${name}(${argscast}); +#ifdef CONFIG_64BIT + ${retstmt}raw_atomic64_${atomicname}(${argscast_64}); +#else + ${retstmt}raw_atomic_${atomicname}(${argscast_32}); +#endif } EOF @@ -61,8 +71,8 @@ cat << EOF // Generated by $0 // DO NOT MODIFY THIS FILE DIRECTLY -#ifndef _ASM_GENERIC_ATOMIC_LONG_H -#define _ASM_GENERIC_ATOMIC_LONG_H +#ifndef _LINUX_ATOMIC_LONG_H +#define _LINUX_ATOMIC_LONG_H #include <linux/compiler.h> #include <asm/types.h> @@ -79,24 +89,12 @@ typedef atomic_t atomic_long_t; #define atomic_long_cond_read_relaxed atomic_cond_read_relaxed #endif -#ifdef CONFIG_64BIT - -EOF - -grep '^[a-z]' "$1" | while read name meta args; do - gen_proto "${meta}" "${name}" "atomic64" "s64" ${args} -done - -cat <<EOF -#else /* CONFIG_64BIT */ - EOF grep '^[a-z]' "$1" | while read name meta args; do - gen_proto "${meta}" "${name}" "atomic" "int" ${args} + gen_proto "${meta}" "${name}" ${args} done cat <<EOF -#endif /* CONFIG_64BIT */ -#endif /* _ASM_GENERIC_ATOMIC_LONG_H */ +#endif /* _LINUX_ATOMIC_LONG_H */ EOF diff --git a/scripts/atomic/gen-atomics.sh b/scripts/atomic/gen-atomics.sh index d29e159ef489..5b98a8307693 100644..100755 --- a/scripts/atomic/gen-atomics.sh +++ b/scripts/atomic/gen-atomics.sh @@ -8,10 +8,9 @@ ATOMICTBL=${ATOMICDIR}/atomics.tbl LINUXDIR=${ATOMICDIR}/../.. cat <<EOF | -gen-atomic-instrumented.sh asm-generic/atomic-instrumented.h -gen-atomic-long.sh asm-generic/atomic-long.h -gen-atomic-fallback.sh linux/atomic-arch-fallback.h arch_ -gen-atomic-fallback.sh linux/atomic-fallback.h +gen-atomic-instrumented.sh linux/atomic/atomic-instrumented.h +gen-atomic-long.sh linux/atomic/atomic-long.h +gen-atomic-fallback.sh linux/atomic/atomic-arch-fallback.h EOF while read script header args; do /bin/sh ${ATOMICDIR}/${script} ${ATOMICTBL} ${args} > ${LINUXDIR}/include/${header} diff --git a/scripts/atomic/kerneldoc/add b/scripts/atomic/kerneldoc/add new file mode 100644 index 000000000000..991f3dafceea --- /dev/null +++ b/scripts/atomic/kerneldoc/add @@ -0,0 +1,13 @@ +cat <<EOF +/** + * ${class}${atomicname}() - atomic add with ${desc_order} ordering + * @i: ${int} value to add + * @v: pointer to ${atomic}_t + * + * Atomically updates @v to (@v + @i) with ${desc_order} ordering. + * + * ${desc_noinstr} + * + * ${desc_return} + */ +EOF diff --git a/scripts/atomic/kerneldoc/add_negative b/scripts/atomic/kerneldoc/add_negative new file mode 100644 index 000000000000..f4ca1f05d1d8 --- /dev/null +++ b/scripts/atomic/kerneldoc/add_negative @@ -0,0 +1,13 @@ +cat <<EOF +/** + * ${class}${atomicname}() - atomic add and test if negative with ${desc_order} ordering + * @i: ${int} value to add + * @v: pointer to ${atomic}_t + * + * Atomically updates @v to (@v + @i) with ${desc_order} ordering. + * + * ${desc_noinstr} + * + * Return: @true if the resulting value of @v is negative, @false otherwise. + */ +EOF diff --git a/scripts/atomic/kerneldoc/add_unless b/scripts/atomic/kerneldoc/add_unless new file mode 100644 index 000000000000..f828e5f6750c --- /dev/null +++ b/scripts/atomic/kerneldoc/add_unless @@ -0,0 +1,18 @@ +if [ -z "${pfx}" ]; then + desc_return="Return: @true if @v was updated, @false otherwise." +fi + +cat <<EOF +/** + * ${class}${atomicname}() - atomic add unless value with ${desc_order} ordering + * @v: pointer to ${atomic}_t + * @a: ${int} value to add + * @u: ${int} value to compare with + * + * If (@v != @u), atomically updates @v to (@v + @a) with ${desc_order} ordering. + * + * ${desc_noinstr} + * + * ${desc_return} + */ +EOF diff --git a/scripts/atomic/kerneldoc/and b/scripts/atomic/kerneldoc/and new file mode 100644 index 000000000000..a923574351fc --- /dev/null +++ b/scripts/atomic/kerneldoc/and @@ -0,0 +1,13 @@ +cat <<EOF +/** + * ${class}${atomicname}() - atomic bitwise AND with ${desc_order} ordering + * @i: ${int} value + * @v: pointer to ${atomic}_t + * + * Atomically updates @v to (@v & @i) with ${desc_order} ordering. + * + * ${desc_noinstr} + * + * ${desc_return} + */ +EOF diff --git a/scripts/atomic/kerneldoc/andnot b/scripts/atomic/kerneldoc/andnot new file mode 100644 index 000000000000..64bb509f866b --- /dev/null +++ b/scripts/atomic/kerneldoc/andnot @@ -0,0 +1,13 @@ +cat <<EOF +/** + * ${class}${atomicname}() - atomic bitwise AND NOT with ${desc_order} ordering + * @i: ${int} value + * @v: pointer to ${atomic}_t + * + * Atomically updates @v to (@v & ~@i) with ${desc_order} ordering. + * + * ${desc_noinstr} + * + * ${desc_return} + */ +EOF diff --git a/scripts/atomic/kerneldoc/cmpxchg b/scripts/atomic/kerneldoc/cmpxchg new file mode 100644 index 000000000000..3bce328f50cf --- /dev/null +++ b/scripts/atomic/kerneldoc/cmpxchg @@ -0,0 +1,14 @@ +cat <<EOF +/** + * ${class}${atomicname}() - atomic compare and exchange with ${desc_order} ordering + * @v: pointer to ${atomic}_t + * @old: ${int} value to compare with + * @new: ${int} value to assign + * + * If (@v == @old), atomically updates @v to @new with ${desc_order} ordering. + * + * ${desc_noinstr} + * + * Return: The original value of @v. + */ +EOF diff --git a/scripts/atomic/kerneldoc/dec b/scripts/atomic/kerneldoc/dec new file mode 100644 index 000000000000..bbeecbc4c20a --- /dev/null +++ b/scripts/atomic/kerneldoc/dec @@ -0,0 +1,12 @@ +cat <<EOF +/** + * ${class}${atomicname}() - atomic decrement with ${desc_order} ordering + * @v: pointer to ${atomic}_t + * + * Atomically updates @v to (@v - 1) with ${desc_order} ordering. + * + * ${desc_noinstr} + * + * ${desc_return} + */ +EOF diff --git a/scripts/atomic/kerneldoc/dec_and_test b/scripts/atomic/kerneldoc/dec_and_test new file mode 100644 index 000000000000..71bbd23ce4bc --- /dev/null +++ b/scripts/atomic/kerneldoc/dec_and_test @@ -0,0 +1,12 @@ +cat <<EOF +/** + * ${class}${atomicname}() - atomic decrement and test if zero with ${desc_order} ordering + * @v: pointer to ${atomic}_t + * + * Atomically updates @v to (@v - 1) with ${desc_order} ordering. + * + * ${desc_noinstr} + * + * Return: @true if the resulting value of @v is zero, @false otherwise. + */ +EOF diff --git a/scripts/atomic/kerneldoc/dec_if_positive b/scripts/atomic/kerneldoc/dec_if_positive new file mode 100644 index 000000000000..04f1aed3cf83 --- /dev/null +++ b/scripts/atomic/kerneldoc/dec_if_positive @@ -0,0 +1,12 @@ +cat <<EOF +/** + * ${class}${atomicname}() - atomic decrement if positive with ${desc_order} ordering + * @v: pointer to ${atomic}_t + * + * If (@v > 0), atomically updates @v to (@v - 1) with ${desc_order} ordering. + * + * ${desc_noinstr} + * + * Return: The old value of (@v - 1), regardless of whether @v was updated. + */ +EOF diff --git a/scripts/atomic/kerneldoc/dec_unless_positive b/scripts/atomic/kerneldoc/dec_unless_positive new file mode 100644 index 000000000000..ee73612f0354 --- /dev/null +++ b/scripts/atomic/kerneldoc/dec_unless_positive @@ -0,0 +1,12 @@ +cat <<EOF +/** + * ${class}${atomicname}() - atomic decrement unless positive with ${desc_order} ordering + * @v: pointer to ${atomic}_t + * + * If (@v <= 0), atomically updates @v to (@v - 1) with ${desc_order} ordering. + * + * ${desc_noinstr} + * + * Return: @true if @v was updated, @false otherwise. + */ +EOF diff --git a/scripts/atomic/kerneldoc/inc b/scripts/atomic/kerneldoc/inc new file mode 100644 index 000000000000..9f14f1b3d2ef --- /dev/null +++ b/scripts/atomic/kerneldoc/inc @@ -0,0 +1,12 @@ +cat <<EOF +/** + * ${class}${atomicname}() - atomic increment with ${desc_order} ordering + * @v: pointer to ${atomic}_t + * + * Atomically updates @v to (@v + 1) with ${desc_order} ordering. + * + * ${desc_noinstr} + * + * ${desc_return} + */ +EOF diff --git a/scripts/atomic/kerneldoc/inc_and_test b/scripts/atomic/kerneldoc/inc_and_test new file mode 100644 index 000000000000..971694d59bbd --- /dev/null +++ b/scripts/atomic/kerneldoc/inc_and_test @@ -0,0 +1,12 @@ +cat <<EOF +/** + * ${class}${atomicname}() - atomic increment and test if zero with ${desc_order} ordering + * @v: pointer to ${atomic}_t + * + * Atomically updates @v to (@v + 1) with ${desc_order} ordering. + * + * ${desc_noinstr} + * + * Return: @true if the resulting value of @v is zero, @false otherwise. + */ +EOF diff --git a/scripts/atomic/kerneldoc/inc_not_zero b/scripts/atomic/kerneldoc/inc_not_zero new file mode 100644 index 000000000000..618be08e653e --- /dev/null +++ b/scripts/atomic/kerneldoc/inc_not_zero @@ -0,0 +1,12 @@ +cat <<EOF +/** + * ${class}${atomicname}() - atomic increment unless zero with ${desc_order} ordering + * @v: pointer to ${atomic}_t + * + * If (@v != 0), atomically updates @v to (@v + 1) with ${desc_order} ordering. + * + * ${desc_noinstr} + * + * Return: @true if @v was updated, @false otherwise. + */ +EOF diff --git a/scripts/atomic/kerneldoc/inc_unless_negative b/scripts/atomic/kerneldoc/inc_unless_negative new file mode 100644 index 000000000000..597f23d4dc8d --- /dev/null +++ b/scripts/atomic/kerneldoc/inc_unless_negative @@ -0,0 +1,12 @@ +cat <<EOF +/** + * ${class}${atomicname}() - atomic increment unless negative with ${desc_order} ordering + * @v: pointer to ${atomic}_t + * + * If (@v >= 0), atomically updates @v to (@v + 1) with ${desc_order} ordering. + * + * ${desc_noinstr} + * + * Return: @true if @v was updated, @false otherwise. + */ +EOF diff --git a/scripts/atomic/kerneldoc/or b/scripts/atomic/kerneldoc/or new file mode 100644 index 000000000000..55b33de50416 --- /dev/null +++ b/scripts/atomic/kerneldoc/or @@ -0,0 +1,13 @@ +cat <<EOF +/** + * ${class}${atomicname}() - atomic bitwise OR with ${desc_order} ordering + * @i: ${int} value + * @v: pointer to ${atomic}_t + * + * Atomically updates @v to (@v | @i) with ${desc_order} ordering. + * + * ${desc_noinstr} + * + * ${desc_return} + */ +EOF diff --git a/scripts/atomic/kerneldoc/read b/scripts/atomic/kerneldoc/read new file mode 100644 index 000000000000..89fe6147c964 --- /dev/null +++ b/scripts/atomic/kerneldoc/read @@ -0,0 +1,12 @@ +cat <<EOF +/** + * ${class}${atomicname}() - atomic load with ${desc_order} ordering + * @v: pointer to ${atomic}_t + * + * Atomically loads the value of @v with ${desc_order} ordering. + * + * ${desc_noinstr} + * + * Return: The value loaded from @v. + */ +EOF diff --git a/scripts/atomic/kerneldoc/set b/scripts/atomic/kerneldoc/set new file mode 100644 index 000000000000..e82cb9ebbc42 --- /dev/null +++ b/scripts/atomic/kerneldoc/set @@ -0,0 +1,13 @@ +cat <<EOF +/** + * ${class}${atomicname}() - atomic set with ${desc_order} ordering + * @v: pointer to ${atomic}_t + * @i: ${int} value to assign + * + * Atomically sets @v to @i with ${desc_order} ordering. + * + * ${desc_noinstr} + * + * Return: Nothing. + */ +EOF diff --git a/scripts/atomic/kerneldoc/sub b/scripts/atomic/kerneldoc/sub new file mode 100644 index 000000000000..3ba642d04407 --- /dev/null +++ b/scripts/atomic/kerneldoc/sub @@ -0,0 +1,13 @@ +cat <<EOF +/** + * ${class}${atomicname}() - atomic subtract with ${desc_order} ordering + * @i: ${int} value to subtract + * @v: pointer to ${atomic}_t + * + * Atomically updates @v to (@v - @i) with ${desc_order} ordering. + * + * ${desc_noinstr} + * + * ${desc_return} + */ +EOF diff --git a/scripts/atomic/kerneldoc/sub_and_test b/scripts/atomic/kerneldoc/sub_and_test new file mode 100644 index 000000000000..d3760f7749d4 --- /dev/null +++ b/scripts/atomic/kerneldoc/sub_and_test @@ -0,0 +1,13 @@ +cat <<EOF +/** + * ${class}${atomicname}() - atomic subtract and test if zero with ${desc_order} ordering + * @i: ${int} value to add + * @v: pointer to ${atomic}_t + * + * Atomically updates @v to (@v - @i) with ${desc_order} ordering. + * + * ${desc_noinstr} + * + * Return: @true if the resulting value of @v is zero, @false otherwise. + */ +EOF diff --git a/scripts/atomic/kerneldoc/try_cmpxchg b/scripts/atomic/kerneldoc/try_cmpxchg new file mode 100644 index 000000000000..296553206c06 --- /dev/null +++ b/scripts/atomic/kerneldoc/try_cmpxchg @@ -0,0 +1,15 @@ +cat <<EOF +/** + * ${class}${atomicname}() - atomic compare and exchange with ${desc_order} ordering + * @v: pointer to ${atomic}_t + * @old: pointer to ${int} value to compare with + * @new: ${int} value to assign + * + * If (@v == @old), atomically updates @v to @new with ${desc_order} ordering. + * Otherwise, updates @old to the current value of @v. + * + * ${desc_noinstr} + * + * Return: @true if the exchange occured, @false otherwise. + */ +EOF diff --git a/scripts/atomic/kerneldoc/xchg b/scripts/atomic/kerneldoc/xchg new file mode 100644 index 000000000000..75f04c085f25 --- /dev/null +++ b/scripts/atomic/kerneldoc/xchg @@ -0,0 +1,13 @@ +cat <<EOF +/** + * ${class}${atomicname}() - atomic exchange with ${desc_order} ordering + * @v: pointer to ${atomic}_t + * @new: ${int} value to assign + * + * Atomically updates @v to @new with ${desc_order} ordering. + * + * ${desc_noinstr} + * + * Return: The original value of @v. + */ +EOF diff --git a/scripts/atomic/kerneldoc/xor b/scripts/atomic/kerneldoc/xor new file mode 100644 index 000000000000..8837270f2806 --- /dev/null +++ b/scripts/atomic/kerneldoc/xor @@ -0,0 +1,13 @@ +cat <<EOF +/** + * ${class}${atomicname}() - atomic bitwise XOR with ${desc_order} ordering + * @i: ${int} value + * @v: pointer to ${atomic}_t + * + * Atomically updates @v to (@v ^ @i) with ${desc_order} ordering. + * + * ${desc_noinstr} + * + * ${desc_return} + */ +EOF |