KleidiAI Coverage Report


Directory: ./
File: test/common/buffer.hpp
Date: 2025-10-20 13:18:31
Coverage Exec Excl Total
Lines: 100.0% 16 0 16
Functions: 100.0% 6 0 6
Branches: -% 0 0 0

Line Branch Exec Source
1 //
2 // SPDX-FileCopyrightText: Copyright 2025 Arm Limited and/or its affiliates <open-source-office@arm.com>
3 //
4 // SPDX-License-Identifier: Apache-2.0
5 //
6
7 #pragma once
8
9 #include <cstddef>
10 #include <cstdint>
11 #include <functional>
12 #include <memory>
13
14 namespace kai::test {
15
16 /// Buffer is a high-level abstraction for a block of memory.
17 ///
18 /// The class performs dynamic memory allocation and management in an opaque manner. The underlying memory resource can
19 /// be requested using the familiar @ref Buffer::data() method and interacted with using @ref
20 /// kai::test::read_array<T>() and @ref kai::test::write_array<T>() utilities.
21 ///
22 /// Buffer comes with protection mechanisms defined by @ref BufferProtectionPolicy. These are enabled by setting the
23 /// KAI_TEST_BUFFER_POLICY environment variable, for example:
24 /// KAI_TEST_BUFFER_POLICY=PROTECT_UNDERFLOW to enable @ref BufferProtectionPolicy::ProtectUnderflow.
25 /// KAI_TEST_BUFFER_POLICY=PROTECT_OVERFLOW to enable @ref BufferProtectionPolicy::ProtectOverflow.
26 ///
27 class Buffer {
28 // Handle to the underlying memory resource and its deleter
29 using handle = std::unique_ptr<void, std::function<void(void*)>>;
30
31 public:
32 184119 Buffer() = default;
33 explicit Buffer(size_t size);
34 Buffer(size_t size, uint8_t init_value);
35
36 Buffer(const Buffer& other) = delete;
37 246626 Buffer(Buffer&& other) noexcept = default;
38 Buffer& operator=(const Buffer& other) = delete;
39 55044 Buffer& operator=(Buffer&& other) noexcept = default;
40
41 1077534 ~Buffer() = default;
42
43 /// Gets the base memory address of the user buffer.
44 ///
45 /// @return Base memory address of the user buffer.
46 418798584 [[nodiscard]] std::byte* data() const {
47 418798584 return static_cast<std::byte*>(m_buffer.get()) + m_user_buffer_offset;
48 }
49
50 /// Gets the size of the user buffer.
51 ///
52 /// Depending on the @ref BufferProtectionPolicy policy enabled, the actual size of memory allocated may be larger.
53 /// However, this function guarantees to always provide the size of the user buffer only.
54 ///
55 /// @return Size of the user buffer in bytes.
56 4098469 [[nodiscard]] size_t size() const {
57 4098469 return m_user_buffer_size;
58 }
59
60 static constexpr const char* buffer_policy_env_name = "KAI_TEST_BUFFER_POLICY";
61
62 private:
63 /// Buffer can be protected with one of the following protection policies:
64 /// - @ref BufferProtectionPolicy::None No protection mechanisms are enabled.
65 /// - @ref BufferProtectionPolicy::ProtectUnderflow Memory equal to the size of the user buffer rounded to the
66 /// nearest whole page plus adjacent guard pages is allocated,
67 /// and the user buffer is aligned to the end of the head guard
68 /// page thus detecting whenever a buffer underflow occurs.
69 /// - @ref BufferProtectionPolicy::ProtectOverflow Same as above, but now the edge of the user buffer is aligned
70 /// to the start of the tail guard page thus detecting whenever a
71 /// buffer overflow occurs.
72 enum class BufferProtectionPolicy : uint8_t {
73 None = 0,
74 ProtectUnderflow = 1,
75 ProtectOverflow = 2,
76 };
77
78 /// Naively allocate memory.
79 void allocate();
80
81 #if defined(__linux__) || defined(__APPLE__)
82 /// Allocate memory with adjacent guard pages.
83 void allocate_with_guard_pages();
84 #endif // defined(__linux__) || defined(__APPLE__)
85
86 61373 handle m_buffer = nullptr;
87
88 61373 size_t m_user_buffer_size = 0;
89 61373 size_t m_user_buffer_offset = 0;
90
91 61373 BufferProtectionPolicy m_protection_policy = BufferProtectionPolicy::None;
92 };
93
94 } // namespace kai::test
95