/src/botan/src/lib/utils/prefetch.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * (C) 2023 Jack Lloyd |
3 | | * |
4 | | * Botan is released under the Simplified BSD License (see license.txt) |
5 | | */ |
6 | | |
7 | | #include <botan/internal/prefetch.h> |
8 | | |
9 | | #include <botan/internal/bit_ops.h> |
10 | | #include <new> |
11 | | |
12 | | namespace Botan { |
13 | | |
14 | 0 | uint64_t prefetch_array_raw(size_t bytes, const void* arrayv) noexcept { |
15 | | // Android NDK is garbage and defines the feature macro, but not the variable |
16 | | #if defined(__cpp_lib_hardware_interference_size) && !defined(BOTAN_TARGET_OS_IS_ANDROID) |
17 | | const size_t cache_line_size = std::hardware_destructive_interference_size; |
18 | | #else |
19 | | // We arbitrarily use a 64 byte cache line, which is by far the most |
20 | | // common size. |
21 | | // |
22 | | // Runtime detection adds too much overhead to this function. |
23 | 0 | const size_t cache_line_size = 64; |
24 | 0 | #endif |
25 | |
|
26 | 0 | const uint8_t* array = static_cast<const uint8_t*>(arrayv); |
27 | |
|
28 | 0 | volatile uint64_t combiner = 1; |
29 | |
|
30 | 0 | for(size_t idx = 0; idx < bytes; idx += cache_line_size) { |
31 | 0 | #if BOTAN_COMPILER_HAS_BUILTIN(__builtin_prefetch) |
32 | | // we have no way of knowing if the compiler will emit anything here |
33 | 0 | __builtin_prefetch(&array[idx]); |
34 | 0 | #endif |
35 | |
|
36 | 0 | combiner = combiner | array[idx]; |
37 | 0 | } |
38 | | |
39 | | /* |
40 | | * The combiner variable is initialized with 1, and we accumulate using OR, so |
41 | | * now combiner must be a value other than zero. This being the case we will |
42 | | * always return zero here. Hopefully the compiler will not figure this out. |
43 | | */ |
44 | 0 | return ct_is_zero(combiner); |
45 | 0 | } |
46 | | |
47 | | } // namespace Botan |