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 | meta_in "$1" "BFIR" | 36 | meta_in "$1" "BFIR" |
| 37 | } | 37 | } |
| 38 | 38 | ||
| 39 | #find_fallback_template(pfx, name, sfx, order) | 39 | #meta_is_implicitly_relaxed(meta) |
| 40 | find_fallback_template() | 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 | local pfx="$1"; shift | 49 | local pfx="$1"; shift |
| 43 | local name="$1"; shift | 50 | local name="$1"; shift |
| 44 | local sfx="$1"; shift | 51 | local sfx="$1"; shift |
| @@ -52,8 +59,8 @@ find_fallback_template() · 7 unmodified lines | |||
| 52 | # | 59 | # |
| 53 | # Start at the most specific, and fall back to the most general. Once | 60 | # Start at the most specific, and fall back to the most general. Once |
| 54 | # we find a specific fallback, don't bother looking for more. | 61 | # we find a specific fallback, don't bother looking for more. |
| 55 | for base in "${pfx}${name}${sfx}${order}" "${name}"; do | 62 | for base in "${pfx}${name}${sfx}${order}" "${pfx}${name}${sfx}" "${name}"; do |
| 56 | file="${ATOMICDIR}/fallbacks/${base}" | 63 | file="${ATOMICDIR}/${tmpltype}/${base}" |
| 57 | 64 | ||
| 58 | if [ -f "${file}" ]; then | 65 | if [ -f "${file}" ]; then |
| 59 | printf "${file}" | 66 | printf "${file}" |
| @@ -62,6 +69,18 @@ find_fallback_template() · 2 unmodified lines | |||
| 62 | done | 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 | #gen_ret_type(meta, int) | 84 | #gen_ret_type(meta, int) |
| 66 | gen_ret_type() { | 85 | gen_ret_type() { |
| 67 | local meta="$1"; shift | 86 | local meta="$1"; shift |
| @@ -142,6 +161,91 @@ gen_args() · 74 unmodified lines | |||
| 142 | done | 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 | #gen_proto_order_variants(meta, pfx, name, sfx, ...) | 249 | #gen_proto_order_variants(meta, pfx, name, sfx, ...) |
| 146 | gen_proto_order_variants() | 250 | gen_proto_order_variants() |
| 147 | { | 251 | { |
| @@ -27,7 +27,7 @@ and vF i v · 26 unmodified lines | |||
| 27 | andnot vF i v | 27 | andnot vF i v |
| 28 | or vF i v | 28 | or vF i v |
| 29 | xor vF i v | 29 | xor vF i v |
| 30 | xchg I v i | 30 | xchg I v i:new |
| 31 | cmpxchg I v i:old i:new | 31 | cmpxchg I v i:old i:new |
| 32 | try_cmpxchg B v p:old i:new | 32 | try_cmpxchg B v p:old i:new |
| 33 | sub_and_test b i v | 33 | sub_and_test b i v |
| @@ -1,9 +1,5 @@ | |||
| 1 | cat <<EOF | 1 | cat <<EOF |
| 2 | static __always_inline ${ret} | ||
| 3 | arch_${atomic}_${pfx}${name}${sfx}_acquire(${params}) | ||
| 4 | { | ||
| 5 | ${ret} ret = arch_${atomic}_${pfx}${name}${sfx}_relaxed(${args}); | 2 | ${ret} ret = arch_${atomic}_${pfx}${name}${sfx}_relaxed(${args}); |
| 6 | __atomic_acquire_fence(); | 3 | __atomic_acquire_fence(); |
| 7 | return ret; | 4 | return ret; |
| 8 | } | ||
| 9 | EOF | 5 | EOF |
| @@ -1,15 +1,3 @@ | |||
| 1 | cat <<EOF | 1 | cat <<EOF |
| 2 | /** | 2 | return raw_${atomic}_add_return${order}(i, v) < 0; |
| 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 | } | ||
| 15 | EOF | 3 | EOF |
| @@ -1,16 +1,3 @@ | |||
| 1 | cat << EOF | 1 | cat << EOF |
| 2 | /** | 2 | return raw_${atomic}_fetch_add_unless(v, a, u) != u; |
| 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 | } | ||
| 16 | EOF | 3 | EOF |
| @@ -1,7 +1,3 @@ | |||
| 1 | cat <<EOF | 1 | cat <<EOF |
| 2 | static __always_inline ${ret} | 2 | ${retstmt}raw_${atomic}_${pfx}and${sfx}${order}(~i, v); |
| 3 | arch_${atomic}_${pfx}andnot${sfx}${order}(${int} i, ${atomic}_t *v) | ||
| 4 | { | ||
| 5 | ${retstmt}arch_${atomic}_${pfx}and${sfx}${order}(~i, v); | ||
| 6 | } | ||
| 7 | EOF | 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 | cat <<EOF | 1 | cat <<EOF |
| 2 | static __always_inline ${ret} | 2 | ${retstmt}raw_${atomic}_${pfx}sub${sfx}${order}(1, v); |
| 3 | arch_${atomic}_${pfx}dec${sfx}${order}(${atomic}_t *v) | ||
| 4 | { | ||
| 5 | ${retstmt}arch_${atomic}_${pfx}sub${sfx}${order}(1, v); | ||
| 6 | } | ||
| 7 | EOF | 3 | EOF |
| @@ -1,15 +1,3 @@ | |||
| 1 | cat <<EOF | 1 | cat <<EOF |
| 2 | /** | 2 | return raw_${atomic}_dec_return(v) == 0; |
| 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 | } | ||
| 15 | EOF | 3 | EOF |
| @@ -1,15 +1,11 @@ | |||
| 1 | cat <<EOF | 1 | cat <<EOF |
| 2 | static __always_inline ${ret} | 2 | ${int} dec, c = raw_${atomic}_read(v); |
| 3 | arch_${atomic}_dec_if_positive(${atomic}_t *v) | ||
| 4 | { | ||
| 5 | ${int} dec, c = arch_${atomic}_read(v); | ||
| 6 | 3 | ||
| 7 | do { | 4 | do { |
| 8 | dec = c - 1; | 5 | dec = c - 1; |
| 9 | if (unlikely(dec < 0)) | 6 | if (unlikely(dec < 0)) |
| 10 | break; | 7 | break; |
| 11 | } while (!arch_${atomic}_try_cmpxchg(v, &c, dec)); | 8 | } while (!raw_${atomic}_try_cmpxchg(v, &c, dec)); |
| 12 | 9 | ||
| 13 | return dec; | 10 | return dec; |
| 14 | } | ||
| 15 | EOF | 11 | EOF |
| @@ -1,14 +1,10 @@ | |||
| 1 | cat <<EOF | 1 | cat <<EOF |
| 2 | static __always_inline bool | 2 | ${int} c = raw_${atomic}_read(v); |
| 3 | arch_${atomic}_dec_unless_positive(${atomic}_t *v) | ||
| 4 | { | ||
| 5 | ${int} c = arch_${atomic}_read(v); | ||
| 6 | 3 | ||
| 7 | do { | 4 | do { |
| 8 | if (unlikely(c > 0)) | 5 | if (unlikely(c > 0)) |
| 9 | return false; | 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 | return true; | 9 | return true; |
| 13 | } | ||
| 14 | EOF | 10 | EOF |
| @@ -1,11 +1,7 @@ | |||
| 1 | cat <<EOF | 1 | cat <<EOF |
| 2 | static __always_inline ${ret} | ||
| 3 | arch_${atomic}_${pfx}${name}${sfx}(${params}) | ||
| 4 | { | ||
| 5 | ${ret} ret; | 2 | ${ret} ret; |
| 6 | __atomic_pre_full_fence(); | 3 | __atomic_pre_full_fence(); |
| 7 | ret = arch_${atomic}_${pfx}${name}${sfx}_relaxed(${args}); | 4 | ret = arch_${atomic}_${pfx}${name}${sfx}_relaxed(${args}); |
| 8 | __atomic_post_full_fence(); | 5 | __atomic_post_full_fence(); |
| 9 | return ret; | 6 | return ret; |
| 10 | } | ||
| 11 | EOF | 7 | EOF |
| @@ -1,23 +1,10 @@ | |||
| 1 | cat << EOF | 1 | cat << EOF |
| 2 | /** | 2 | ${int} c = raw_${atomic}_read(v); |
| 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); | ||
| 15 | 3 | ||
| 16 | do { | 4 | do { |
| 17 | if (unlikely(c == u)) | 5 | if (unlikely(c == u)) |
| 18 | break; | 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 | return c; | 9 | return c; |
| 22 | } | ||
| 23 | EOF | 10 | EOF |
| @@ -1,7 +1,3 @@ | |||
| 1 | cat <<EOF | 1 | cat <<EOF |
| 2 | static __always_inline ${ret} | 2 | ${retstmt}raw_${atomic}_${pfx}add${sfx}${order}(1, v); |
| 3 | arch_${atomic}_${pfx}inc${sfx}${order}(${atomic}_t *v) | ||
| 4 | { | ||
| 5 | ${retstmt}arch_${atomic}_${pfx}add${sfx}${order}(1, v); | ||
| 6 | } | ||
| 7 | EOF | 3 | EOF |
| @@ -1,15 +1,3 @@ | |||
| 1 | cat <<EOF | 1 | cat <<EOF |
| 2 | /** | 2 | return raw_${atomic}_inc_return(v) == 0; |
| 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 | } | ||
| 15 | EOF | 3 | EOF |
| @@ -1,14 +1,3 @@ | |||
| 1 | cat <<EOF | 1 | cat <<EOF |
| 2 | /** | 2 | return raw_${atomic}_add_unless(v, 1, 0); |
| 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 | } | ||
| 14 | EOF | 3 | EOF |
| @@ -1,14 +1,10 @@ | |||
| 1 | cat <<EOF | 1 | cat <<EOF |
| 2 | static __always_inline bool | 2 | ${int} c = raw_${atomic}_read(v); |
| 3 | arch_${atomic}_inc_unless_negative(${atomic}_t *v) | ||
| 4 | { | ||
| 5 | ${int} c = arch_${atomic}_read(v); | ||
| 6 | 3 | ||
| 7 | do { | 4 | do { |
| 8 | if (unlikely(c < 0)) | 5 | if (unlikely(c < 0)) |
| 9 | return false; | 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 | return true; | 9 | return true; |
| 13 | } | ||
| 14 | EOF | 10 | EOF |
| @@ -1,16 +1,12 @@ | |||
| 1 | cat <<EOF | 1 | cat <<EOF |
| 2 | static __always_inline ${ret} | ||
| 3 | arch_${atomic}_read_acquire(const ${atomic}_t *v) | ||
| 4 | { | ||
| 5 | ${int} ret; | 2 | ${int} ret; |
| 6 | 3 | ||
| 7 | if (__native_word(${atomic}_t)) { | 4 | if (__native_word(${atomic}_t)) { |
| 8 | ret = smp_load_acquire(&(v)->counter); | 5 | ret = smp_load_acquire(&(v)->counter); |
| 9 | } else { | 6 | } else { |
| 10 | ret = arch_${atomic}_read(v); | 7 | ret = raw_${atomic}_read(v); |
| 11 | __atomic_acquire_fence(); | 8 | __atomic_acquire_fence(); |
| 12 | } | 9 | } |
| 13 | 10 | ||
| 14 | return ret; | 11 | return ret; |
| 15 | } | ||
| 16 | EOF | 12 | EOF |
| @@ -1,8 +1,4 @@ | |||
| 1 | cat <<EOF | 1 | cat <<EOF |
| 2 | static __always_inline ${ret} | ||
| 3 | arch_${atomic}_${pfx}${name}${sfx}_release(${params}) | ||
| 4 | { | ||
| 5 | __atomic_release_fence(); | 2 | __atomic_release_fence(); |
| 6 | ${retstmt}arch_${atomic}_${pfx}${name}${sfx}_relaxed(${args}); | 3 | ${retstmt}arch_${atomic}_${pfx}${name}${sfx}_relaxed(${args}); |
| 7 | } | ||
| 8 | EOF | 4 | EOF |
| @@ -1,12 +1,8 @@ | |||
| 1 | cat <<EOF | 1 | cat <<EOF |
| 2 | static __always_inline void | ||
| 3 | arch_${atomic}_set_release(${atomic}_t *v, ${int} i) | ||
| 4 | { | ||
| 5 | if (__native_word(${atomic}_t)) { | 2 | if (__native_word(${atomic}_t)) { |
| 6 | smp_store_release(&(v)->counter, i); | 3 | smp_store_release(&(v)->counter, i); |
| 7 | } else { | 4 | } else { |
| 8 | __atomic_release_fence(); | 5 | __atomic_release_fence(); |
| 9 | arch_${atomic}_set(v, i); | 6 | raw_${atomic}_set(v, i); |
| 10 | } | 7 | } |
| 11 | } | ||
| 12 | EOF | 8 | EOF |
| @@ -1,16 +1,3 @@ | |||
| 1 | cat <<EOF | 1 | cat <<EOF |
| 2 | /** | 2 | return raw_${atomic}_sub_return(i, v) == 0; |
| 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 | } | ||
| 16 | EOF | 3 | EOF |
| @@ -1,11 +1,7 @@ | |||
| 1 | cat <<EOF | 1 | cat <<EOF |
| 2 | static __always_inline bool | ||
| 3 | arch_${atomic}_try_cmpxchg${order}(${atomic}_t *v, ${int} *old, ${int} new) | ||
| 4 | { | ||
| 5 | ${int} r, o = *old; | 2 | ${int} r, o = *old; |
| 6 | r = arch_${atomic}_cmpxchg${order}(v, o, new); | 3 | r = raw_${atomic}_cmpxchg${order}(v, o, new); |
| 7 | if (unlikely(r != o)) | 4 | if (unlikely(r != o)) |
| 8 | *old = r; | 5 | *old = r; |
| 9 | return likely(r == o); | 6 | return likely(r == o); |
| 10 | } | ||
| 11 | EOF | 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 | local atomic="$1"; shift | 17 | local atomic="$1"; shift |
| 18 | local int="$1"; shift | 18 | local int="$1"; shift |
| 19 | 19 | ||
| 20 | local atomicname="arch_${atomic}_${pfx}${name}${sfx}${order}" | ||
| 21 | |||
| 22 | local ret="$(gen_ret_type "${meta}" "${int}")" | 20 | local ret="$(gen_ret_type "${meta}" "${int}")" |
| 23 | local retstmt="$(gen_ret_stmt "${meta}")" | 21 | local retstmt="$(gen_ret_stmt "${meta}")" |
| 24 | local params="$(gen_params "${int}" "${atomic}" "$@")" | 22 | local params="$(gen_params "${int}" "${atomic}" "$@")" |
| 25 | local args="$(gen_args "$@")" | 23 | local args="$(gen_args "$@")" |
| 26 | 24 | ||
| 27 | if [ ! -z "${template}" ]; then | 25 | . ${template} |
| 28 | printf "#ifndef ${atomicname}\n" | ||
| 29 | . ${template} | ||
| 30 | printf "#define ${atomicname} ${atomicname}\n" | ||
| 31 | printf "#endif\n\n" | ||
| 32 | fi | ||
| 33 | } | 26 | } |
| 34 | 27 | ||
| 35 | #gen_proto_fallback(meta, pfx, name, sfx, order, atomic, int, args...) | 28 | #gen_order_fallback(meta, pfx, name, sfx, order, atomic, int, args...) |
| 36 | gen_proto_fallback() | 29 | gen_order_fallback() |
| 37 | { | 30 | { |
| 38 | local meta="$1"; shift | 31 | local meta="$1"; shift |
| 39 | local pfx="$1"; shift | 32 | local pfx="$1"; shift |
| @@ -41,87 +34,124 @@ gen_proto_fallback() · 1 unmodified line | |||
| 41 | local sfx="$1"; shift | 34 | local sfx="$1"; shift |
| 42 | local order="$1"; shift | 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 | gen_template_fallback "${tmpl}" "${meta}" "${pfx}" "${name}" "${sfx}" "${order}" "$@" | 39 | gen_template_fallback "${tmpl}" "${meta}" "${pfx}" "${name}" "${sfx}" "${order}" "$@" |
| 46 | } | 40 | } |
| 47 | 41 | ||
| 48 | #gen_basic_fallbacks(basename) | 42 | #gen_proto_fallback(meta, pfx, name, sfx, order, atomic, int, args...) |
| 49 | gen_basic_fallbacks() | 43 | gen_proto_fallback() |
| 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() | ||
| 60 | { | 44 | { |
| 61 | local meta="$1"; shift | 45 | local meta="$1"; shift |
| 62 | local pfx="$1"; shift | 46 | local pfx="$1"; shift |
| 63 | local name="$1"; shift | 47 | local name="$1"; shift |
| 64 | local sfx="$1"; shift | 48 | local sfx="$1"; shift |
| 65 | local order="$1"; shift | 49 | local order="$1"; shift |
| 66 | local atomic="$1" | ||
| 67 | 50 | ||
| 68 | local basename="arch_${atomic}_${pfx}${name}${sfx}" | 51 | local tmpl="$(find_fallback_template "${pfx}" "${name}" "${sfx}" "${order}")" |
| 69 | 52 | gen_template_fallback "${tmpl}" "${meta}" "${pfx}" "${name}" "${sfx}" "${order}" "$@" | |
| 70 | printf "#define ${basename}${order} ${basename}${order}\n" | ||
| 71 | } | 53 | } |
| 72 | 54 | ||
| 73 | #gen_proto_order_variants(meta, pfx, name, sfx, atomic, int, args...) | 55 | #gen_proto_order_variant(meta, pfx, name, sfx, order, atomic, int, args...) |
| 74 | gen_proto_order_variants() | 56 | gen_proto_order_variant() |
| 75 | { | 57 | { |
| 76 | local meta="$1"; shift | 58 | local meta="$1"; shift |
| 77 | local pfx="$1"; shift | 59 | local pfx="$1"; shift |
| 78 | local name="$1"; shift | 60 | local name="$1"; shift |
| 79 | local sfx="$1"; shift | 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 | local template="$(find_fallback_template "${pfx}" "${name}" "${sfx}" "${order}")" | 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 | 71 | local ret="$(gen_ret_type "${meta}" "${int}")" |
| 87 | # read_acquire and set_release need to be templated, though | 72 | local retstmt="$(gen_ret_stmt "${meta}")" |
| 88 | if ! meta_has_relaxed "${meta}"; then | 73 | local params="$(gen_params "${int}" "${atomic}" "$@")" |
| 89 | gen_proto_fallback "${meta}" "${pfx}" "${name}" "${sfx}" "" "$@" | 74 | local args="$(gen_args "$@")" |
| 90 | 75 | ||
| 91 | if meta_has_acquire "${meta}"; then | 76 | gen_kerneldoc "raw_" "${meta}" "${pfx}" "${name}" "${sfx}" "${order}" "${atomic}" "${int}" "$@" |
| 92 | gen_proto_fallback "${meta}" "${pfx}" "${name}" "${sfx}" "_acquire" "$@" | 77 | |
| 93 | fi | 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 | 95 | printf "#if defined(arch_${atomicname})\n" |
| 96 | gen_proto_fallback "${meta}" "${pfx}" "${name}" "${sfx}" "_release" "$@" | 96 | printf "\t${retstmt}arch_${atomicname}(${args});\n" |
| 97 | fi | ||
| 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 | fi | 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 | if [ ! -z "${template}" ]; then | 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 | fi | 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 | 121 | |
| 111 | printf "#endif /* ${basename} */\n\n" | 122 | #gen_proto_order_variants(meta, pfx, name, sfx, atomic, int, args...) |
| 112 | gen_proto_fallback "${meta}" "${pfx}" "${name}" "${sfx}" "" "$@" | 123 | gen_proto_order_variants() |
| 113 | gen_proto_fallback "${meta}" "${pfx}" "${name}" "${sfx}" "_acquire" "$@" | 124 | { |
| 114 | gen_proto_fallback "${meta}" "${pfx}" "${name}" "${sfx}" "_release" "$@" | 125 | local meta="$1"; shift |
| 115 | gen_proto_fallback "${meta}" "${pfx}" "${name}" "${sfx}" "_relaxed" "$@" | 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 | fi | 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" "$@" | 141 | if meta_has_relaxed "${meta}"; then |
| 121 | gen_template_fallback "${ATOMICDIR}/fallbacks/release" "${meta}" "${pfx}" "${name}" "${sfx}" "_release" "$@" | 142 | gen_proto_order_variant "${meta}" "${pfx}" "${name}" "${sfx}" "_relaxed" "$@" |
| 122 | gen_template_fallback "${ATOMICDIR}/fallbacks/fence" "${meta}" "${pfx}" "${name}" "${sfx}" "" "$@" | 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 | gen_order_fallbacks() | 157 | gen_order_fallbacks() |
| @@ -130,36 +160,65 @@ gen_order_fallbacks() · 2 unmodified lines | |||
| 130 | 160 | ||
| 131 | cat <<EOF | 161 | cat <<EOF |
| 132 | 162 | ||
| 133 | #ifndef ${xchg}_acquire | 163 | #define raw_${xchg}_relaxed arch_${xchg}_relaxed |
| 134 | #define ${xchg}_acquire(...) \\ | 164 | |
| 135 | __atomic_op_acquire(${xchg}, __VA_ARGS__) | 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 | #endif | 170 | #endif |
| 137 | 171 | ||
| 138 | #ifndef ${xchg}_release | 172 | #ifdef arch_${xchg}_release |
| 139 | #define ${xchg}_release(...) \\ | 173 | #define raw_${xchg}_release arch_${xchg}_release |
| 140 | __atomic_op_release(${xchg}, __VA_ARGS__) | 174 | #else |
| 175 | #define raw_${xchg}_release(...) \\ | ||
| 176 | __atomic_op_release(arch_${xchg}, __VA_ARGS__) | ||
| 141 | #endif | 177 | #endif |
| 142 | 178 | ||
| 143 | #ifndef ${xchg} | 179 | #ifdef arch_${xchg} |
| 144 | #define ${xchg}(...) \\ | 180 | #define raw_${xchg} arch_${xchg} |
| 145 | __atomic_op_fence(${xchg}, __VA_ARGS__) | 181 | #else |
| 182 | #define raw_${xchg}(...) \\ | ||
| 183 | __atomic_op_fence(arch_${xchg}, __VA_ARGS__) | ||
| 146 | #endif | 184 | #endif |
| 147 | 185 | ||
| 148 | EOF | 186 | EOF |
| 149 | } | 187 | } |
| 150 | 188 | ||
| 151 | gen_xchg_fallbacks() | 189 | gen_xchg_order_fallback() |
| 152 | { | 190 | { |
| 153 | local xchg="$1"; shift | 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 | gen_try_cmpxchg_fallback() | 224 | gen_try_cmpxchg_fallback() |
| @@ -168,40 +227,61 @@ gen_try_cmpxchg_fallback() · 2 unmodified lines | |||
| 168 | local order="$1"; shift; | 227 | local order="$1"; shift; |
| 169 | 228 | ||
| 170 | cat <<EOF | 229 | cat <<EOF |
| 171 | #ifndef arch_try_${cmpxchg}${order} | 230 | #define raw_try_${cmpxchg}${order}(_ptr, _oldp, _new) \\ |
| 172 | #define arch_try_${cmpxchg}${order}(_ptr, _oldp, _new) \\ | ||
| 173 | ({ \\ | 231 | ({ \\ |
| 174 | typeof(*(_ptr)) *___op = (_oldp), ___o = *___op, ___r; \\ | 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 | if (unlikely(___r != ___o)) \\ | 234 | if (unlikely(___r != ___o)) \\ |
| 177 | *___op = ___r; \\ | 235 | *___op = ___r; \\ |
| 178 | likely(___r == ___o); \\ | 236 | likely(___r == ___o); \\ |
| 179 | }) | 237 | }) |
| 180 | #endif /* arch_try_${cmpxchg}${order} */ | ||
| 181 | |||
| 182 | EOF | 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" | 247 | printf "#if defined(arch_try_${cmpxchg}${order})\n" |
| 190 | printf "#ifdef arch_try_${cmpxchg}\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 | for order in "" "_acquire" "_release" "_relaxed"; do | 270 | for order in "" "_acquire" "_release" "_relaxed"; do |
| 197 | gen_try_cmpxchg_fallback "${cmpxchg}" "${order}" | 271 | gen_try_cmpxchg_order_fallback "${cmpxchg}" "${order}" |
| 198 | done | 272 | done |
| 273 | } | ||
| 199 | 274 | ||
| 200 | printf "#else /* arch_try_${cmpxchg}_relaxed */\n" | 275 | gen_cmpxchg_local_fallbacks() |
| 201 | 276 | { | |
| 202 | gen_order_fallbacks "arch_try_${cmpxchg}" | 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 | cat << EOF | 287 | cat << EOF |
| @@ -217,16 +297,20 @@ cat << EOF · 9 unmodified lines | |||
| 217 | 297 | ||
| 218 | EOF | 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 | gen_xchg_fallbacks "${xchg}" | 301 | gen_xchg_fallbacks "${xchg}" |
| 222 | done | 302 | done |
| 223 | 303 | ||
| 224 | for cmpxchg in "cmpxchg" "cmpxchg64"; do | 304 | for cmpxchg in "cmpxchg" "cmpxchg64" "cmpxchg128"; do |
| 225 | gen_try_cmpxchg_fallbacks "${cmpxchg}" | 305 | gen_try_cmpxchg_fallbacks "${cmpxchg}" |
| 226 | done | 306 | done |
| 227 | 307 | ||
| 228 | for cmpxchg in "cmpxchg_local" "cmpxchg64_local"; do | 308 | for cmpxchg in "cmpxchg_local" "cmpxchg64_local" "cmpxchg128_local"; do |
| 229 | gen_try_cmpxchg_fallback "${cmpxchg}" "" | 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 | done | 314 | done |
| 231 | 315 | ||
| 232 | grep '^[a-z]' "$1" | while read name meta args; do | 316 | grep '^[a-z]' "$1" | while read name meta args; do |
| @@ -68,12 +68,14 @@ gen_proto_order_variant() · 67 unmodified lines | |||
| 68 | local args="$(gen_args "$@")" | 68 | local args="$(gen_args "$@")" |
| 69 | local retstmt="$(gen_ret_stmt "${meta}")" | 69 | local retstmt="$(gen_ret_stmt "${meta}")" |
| 70 | 70 | ||
| 71 | gen_kerneldoc "" "${meta}" "${pfx}" "${name}" "${sfx}" "${order}" "${atomic}" "${int}" "$@" | ||
| 72 | |||
| 71 | cat <<EOF | 73 | cat <<EOF |
| 72 | static __always_inline ${ret} | 74 | static __always_inline ${ret} |
| 73 | ${atomicname}(${params}) | 75 | ${atomicname}(${params}) |
| 74 | { | 76 | { |
| 75 | ${checks} | 77 | ${checks} |
| 76 | ${retstmt}arch_${atomicname}(${args}); | 78 | ${retstmt}raw_${atomicname}(${args}); |
| 77 | } | 79 | } |
| 78 | EOF | 80 | EOF |
| 79 | 81 | ||
| @@ -84,7 +86,6 @@ gen_xchg() · 4 unmodified lines | |||
| 84 | { | 86 | { |
| 85 | local xchg="$1"; shift | 87 | local xchg="$1"; shift |
| 86 | local order="$1"; shift | 88 | local order="$1"; shift |
| 87 | local mult="$1"; shift | ||
| 88 | 89 | ||
| 89 | kcsan_barrier="" | 90 | kcsan_barrier="" |
| 90 | if [ "${xchg%_local}" = "${xchg}" ]; then | 91 | if [ "${xchg%_local}" = "${xchg}" ]; then |
| @@ -104,9 +105,9 @@ cat <<EOF · 13 unmodified lines | |||
| 104 | EOF | 105 | EOF |
| 105 | [ -n "$kcsan_barrier" ] && printf "\t${kcsan_barrier}; \\\\\n" | 106 | [ -n "$kcsan_barrier" ] && printf "\t${kcsan_barrier}; \\\\\n" |
| 106 | cat <<EOF | 107 | cat <<EOF |
| 107 | instrument_atomic_read_write(__ai_ptr, ${mult}sizeof(*__ai_ptr)); \\ | 108 | instrument_atomic_read_write(__ai_ptr, sizeof(*__ai_ptr)); \\ |
| 108 | instrument_read_write(__ai_oldp, ${mult}sizeof(*__ai_oldp)); \\ | 109 | instrument_read_write(__ai_oldp, sizeof(*__ai_oldp)); \\ |
| 109 | arch_${xchg}${order}(__ai_ptr, __ai_oldp, __VA_ARGS__); \\ | 110 | raw_${xchg}${order}(__ai_ptr, __ai_oldp, __VA_ARGS__); \\ |
| 110 | }) | 111 | }) |
| 111 | EOF | 112 | EOF |
| 112 | 113 | ||
| @@ -119,8 +120,8 @@ cat <<EOF · 6 unmodified lines | |||
| 119 | EOF | 120 | EOF |
| 120 | [ -n "$kcsan_barrier" ] && printf "\t${kcsan_barrier}; \\\\\n" | 121 | [ -n "$kcsan_barrier" ] && printf "\t${kcsan_barrier}; \\\\\n" |
| 121 | cat <<EOF | 122 | cat <<EOF |
| 122 | instrument_atomic_read_write(__ai_ptr, ${mult}sizeof(*__ai_ptr)); \\ | 123 | instrument_atomic_read_write(__ai_ptr, sizeof(*__ai_ptr)); \\ |
| 123 | arch_${xchg}${order}(__ai_ptr, __VA_ARGS__); \\ | 124 | raw_${xchg}${order}(__ai_ptr, __VA_ARGS__); \\ |
| 124 | }) | 125 | }) |
| 125 | EOF | 126 | EOF |
| 126 | 127 | ||
| @@ -134,15 +135,10 @@ cat << EOF · 7 unmodified lines | |||
| 134 | // DO NOT MODIFY THIS FILE DIRECTLY | 135 | // DO NOT MODIFY THIS FILE DIRECTLY |
| 135 | 136 | ||
| 136 | /* | 137 | /* |
| 137 | * This file provides wrappers with KASAN instrumentation for atomic operations. | 138 | * This file provoides atomic operations with explicit instrumentation (e.g. |
| 138 | * To use this functionality an arch's atomic.h file needs to define all | 139 | * KASAN, KCSAN), which should be used unless it is necessary to avoid |
| 139 | * atomic operations with arch_ prefix (e.g. arch_atomic_read()) and include | 140 | * instrumentation. Where it is necessary to aovid instrumenation, the |
| 140 | * this file at the end. This file provides atomic_read() that forwards to | 141 | * raw_atomic*() operations should be used. |
| 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. | ||
| 146 | */ | 142 | */ |
| 147 | #ifndef _LINUX_ATOMIC_INSTRUMENTED_H | 143 | #ifndef _LINUX_ATOMIC_INSTRUMENTED_H |
| 148 | #define _LINUX_ATOMIC_INSTRUMENTED_H | 144 | #define _LINUX_ATOMIC_INSTRUMENTED_H |
| @@ -166,24 +162,18 @@ grep '^[a-z]' "$1" | while read name meta args; do · 17 unmodified lines | |||
| 166 | done | 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 | for order in "" "_acquire" "_release" "_relaxed"; do | 166 | for order in "" "_acquire" "_release" "_relaxed"; do |
| 171 | gen_xchg "${xchg}" "${order}" "" | 167 | gen_xchg "${xchg}" "${order}" |
| 172 | printf "\n" | 168 | printf "\n" |
| 173 | done | 169 | done |
| 174 | done | 170 | done |
| 175 | 171 | ||
| 176 | for xchg in "cmpxchg_local" "cmpxchg64_local" "sync_cmpxchg" "try_cmpxchg_local" "try_cmpxchg64_local" ; do | 172 | for xchg in "cmpxchg_local" "cmpxchg64_local" "cmpxchg128_local" "sync_cmpxchg" "try_cmpxchg_local" "try_cmpxchg64_local" "try_cmpxchg128_local"; do |
| 177 | gen_xchg "${xchg}" "" "" | 173 | gen_xchg "${xchg}" "" |
| 178 | printf "\n" | 174 | printf "\n" |
| 179 | done | 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 | cat <<EOF | 177 | cat <<EOF |
| 188 | 178 | ||
| 189 | #endif /* _LINUX_ATOMIC_INSTRUMENTED_H */ | 179 | #endif /* _LINUX_ATOMIC_INSTRUMENTED_H */ |
| @@ -32,24 +32,34 @@ gen_args_cast() · 31 unmodified lines | |||
| 32 | done | 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 | gen_proto_order_variant() | 36 | gen_proto_order_variant() |
| 37 | { | 37 | { |
| 38 | local meta="$1"; shift | 38 | local meta="$1"; shift |
| 39 | local name="$1$2$3$4"; shift; shift; shift; shift | 39 | local pfx="$1"; shift |
| 40 | local atomic="$1"; shift | 40 | local name="$1"; shift |
| 41 | local int="$1"; shift | 41 | local sfx="$1"; shift |
| 42 | local order="$1"; shift | ||
| 43 | |||
| 44 | local atomicname="${pfx}${name}${sfx}${order}" | ||
| 42 | 45 | ||
| 43 | local ret="$(gen_ret_type "${meta}" "long")" | 46 | local ret="$(gen_ret_type "${meta}" "long")" |
| 44 | local params="$(gen_params "long" "atomic_long" "$@")" | 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 | local retstmt="$(gen_ret_stmt "${meta}")" | 50 | local retstmt="$(gen_ret_stmt "${meta}")" |
| 47 | 51 | ||
| 52 | gen_kerneldoc "raw_" "${meta}" "${pfx}" "${name}" "${sfx}" "${order}" "atomic_long" "long" "$@" | ||
| 53 | |||
| 48 | cat <<EOF | 54 | cat <<EOF |
| 49 | static __always_inline ${ret} | 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 | EOF | 65 | EOF |
| @@ -79,24 +89,12 @@ typedef atomic_t atomic_long_t; · 23 unmodified lines | |||
| 79 | #define atomic_long_cond_read_relaxed atomic_cond_read_relaxed | 89 | #define atomic_long_cond_read_relaxed atomic_cond_read_relaxed |
| 80 | #endif | 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 | EOF | 92 | EOF |
| 94 | 93 | ||
| 95 | grep '^[a-z]' "$1" | while read name meta args; do | 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 | done | 96 | done |
| 98 | 97 | ||
| 99 | cat <<EOF | 98 | cat <<EOF |
| 100 | #endif /* CONFIG_64BIT */ | ||
| 101 | #endif /* _LINUX_ATOMIC_LONG_H */ | 99 | #endif /* _LINUX_ATOMIC_LONG_H */ |
| 102 | EOF | 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 | my $type_constant2 = '\%([-_\w]+)'; | 64 | my $type_constant2 = '\%([-_\w]+)'; |
| 65 | my $type_func = '(\w+)\(\)'; | 65 | my $type_func = '(\w+)\(\)'; |
| 66 | my $type_param = '\@(\w*((\.\w+)|(->\w+))*(\.\.\.)?)'; | 66 | my $type_param = '\@(\w*((\.\w+)|(->\w+))*(\.\.\.)?)'; |
| 67 | my $type_param_ref = '([\!]?)\@(\w*((\.\w+)|(->\w+))*(\.\.\.)?)'; | 67 | my $type_param_ref = '([\!~]?)\@(\w*((\.\w+)|(->\w+))*(\.\.\.)?)'; |
| 68 | my $type_fp_param = '\@(\w+)\(\)'; # Special RST handling for func ptr params | 68 | my $type_fp_param = '\@(\w+)\(\)'; # Special RST handling for func ptr params |
| 69 | my $type_fp_param2 = '\@(\w+->\S+)\(\)'; # Special RST handling for structs with func ptr params | 69 | my $type_fp_param2 = '\@(\w+->\S+)\(\)'; # Special RST handling for structs with func ptr params |
| 70 | my $type_env = '(\$\w+)'; | 70 | my $type_env = '(\$\w+)'; |
| @@ -17,7 +17,11 @@ binutils) · 16 unmodified lines | |||
| 17 | echo 2.25.0 | 17 | echo 2.25.0 |
| 18 | ;; | 18 | ;; |
| 19 | gcc) | 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 | llvm) | 26 | llvm) |
| 23 | if [ "$SRCARCH" = s390 ]; then | 27 | if [ "$SRCARCH" = s390 ]; then |