60 lines · c
1/* SPDX-License-Identifier: GPL-2.0-only */2/*3 * Copyright 2023 Red Hat4 */5 6#ifndef UDS_CPU_H7#define UDS_CPU_H8 9#include <linux/cache.h>10 11/**12 * uds_prefetch_address() - Minimize cache-miss latency by attempting to move data into a CPU cache13 * before it is accessed.14 *15 * @address: the address to fetch (may be invalid)16 * @for_write: must be constant at compile time--false if for reading, true if for writing17 */18static inline void uds_prefetch_address(const void *address, bool for_write)19{20 /*21 * for_write won't be a constant if we are compiled with optimization turned off, in which22 * case prefetching really doesn't matter. clang can't figure out that if for_write is a23 * constant, it can be passed as the second, mandatorily constant argument to prefetch(),24 * at least currently on llvm 12.25 */26 if (__builtin_constant_p(for_write)) {27 if (for_write)28 __builtin_prefetch(address, true);29 else30 __builtin_prefetch(address, false);31 }32}33 34/**35 * uds_prefetch_range() - Minimize cache-miss latency by attempting to move a range of addresses36 * into a CPU cache before they are accessed.37 *38 * @start: the starting address to fetch (may be invalid)39 * @size: the number of bytes in the address range40 * @for_write: must be constant at compile time--false if for reading, true if for writing41 */42static inline void uds_prefetch_range(const void *start, unsigned int size,43 bool for_write)44{45 /*46 * Count the number of cache lines to fetch, allowing for the address range to span an47 * extra cache line boundary due to address alignment.48 */49 const char *address = (const char *) start;50 unsigned int offset = ((uintptr_t) address % L1_CACHE_BYTES);51 unsigned int cache_lines = (1 + ((size + offset) / L1_CACHE_BYTES));52 53 while (cache_lines-- > 0) {54 uds_prefetch_address(address, for_write);55 address += L1_CACHE_BYTES;56 }57}58 59#endif /* UDS_CPU_H */60