1 // Copyright (c) the JPEG XL Project Authors. All rights reserved.
2 //
3 // Use of this source code is governed by a BSD-style
4 // license that can be found in the LICENSE file.
5
6 #ifndef LIB_JXL_BASE_CACHE_ALIGNED_H_
7 #define LIB_JXL_BASE_CACHE_ALIGNED_H_
8
9 // Memory allocator with support for alignment + misalignment.
10
11 #include <stddef.h>
12 #include <stdint.h>
13
14 #include <memory>
15
16 #include "lib/jxl/base/compiler_specific.h"
17
18 namespace jxl {
19
20 // Functions that depend on the cache line size.
21 class CacheAligned {
22 public:
23 static void PrintStats();
24
25 static constexpr size_t kPointerSize = sizeof(void*);
26 static constexpr size_t kCacheLineSize = 64;
27 // To avoid RFOs, match L2 fill size (pairs of lines).
28 static constexpr size_t kAlignment = 2 * kCacheLineSize;
29 // Minimum multiple for which cache set conflicts and/or loads blocked by
30 // preceding stores can occur.
31 static constexpr size_t kAlias = 2048;
32
33 // Returns a 'random' (cyclical) offset suitable for Allocate.
34 static size_t NextOffset();
35
36 // Returns null or memory whose address is congruent to `offset` (mod kAlias).
37 // This reduces cache conflicts and load/store stalls, especially with large
38 // allocations that would otherwise have similar alignments. At least
39 // `payload_size` (which can be zero) bytes will be accessible.
40 static void* Allocate(size_t payload_size, size_t offset);
41
Allocate(const size_t payload_size)42 static void* Allocate(const size_t payload_size) {
43 return Allocate(payload_size, NextOffset());
44 }
45
46 static void Free(const void* aligned_pointer);
47 };
48
49 // Avoids the need for a function pointer (deleter) in CacheAlignedUniquePtr.
50 struct CacheAlignedDeleter {
operatorCacheAlignedDeleter51 void operator()(uint8_t* aligned_pointer) const {
52 return CacheAligned::Free(aligned_pointer);
53 }
54 };
55
56 using CacheAlignedUniquePtr = std::unique_ptr<uint8_t[], CacheAlignedDeleter>;
57
58 // Does not invoke constructors.
AllocateArray(const size_t bytes)59 static inline CacheAlignedUniquePtr AllocateArray(const size_t bytes) {
60 return CacheAlignedUniquePtr(
61 static_cast<uint8_t*>(CacheAligned::Allocate(bytes)),
62 CacheAlignedDeleter());
63 }
64
AllocateArray(const size_t bytes,const size_t offset)65 static inline CacheAlignedUniquePtr AllocateArray(const size_t bytes,
66 const size_t offset) {
67 return CacheAlignedUniquePtr(
68 static_cast<uint8_t*>(CacheAligned::Allocate(bytes, offset)),
69 CacheAlignedDeleter());
70 }
71
72 } // namespace jxl
73
74 #endif // LIB_JXL_BASE_CACHE_ALIGNED_H_
75