162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */ 262306a36Sopenharmony_ci 362306a36Sopenharmony_ci/* 462306a36Sopenharmony_ci * This file provides wrappers with sanitizer instrumentation for atomic bit 562306a36Sopenharmony_ci * operations. 662306a36Sopenharmony_ci * 762306a36Sopenharmony_ci * To use this functionality, an arch's bitops.h file needs to define each of 862306a36Sopenharmony_ci * the below bit operations with an arch_ prefix (e.g. arch_set_bit(), 962306a36Sopenharmony_ci * arch___set_bit(), etc.). 1062306a36Sopenharmony_ci */ 1162306a36Sopenharmony_ci#ifndef _ASM_GENERIC_BITOPS_INSTRUMENTED_ATOMIC_H 1262306a36Sopenharmony_ci#define _ASM_GENERIC_BITOPS_INSTRUMENTED_ATOMIC_H 1362306a36Sopenharmony_ci 1462306a36Sopenharmony_ci#include <linux/instrumented.h> 1562306a36Sopenharmony_ci 1662306a36Sopenharmony_ci/** 1762306a36Sopenharmony_ci * set_bit - Atomically set a bit in memory 1862306a36Sopenharmony_ci * @nr: the bit to set 1962306a36Sopenharmony_ci * @addr: the address to start counting from 2062306a36Sopenharmony_ci * 2162306a36Sopenharmony_ci * This is a relaxed atomic operation (no implied memory barriers). 2262306a36Sopenharmony_ci * 2362306a36Sopenharmony_ci * Note that @nr may be almost arbitrarily large; this function is not 2462306a36Sopenharmony_ci * restricted to acting on a single-word quantity. 2562306a36Sopenharmony_ci */ 2662306a36Sopenharmony_cistatic __always_inline void set_bit(long nr, volatile unsigned long *addr) 2762306a36Sopenharmony_ci{ 2862306a36Sopenharmony_ci instrument_atomic_write(addr + BIT_WORD(nr), sizeof(long)); 2962306a36Sopenharmony_ci arch_set_bit(nr, addr); 3062306a36Sopenharmony_ci} 3162306a36Sopenharmony_ci 3262306a36Sopenharmony_ci/** 3362306a36Sopenharmony_ci * clear_bit - Clears a bit in memory 3462306a36Sopenharmony_ci * @nr: Bit to clear 3562306a36Sopenharmony_ci * @addr: Address to start counting from 3662306a36Sopenharmony_ci * 3762306a36Sopenharmony_ci * This is a relaxed atomic operation (no implied memory barriers). 3862306a36Sopenharmony_ci */ 3962306a36Sopenharmony_cistatic __always_inline void clear_bit(long nr, volatile unsigned long *addr) 4062306a36Sopenharmony_ci{ 4162306a36Sopenharmony_ci instrument_atomic_write(addr + BIT_WORD(nr), sizeof(long)); 4262306a36Sopenharmony_ci arch_clear_bit(nr, addr); 4362306a36Sopenharmony_ci} 4462306a36Sopenharmony_ci 4562306a36Sopenharmony_ci/** 4662306a36Sopenharmony_ci * change_bit - Toggle a bit in memory 4762306a36Sopenharmony_ci * @nr: Bit to change 4862306a36Sopenharmony_ci * @addr: Address to start counting from 4962306a36Sopenharmony_ci * 5062306a36Sopenharmony_ci * This is a relaxed atomic operation (no implied memory barriers). 5162306a36Sopenharmony_ci * 5262306a36Sopenharmony_ci * Note that @nr may be almost arbitrarily large; this function is not 5362306a36Sopenharmony_ci * restricted to acting on a single-word quantity. 5462306a36Sopenharmony_ci */ 5562306a36Sopenharmony_cistatic __always_inline void change_bit(long nr, volatile unsigned long *addr) 5662306a36Sopenharmony_ci{ 5762306a36Sopenharmony_ci instrument_atomic_write(addr + BIT_WORD(nr), sizeof(long)); 5862306a36Sopenharmony_ci arch_change_bit(nr, addr); 5962306a36Sopenharmony_ci} 6062306a36Sopenharmony_ci 6162306a36Sopenharmony_ci/** 6262306a36Sopenharmony_ci * test_and_set_bit - Set a bit and return its old value 6362306a36Sopenharmony_ci * @nr: Bit to set 6462306a36Sopenharmony_ci * @addr: Address to count from 6562306a36Sopenharmony_ci * 6662306a36Sopenharmony_ci * This is an atomic fully-ordered operation (implied full memory barrier). 6762306a36Sopenharmony_ci */ 6862306a36Sopenharmony_cistatic __always_inline bool test_and_set_bit(long nr, volatile unsigned long *addr) 6962306a36Sopenharmony_ci{ 7062306a36Sopenharmony_ci kcsan_mb(); 7162306a36Sopenharmony_ci instrument_atomic_read_write(addr + BIT_WORD(nr), sizeof(long)); 7262306a36Sopenharmony_ci return arch_test_and_set_bit(nr, addr); 7362306a36Sopenharmony_ci} 7462306a36Sopenharmony_ci 7562306a36Sopenharmony_ci/** 7662306a36Sopenharmony_ci * test_and_clear_bit - Clear a bit and return its old value 7762306a36Sopenharmony_ci * @nr: Bit to clear 7862306a36Sopenharmony_ci * @addr: Address to count from 7962306a36Sopenharmony_ci * 8062306a36Sopenharmony_ci * This is an atomic fully-ordered operation (implied full memory barrier). 8162306a36Sopenharmony_ci */ 8262306a36Sopenharmony_cistatic __always_inline bool test_and_clear_bit(long nr, volatile unsigned long *addr) 8362306a36Sopenharmony_ci{ 8462306a36Sopenharmony_ci kcsan_mb(); 8562306a36Sopenharmony_ci instrument_atomic_read_write(addr + BIT_WORD(nr), sizeof(long)); 8662306a36Sopenharmony_ci return arch_test_and_clear_bit(nr, addr); 8762306a36Sopenharmony_ci} 8862306a36Sopenharmony_ci 8962306a36Sopenharmony_ci/** 9062306a36Sopenharmony_ci * test_and_change_bit - Change a bit and return its old value 9162306a36Sopenharmony_ci * @nr: Bit to change 9262306a36Sopenharmony_ci * @addr: Address to count from 9362306a36Sopenharmony_ci * 9462306a36Sopenharmony_ci * This is an atomic fully-ordered operation (implied full memory barrier). 9562306a36Sopenharmony_ci */ 9662306a36Sopenharmony_cistatic __always_inline bool test_and_change_bit(long nr, volatile unsigned long *addr) 9762306a36Sopenharmony_ci{ 9862306a36Sopenharmony_ci kcsan_mb(); 9962306a36Sopenharmony_ci instrument_atomic_read_write(addr + BIT_WORD(nr), sizeof(long)); 10062306a36Sopenharmony_ci return arch_test_and_change_bit(nr, addr); 10162306a36Sopenharmony_ci} 10262306a36Sopenharmony_ci 10362306a36Sopenharmony_ci#endif /* _ASM_GENERIC_BITOPS_INSTRUMENTED_NON_ATOMIC_H */ 104