Back to home page

OSCL-LXR

 
 

    


0001 #!/bin/sh
0002 # SPDX-License-Identifier: GPL-2.0
0003 
0004 ATOMICDIR=$(dirname $0)
0005 
0006 . ${ATOMICDIR}/atomic-tbl.sh
0007 
0008 #gen_param_check(meta, arg)
0009 gen_param_check()
0010 {
0011         local meta="$1"; shift
0012         local arg="$1"; shift
0013         local type="${arg%%:*}"
0014         local name="$(gen_param_name "${arg}")"
0015         local rw="write"
0016 
0017         case "${type#c}" in
0018         i) return;;
0019         esac
0020 
0021         if [ ${type#c} != ${type} ]; then
0022                 # We don't write to constant parameters.
0023                 rw="read"
0024         elif [ "${meta}" != "s" ]; then
0025                 # An atomic RMW: if this parameter is not a constant, and this atomic is
0026                 # not just a 's'tore, this parameter is both read from and written to.
0027                 rw="read_write"
0028         fi
0029 
0030         printf "\tinstrument_atomic_${rw}(${name}, sizeof(*${name}));\n"
0031 }
0032 
0033 #gen_params_checks(meta, arg...)
0034 gen_params_checks()
0035 {
0036         local meta="$1"; shift
0037         local order="$1"; shift
0038 
0039         if [ "${order}" = "_release" ]; then
0040                 printf "\tkcsan_release();\n"
0041         elif [ -z "${order}" ] && ! meta_in "$meta" "slv"; then
0042                 # RMW with return value is fully ordered
0043                 printf "\tkcsan_mb();\n"
0044         fi
0045 
0046         while [ "$#" -gt 0 ]; do
0047                 gen_param_check "$meta" "$1"
0048                 shift;
0049         done
0050 }
0051 
0052 #gen_proto_order_variant(meta, pfx, name, sfx, order, atomic, int, arg...)
0053 gen_proto_order_variant()
0054 {
0055         local meta="$1"; shift
0056         local pfx="$1"; shift
0057         local name="$1"; shift
0058         local sfx="$1"; shift
0059         local order="$1"; shift
0060         local atomic="$1"; shift
0061         local int="$1"; shift
0062 
0063         local atomicname="${atomic}_${pfx}${name}${sfx}${order}"
0064 
0065         local ret="$(gen_ret_type "${meta}" "${int}")"
0066         local params="$(gen_params "${int}" "${atomic}" "$@")"
0067         local checks="$(gen_params_checks "${meta}" "${order}" "$@")"
0068         local args="$(gen_args "$@")"
0069         local retstmt="$(gen_ret_stmt "${meta}")"
0070 
0071 cat <<EOF
0072 static __always_inline ${ret}
0073 ${atomicname}(${params})
0074 {
0075 ${checks}
0076         ${retstmt}arch_${atomicname}(${args});
0077 }
0078 EOF
0079 
0080         printf "\n"
0081 }
0082 
0083 gen_xchg()
0084 {
0085         local xchg="$1"; shift
0086         local order="$1"; shift
0087         local mult="$1"; shift
0088 
0089         kcsan_barrier=""
0090         if [ "${xchg%_local}" = "${xchg}" ]; then
0091                 case "$order" in
0092                 _release)       kcsan_barrier="kcsan_release()" ;;
0093                 "")                     kcsan_barrier="kcsan_mb()" ;;
0094                 esac
0095         fi
0096 
0097         if [ "${xchg%${xchg#try_cmpxchg}}" = "try_cmpxchg" ] ; then
0098 
0099 cat <<EOF
0100 #define ${xchg}${order}(ptr, oldp, ...) \\
0101 ({ \\
0102         typeof(ptr) __ai_ptr = (ptr); \\
0103         typeof(oldp) __ai_oldp = (oldp); \\
0104 EOF
0105 [ -n "$kcsan_barrier" ] && printf "\t${kcsan_barrier}; \\\\\n"
0106 cat <<EOF
0107         instrument_atomic_write(__ai_ptr, ${mult}sizeof(*__ai_ptr)); \\
0108         instrument_atomic_write(__ai_oldp, ${mult}sizeof(*__ai_oldp)); \\
0109         arch_${xchg}${order}(__ai_ptr, __ai_oldp, __VA_ARGS__); \\
0110 })
0111 EOF
0112 
0113         else
0114 
0115 cat <<EOF
0116 #define ${xchg}${order}(ptr, ...) \\
0117 ({ \\
0118         typeof(ptr) __ai_ptr = (ptr); \\
0119 EOF
0120 [ -n "$kcsan_barrier" ] && printf "\t${kcsan_barrier}; \\\\\n"
0121 cat <<EOF
0122         instrument_atomic_write(__ai_ptr, ${mult}sizeof(*__ai_ptr)); \\
0123         arch_${xchg}${order}(__ai_ptr, __VA_ARGS__); \\
0124 })
0125 EOF
0126 
0127         fi
0128 }
0129 
0130 cat << EOF
0131 // SPDX-License-Identifier: GPL-2.0
0132 
0133 // Generated by $0
0134 // DO NOT MODIFY THIS FILE DIRECTLY
0135 
0136 /*
0137  * This file provides wrappers with KASAN instrumentation for atomic operations.
0138  * To use this functionality an arch's atomic.h file needs to define all
0139  * atomic operations with arch_ prefix (e.g. arch_atomic_read()) and include
0140  * this file at the end. This file provides atomic_read() that forwards to
0141  * arch_atomic_read() for actual atomic operation.
0142  * Note: if an arch atomic operation is implemented by means of other atomic
0143  * operations (e.g. atomic_read()/atomic_cmpxchg() loop), then it needs to use
0144  * arch_ variants (i.e. arch_atomic_read()/arch_atomic_cmpxchg()) to avoid
0145  * double instrumentation.
0146  */
0147 #ifndef _LINUX_ATOMIC_INSTRUMENTED_H
0148 #define _LINUX_ATOMIC_INSTRUMENTED_H
0149 
0150 #include <linux/build_bug.h>
0151 #include <linux/compiler.h>
0152 #include <linux/instrumented.h>
0153 
0154 EOF
0155 
0156 grep '^[a-z]' "$1" | while read name meta args; do
0157         gen_proto "${meta}" "${name}" "atomic" "int" ${args}
0158 done
0159 
0160 grep '^[a-z]' "$1" | while read name meta args; do
0161         gen_proto "${meta}" "${name}" "atomic64" "s64" ${args}
0162 done
0163 
0164 grep '^[a-z]' "$1" | while read name meta args; do
0165         gen_proto "${meta}" "${name}" "atomic_long" "long" ${args}
0166 done
0167 
0168 
0169 for xchg in "xchg" "cmpxchg" "cmpxchg64" "try_cmpxchg" "try_cmpxchg64"; do
0170         for order in "" "_acquire" "_release" "_relaxed"; do
0171                 gen_xchg "${xchg}" "${order}" ""
0172                 printf "\n"
0173         done
0174 done
0175 
0176 for xchg in "cmpxchg_local" "cmpxchg64_local" "sync_cmpxchg"; do
0177         gen_xchg "${xchg}" "" ""
0178         printf "\n"
0179 done
0180 
0181 gen_xchg "cmpxchg_double" "" "2 * "
0182 
0183 printf "\n\n"
0184 
0185 gen_xchg "cmpxchg_double_local" "" "2 * "
0186 
0187 cat <<EOF
0188 
0189 #endif /* _LINUX_ATOMIC_INSTRUMENTED_H */
0190 EOF