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