LCOV - code coverage report
Current view: top level - include/asm-generic/bitops - instrumented-non-atomic.h (source / functions) Hit Total Coverage
Test: coverage.info Lines: 9 15 60.0 %
Date: 2023-08-24 13:40:31 Functions: 0 0 -

          Line data    Source code
       1             : /* SPDX-License-Identifier: GPL-2.0 */
       2             : 
       3             : /*
       4             :  * This file provides wrappers with sanitizer instrumentation for non-atomic
       5             :  * bit operations.
       6             :  *
       7             :  * To use this functionality, an arch's bitops.h file needs to define each of
       8             :  * the below bit operations with an arch_ prefix (e.g. arch_set_bit(),
       9             :  * arch___set_bit(), etc.).
      10             :  */
      11             : #ifndef _ASM_GENERIC_BITOPS_INSTRUMENTED_NON_ATOMIC_H
      12             : #define _ASM_GENERIC_BITOPS_INSTRUMENTED_NON_ATOMIC_H
      13             : 
      14             : #include <linux/instrumented.h>
      15             : 
      16             : /**
      17             :  * ___set_bit - Set a bit in memory
      18             :  * @nr: the bit to set
      19             :  * @addr: the address to start counting from
      20             :  *
      21             :  * Unlike set_bit(), this function is non-atomic. If it is called on the same
      22             :  * region of memory concurrently, the effect may be that only one operation
      23             :  * succeeds.
      24             :  */
      25             : static __always_inline void
      26             : ___set_bit(unsigned long nr, volatile unsigned long *addr)
      27             : {
      28       24122 :         instrument_write(addr + BIT_WORD(nr), sizeof(long));
      29       12061 :         arch___set_bit(nr, addr);
      30             : }
      31             : 
      32             : /**
      33             :  * ___clear_bit - Clears a bit in memory
      34             :  * @nr: the bit to clear
      35             :  * @addr: the address to start counting from
      36             :  *
      37             :  * Unlike clear_bit(), this function is non-atomic. If it is called on the same
      38             :  * region of memory concurrently, the effect may be that only one operation
      39             :  * succeeds.
      40             :  */
      41             : static __always_inline void
      42             : ___clear_bit(unsigned long nr, volatile unsigned long *addr)
      43             : {
      44      528064 :         instrument_write(addr + BIT_WORD(nr), sizeof(long));
      45      264032 :         arch___clear_bit(nr, addr);
      46             : }
      47             : 
      48             : /**
      49             :  * ___change_bit - Toggle a bit in memory
      50             :  * @nr: the bit to change
      51             :  * @addr: the address to start counting from
      52             :  *
      53             :  * Unlike change_bit(), this function is non-atomic. If it is called on the same
      54             :  * region of memory concurrently, the effect may be that only one operation
      55             :  * succeeds.
      56             :  */
      57             : static __always_inline void
      58             : ___change_bit(unsigned long nr, volatile unsigned long *addr)
      59             : {
      60           0 :         instrument_write(addr + BIT_WORD(nr), sizeof(long));
      61           0 :         arch___change_bit(nr, addr);
      62             : }
      63             : 
      64             : static __always_inline void __instrument_read_write_bitop(long nr, volatile unsigned long *addr)
      65             : {
      66             :         if (IS_ENABLED(CONFIG_KCSAN_ASSUME_PLAIN_WRITES_ATOMIC)) {
      67             :                 /*
      68             :                  * We treat non-atomic read-write bitops a little more special.
      69             :                  * Given the operations here only modify a single bit, assuming
      70             :                  * non-atomicity of the writer is sufficient may be reasonable
      71             :                  * for certain usage (and follows the permissible nature of the
      72             :                  * assume-plain-writes-atomic rule):
      73             :                  * 1. report read-modify-write races -> check read;
      74             :                  * 2. do not report races with marked readers, but do report
      75             :                  *    races with unmarked readers -> check "atomic" write.
      76             :                  */
      77             :                 kcsan_check_read(addr + BIT_WORD(nr), sizeof(long));
      78             :                 /*
      79             :                  * Use generic write instrumentation, in case other sanitizers
      80             :                  * or tools are enabled alongside KCSAN.
      81             :                  */
      82             :                 instrument_write(addr + BIT_WORD(nr), sizeof(long));
      83             :         } else {
      84           2 :                 instrument_read_write(addr + BIT_WORD(nr), sizeof(long));
      85             :         }
      86             : }
      87             : 
      88             : /**
      89             :  * ___test_and_set_bit - Set a bit and return its old value
      90             :  * @nr: Bit to set
      91             :  * @addr: Address to count from
      92             :  *
      93             :  * This operation is non-atomic. If two instances of this operation race, one
      94             :  * can appear to succeed but actually fail.
      95             :  */
      96             : static __always_inline bool
      97             : ___test_and_set_bit(unsigned long nr, volatile unsigned long *addr)
      98             : {
      99           0 :         __instrument_read_write_bitop(nr, addr);
     100           0 :         return arch___test_and_set_bit(nr, addr);
     101             : }
     102             : 
     103             : /**
     104             :  * ___test_and_clear_bit - Clear a bit and return its old value
     105             :  * @nr: Bit to clear
     106             :  * @addr: Address to count from
     107             :  *
     108             :  * This operation is non-atomic. If two instances of this operation race, one
     109             :  * can appear to succeed but actually fail.
     110             :  */
     111             : static __always_inline bool
     112             : ___test_and_clear_bit(unsigned long nr, volatile unsigned long *addr)
     113             : {
     114           2 :         __instrument_read_write_bitop(nr, addr);
     115           1 :         return arch___test_and_clear_bit(nr, addr);
     116             : }
     117             : 
     118             : /**
     119             :  * ___test_and_change_bit - Change a bit and return its old value
     120             :  * @nr: Bit to change
     121             :  * @addr: Address to count from
     122             :  *
     123             :  * This operation is non-atomic. If two instances of this operation race, one
     124             :  * can appear to succeed but actually fail.
     125             :  */
     126             : static __always_inline bool
     127             : ___test_and_change_bit(unsigned long nr, volatile unsigned long *addr)
     128             : {
     129             :         __instrument_read_write_bitop(nr, addr);
     130             :         return arch___test_and_change_bit(nr, addr);
     131             : }
     132             : 
     133             : /**
     134             :  * _test_bit - Determine whether a bit is set
     135             :  * @nr: bit number to test
     136             :  * @addr: Address to start counting from
     137             :  */
     138             : static __always_inline bool
     139             : _test_bit(unsigned long nr, const volatile unsigned long *addr)
     140             : {
     141      111044 :         instrument_atomic_read(addr + BIT_WORD(nr), sizeof(long));
     142       55522 :         return arch_test_bit(nr, addr);
     143             : }
     144             : 
     145             : /**
     146             :  * _test_bit_acquire - Determine, with acquire semantics, whether a bit is set
     147             :  * @nr: bit number to test
     148             :  * @addr: Address to start counting from
     149             :  */
     150             : static __always_inline bool
     151             : _test_bit_acquire(unsigned long nr, const volatile unsigned long *addr)
     152             : {
     153           0 :         instrument_atomic_read(addr + BIT_WORD(nr), sizeof(long));
     154           0 :         return arch_test_bit_acquire(nr, addr);
     155             : }
     156             : 
     157             : #endif /* _ASM_GENERIC_BITOPS_INSTRUMENTED_NON_ATOMIC_H */

Generated by: LCOV version 1.14