MySQL 9.1.0
Source Code Documentation
header.h
Go to the documentation of this file.
1/* Copyright (c) 2019, 2024, Oracle and/or its affiliates.
2
3This program is free software; you can redistribute it and/or modify it under
4the terms of the GNU General Public License, version 2.0, as published by the
5Free Software Foundation.
6
7This program is designed to work with certain software (including
8but not limited to OpenSSL) that is licensed under separate terms,
9as designated in a particular file or component or in included license
10documentation. The authors of MySQL hereby grant you an additional
11permission to link the program and your derivative works with the
12separately licensed software that they have either included with
13the program or referenced in the documentation.
14
15This program is distributed in the hope that it will be useful, but WITHOUT
16ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
17FOR A PARTICULAR PURPOSE. See the GNU General Public License, version 2.0,
18for more details.
19
20You should have received a copy of the GNU General Public License along with
21this program; if not, write to the Free Software Foundation, Inc.,
2251 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
23
24/** @file storage/temptable/include/temptable/header.h
25Header abstraction for temptable Block allocator. Each Block is described by
26header. */
27
28#ifndef TEMPTABLE_HEADER_H
29#define TEMPTABLE_HEADER_H
30
31#include <assert.h>
32#include <cstddef> // size_t
33#include <cstdint> // uint8_t, uintptr_t
34
36
37namespace temptable {
38
39/** Header is an abstraction with the purpose of holding and maintaining
40 * the Block metadata.
41 *
42 * Block metadata has the following structure:
43 * - N bytes for the block type which indicates where the block
44 * memory was allocated from.
45 * - N bytes for the block size (set at block creation and never
46 * changed later).
47 * - N bytes for the number of used/allocated chunks from this
48 * block (set to 0 at block creation).
49 * - N bytes for the offset of the first byte relative to the
50 * block start that is free and can be used by the next allocation request
51 * (set to 4 * N at block creation). We call this first pristine offset.
52 *
53 * That implies Chunks occupy the following range in memory:
54 * - bytes [4 * N, block size) a sequence of chunks appended to each other.
55 *
56 * 1st byte of [0, N) region is an actual pointer returned by memory
57 * allocation functions (e.g. malloc/new/mmap/etc.). Given that we are working
58 * with contiguous memory, storing that byte (offset) is just enough to be
59 * able to build-up and deduce Header metadata structure.
60 *
61 * Part of the Header contract is to have its metadata properly aligned in
62 * memory. Given that this memory is provided by the Block, Header
63 * implements debug-asserts to actually check if this condition has been met.
64 * If that was not the case, then accessing unaligned memory addresses would:
65 * 1. Incur performance penalty cost on architectures which can
66 * handle misaligned memory access (e.g. x86).
67 * 2. Result with a CPU trap (exception) on architectures which
68 * cannot handle misaligned memory access (e.g. SPARC).
69 *
70 * In order to maintain proper memory alignment of the whole metadata structure,
71 * CPU word-size data-type is used. Our N is defined by the size of that type
72 * (Header::metadata_type).
73 * */
74class Header {
75 public:
76 /** Type that we will be using for storing metadata information. */
77 using metadata_type = uintptr_t;
78
79 /** Block header (metadata) size. As described, there are 4 elements. */
80 static constexpr size_t SIZE = 4 * sizeof(Header::metadata_type);
81
82 public:
83 /** Get the Block Source type (memory where it resides).
84 *
85 * @return One of Source values */
87
88 /** Get the Block size.
89 *
90 * @return Size of the Block */
91 size_t block_size() const;
92
93 /** Get current number of Chunks allocated by the Block.
94 *
95 * @return Number of Chunks allocated by this Block */
96 size_t number_of_used_chunks() const;
97
98 /** Get current first-pristine-offset. This offset is always relative to the
99 * block start (block-address).
100 *
101 * @return Offset relative to the block start */
102 size_t first_pristine_offset() const;
103
104 protected:
105 /** Default constructor which creates an empty Header. */
106 Header() noexcept;
107
108 /** Constructor which initializes the Header metadata when
109 * constructing fresh Blocks.
110 *
111 * [in] Pointer to the allocated Block memory.
112 * [in] Source where Block has allocated actual memory from.
113 * [in] Size of the Block */
114 Header(uint8_t *block_memory, Source block_memory_type,
115 size_t block_size) noexcept;
116
117 /** Constructor which initializes the Header metadata from
118 * already existing Blocks in memory (e.g. ones that are
119 * deduced from Chunks).
120 *
121 * [in] Pointer to the existing Block. */
122 explicit Header(uint8_t *block_memory) noexcept;
123
124 /** Enable Block to get the next available slot that it can use for next
125 * Chunk allocation.
126 *
127 * @return An absolute memory-location offset */
128 uint8_t *next_available_slot() const;
129
130 /** Enable Block to get its memory address.
131 *
132 * @return An address where Block was allocated from. */
133 uint8_t *block_address() const;
134
135 /** Enable Block to increment the reference-count when (logically)
136 * allocating new Chunks.
137 *
138 * [in] Size of the Chunk.
139 * @return New number of Chunks used/allocated by the Block after this
140 * operation. */
141 size_t increment_number_of_used_chunks(size_t chunk_size);
142
143 /** Enable Block to decrement the reference-count when (logically)
144 * deallocating existing Chunks.
145 *
146 * [in] Size of the Chunk.
147 * [in] Boolean which denotes if Chunk being deallocated is the
148 * last (rightmost) one.
149 * @return New number of Chunks used/allocated by the Block after this
150 * operation. */
151 size_t decrement_number_of_used_chunks(size_t chunk_size,
152 bool rightmost_chunk);
153
154 /** Enable Block to reset the Header metadata upon Block destruction. */
155 void reset();
156
157 private:
158 /** Deduce a pointer to the memory type of given Block. */
159 static Header::metadata_type *block_memory_type_ptr(uint8_t *block);
160 /** Deduce a pointer to the size of given Block. */
161 static Header::metadata_type *block_size_ptr(uint8_t *block);
162 /** Deduce a pointer to the number of used/allocated Chunks of given Block. */
164 /** Deduce a pointer to the first-pristine-offset of given Block. */
166
167 private:
168 /** A pointer to the allocated Block memory which is used to deduce all
169 * of the other remaining metadata structure. */
170 uint8_t *m_offset;
171};
172
173inline Header::Header() noexcept : Header(nullptr) {}
174
175inline Header::Header(uint8_t *block_memory) noexcept : m_offset(block_memory) {
176 assert(reinterpret_cast<Header::metadata_type>(m_offset) %
177 alignof(Header::metadata_type) ==
178 0);
179}
180
181inline Header::Header(uint8_t *block_memory, Source block_memory_type,
182 size_t block_size) noexcept
183 : Header(block_memory) {
185 static_cast<Header::metadata_type>(block_memory_type);
189}
190
191inline uint8_t *Header::next_available_slot() const {
193}
194
195inline uint8_t *Header::block_address() const { return m_offset; }
196
198 return static_cast<Source>(*block_memory_type_ptr(m_offset));
199}
200
201inline size_t Header::block_size() const {
202 return static_cast<size_t>(*block_size_ptr(m_offset));
203}
204
205inline size_t Header::number_of_used_chunks() const {
206 return static_cast<size_t>(*block_number_of_used_chunks_ptr(m_offset));
207}
208
209inline size_t Header::first_pristine_offset() const {
210 return static_cast<size_t>(*block_first_pristine_offset_ptr(m_offset));
211}
212
213inline size_t Header::increment_number_of_used_chunks(size_t chunk_size) {
216}
217
218inline size_t Header::decrement_number_of_used_chunks(size_t chunk_size,
219 bool rightmost_chunk) {
222 /* If we are freeing the leftmost chunk in this block, then
223 * first_pristine_offset mark can be reset, so that the memory region
224 * can be reused.
225 */
227 } else if (rightmost_chunk) {
228 /* If we are freeing the rightmost chunk in this block, then lower the
229 * first_pristine_offset mark, so that the memory region can be reused.
230 */
232 }
234}
235
236inline void Header::reset() { m_offset = nullptr; }
237
239 return reinterpret_cast<Header::metadata_type *>(block);
240}
241
243 return reinterpret_cast<Header::metadata_type *>(
244 block + 1 * sizeof(Header::metadata_type));
245}
246
248 uint8_t *block) {
249 return reinterpret_cast<Header::metadata_type *>(
250 block + 2 * sizeof(Header::metadata_type));
251}
252
254 uint8_t *block) {
255 return reinterpret_cast<Header::metadata_type *>(
256 block + 3 * sizeof(Header::metadata_type));
257}
258
259} /* namespace temptable */
260
261#endif /* TEMPTABLE_HEADER_H */
Header is an abstraction with the purpose of holding and maintaining the Block metadata.
Definition: header.h:74
static Header::metadata_type * block_size_ptr(uint8_t *block)
Deduce a pointer to the size of given Block.
Definition: header.h:242
uint8_t * next_available_slot() const
Enable Block to get the next available slot that it can use for next Chunk allocation.
Definition: header.h:191
uintptr_t metadata_type
Type that we will be using for storing metadata information.
Definition: header.h:77
size_t block_size() const
Get the Block size.
Definition: header.h:201
void reset()
Enable Block to reset the Header metadata upon Block destruction.
Definition: header.h:236
Source memory_source_type() const
Get the Block Source type (memory where it resides).
Definition: header.h:197
Header() noexcept
Default constructor which creates an empty Header.
Definition: header.h:173
static Header::metadata_type * block_number_of_used_chunks_ptr(uint8_t *block)
Deduce a pointer to the number of used/allocated Chunks of given Block.
Definition: header.h:247
uint8_t * block_address() const
Enable Block to get its memory address.
Definition: header.h:195
size_t increment_number_of_used_chunks(size_t chunk_size)
Enable Block to increment the reference-count when (logically) allocating new Chunks.
Definition: header.h:213
static Header::metadata_type * block_memory_type_ptr(uint8_t *block)
Deduce a pointer to the memory type of given Block.
Definition: header.h:238
uint8_t * m_offset
A pointer to the allocated Block memory which is used to deduce all of the other remaining metadata s...
Definition: header.h:170
static Header::metadata_type * block_first_pristine_offset_ptr(uint8_t *block)
Deduce a pointer to the first-pristine-offset of given Block.
Definition: header.h:253
static constexpr size_t SIZE
Block header (metadata) size.
Definition: header.h:80
size_t decrement_number_of_used_chunks(size_t chunk_size, bool rightmost_chunk)
Enable Block to decrement the reference-count when (logically) deallocating existing Chunks.
Definition: header.h:218
size_t first_pristine_offset() const
Get current first-pristine-offset.
Definition: header.h:209
size_t number_of_used_chunks() const
Get current number of Chunks allocated by the Block.
Definition: header.h:205
Memory utilities for temptable-allocator.
Definition: allocator.h:48
Source
Type of memory allocated.
Definition: memutils.h:68