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