| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859 |
- /* SPDX-License-Identifier: GPL-2.0-only */
- /*
- * Copyright 2023 Red Hat
- */
- #ifndef UDS_CPU_H
- #define UDS_CPU_H
- #include <linux/cache.h>
- /**
- * uds_prefetch_address() - Minimize cache-miss latency by attempting to move data into a CPU cache
- * before it is accessed.
- *
- * @address: the address to fetch (may be invalid)
- * @for_write: must be constant at compile time--false if for reading, true if for writing
- */
- static inline void uds_prefetch_address(const void *address, bool for_write)
- {
- /*
- * for_write won't be a constant if we are compiled with optimization turned off, in which
- * case prefetching really doesn't matter. clang can't figure out that if for_write is a
- * constant, it can be passed as the second, mandatorily constant argument to prefetch(),
- * at least currently on llvm 12.
- */
- if (__builtin_constant_p(for_write)) {
- if (for_write)
- __builtin_prefetch(address, true);
- else
- __builtin_prefetch(address, false);
- }
- }
- /**
- * uds_prefetch_range() - Minimize cache-miss latency by attempting to move a range of addresses
- * into a CPU cache before they are accessed.
- *
- * @start: the starting address to fetch (may be invalid)
- * @size: the number of bytes in the address range
- * @for_write: must be constant at compile time--false if for reading, true if for writing
- */
- static inline void uds_prefetch_range(const void *start, unsigned int size,
- bool for_write)
- {
- /*
- * Count the number of cache lines to fetch, allowing for the address range to span an
- * extra cache line boundary due to address alignment.
- */
- const char *address = (const char *) start;
- unsigned int offset = ((uintptr_t) address % L1_CACHE_BYTES);
- unsigned int cache_lines = (1 + ((size + offset) / L1_CACHE_BYTES));
- while (cache_lines-- > 0) {
- uds_prefetch_address(address, for_write);
- address += L1_CACHE_BYTES;
- }
- }
- #endif /* UDS_CPU_H */
|