Pull locking updates from Ingo Molnar: - Introduce cmpxchg128() -- aka. the demise of cmpxchg_double() The cmpxchg128() family of functions is basically & functionally the same as cmpxchg_double(), but with a saner interface. Instead of a 6-parameter horror that forced u128 - u64/u64-halves layout details on the interface and exposed users to complexity, fragility & bugs, use a natural 3-parameter interface with u128 types. - Restructure the generated atomic headers, and add kerneldoc comments for all of the generic atomic{,64,_long}_t operations. The generated definitions are much cleaner now, and come with documentation. - Implement lock_set_cmp_fn() on lockdep, for defining an ordering when taking multiple locks of the same type. This gets rid of one use of lockdep_set_novalidate_class() in the bcache code. - Fix raw_cpu_generic_try_cmpxchg() bug due to an unintended variable shadowing generating garbage code on Clang on certain ARM builds. * tag 'locking-core-2023-06-27' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: (43 commits) locking/atomic: scripts: fix ${atomic}_dec_if_positive() kerneldoc percpu: Fix self-assignment of __old in raw_cpu_generic_try_cmpxchg() locking/atomic: treewide: delete arch_atomic_*() kerneldoc locking/atomic: docs: Add atomic operations to the driver basic API documentation locking/atomic: scripts: generate kerneldoc comments docs: scripts: kernel-doc: accept bitwise negation like ~@var locking/atomic: scripts: simplify raw_atomic*() definitions locking/atomic: scripts: simplify raw_atomic_long*() definitions locking/atomic: scripts: split pfx/name/sfx/order locking/atomic: scripts: restructure fallback ifdeffery locking/atomic: scripts: build raw_atomic_long*() directly locking/atomic: treewide: use raw_atomic*_<op>() locking/atomic: scripts: add trivial raw_atomic*_<op>() locking/atomic: scripts: factor out order template generation locking/atomic: scripts: remove leftover "${mult}" locking/atomic: scripts: remove bogus order parameter locking/atomic: xtensa: add preprocessor symbols locking/atomic: x86: add preprocessor symbols locking/atomic: sparc: add preprocessor symbols locking/atomic: sh: add preprocessor symbols ...
Showing the changes to scripts (50 of 136 files). Show all
Unified · Split
| @@ -36,9 +36,16 @@ meta_has_relaxed() · 35 unmodified lines | ||
| 36 | 36 | meta_in "$1" "BFIR" |
| 37 | 37 | } |
| 38 | 38 | |
| 39 | −#find_fallback_template(pfx, name, sfx, order) | |
| 40 | −find_fallback_template() | |
| 39 | +#meta_is_implicitly_relaxed(meta) | |
| 40 | +meta_is_implicitly_relaxed() | |
| 41 | 41 | { |
| 42 | + meta_in "$1" "vls" | |
| 43 | +} | |
| 44 | + | |
| 45 | +#find_template(tmpltype, pfx, name, sfx, order) | |
| 46 | +find_template() | |
| 47 | +{ | |
| 48 | + local tmpltype="$1"; shift | |
| 42 | 49 | local pfx="$1"; shift |
| 43 | 50 | local name="$1"; shift |
| 44 | 51 | local sfx="$1"; shift |
| @@ -52,8 +59,8 @@ find_fallback_template() · 7 unmodified lines | ||
| 52 | 59 | # |
| 53 | 60 | # Start at the most specific, and fall back to the most general. Once |
| 54 | 61 | # we find a specific fallback, don't bother looking for more. |
| 55 | − for base in "${pfx}${name}${sfx}${order}" "${name}"; do | |
| 56 | − file="${ATOMICDIR}/fallbacks/${base}" | |
| 62 | + for base in "${pfx}${name}${sfx}${order}" "${pfx}${name}${sfx}" "${name}"; do | |
| 63 | + file="${ATOMICDIR}/${tmpltype}/${base}" | |
| 57 | 64 | |
| 58 | 65 | if [ -f "${file}" ]; then |
| 59 | 66 | printf "${file}" |
| @@ -62,6 +69,18 @@ find_fallback_template() · 2 unmodified lines | ||
| 62 | 69 | done |
| 63 | 70 | } |
| 64 | 71 | |
| 72 | +#find_fallback_template(pfx, name, sfx, order) | |
| 73 | +find_fallback_template() | |
| 74 | +{ | |
| 75 | + find_template "fallbacks" "$@" | |
| 76 | +} | |
| 77 | + | |
| 78 | +#find_kerneldoc_template(pfx, name, sfx, order) | |
| 79 | +find_kerneldoc_template() | |
| 80 | +{ | |
| 81 | + find_template "kerneldoc" "$@" | |
| 82 | +} | |
| 83 | + | |
| 65 | 84 | #gen_ret_type(meta, int) |
| 66 | 85 | gen_ret_type() { |
| 67 | 86 | local meta="$1"; shift |
| @@ -142,6 +161,91 @@ gen_args() · 74 unmodified lines | ||
| 142 | 161 | done |
| 143 | 162 | } |
| 144 | 163 | |
| 164 | +#gen_desc_return(meta) | |
| 165 | +gen_desc_return() | |
| 166 | +{ | |
| 167 | + local meta="$1"; shift | |
| 168 | + | |
| 169 | + case "${meta}" in | |
| 170 | + [v]) | |
| 171 | + printf "Return: Nothing." | |
| 172 | + ;; | |
| 173 | + [Ff]) | |
| 174 | + printf "Return: The original value of @v." | |
| 175 | + ;; | |
| 176 | + [R]) | |
| 177 | + printf "Return: The updated value of @v." | |
| 178 | + ;; | |
| 179 | + [l]) | |
| 180 | + printf "Return: The value of @v." | |
| 181 | + ;; | |
| 182 | + esac | |
| 183 | +} | |
| 184 | + | |
| 185 | +#gen_template_kerneldoc(template, class, meta, pfx, name, sfx, order, atomic, int, args...) | |
| 186 | +gen_template_kerneldoc() | |
| 187 | +{ | |
| 188 | + local template="$1"; shift | |
| 189 | + local class="$1"; shift | |
| 190 | + local meta="$1"; shift | |
| 191 | + local pfx="$1"; shift | |
| 192 | + local name="$1"; shift | |
| 193 | + local sfx="$1"; shift | |
| 194 | + local order="$1"; shift | |
| 195 | + local atomic="$1"; shift | |
| 196 | + local int="$1"; shift | |
| 197 | + | |
| 198 | + local atomicname="${atomic}_${pfx}${name}${sfx}${order}" | |
| 199 | + | |
| 200 | + local ret="$(gen_ret_type "${meta}" "${int}")" | |
| 201 | + local retstmt="$(gen_ret_stmt "${meta}")" | |
| 202 | + local params="$(gen_params "${int}" "${atomic}" "$@")" | |
| 203 | + local args="$(gen_args "$@")" | |
| 204 | + local desc_order="" | |
| 205 | + local desc_instrumentation="" | |
| 206 | + local desc_return="" | |
| 207 | + | |
| 208 | + if [ ! -z "${order}" ]; then | |
| 209 | + desc_order="${order##_}" | |
| 210 | + elif meta_is_implicitly_relaxed "${meta}"; then | |
| 211 | + desc_order="relaxed" | |
| 212 | + else | |
| 213 | + desc_order="full" | |
| 214 | + fi | |
| 215 | + | |
| 216 | + if [ -z "${class}" ]; then | |
| 217 | + desc_noinstr="Unsafe to use in noinstr code; use raw_${atomicname}() there." | |
| 218 | + else | |
| 219 | + desc_noinstr="Safe to use in noinstr code; prefer ${atomicname}() elsewhere." | |
| 220 | + fi | |
| 221 | + | |
| 222 | + desc_return="$(gen_desc_return "${meta}")" | |
| 223 | + | |
| 224 | + . ${template} | |
| 225 | +} | |
| 226 | + | |
| 227 | +#gen_kerneldoc(class, meta, pfx, name, sfx, order, atomic, int, args...) | |
| 228 | +gen_kerneldoc() | |
| 229 | +{ | |
| 230 | + local class="$1"; shift | |
| 231 | + local meta="$1"; shift | |
| 232 | + local pfx="$1"; shift | |
| 233 | + local name="$1"; shift | |
| 234 | + local sfx="$1"; shift | |
| 235 | + local order="$1"; shift | |
| 236 | + | |
| 237 | + local atomicname="${atomic}_${pfx}${name}${sfx}${order}" | |
| 238 | + | |
| 239 | + local tmpl="$(find_kerneldoc_template "${pfx}" "${name}" "${sfx}" "${order}")" | |
| 240 | + if [ -z "${tmpl}" ]; then | |
| 241 | + printf "/*\n" | |
| 242 | + printf " * No kerneldoc available for ${class}${atomicname}\n" | |
| 243 | + printf " */\n" | |
| 244 | + else | |
| 245 | + gen_template_kerneldoc "${tmpl}" "${class}" "${meta}" "${pfx}" "${name}" "${sfx}" "${order}" "$@" | |
| 246 | + fi | |
| 247 | +} | |
| 248 | + | |
| 145 | 249 | #gen_proto_order_variants(meta, pfx, name, sfx, ...) |
| 146 | 250 | gen_proto_order_variants() |
| 147 | 251 | { |
| @@ -27,7 +27,7 @@ and vF i v · 26 unmodified lines | ||
| 27 | 27 | andnot vF i v |
| 28 | 28 | or vF i v |
| 29 | 29 | xor vF i v |
| 30 | −xchg I v i | |
| 30 | +xchg I v i:new | |
| 31 | 31 | cmpxchg I v i:old i:new |
| 32 | 32 | try_cmpxchg B v p:old i:new |
| 33 | 33 | sub_and_test b i v |
| @@ -1,9 +1,5 @@ | ||
| 1 | 1 | cat <<EOF |
| 2 | −static __always_inline ${ret} | |
| 3 | −arch_${atomic}_${pfx}${name}${sfx}_acquire(${params}) | |
| 4 | −{ | |
| 5 | 2 | ${ret} ret = arch_${atomic}_${pfx}${name}${sfx}_relaxed(${args}); |
| 6 | 3 | __atomic_acquire_fence(); |
| 7 | 4 | return ret; |
| 8 | −} | |
| 9 | 5 | EOF |
| @@ -1,15 +1,3 @@ | ||
| 1 | 1 | cat <<EOF |
| 2 | −/** | |
| 3 | − * arch_${atomic}_add_negative${order} - Add and test if negative | |
| 4 | − * @i: integer value to add | |
| 5 | − * @v: pointer of type ${atomic}_t | |
| 6 | − * | |
| 7 | − * Atomically adds @i to @v and returns true if the result is negative, | |
| 8 | − * or false when the result is greater than or equal to zero. | |
| 9 | − */ | |
| 10 | −static __always_inline bool | |
| 11 | −arch_${atomic}_add_negative${order}(${int} i, ${atomic}_t *v) | |
| 12 | −{ | |
| 13 | − return arch_${atomic}_add_return${order}(i, v) < 0; | |
| 14 | −} | |
| 2 | + return raw_${atomic}_add_return${order}(i, v) < 0; | |
| 15 | 3 | EOF |
| @@ -1,16 +1,3 @@ | ||
| 1 | 1 | cat << EOF |
| 2 | −/** | |
| 3 | − * arch_${atomic}_add_unless - add unless the number is already a given value | |
| 4 | − * @v: pointer of type ${atomic}_t | |
| 5 | − * @a: the amount to add to v... | |
| 6 | − * @u: ...unless v is equal to u. | |
| 7 | − * | |
| 8 | − * Atomically adds @a to @v, if @v was not already @u. | |
| 9 | − * Returns true if the addition was done. | |
| 10 | − */ | |
| 11 | −static __always_inline bool | |
| 12 | −arch_${atomic}_add_unless(${atomic}_t *v, ${int} a, ${int} u) | |
| 13 | −{ | |
| 14 | − return arch_${atomic}_fetch_add_unless(v, a, u) != u; | |
| 15 | −} | |
| 2 | + return raw_${atomic}_fetch_add_unless(v, a, u) != u; | |
| 16 | 3 | EOF |
| @@ -1,7 +1,3 @@ | ||
| 1 | 1 | cat <<EOF |
| 2 | −static __always_inline ${ret} | |
| 3 | −arch_${atomic}_${pfx}andnot${sfx}${order}(${int} i, ${atomic}_t *v) | |
| 4 | −{ | |
| 5 | − ${retstmt}arch_${atomic}_${pfx}and${sfx}${order}(~i, v); | |
| 6 | −} | |
| 2 | + ${retstmt}raw_${atomic}_${pfx}and${sfx}${order}(~i, v); | |
| 7 | 3 | EOF |
| @@ -0,0 +1,3 @@ | ||
| 1 | +cat <<EOF | |
| 2 | + return raw_cmpxchg${order}(&v->counter, old, new); | |
| 3 | +EOF | |
| @@ -1,7 +1,3 @@ | ||
| 1 | 1 | cat <<EOF |
| 2 | −static __always_inline ${ret} | |
| 3 | −arch_${atomic}_${pfx}dec${sfx}${order}(${atomic}_t *v) | |
| 4 | −{ | |
| 5 | − ${retstmt}arch_${atomic}_${pfx}sub${sfx}${order}(1, v); | |
| 6 | −} | |
| 2 | + ${retstmt}raw_${atomic}_${pfx}sub${sfx}${order}(1, v); | |
| 7 | 3 | EOF |
| @@ -1,15 +1,3 @@ | ||
| 1 | 1 | cat <<EOF |
| 2 | −/** | |
| 3 | − * arch_${atomic}_dec_and_test - decrement and test | |
| 4 | − * @v: pointer of type ${atomic}_t | |
| 5 | − * | |
| 6 | − * Atomically decrements @v by 1 and | |
| 7 | − * returns true if the result is 0, or false for all other | |
| 8 | − * cases. | |
| 9 | − */ | |
| 10 | −static __always_inline bool | |
| 11 | −arch_${atomic}_dec_and_test(${atomic}_t *v) | |
| 12 | −{ | |
| 13 | − return arch_${atomic}_dec_return(v) == 0; | |
| 14 | −} | |
| 2 | + return raw_${atomic}_dec_return(v) == 0; | |
| 15 | 3 | EOF |
| @@ -1,15 +1,11 @@ | ||
| 1 | 1 | cat <<EOF |
| 2 | −static __always_inline ${ret} | |
| 3 | −arch_${atomic}_dec_if_positive(${atomic}_t *v) | |
| 4 | −{ | |
| 5 | − ${int} dec, c = arch_${atomic}_read(v); | |
| 2 | + ${int} dec, c = raw_${atomic}_read(v); | |
| 6 | 3 | |
| 7 | 4 | do { |
| 8 | 5 | dec = c - 1; |
| 9 | 6 | if (unlikely(dec < 0)) |
| 10 | 7 | break; |
| 11 | − } while (!arch_${atomic}_try_cmpxchg(v, &c, dec)); | |
| 8 | + } while (!raw_${atomic}_try_cmpxchg(v, &c, dec)); | |
| 12 | 9 | |
| 13 | 10 | return dec; |
| 14 | −} | |
| 15 | 11 | EOF |
| @@ -1,14 +1,10 @@ | ||
| 1 | 1 | cat <<EOF |
| 2 | −static __always_inline bool | |
| 3 | −arch_${atomic}_dec_unless_positive(${atomic}_t *v) | |
| 4 | −{ | |
| 5 | − ${int} c = arch_${atomic}_read(v); | |
| 2 | + ${int} c = raw_${atomic}_read(v); | |
| 6 | 3 | |
| 7 | 4 | do { |
| 8 | 5 | if (unlikely(c > 0)) |
| 9 | 6 | return false; |
| 10 | − } while (!arch_${atomic}_try_cmpxchg(v, &c, c - 1)); | |
| 7 | + } while (!raw_${atomic}_try_cmpxchg(v, &c, c - 1)); | |
| 11 | 8 | |
| 12 | 9 | return true; |
| 13 | −} | |
| 14 | 10 | EOF |
| @@ -1,11 +1,7 @@ | ||
| 1 | 1 | cat <<EOF |
| 2 | −static __always_inline ${ret} | |
| 3 | −arch_${atomic}_${pfx}${name}${sfx}(${params}) | |
| 4 | −{ | |
| 5 | 2 | ${ret} ret; |
| 6 | 3 | __atomic_pre_full_fence(); |
| 7 | 4 | ret = arch_${atomic}_${pfx}${name}${sfx}_relaxed(${args}); |
| 8 | 5 | __atomic_post_full_fence(); |
| 9 | 6 | return ret; |
| 10 | −} | |
| 11 | 7 | EOF |
| @@ -1,23 +1,10 @@ | ||
| 1 | 1 | cat << EOF |
| 2 | −/** | |
| 3 | − * arch_${atomic}_fetch_add_unless - add unless the number is already a given value | |
| 4 | − * @v: pointer of type ${atomic}_t | |
| 5 | − * @a: the amount to add to v... | |
| 6 | − * @u: ...unless v is equal to u. | |
| 7 | − * | |
| 8 | − * Atomically adds @a to @v, so long as @v was not already @u. | |
| 9 | − * Returns original value of @v | |
| 10 | − */ | |
| 11 | −static __always_inline ${int} | |
| 12 | −arch_${atomic}_fetch_add_unless(${atomic}_t *v, ${int} a, ${int} u) | |
| 13 | −{ | |
| 14 | − ${int} c = arch_${atomic}_read(v); | |
| 2 | + ${int} c = raw_${atomic}_read(v); | |
| 15 | 3 | |
| 16 | 4 | do { |
| 17 | 5 | if (unlikely(c == u)) |
| 18 | 6 | break; |
| 19 | − } while (!arch_${atomic}_try_cmpxchg(v, &c, c + a)); | |
| 7 | + } while (!raw_${atomic}_try_cmpxchg(v, &c, c + a)); | |
| 20 | 8 | |
| 21 | 9 | return c; |
| 22 | −} | |
| 23 | 10 | EOF |
| @@ -1,7 +1,3 @@ | ||
| 1 | 1 | cat <<EOF |
| 2 | −static __always_inline ${ret} | |
| 3 | −arch_${atomic}_${pfx}inc${sfx}${order}(${atomic}_t *v) | |
| 4 | −{ | |
| 5 | − ${retstmt}arch_${atomic}_${pfx}add${sfx}${order}(1, v); | |
| 6 | −} | |
| 2 | + ${retstmt}raw_${atomic}_${pfx}add${sfx}${order}(1, v); | |
| 7 | 3 | EOF |
| @@ -1,15 +1,3 @@ | ||
| 1 | 1 | cat <<EOF |
| 2 | −/** | |
| 3 | − * arch_${atomic}_inc_and_test - increment and test | |
| 4 | − * @v: pointer of type ${atomic}_t | |
| 5 | − * | |
| 6 | − * Atomically increments @v by 1 | |
| 7 | − * and returns true if the result is zero, or false for all | |
| 8 | − * other cases. | |
| 9 | − */ | |
| 10 | −static __always_inline bool | |
| 11 | −arch_${atomic}_inc_and_test(${atomic}_t *v) | |
| 12 | −{ | |
| 13 | − return arch_${atomic}_inc_return(v) == 0; | |
| 14 | −} | |
| 2 | + return raw_${atomic}_inc_return(v) == 0; | |
| 15 | 3 | EOF |
| @@ -1,14 +1,3 @@ | ||
| 1 | 1 | cat <<EOF |
| 2 | −/** | |
| 3 | − * arch_${atomic}_inc_not_zero - increment unless the number is zero | |
| 4 | − * @v: pointer of type ${atomic}_t | |
| 5 | − * | |
| 6 | − * Atomically increments @v by 1, if @v is non-zero. | |
| 7 | − * Returns true if the increment was done. | |
| 8 | − */ | |
| 9 | −static __always_inline bool | |
| 10 | −arch_${atomic}_inc_not_zero(${atomic}_t *v) | |
| 11 | −{ | |
| 12 | − return arch_${atomic}_add_unless(v, 1, 0); | |
| 13 | −} | |
| 2 | + return raw_${atomic}_add_unless(v, 1, 0); | |
| 14 | 3 | EOF |
| @@ -1,14 +1,10 @@ | ||
| 1 | 1 | cat <<EOF |
| 2 | −static __always_inline bool | |
| 3 | −arch_${atomic}_inc_unless_negative(${atomic}_t *v) | |
| 4 | −{ | |
| 5 | − ${int} c = arch_${atomic}_read(v); | |
| 2 | + ${int} c = raw_${atomic}_read(v); | |
| 6 | 3 | |
| 7 | 4 | do { |
| 8 | 5 | if (unlikely(c < 0)) |
| 9 | 6 | return false; |
| 10 | − } while (!arch_${atomic}_try_cmpxchg(v, &c, c + 1)); | |
| 7 | + } while (!raw_${atomic}_try_cmpxchg(v, &c, c + 1)); | |
| 11 | 8 | |
| 12 | 9 | return true; |
| 13 | −} | |
| 14 | 10 | EOF |
| @@ -1,16 +1,12 @@ | ||
| 1 | 1 | cat <<EOF |
| 2 | −static __always_inline ${ret} | |
| 3 | −arch_${atomic}_read_acquire(const ${atomic}_t *v) | |
| 4 | −{ | |
| 5 | 2 | ${int} ret; |
| 6 | 3 | |
| 7 | 4 | if (__native_word(${atomic}_t)) { |
| 8 | 5 | ret = smp_load_acquire(&(v)->counter); |
| 9 | 6 | } else { |
| 10 | − ret = arch_${atomic}_read(v); | |
| 7 | + ret = raw_${atomic}_read(v); | |
| 11 | 8 | __atomic_acquire_fence(); |
| 12 | 9 | } |
| 13 | 10 | |
| 14 | 11 | return ret; |
| 15 | −} | |
| 16 | 12 | EOF |
| @@ -1,8 +1,4 @@ | ||
| 1 | 1 | cat <<EOF |
| 2 | −static __always_inline ${ret} | |
| 3 | −arch_${atomic}_${pfx}${name}${sfx}_release(${params}) | |
| 4 | −{ | |
| 5 | 2 | __atomic_release_fence(); |
| 6 | 3 | ${retstmt}arch_${atomic}_${pfx}${name}${sfx}_relaxed(${args}); |
| 7 | −} | |
| 8 | 4 | EOF |
| @@ -1,12 +1,8 @@ | ||
| 1 | 1 | cat <<EOF |
| 2 | −static __always_inline void | |
| 3 | −arch_${atomic}_set_release(${atomic}_t *v, ${int} i) | |
| 4 | −{ | |
| 5 | 2 | if (__native_word(${atomic}_t)) { |
| 6 | 3 | smp_store_release(&(v)->counter, i); |
| 7 | 4 | } else { |
| 8 | 5 | __atomic_release_fence(); |
| 9 | − arch_${atomic}_set(v, i); | |
| 6 | + raw_${atomic}_set(v, i); | |
| 10 | 7 | } |
| 11 | −} | |
| 12 | 8 | EOF |
| @@ -1,16 +1,3 @@ | ||
| 1 | 1 | cat <<EOF |
| 2 | −/** | |
| 3 | − * arch_${atomic}_sub_and_test - subtract value from variable and test result | |
| 4 | − * @i: integer value to subtract | |
| 5 | − * @v: pointer of type ${atomic}_t | |
| 6 | − * | |
| 7 | − * Atomically subtracts @i from @v and returns | |
| 8 | − * true if the result is zero, or false for all | |
| 9 | − * other cases. | |
| 10 | − */ | |
| 11 | −static __always_inline bool | |
| 12 | −arch_${atomic}_sub_and_test(${int} i, ${atomic}_t *v) | |
| 13 | −{ | |
| 14 | − return arch_${atomic}_sub_return(i, v) == 0; | |
| 15 | −} | |
| 2 | + return raw_${atomic}_sub_return(i, v) == 0; | |
| 16 | 3 | EOF |
| @@ -1,11 +1,7 @@ | ||
| 1 | 1 | cat <<EOF |
| 2 | −static __always_inline bool | |
| 3 | −arch_${atomic}_try_cmpxchg${order}(${atomic}_t *v, ${int} *old, ${int} new) | |
| 4 | −{ | |
| 5 | 2 | ${int} r, o = *old; |
| 6 | − r = arch_${atomic}_cmpxchg${order}(v, o, new); | |
| 3 | + r = raw_${atomic}_cmpxchg${order}(v, o, new); | |
| 7 | 4 | if (unlikely(r != o)) |
| 8 | 5 | *old = r; |
| 9 | 6 | return likely(r == o); |
| 10 | −} | |
| 11 | 7 | EOF |
| @@ -0,0 +1,3 @@ | ||
| 1 | +cat <<EOF | |
| 2 | + return raw_xchg${order}(&v->counter, new); | |
| 3 | +EOF | |
| @@ -17,23 +17,16 @@ gen_template_fallback() · 16 unmodified lines | ||
| 17 | 17 | local atomic="$1"; shift |
| 18 | 18 | local int="$1"; shift |
| 19 | 19 | |
| 20 | − local atomicname="arch_${atomic}_${pfx}${name}${sfx}${order}" | |
| 21 | − | |
| 22 | 20 | local ret="$(gen_ret_type "${meta}" "${int}")" |
| 23 | 21 | local retstmt="$(gen_ret_stmt "${meta}")" |
| 24 | 22 | local params="$(gen_params "${int}" "${atomic}" "$@")" |
| 25 | 23 | local args="$(gen_args "$@")" |
| 26 | 24 | |
| 27 | − if [ ! -z "${template}" ]; then | |
| 28 | − printf "#ifndef ${atomicname}\n" | |
| 29 | − . ${template} | |
| 30 | − printf "#define ${atomicname} ${atomicname}\n" | |
| 31 | − printf "#endif\n\n" | |
| 32 | − fi | |
| 25 | + . ${template} | |
| 33 | 26 | } |
| 34 | 27 | |
| 35 | −#gen_proto_fallback(meta, pfx, name, sfx, order, atomic, int, args...) | |
| 36 | −gen_proto_fallback() | |
| 28 | +#gen_order_fallback(meta, pfx, name, sfx, order, atomic, int, args...) | |
| 29 | +gen_order_fallback() | |
| 37 | 30 | { |
| 38 | 31 | local meta="$1"; shift |
| 39 | 32 | local pfx="$1"; shift |
| @@ -41,87 +34,124 @@ gen_proto_fallback() · 1 unmodified line | ||
| 41 | 34 | local sfx="$1"; shift |
| 42 | 35 | local order="$1"; shift |
| 43 | 36 | |
| 44 | − local tmpl="$(find_fallback_template "${pfx}" "${name}" "${sfx}" "${order}")" | |
| 37 | + local tmpl_order=${order#_} | |
| 38 | + local tmpl="${ATOMICDIR}/fallbacks/${tmpl_order:-fence}" | |
| 45 | 39 | gen_template_fallback "${tmpl}" "${meta}" "${pfx}" "${name}" "${sfx}" "${order}" "$@" |
| 46 | 40 | } |
| 47 | 41 | |
| 48 | −#gen_basic_fallbacks(basename) | |
| 49 | −gen_basic_fallbacks() | |
| 50 | −{ | |
| 51 | − local basename="$1"; shift | |
| 52 | −cat << EOF | |
| 53 | −#define ${basename}_acquire ${basename} | |
| 54 | −#define ${basename}_release ${basename} | |
| 55 | −#define ${basename}_relaxed ${basename} | |
| 56 | −EOF | |
| 57 | −} | |
| 58 | − | |
| 59 | −gen_proto_order_variant() | |
| 42 | +#gen_proto_fallback(meta, pfx, name, sfx, order, atomic, int, args...) | |
| 43 | +gen_proto_fallback() | |
| 60 | 44 | { |
| 61 | 45 | local meta="$1"; shift |
| 62 | 46 | local pfx="$1"; shift |
| 63 | 47 | local name="$1"; shift |
| 64 | 48 | local sfx="$1"; shift |
| 65 | 49 | local order="$1"; shift |
| 66 | − local atomic="$1" | |
| 67 | 50 | |
| 68 | − local basename="arch_${atomic}_${pfx}${name}${sfx}" | |
| 69 | − | |
| 70 | − printf "#define ${basename}${order} ${basename}${order}\n" | |
| 51 | + local tmpl="$(find_fallback_template "${pfx}" "${name}" "${sfx}" "${order}")" | |
| 52 | + gen_template_fallback "${tmpl}" "${meta}" "${pfx}" "${name}" "${sfx}" "${order}" "$@" | |
| 71 | 53 | } |
| 72 | 54 | |
| 73 | −#gen_proto_order_variants(meta, pfx, name, sfx, atomic, int, args...) | |
| 74 | −gen_proto_order_variants() | |
| 55 | +#gen_proto_order_variant(meta, pfx, name, sfx, order, atomic, int, args...) | |
| 56 | +gen_proto_order_variant() | |
| 75 | 57 | { |
| 76 | 58 | local meta="$1"; shift |
| 77 | 59 | local pfx="$1"; shift |
| 78 | 60 | local name="$1"; shift |
| 79 | 61 | local sfx="$1"; shift |
| 80 | − local atomic="$1" | |
| 62 | + local order="$1"; shift | |
| 63 | + local atomic="$1"; shift | |
| 64 | + local int="$1"; shift | |
| 81 | 65 | |
| 82 | − local basename="arch_${atomic}_${pfx}${name}${sfx}" | |
| 66 | + local atomicname="${atomic}_${pfx}${name}${sfx}${order}" | |
| 67 | + local basename="${atomic}_${pfx}${name}${sfx}" | |
| 83 | 68 | |
| 84 | 69 | local template="$(find_fallback_template "${pfx}" "${name}" "${sfx}" "${order}")" |
| 85 | 70 | |
| 86 | − # If we don't have relaxed atomics, then we don't bother with ordering fallbacks | |
| 87 | − # read_acquire and set_release need to be templated, though | |
| 88 | − if ! meta_has_relaxed "${meta}"; then | |
| 89 | − gen_proto_fallback "${meta}" "${pfx}" "${name}" "${sfx}" "" "$@" | |
| 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 "$@")" | |
| 90 | 75 | |
| 91 | − if meta_has_acquire "${meta}"; then | |
| 92 | − gen_proto_fallback "${meta}" "${pfx}" "${name}" "${sfx}" "_acquire" "$@" | |
| 93 | − fi | |
| 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 | 94 | |
| 95 | − if meta_has_release "${meta}"; then | |
| 96 | − gen_proto_fallback "${meta}" "${pfx}" "${name}" "${sfx}" "_release" "$@" | |
| 97 | − fi | |
| 95 | + printf "#if defined(arch_${atomicname})\n" | |
| 96 | + printf "\t${retstmt}arch_${atomicname}(${args});\n" | |
| 98 | 97 | |
| 99 | − return | |
| 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}" "$@" | |
| 100 | 102 | fi |
| 101 | 103 | |
| 102 | − printf "#ifndef ${basename}_relaxed\n" | |
| 104 | + # Allow ACQUIRE/RELEASE/RELAXED ops to be defined in terms of FULL ops | |
| 105 | + if [ ! -z "${order}" ]; then | |
| 106 | + printf "#elif defined(arch_${basename})\n" | |
| 107 | + printf "\t${retstmt}arch_${basename}(${args});\n" | |
| 108 | + fi | |
| 103 | 109 | |
| 110 | + printf "#else\n" | |
| 104 | 111 | if [ ! -z "${template}" ]; then |
| 105 | − printf "#ifdef ${basename}\n" | |
| 112 | + gen_proto_fallback "${meta}" "${pfx}" "${name}" "${sfx}" "${order}" "${atomic}" "${int}" "$@" | |
| 113 | + else | |
| 114 | + printf "#error \"Unable to define raw_${atomicname}\"\n" | |
| 106 | 115 | fi |
| 107 | 116 | |
| 108 | − gen_basic_fallbacks "${basename}" | |
| 117 | + printf "#endif\n" | |
| 118 | + printf "}\n\n" | |
| 119 | +} | |
| 109 | 120 | |
| 110 | − if [ ! -z "${template}" ]; then | |
| 111 | − printf "#endif /* ${basename} */\n\n" | |
| 112 | − gen_proto_fallback "${meta}" "${pfx}" "${name}" "${sfx}" "" "$@" | |
| 113 | − gen_proto_fallback "${meta}" "${pfx}" "${name}" "${sfx}" "_acquire" "$@" | |
| 114 | − gen_proto_fallback "${meta}" "${pfx}" "${name}" "${sfx}" "_release" "$@" | |
| 115 | − gen_proto_fallback "${meta}" "${pfx}" "${name}" "${sfx}" "_relaxed" "$@" | |
| 121 | + | |
| 122 | +#gen_proto_order_variants(meta, pfx, name, sfx, atomic, int, args...) | |
| 123 | +gen_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" "$@" | |
| 116 | 135 | fi |
| 117 | 136 | |
| 118 | − printf "#else /* ${basename}_relaxed */\n\n" | |
| 137 | + if meta_has_release "${meta}"; then | |
| 138 | + gen_proto_order_variant "${meta}" "${pfx}" "${name}" "${sfx}" "_release" "$@" | |
| 139 | + fi | |
| 119 | 140 | |
| 120 | − gen_template_fallback "${ATOMICDIR}/fallbacks/acquire" "${meta}" "${pfx}" "${name}" "${sfx}" "_acquire" "$@" | |
| 121 | − gen_template_fallback "${ATOMICDIR}/fallbacks/release" "${meta}" "${pfx}" "${name}" "${sfx}" "_release" "$@" | |
| 122 | − gen_template_fallback "${ATOMICDIR}/fallbacks/fence" "${meta}" "${pfx}" "${name}" "${sfx}" "" "$@" | |
| 141 | + if meta_has_relaxed "${meta}"; then | |
| 142 | + gen_proto_order_variant "${meta}" "${pfx}" "${name}" "${sfx}" "_relaxed" "$@" | |
| 143 | + fi | |
| 144 | +} | |
| 123 | 145 | |
| 124 | − printf "#endif /* ${basename}_relaxed */\n\n" | |
| 146 | +#gen_basic_fallbacks(basename) | |
| 147 | +gen_basic_fallbacks() | |
| 148 | +{ | |
| 149 | + local basename="$1"; shift | |
| 150 | +cat << EOF | |
| 151 | +#define raw_${basename}_acquire arch_${basename} | |
| 152 | +#define raw_${basename}_release arch_${basename} | |
| 153 | +#define raw_${basename}_relaxed arch_${basename} | |
| 154 | +EOF | |
| 125 | 155 | } |
| 126 | 156 | |
| 127 | 157 | gen_order_fallbacks() |
| @@ -130,36 +160,65 @@ gen_order_fallbacks() · 2 unmodified lines | ||
| 130 | 160 | |
| 131 | 161 | cat <<EOF |
| 132 | 162 | |
| 133 | −#ifndef ${xchg}_acquire | |
| 134 | −#define ${xchg}_acquire(...) \\ | |
| 135 | − __atomic_op_acquire(${xchg}, __VA_ARGS__) | |
| 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__) | |
| 136 | 170 | #endif |
| 137 | 171 | |
| 138 | −#ifndef ${xchg}_release | |
| 139 | −#define ${xchg}_release(...) \\ | |
| 140 | − __atomic_op_release(${xchg}, __VA_ARGS__) | |
| 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__) | |
| 141 | 177 | #endif |
| 142 | 178 | |
| 143 | −#ifndef ${xchg} | |
| 144 | −#define ${xchg}(...) \\ | |
| 145 | − __atomic_op_fence(${xchg}, __VA_ARGS__) | |
| 179 | +#ifdef arch_${xchg} | |
| 180 | +#define raw_${xchg} arch_${xchg} | |
| 181 | +#else | |
| 182 | +#define raw_${xchg}(...) \\ | |
| 183 | + __atomic_op_fence(arch_${xchg}, __VA_ARGS__) | |
| 146 | 184 | #endif |
| 147 | 185 | |
| 148 | 186 | EOF |
| 149 | 187 | } |
| 150 | 188 | |
| 151 | −gen_xchg_fallbacks() | |
| 189 | +gen_xchg_order_fallback() | |
| 152 | 190 | { |
| 153 | 191 | local xchg="$1"; shift |
| 154 | − printf "#ifndef ${xchg}_relaxed\n" | |
| 192 | + local order="$1"; shift | |
| 193 | + local forder="${order:-_fence}" | |
| 155 | 194 | |
| 156 | − gen_basic_fallbacks ${xchg} | |
| 195 | + printf "#if defined(arch_${xchg}${order})\n" | |
| 196 | + printf "#define raw_${xchg}${order} arch_${xchg}${order}\n" | |
| 157 | 197 | |
| 158 | − printf "#else /* ${xchg}_relaxed */\n" | |
| 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 | |
| 159 | 208 | |
| 160 | − gen_order_fallbacks ${xchg} | |
| 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 | + | |
| 215 | +gen_xchg_fallbacks() | |
| 216 | +{ | |
| 217 | + local xchg="$1"; shift | |
| 161 | 218 | |
| 162 | − printf "#endif /* ${xchg}_relaxed */\n\n" | |
| 219 | + for order in "" "_acquire" "_release" "_relaxed"; do | |
| 220 | + gen_xchg_order_fallback "${xchg}" "${order}" | |
| 221 | + done | |
| 163 | 222 | } |
| 164 | 223 | |
| 165 | 224 | gen_try_cmpxchg_fallback() |
| @@ -168,40 +227,61 @@ gen_try_cmpxchg_fallback() · 2 unmodified lines | ||
| 168 | 227 | local order="$1"; shift; |
| 169 | 228 | |
| 170 | 229 | cat <<EOF |
| 171 | −#ifndef arch_try_${cmpxchg}${order} | |
| 172 | −#define arch_try_${cmpxchg}${order}(_ptr, _oldp, _new) \\ | |
| 230 | +#define raw_try_${cmpxchg}${order}(_ptr, _oldp, _new) \\ | |
| 173 | 231 | ({ \\ |
| 174 | 232 | typeof(*(_ptr)) *___op = (_oldp), ___o = *___op, ___r; \\ |
| 175 | − ___r = arch_${cmpxchg}${order}((_ptr), ___o, (_new)); \\ | |
| 233 | + ___r = raw_${cmpxchg}${order}((_ptr), ___o, (_new)); \\ | |
| 176 | 234 | if (unlikely(___r != ___o)) \\ |
| 177 | 235 | *___op = ___r; \\ |
| 178 | 236 | likely(___r == ___o); \\ |
| 179 | 237 | }) |
| 180 | −#endif /* arch_try_${cmpxchg}${order} */ | |
| 181 | − | |
| 182 | 238 | EOF |
| 183 | 239 | } |
| 184 | 240 | |
| 185 | −gen_try_cmpxchg_fallbacks() | |
| 241 | +gen_try_cmpxchg_order_fallback() | |
| 186 | 242 | { |
| 187 | − local cmpxchg="$1"; shift; | |
| 243 | + local cmpxchg="$1"; shift | |
| 244 | + local order="$1"; shift | |
| 245 | + local forder="${order:-_fence}" | |
| 188 | 246 | |
| 189 | − printf "#ifndef arch_try_${cmpxchg}_relaxed\n" | |
| 190 | − printf "#ifdef arch_try_${cmpxchg}\n" | |
| 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 | |
| 191 | 255 | |
| 192 | − gen_basic_fallbacks "arch_try_${cmpxchg}" | |
| 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 | |
| 193 | 260 | |
| 194 | − printf "#endif /* arch_try_${cmpxchg} */\n\n" | |
| 261 | + printf "#else\n" | |
| 262 | + gen_try_cmpxchg_fallback "${cmpxchg}" "${order}" | |
| 263 | + printf "#endif\n\n" | |
| 264 | +} | |
| 265 | + | |
| 266 | +gen_try_cmpxchg_fallbacks() | |
| 267 | +{ | |
| 268 | + local cmpxchg="$1"; shift; | |
| 195 | 269 | |
| 196 | 270 | for order in "" "_acquire" "_release" "_relaxed"; do |
| 197 | − gen_try_cmpxchg_fallback "${cmpxchg}" "${order}" | |
| 271 | + gen_try_cmpxchg_order_fallback "${cmpxchg}" "${order}" | |
| 198 | 272 | done |
| 273 | +} | |
| 199 | 274 | |
| 200 | − printf "#else /* arch_try_${cmpxchg}_relaxed */\n" | |
| 201 | − | |
| 202 | − gen_order_fallbacks "arch_try_${cmpxchg}" | |
| 275 | +gen_cmpxchg_local_fallbacks() | |
| 276 | +{ | |
| 277 | + local cmpxchg="$1"; shift | |
| 203 | 278 | |
| 204 | − printf "#endif /* arch_try_${cmpxchg}_relaxed */\n\n" | |
| 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" | |
| 205 | 285 | } |
| 206 | 286 | |
| 207 | 287 | cat << EOF |
| @@ -217,16 +297,20 @@ cat << EOF · 9 unmodified lines | ||
| 217 | 297 | |
| 218 | 298 | EOF |
| 219 | 299 | |
| 220 | −for xchg in "arch_xchg" "arch_cmpxchg" "arch_cmpxchg64"; do | |
| 300 | +for xchg in "xchg" "cmpxchg" "cmpxchg64" "cmpxchg128"; do | |
| 221 | 301 | gen_xchg_fallbacks "${xchg}" |
| 222 | 302 | done |
| 223 | 303 | |
| 224 | −for cmpxchg in "cmpxchg" "cmpxchg64"; do | |
| 304 | +for cmpxchg in "cmpxchg" "cmpxchg64" "cmpxchg128"; do | |
| 225 | 305 | gen_try_cmpxchg_fallbacks "${cmpxchg}" |
| 226 | 306 | done |
| 227 | 307 | |
| 228 | −for cmpxchg in "cmpxchg_local" "cmpxchg64_local"; do | |
| 229 | − gen_try_cmpxchg_fallback "${cmpxchg}" "" | |
| 308 | +for cmpxchg in "cmpxchg_local" "cmpxchg64_local" "cmpxchg128_local"; do | |
| 309 | + gen_cmpxchg_local_fallbacks "${cmpxchg}" "" | |
| 310 | +done | |
| 311 | + | |
| 312 | +for cmpxchg in "sync_cmpxchg"; do | |
| 313 | + printf "#define raw_${cmpxchg} arch_${cmpxchg}\n\n" | |
| 230 | 314 | done |
| 231 | 315 | |
| 232 | 316 | grep '^[a-z]' "$1" | while read name meta args; do |
| @@ -68,12 +68,14 @@ gen_proto_order_variant() · 67 unmodified lines | ||
| 68 | 68 | local args="$(gen_args "$@")" |
| 69 | 69 | local retstmt="$(gen_ret_stmt "${meta}")" |
| 70 | 70 | |
| 71 | + gen_kerneldoc "" "${meta}" "${pfx}" "${name}" "${sfx}" "${order}" "${atomic}" "${int}" "$@" | |
| 72 | + | |
| 71 | 73 | cat <<EOF |
| 72 | 74 | static __always_inline ${ret} |
| 73 | 75 | ${atomicname}(${params}) |
| 74 | 76 | { |
| 75 | 77 | ${checks} |
| 76 | − ${retstmt}arch_${atomicname}(${args}); | |
| 78 | + ${retstmt}raw_${atomicname}(${args}); | |
| 77 | 79 | } |
| 78 | 80 | EOF |
| 79 | 81 | |
| @@ -84,7 +86,6 @@ gen_xchg() · 4 unmodified lines | ||
| 84 | 86 | { |
| 85 | 87 | local xchg="$1"; shift |
| 86 | 88 | local order="$1"; shift |
| 87 | − local mult="$1"; shift | |
| 88 | 89 | |
| 89 | 90 | kcsan_barrier="" |
| 90 | 91 | if [ "${xchg%_local}" = "${xchg}" ]; then |
| @@ -104,9 +105,9 @@ cat <<EOF · 13 unmodified lines | ||
| 104 | 105 | EOF |
| 105 | 106 | [ -n "$kcsan_barrier" ] && printf "\t${kcsan_barrier}; \\\\\n" |
| 106 | 107 | cat <<EOF |
| 107 | − instrument_atomic_read_write(__ai_ptr, ${mult}sizeof(*__ai_ptr)); \\ | |
| 108 | − instrument_read_write(__ai_oldp, ${mult}sizeof(*__ai_oldp)); \\ | |
| 109 | − arch_${xchg}${order}(__ai_ptr, __ai_oldp, __VA_ARGS__); \\ | |
| 108 | + instrument_atomic_read_write(__ai_ptr, sizeof(*__ai_ptr)); \\ | |
| 109 | + instrument_read_write(__ai_oldp, sizeof(*__ai_oldp)); \\ | |
| 110 | + raw_${xchg}${order}(__ai_ptr, __ai_oldp, __VA_ARGS__); \\ | |
| 110 | 111 | }) |
| 111 | 112 | EOF |
| 112 | 113 | |
| @@ -119,8 +120,8 @@ cat <<EOF · 6 unmodified lines | ||
| 119 | 120 | EOF |
| 120 | 121 | [ -n "$kcsan_barrier" ] && printf "\t${kcsan_barrier}; \\\\\n" |
| 121 | 122 | cat <<EOF |
| 122 | − instrument_atomic_read_write(__ai_ptr, ${mult}sizeof(*__ai_ptr)); \\ | |
| 123 | − arch_${xchg}${order}(__ai_ptr, __VA_ARGS__); \\ | |
| 123 | + instrument_atomic_read_write(__ai_ptr, sizeof(*__ai_ptr)); \\ | |
| 124 | + raw_${xchg}${order}(__ai_ptr, __VA_ARGS__); \\ | |
| 124 | 125 | }) |
| 125 | 126 | EOF |
| 126 | 127 | |
| @@ -134,15 +135,10 @@ cat << EOF · 7 unmodified lines | ||
| 134 | 135 | // DO NOT MODIFY THIS FILE DIRECTLY |
| 135 | 136 | |
| 136 | 137 | /* |
| 137 | − * This file provides wrappers with KASAN instrumentation for atomic operations. | |
| 138 | − * To use this functionality an arch's atomic.h file needs to define all | |
| 139 | − * atomic operations with arch_ prefix (e.g. arch_atomic_read()) and include | |
| 140 | − * this file at the end. This file provides atomic_read() that forwards to | |
| 141 | − * arch_atomic_read() for actual atomic operation. | |
| 142 | − * Note: if an arch atomic operation is implemented by means of other atomic | |
| 143 | − * operations (e.g. atomic_read()/atomic_cmpxchg() loop), then it needs to use | |
| 144 | − * arch_ variants (i.e. arch_atomic_read()/arch_atomic_cmpxchg()) to avoid | |
| 145 | − * double instrumentation. | |
| 138 | + * This file provoides atomic operations with explicit instrumentation (e.g. | |
| 139 | + * KASAN, KCSAN), which should be used unless it is necessary to avoid | |
| 140 | + * instrumentation. Where it is necessary to aovid instrumenation, the | |
| 141 | + * raw_atomic*() operations should be used. | |
| 146 | 142 | */ |
| 147 | 143 | #ifndef _LINUX_ATOMIC_INSTRUMENTED_H |
| 148 | 144 | #define _LINUX_ATOMIC_INSTRUMENTED_H |
| @@ -166,24 +162,18 @@ grep '^[a-z]' "$1" | while read name meta args; do · 17 unmodified lines | ||
| 166 | 162 | done |
| 167 | 163 | |
| 168 | 164 | |
| 169 | −for xchg in "xchg" "cmpxchg" "cmpxchg64" "try_cmpxchg" "try_cmpxchg64"; do | |
| 165 | +for xchg in "xchg" "cmpxchg" "cmpxchg64" "cmpxchg128" "try_cmpxchg" "try_cmpxchg64" "try_cmpxchg128"; do | |
| 170 | 166 | for order in "" "_acquire" "_release" "_relaxed"; do |
| 171 | − gen_xchg "${xchg}" "${order}" "" | |
| 167 | + gen_xchg "${xchg}" "${order}" | |
| 172 | 168 | printf "\n" |
| 173 | 169 | done |
| 174 | 170 | done |
| 175 | 171 | |
| 176 | −for xchg in "cmpxchg_local" "cmpxchg64_local" "sync_cmpxchg" "try_cmpxchg_local" "try_cmpxchg64_local" ; do | |
| 177 | − gen_xchg "${xchg}" "" "" | |
| 172 | +for xchg in "cmpxchg_local" "cmpxchg64_local" "cmpxchg128_local" "sync_cmpxchg" "try_cmpxchg_local" "try_cmpxchg64_local" "try_cmpxchg128_local"; do | |
| 173 | + gen_xchg "${xchg}" "" | |
| 178 | 174 | printf "\n" |
| 179 | 175 | done |
| 180 | 176 | |
| 181 | −gen_xchg "cmpxchg_double" "" "2 * " | |
| 182 | − | |
| 183 | −printf "\n\n" | |
| 184 | − | |
| 185 | −gen_xchg "cmpxchg_double_local" "" "2 * " | |
| 186 | − | |
| 187 | 177 | cat <<EOF |
| 188 | 178 | |
| 189 | 179 | #endif /* _LINUX_ATOMIC_INSTRUMENTED_H */ |
| @@ -32,24 +32,34 @@ gen_args_cast() · 31 unmodified lines | ||
| 32 | 32 | done |
| 33 | 33 | } |
| 34 | 34 | |
| 35 | −#gen_proto_order_variant(meta, pfx, name, sfx, order, atomic, int, arg...) | |
| 35 | +#gen_proto_order_variant(meta, pfx, name, sfx, order, arg...) | |
| 36 | 36 | gen_proto_order_variant() |
| 37 | 37 | { |
| 38 | 38 | local meta="$1"; shift |
| 39 | − local name="$1$2$3$4"; shift; shift; shift; shift | |
| 40 | − local atomic="$1"; shift | |
| 41 | − local int="$1"; shift | |
| 39 | + local pfx="$1"; shift | |
| 40 | + local name="$1"; shift | |
| 41 | + local sfx="$1"; shift | |
| 42 | + local order="$1"; shift | |
| 43 | + | |
| 44 | + local atomicname="${pfx}${name}${sfx}${order}" | |
| 42 | 45 | |
| 43 | 46 | local ret="$(gen_ret_type "${meta}" "long")" |
| 44 | 47 | local params="$(gen_params "long" "atomic_long" "$@")" |
| 45 | − local argscast="$(gen_args_cast "${int}" "${atomic}" "$@")" | |
| 48 | + local argscast_32="$(gen_args_cast "int" "atomic" "$@")" | |
| 49 | + local argscast_64="$(gen_args_cast "s64" "atomic64" "$@")" | |
| 46 | 50 | local retstmt="$(gen_ret_stmt "${meta}")" |
| 47 | 51 | |
| 52 | + gen_kerneldoc "raw_" "${meta}" "${pfx}" "${name}" "${sfx}" "${order}" "atomic_long" "long" "$@" | |
| 53 | + | |
| 48 | 54 | cat <<EOF |
| 49 | 55 | static __always_inline ${ret} |
| 50 | −arch_atomic_long_${name}(${params}) | |
| 56 | +raw_atomic_long_${atomicname}(${params}) | |
| 51 | 57 | { |
| 52 | − ${retstmt}arch_${atomic}_${name}(${argscast}); | |
| 58 | +#ifdef CONFIG_64BIT | |
| 59 | + ${retstmt}raw_atomic64_${atomicname}(${argscast_64}); | |
| 60 | +#else | |
| 61 | + ${retstmt}raw_atomic_${atomicname}(${argscast_32}); | |
| 62 | +#endif | |
| 53 | 63 | } |
| 54 | 64 | |
| 55 | 65 | EOF |
| @@ -79,24 +89,12 @@ typedef atomic_t atomic_long_t; · 23 unmodified lines | ||
| 79 | 89 | #define atomic_long_cond_read_relaxed atomic_cond_read_relaxed |
| 80 | 90 | #endif |
| 81 | 91 | |
| 82 | −#ifdef CONFIG_64BIT | |
| 83 | − | |
| 84 | −EOF | |
| 85 | − | |
| 86 | −grep '^[a-z]' "$1" | while read name meta args; do | |
| 87 | − gen_proto "${meta}" "${name}" "atomic64" "s64" ${args} | |
| 88 | −done | |
| 89 | − | |
| 90 | −cat <<EOF | |
| 91 | −#else /* CONFIG_64BIT */ | |
| 92 | − | |
| 93 | 92 | EOF |
| 94 | 93 | |
| 95 | 94 | grep '^[a-z]' "$1" | while read name meta args; do |
| 96 | − gen_proto "${meta}" "${name}" "atomic" "int" ${args} | |
| 95 | + gen_proto "${meta}" "${name}" ${args} | |
| 97 | 96 | done |
| 98 | 97 | |
| 99 | 98 | cat <<EOF |
| 100 | −#endif /* CONFIG_64BIT */ | |
| 101 | 99 | #endif /* _LINUX_ATOMIC_LONG_H */ |
| 102 | 100 | EOF |
| @@ -0,0 +1,13 @@ | ||
| 1 | +cat <<EOF | |
| 2 | +/** | |
| 3 | + * ${class}${atomicname}() - atomic add with ${desc_order} ordering | |
| 4 | + * @i: ${int} value to add | |
| 5 | + * @v: pointer to ${atomic}_t | |
| 6 | + * | |
| 7 | + * Atomically updates @v to (@v + @i) with ${desc_order} ordering. | |
| 8 | + * | |
| 9 | + * ${desc_noinstr} | |
| 10 | + * | |
| 11 | + * ${desc_return} | |
| 12 | + */ | |
| 13 | +EOF | |
| @@ -0,0 +1,13 @@ | ||
| 1 | +cat <<EOF | |
| 2 | +/** | |
| 3 | + * ${class}${atomicname}() - atomic add and test if negative with ${desc_order} ordering | |
| 4 | + * @i: ${int} value to add | |
| 5 | + * @v: pointer to ${atomic}_t | |
| 6 | + * | |
| 7 | + * Atomically updates @v to (@v + @i) with ${desc_order} ordering. | |
| 8 | + * | |
| 9 | + * ${desc_noinstr} | |
| 10 | + * | |
| 11 | + * Return: @true if the resulting value of @v is negative, @false otherwise. | |
| 12 | + */ | |
| 13 | +EOF | |
| @@ -0,0 +1,18 @@ | ||
| 1 | +if [ -z "${pfx}" ]; then | |
| 2 | + desc_return="Return: @true if @v was updated, @false otherwise." | |
| 3 | +fi | |
| 4 | + | |
| 5 | +cat <<EOF | |
| 6 | +/** | |
| 7 | + * ${class}${atomicname}() - atomic add unless value with ${desc_order} ordering | |
| 8 | + * @v: pointer to ${atomic}_t | |
| 9 | + * @a: ${int} value to add | |
| 10 | + * @u: ${int} value to compare with | |
| 11 | + * | |
| 12 | + * If (@v != @u), atomically updates @v to (@v + @a) with ${desc_order} ordering. | |
| 13 | + * | |
| 14 | + * ${desc_noinstr} | |
| 15 | + * | |
| 16 | + * ${desc_return} | |
| 17 | + */ | |
| 18 | +EOF | |
| @@ -0,0 +1,13 @@ | ||
| 1 | +cat <<EOF | |
| 2 | +/** | |
| 3 | + * ${class}${atomicname}() - atomic bitwise AND with ${desc_order} ordering | |
| 4 | + * @i: ${int} value | |
| 5 | + * @v: pointer to ${atomic}_t | |
| 6 | + * | |
| 7 | + * Atomically updates @v to (@v & @i) with ${desc_order} ordering. | |
| 8 | + * | |
| 9 | + * ${desc_noinstr} | |
| 10 | + * | |
| 11 | + * ${desc_return} | |
| 12 | + */ | |
| 13 | +EOF | |
| @@ -0,0 +1,13 @@ | ||
| 1 | +cat <<EOF | |
| 2 | +/** | |
| 3 | + * ${class}${atomicname}() - atomic bitwise AND NOT with ${desc_order} ordering | |
| 4 | + * @i: ${int} value | |
| 5 | + * @v: pointer to ${atomic}_t | |
| 6 | + * | |
| 7 | + * Atomically updates @v to (@v & ~@i) with ${desc_order} ordering. | |
| 8 | + * | |
| 9 | + * ${desc_noinstr} | |
| 10 | + * | |
| 11 | + * ${desc_return} | |
| 12 | + */ | |
| 13 | +EOF | |
| @@ -0,0 +1,14 @@ | ||
| 1 | +cat <<EOF | |
| 2 | +/** | |
| 3 | + * ${class}${atomicname}() - atomic compare and exchange with ${desc_order} ordering | |
| 4 | + * @v: pointer to ${atomic}_t | |
| 5 | + * @old: ${int} value to compare with | |
| 6 | + * @new: ${int} value to assign | |
| 7 | + * | |
| 8 | + * If (@v == @old), atomically updates @v to @new with ${desc_order} ordering. | |
| 9 | + * | |
| 10 | + * ${desc_noinstr} | |
| 11 | + * | |
| 12 | + * Return: The original value of @v. | |
| 13 | + */ | |
| 14 | +EOF | |
| @@ -0,0 +1,12 @@ | ||
| 1 | +cat <<EOF | |
| 2 | +/** | |
| 3 | + * ${class}${atomicname}() - atomic decrement with ${desc_order} ordering | |
| 4 | + * @v: pointer to ${atomic}_t | |
| 5 | + * | |
| 6 | + * Atomically updates @v to (@v - 1) with ${desc_order} ordering. | |
| 7 | + * | |
| 8 | + * ${desc_noinstr} | |
| 9 | + * | |
| 10 | + * ${desc_return} | |
| 11 | + */ | |
| 12 | +EOF | |
| @@ -0,0 +1,12 @@ | ||
| 1 | +cat <<EOF | |
| 2 | +/** | |
| 3 | + * ${class}${atomicname}() - atomic decrement and test if zero with ${desc_order} ordering | |
| 4 | + * @v: pointer to ${atomic}_t | |
| 5 | + * | |
| 6 | + * Atomically updates @v to (@v - 1) with ${desc_order} ordering. | |
| 7 | + * | |
| 8 | + * ${desc_noinstr} | |
| 9 | + * | |
| 10 | + * Return: @true if the resulting value of @v is zero, @false otherwise. | |
| 11 | + */ | |
| 12 | +EOF | |
| @@ -0,0 +1,12 @@ | ||
| 1 | +cat <<EOF | |
| 2 | +/** | |
| 3 | + * ${class}${atomicname}() - atomic decrement if positive with ${desc_order} ordering | |
| 4 | + * @v: pointer to ${atomic}_t | |
| 5 | + * | |
| 6 | + * If (@v > 0), atomically updates @v to (@v - 1) with ${desc_order} ordering. | |
| 7 | + * | |
| 8 | + * ${desc_noinstr} | |
| 9 | + * | |
| 10 | + * Return: The old value of (@v - 1), regardless of whether @v was updated. | |
| 11 | + */ | |
| 12 | +EOF | |
| @@ -0,0 +1,12 @@ | ||
| 1 | +cat <<EOF | |
| 2 | +/** | |
| 3 | + * ${class}${atomicname}() - atomic decrement unless positive with ${desc_order} ordering | |
| 4 | + * @v: pointer to ${atomic}_t | |
| 5 | + * | |
| 6 | + * If (@v <= 0), atomically updates @v to (@v - 1) with ${desc_order} ordering. | |
| 7 | + * | |
| 8 | + * ${desc_noinstr} | |
| 9 | + * | |
| 10 | + * Return: @true if @v was updated, @false otherwise. | |
| 11 | + */ | |
| 12 | +EOF | |
| @@ -0,0 +1,12 @@ | ||
| 1 | +cat <<EOF | |
| 2 | +/** | |
| 3 | + * ${class}${atomicname}() - atomic increment with ${desc_order} ordering | |
| 4 | + * @v: pointer to ${atomic}_t | |
| 5 | + * | |
| 6 | + * Atomically updates @v to (@v + 1) with ${desc_order} ordering. | |
| 7 | + * | |
| 8 | + * ${desc_noinstr} | |
| 9 | + * | |
| 10 | + * ${desc_return} | |
| 11 | + */ | |
| 12 | +EOF | |
| @@ -0,0 +1,12 @@ | ||
| 1 | +cat <<EOF | |
| 2 | +/** | |
| 3 | + * ${class}${atomicname}() - atomic increment and test if zero with ${desc_order} ordering | |
| 4 | + * @v: pointer to ${atomic}_t | |
| 5 | + * | |
| 6 | + * Atomically updates @v to (@v + 1) with ${desc_order} ordering. | |
| 7 | + * | |
| 8 | + * ${desc_noinstr} | |
| 9 | + * | |
| 10 | + * Return: @true if the resulting value of @v is zero, @false otherwise. | |
| 11 | + */ | |
| 12 | +EOF | |
| @@ -0,0 +1,12 @@ | ||
| 1 | +cat <<EOF | |
| 2 | +/** | |
| 3 | + * ${class}${atomicname}() - atomic increment unless zero with ${desc_order} ordering | |
| 4 | + * @v: pointer to ${atomic}_t | |
| 5 | + * | |
| 6 | + * If (@v != 0), atomically updates @v to (@v + 1) with ${desc_order} ordering. | |
| 7 | + * | |
| 8 | + * ${desc_noinstr} | |
| 9 | + * | |
| 10 | + * Return: @true if @v was updated, @false otherwise. | |
| 11 | + */ | |
| 12 | +EOF | |
| @@ -0,0 +1,12 @@ | ||
| 1 | +cat <<EOF | |
| 2 | +/** | |
| 3 | + * ${class}${atomicname}() - atomic increment unless negative with ${desc_order} ordering | |
| 4 | + * @v: pointer to ${atomic}_t | |
| 5 | + * | |
| 6 | + * If (@v >= 0), atomically updates @v to (@v + 1) with ${desc_order} ordering. | |
| 7 | + * | |
| 8 | + * ${desc_noinstr} | |
| 9 | + * | |
| 10 | + * Return: @true if @v was updated, @false otherwise. | |
| 11 | + */ | |
| 12 | +EOF | |
| @@ -0,0 +1,13 @@ | ||
| 1 | +cat <<EOF | |
| 2 | +/** | |
| 3 | + * ${class}${atomicname}() - atomic bitwise OR with ${desc_order} ordering | |
| 4 | + * @i: ${int} value | |
| 5 | + * @v: pointer to ${atomic}_t | |
| 6 | + * | |
| 7 | + * Atomically updates @v to (@v | @i) with ${desc_order} ordering. | |
| 8 | + * | |
| 9 | + * ${desc_noinstr} | |
| 10 | + * | |
| 11 | + * ${desc_return} | |
| 12 | + */ | |
| 13 | +EOF | |
| @@ -0,0 +1,12 @@ | ||
| 1 | +cat <<EOF | |
| 2 | +/** | |
| 3 | + * ${class}${atomicname}() - atomic load with ${desc_order} ordering | |
| 4 | + * @v: pointer to ${atomic}_t | |
| 5 | + * | |
| 6 | + * Atomically loads the value of @v with ${desc_order} ordering. | |
| 7 | + * | |
| 8 | + * ${desc_noinstr} | |
| 9 | + * | |
| 10 | + * Return: The value loaded from @v. | |
| 11 | + */ | |
| 12 | +EOF | |
| @@ -0,0 +1,13 @@ | ||
| 1 | +cat <<EOF | |
| 2 | +/** | |
| 3 | + * ${class}${atomicname}() - atomic set with ${desc_order} ordering | |
| 4 | + * @v: pointer to ${atomic}_t | |
| 5 | + * @i: ${int} value to assign | |
| 6 | + * | |
| 7 | + * Atomically sets @v to @i with ${desc_order} ordering. | |
| 8 | + * | |
| 9 | + * ${desc_noinstr} | |
| 10 | + * | |
| 11 | + * Return: Nothing. | |
| 12 | + */ | |
| 13 | +EOF | |
| @@ -0,0 +1,13 @@ | ||
| 1 | +cat <<EOF | |
| 2 | +/** | |
| 3 | + * ${class}${atomicname}() - atomic subtract with ${desc_order} ordering | |
| 4 | + * @i: ${int} value to subtract | |
| 5 | + * @v: pointer to ${atomic}_t | |
| 6 | + * | |
| 7 | + * Atomically updates @v to (@v - @i) with ${desc_order} ordering. | |
| 8 | + * | |
| 9 | + * ${desc_noinstr} | |
| 10 | + * | |
| 11 | + * ${desc_return} | |
| 12 | + */ | |
| 13 | +EOF | |
| @@ -0,0 +1,13 @@ | ||
| 1 | +cat <<EOF | |
| 2 | +/** | |
| 3 | + * ${class}${atomicname}() - atomic subtract and test if zero with ${desc_order} ordering | |
| 4 | + * @i: ${int} value to add | |
| 5 | + * @v: pointer to ${atomic}_t | |
| 6 | + * | |
| 7 | + * Atomically updates @v to (@v - @i) with ${desc_order} ordering. | |
| 8 | + * | |
| 9 | + * ${desc_noinstr} | |
| 10 | + * | |
| 11 | + * Return: @true if the resulting value of @v is zero, @false otherwise. | |
| 12 | + */ | |
| 13 | +EOF | |
| @@ -0,0 +1,15 @@ | ||
| 1 | +cat <<EOF | |
| 2 | +/** | |
| 3 | + * ${class}${atomicname}() - atomic compare and exchange with ${desc_order} ordering | |
| 4 | + * @v: pointer to ${atomic}_t | |
| 5 | + * @old: pointer to ${int} value to compare with | |
| 6 | + * @new: ${int} value to assign | |
| 7 | + * | |
| 8 | + * If (@v == @old), atomically updates @v to @new with ${desc_order} ordering. | |
| 9 | + * Otherwise, updates @old to the current value of @v. | |
| 10 | + * | |
| 11 | + * ${desc_noinstr} | |
| 12 | + * | |
| 13 | + * Return: @true if the exchange occured, @false otherwise. | |
| 14 | + */ | |
| 15 | +EOF | |
| @@ -0,0 +1,13 @@ | ||
| 1 | +cat <<EOF | |
| 2 | +/** | |
| 3 | + * ${class}${atomicname}() - atomic exchange with ${desc_order} ordering | |
| 4 | + * @v: pointer to ${atomic}_t | |
| 5 | + * @new: ${int} value to assign | |
| 6 | + * | |
| 7 | + * Atomically updates @v to @new with ${desc_order} ordering. | |
| 8 | + * | |
| 9 | + * ${desc_noinstr} | |
| 10 | + * | |
| 11 | + * Return: The original value of @v. | |
| 12 | + */ | |
| 13 | +EOF | |
| @@ -0,0 +1,13 @@ | ||
| 1 | +cat <<EOF | |
| 2 | +/** | |
| 3 | + * ${class}${atomicname}() - atomic bitwise XOR with ${desc_order} ordering | |
| 4 | + * @i: ${int} value | |
| 5 | + * @v: pointer to ${atomic}_t | |
| 6 | + * | |
| 7 | + * Atomically updates @v to (@v ^ @i) with ${desc_order} ordering. | |
| 8 | + * | |
| 9 | + * ${desc_noinstr} | |
| 10 | + * | |
| 11 | + * ${desc_return} | |
| 12 | + */ | |
| 13 | +EOF | |
| @@ -64,7 +64,7 @@ my $type_constant = '\b``([^\`]+)``\b'; · 63 unmodified lines | ||
| 64 | 64 | my $type_constant2 = '\%([-_\w]+)'; |
| 65 | 65 | my $type_func = '(\w+)\(\)'; |
| 66 | 66 | my $type_param = '\@(\w*((\.\w+)|(->\w+))*(\.\.\.)?)'; |
| 67 | −my $type_param_ref = '([\!]?)\@(\w*((\.\w+)|(->\w+))*(\.\.\.)?)'; | |
| 67 | +my $type_param_ref = '([\!~]?)\@(\w*((\.\w+)|(->\w+))*(\.\.\.)?)'; | |
| 68 | 68 | my $type_fp_param = '\@(\w+)\(\)'; # Special RST handling for func ptr params |
| 69 | 69 | my $type_fp_param2 = '\@(\w+->\S+)\(\)'; # Special RST handling for structs with func ptr params |
| 70 | 70 | my $type_env = '(\$\w+)'; |
| @@ -17,7 +17,11 @@ binutils) · 16 unmodified lines | ||
| 17 | 17 | echo 2.25.0 |
| 18 | 18 | ;; |
| 19 | 19 | gcc) |
| 20 | − echo 5.1.0 | |
| 20 | + if [ "$SRCARCH" = parisc ]; then | |
| 21 | + echo 11.0.0 | |
| 22 | + else | |
| 23 | + echo 5.1.0 | |
| 24 | + fi | |
| 21 | 25 | ;; |
| 22 | 26 | llvm) |
| 23 | 27 | if [ "$SRCARCH" = s390 ]; then |