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
3
This program is free software; you can redistribute it and/or modify it under
4
the terms of the GNU General Public License, version 2.0, as published by the
5
Free Software Foundation.
6
7
This program is designed to work with certain software (including
8
but not limited to OpenSSL) that is licensed under separate terms,
9
as designated in a particular file or component or in included license
10
documentation. The authors of MySQL hereby grant you an additional
11
permission to link the program and your derivative works with the
12
separately licensed software that they have either included with
13
the program or referenced in the documentation.
14
15
This program is distributed in the hope that it will be useful, but WITHOUT
16
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
17
FOR A PARTICULAR PURPOSE. See the GNU General Public License, version 2.0,
18
for more details.
19
20
You should have received a copy of the GNU General Public License along with
21
this program; if not, write to the Free Software Foundation, Inc.,
22
51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
23
24
/** @file storage/temptable/include/temptable/header.h
25
Header abstraction for temptable Block allocator. Each Block is described by
26
header. */
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
35
#include "
storage/temptable/include/temptable/memutils.h
"
// Source
36
37
namespace
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
* */
74
class
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 */
86
Source
memory_source_type
()
const
;
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. */
163
static
Header
::
metadata_type
*
block_number_of_used_chunks_ptr
(uint8_t *block);
164
/** Deduce a pointer to the first-pristine-offset of given Block. */
165
static
Header
::
metadata_type
*
block_first_pristine_offset_ptr
(uint8_t *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
173
inline
Header
::
Header
() noexcept :
Header
(
nullptr
) {}
174
175
inline
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
181
inline
Header::Header
(uint8_t *block_memory,
Source
block_memory_type,
182
size_t
block_size
) noexcept
183
:
Header
(block_memory) {
184
*
block_memory_type_ptr
(
m_offset
) =
185
static_cast<
Header::metadata_type
>
(block_memory_type);
186
*
block_size_ptr
(
m_offset
) =
block_size
;
187
*
block_number_of_used_chunks_ptr
(
m_offset
) = 0;
188
*
block_first_pristine_offset_ptr
(
m_offset
) =
Header::SIZE
;
189
}
190
191
inline
uint8_t *
Header::next_available_slot
()
const
{
192
return
block_address
() + *
block_first_pristine_offset_ptr
(
m_offset
);
193
}
194
195
inline
uint8_t *
Header::block_address
()
const
{
return
m_offset
; }
196
197
inline
Source
Header::memory_source_type
()
const
{
198
return
static_cast<
Source
>
(*
block_memory_type_ptr
(
m_offset
));
199
}
200
201
inline
size_t
Header::block_size
()
const
{
202
return
static_cast<
size_t
>
(*
block_size_ptr
(
m_offset
));
203
}
204
205
inline
size_t
Header::number_of_used_chunks
()
const
{
206
return
static_cast<
size_t
>
(*
block_number_of_used_chunks_ptr
(
m_offset
));
207
}
208
209
inline
size_t
Header::first_pristine_offset
()
const
{
210
return
static_cast<
size_t
>
(*
block_first_pristine_offset_ptr
(
m_offset
));
211
}
212
213
inline
size_t
Header::increment_number_of_used_chunks
(
size_t
chunk_size) {
214
*
block_first_pristine_offset_ptr
(
m_offset
) += chunk_size;
215
return
++*
block_number_of_used_chunks_ptr
(
m_offset
);
216
}
217
218
inline
size_t
Header::decrement_number_of_used_chunks
(
size_t
chunk_size,
219
bool
rightmost_chunk) {
220
assert(*
block_number_of_used_chunks_ptr
(
m_offset
) > 0);
221
if
(--*
block_number_of_used_chunks_ptr
(
m_offset
) == 0) {
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
*/
226
*
block_first_pristine_offset_ptr
(
m_offset
) =
Header::SIZE
;
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
*/
231
*
block_first_pristine_offset_ptr
(
m_offset
) -= chunk_size;
232
}
233
return
*
block_number_of_used_chunks_ptr
(
m_offset
);
234
}
235
236
inline
void
Header::reset
() {
m_offset
=
nullptr
; }
237
238
inline
Header::metadata_type
*
Header::block_memory_type_ptr
(uint8_t *block) {
239
return
reinterpret_cast<
Header::metadata_type
*
>
(block);
240
}
241
242
inline
Header::metadata_type
*
Header::block_size_ptr
(uint8_t *block) {
243
return
reinterpret_cast<
Header::metadata_type
*
>
(
244
block + 1 *
sizeof
(
Header::metadata_type
));
245
}
246
247
inline
Header::metadata_type
*
Header::block_number_of_used_chunks_ptr
(
248
uint8_t *block) {
249
return
reinterpret_cast<
Header::metadata_type
*
>
(
250
block + 2 *
sizeof
(
Header::metadata_type
));
251
}
252
253
inline
Header::metadata_type
*
Header::block_first_pristine_offset_ptr
(
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 */
temptable::Header
Header is an abstraction with the purpose of holding and maintaining the Block metadata.
Definition:
header.h:74
temptable::Header::block_size_ptr
static Header::metadata_type * block_size_ptr(uint8_t *block)
Deduce a pointer to the size of given Block.
Definition:
header.h:242
temptable::Header::next_available_slot
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
temptable::Header::metadata_type
uintptr_t metadata_type
Type that we will be using for storing metadata information.
Definition:
header.h:77
temptable::Header::block_size
size_t block_size() const
Get the Block size.
Definition:
header.h:201
temptable::Header::reset
void reset()
Enable Block to reset the Header metadata upon Block destruction.
Definition:
header.h:236
temptable::Header::memory_source_type
Source memory_source_type() const
Get the Block Source type (memory where it resides).
Definition:
header.h:197
temptable::Header::Header
Header() noexcept
Default constructor which creates an empty Header.
Definition:
header.h:173
temptable::Header::block_number_of_used_chunks_ptr
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
temptable::Header::block_address
uint8_t * block_address() const
Enable Block to get its memory address.
Definition:
header.h:195
temptable::Header::increment_number_of_used_chunks
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
temptable::Header::block_memory_type_ptr
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
temptable::Header::m_offset
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
temptable::Header::block_first_pristine_offset_ptr
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
temptable::Header::SIZE
static constexpr size_t SIZE
Block header (metadata) size.
Definition:
header.h:80
temptable::Header::decrement_number_of_used_chunks
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
temptable::Header::first_pristine_offset
size_t first_pristine_offset() const
Get current first-pristine-offset.
Definition:
header.h:209
temptable::Header::number_of_used_chunks
size_t number_of_used_chunks() const
Get current number of Chunks allocated by the Block.
Definition:
header.h:205
memutils.h
Memory utilities for temptable-allocator.
temptable
Definition:
allocator.h:48
temptable::Source
Source
Type of memory allocated.
Definition:
memutils.h:68
storage
temptable
include
temptable
header.h
Generated by
1.9.2