MySQL 9.0.0
Source Code Documentation
ut0new.h
Go to the documentation of this file.
1/*****************************************************************************
2
3Copyright (c) 2014, 2024, Oracle and/or its affiliates.
4
5This program is free software; you can redistribute it and/or modify it under
6the terms of the GNU General Public License, version 2.0, as published by the
7Free Software Foundation.
8
9This program is designed to work with certain software (including
10but not limited to OpenSSL) that is licensed under separate terms,
11as designated in a particular file or component or in included license
12documentation. The authors of MySQL hereby grant you an additional
13permission to link the program and your derivative works with the
14separately licensed software that they have either included with
15the program or referenced in the documentation.
16
17This program is distributed in the hope that it will be useful, but WITHOUT
18ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
19FOR A PARTICULAR PURPOSE. See the GNU General Public License, version 2.0,
20for more details.
21
22You should have received a copy of the GNU General Public License along with
23this program; if not, write to the Free Software Foundation, Inc.,
2451 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
25
26*****************************************************************************/
27
28/** @file include/ut0new.h
29 Dynamic memory allocation routines and custom allocators specifically
30 crafted to support memory instrumentation through performance schema memory
31 engine (PFS).
32 */
33
34/** This file contains a set of libraries providing overloads for regular
35 dynamic allocation routines which allow for opt-in memory instrumentation
36 through performance schema memory engine (PFS).
37
38 In particular, _no_ regular dynamic allocation routines shall be used given
39 that the end goal of instrumentation through PFS is system observability
40 and resource control. In practice this means that we are off the chances to
41 use _any_ standard means of allocating the memory and that we have to
42 provide and re-implement our own PFS-aware variants ourselves.
43
44 This does not only apply to direct memory allocation through malloc or new
45 but also to data structures that may allocate dynamic memory under the hood,
46 like the ones from STL. For that reason, STL data structures shall always
47 be used with PFS-enabled custom memory allocator. STL algorithms OTOH
48 also _may_ allocate dynamic memory but they do not provide customization
49 point for user-code to provide custom memory allocation mechanism so there's
50 nothing that we can do about it.
51
52 Furthermore, facilities that allow safer memory management such as
53 std::unique_ptr, std::shared_ptr and their respective std::make_unique and
54 std::make_shared functions also have to be re-implemented as such so that
55 they become PFS-aware.
56
57 Following is the list of currently implemented PFS-enabled dynamic
58 allocation overloads and associated facilities:
59 * Primitive allocation functions:
60 * ut::malloc
61 * ut::zalloc
62 * ut::realloc
63 * ut::free
64 * ut::{malloc | zalloc | realloc}_withkey
65 * Primitive allocation functions for types with extended alignment:
66 * ut::aligned_alloc
67 * ut::aligned_zalloc
68 * ut::aligned_free
69 * ut::{aligned_alloc | aligned_zalloc}_withkey
70 * Primitive allocation functions for page-aligned allocations:
71 * ut::malloc_page
72 * ut::malloc_page_withkey
73 * ut::free_page
74 * Primitive allocation functions for large (huge) page aligned
75 allocations:
76 * ut::malloc_large_page
77 * ut::malloc_large_page_withkey
78 * ut::free_large_page
79 * Primitive allocation functions for large (huge) aligned allocations with
80 fallback to page-aligned allocations:
81 * ut::malloc_large_page(fallback_to_normal_page_t)
82 * ut::malloc_large_page_withkey(fallback_to_normal_page_t)
83 * ut::free_large_page(fallback_to_normal_page_t)
84 * Overloads for C++ new and delete syntax:
85 * ut::new_
86 * ut::new_arr
87 * ut::{new_ | new_arr_}_withkey
88 * ut::delete_
89 * ut::delete_arr
90 * Overloads for C++ new and delete syntax for types with extended
91 alignment:
92 * ut::aligned_new
93 * ut::aligned_new_arr
94 * ut::{aligned_new_ | aligned_new_arr_}_withkey
95 * ut::aligned_delete
96 * ut::aligned_delete_arr
97 * Custom memory allocators:
98 * ut::allocator
99 * Overloads for std::unique_ptr and std::shared_ptr factory functions
100 * ut::make_unique
101 * ut::make_unique_aligned
102 * ut::make_shared
103 * ut::make_shared_aligned
104 _withkey variants from above are the PFS-enabled dynamic allocation
105 overloads.
106
107 Usages of PFS-enabled library functions are trying to resemble already
108 familiar syntax as close as possible. For concrete examples please see
109 particular function documentation but in general it applies that ::foo(x)
110 becomes ut::foo(x) or ut::foo_withkey(key, x) where foo is some allocation
111 function listed above and key is PFS key to instrument the allocation with.
112*/
113
114#ifndef ut0new_h
115#define ut0new_h
116
117#include <algorithm>
118#include <cerrno>
119#include <cstddef>
120#include <cstdlib>
121#include <cstring>
122#include <limits>
123#include <list>
124#include <map>
125#include <memory>
126#include <set>
127#include <type_traits> /* std::is_trivially_default_constructible */
128#include <unordered_map>
129#include <unordered_set>
130
131#include "my_basename.h"
134#include "mysql/psi/psi_memory.h"
135
136namespace ut {
137/** Can be used to extract pointer and size of the allocation provided by the
138OS. It is a low level information, and is needed only to call low level
139memory-related OS functions. */
141 /** A pointer returned by the OS allocator. */
142 void *base_ptr;
143 /** The size of allocation that OS performed. */
145};
146} // namespace ut
147
148#include "detail/ut0new.h"
149#include "os0proc.h"
150#include "os0thread.h"
151#include "univ.i"
152#include "ut0byte.h" /* ut_align */
153#include "ut0cpu_cache.h"
154#include "ut0dbg.h"
155#include "ut0ut.h"
156
157namespace ut {
158
159/** Light-weight and type-safe wrapper around the PSI_memory_key
160 that eliminates the possibility of introducing silent bugs
161 through the course of implicit conversions and makes them
162 show up as compile-time errors.
163
164 Without this wrapper it was possible to say:
165 aligned_alloc_withkey(10*sizeof(int), key, 64))
166 Which would unfortunately compile just fine but it would silently
167 introduce a bug because it confuses the order of 10*sizeof(int) and
168 key input arguments. Both of them are unsigned types.
169
170 With the wrapper, aligned_alloc_withkey(10*sizeof(int), key, 64)) now
171 results with a compile-time error and the only proper way to accomplish
172 the original intent is to use PSI_memory_key_t wrapper like so:
173 aligned_alloc_withkey(PSI_memory_key_t{key}, 10*sizeof(int), 64))
174
175 Or by making use of the convenience function to create one:
176 aligned_alloc_withkey(make_psi_memory_key(key), 10*sizeof(int), 64))
177*/
180 PSI_memory_key operator()() const { return m_key; }
182};
183
184/** Convenience helper function to create type-safe representation of
185 PSI_memory_key.
186
187 @param[in] key PSI memory key to be held in type-safe PSI_memory_key_t.
188 @return PSI_memory_key_t which wraps the given PSI_memory_key
189 */
191 return PSI_memory_key_t(key);
192}
193
194} // namespace ut
195
196/** Maximum number of retries to allocate memory. */
197extern const size_t alloc_max_retries;
198
199/** Keys for registering allocations with performance schema.
200Pointers to these variables are supplied to PFS code via the pfs_info[]
201array and the PFS code initializes them via PSI_MEMORY_CALL(register_memory)().
202mem_key_other and mem_key_std are special in the following way.
203* If the caller has not provided a key and the file name of the caller is
204 unknown, then mem_key_std will be used. This happens only when called from
205 within std::* containers.
206* If the caller has not provided a key and the file name of the caller is
207 known, but is not amongst the predefined names (see ut_new_boot()) then
208 mem_key_other will be used. Generally this should not happen and if it
209 happens then that means that the list of predefined names must be extended.
210Keep this list alphabetically sorted. */
215/** Memory key for clone */
230/* Please obey alphabetical order in the definitions above. */
231
232/** Setup the internal objects needed for ut::*_withkey() to operate.
233This must be called before the first call to ut::*_withkey(). */
234void ut_new_boot();
235
236/** Setup the internal objects needed for ut::*_withkey() to operate.
237This must be called before the first call to ut::*_withkey(). This
238version of function might be called several times and it will
239simply skip all calls except the first one, during which the
240initialization will happen. */
241void ut_new_boot_safe();
242
243#ifdef UNIV_PFS_MEMORY
244
245/** List of filenames that allocate memory and are instrumented via PFS. */
246static constexpr const char *auto_event_names[] = {
247 /* Keep this list alphabetically sorted. */
248 "api0api",
249 "api0misc",
250 "btr0btr",
251 "btr0cur",
252 "btr0load",
253 "btr0pcur",
254 "btr0sea",
255 "btr0types",
256 "buf",
257 "buf0buddy",
258 "buf0buf",
259 "buf0checksum",
260 "buf0dblwr",
261 "buf0dump",
262 "buf0flu",
263 "buf0lru",
264 "buf0rea",
265 "buf0stats",
266 "buf0types",
267 "checksum",
268 "crc32",
269 "create",
270 "data0data",
271 "data0type",
272 "data0types",
273 "db0err",
274 "ddl0buffer",
275 "ddl0builder",
276 "ddl0ctx",
277 "ddl0ddl",
278 "ddl0file-reader",
279 "ddl0loader",
280 "ddl0merge",
281 "ddl0rtree",
282 "ddl0par-scan",
283 "dict",
284 "dict0boot",
285 "dict0crea",
286 "dict0dd",
287 "dict0dict",
288 "dict0load",
289 "dict0mem",
290 "dict0priv",
291 "dict0sdi",
292 "dict0stats",
293 "dict0stats_bg",
294 "dict0types",
295 "dyn0buf",
296 "dyn0types",
297 "eval0eval",
298 "eval0proc",
299 "fil0fil",
300 "fil0types",
301 "file",
302 "fsp0file",
303 "fsp0fsp",
304 "fsp0space",
305 "fsp0sysspace",
306 "fsp0types",
307 "fts0ast",
308 "fts0blex",
309 "fts0config",
310 "fts0fts",
311 "fts0opt",
312 "fts0pars",
313 "fts0plugin",
314 "fts0priv",
315 "fts0que",
316 "fts0sql",
317 "fts0tlex",
318 "fts0tokenize",
319 "fts0types",
320 "fts0vlc",
321 "fut0fut",
322 "fut0lst",
323 "gis0geo",
324 "gis0rtree",
325 "gis0sea",
326 "gis0type",
327 "ha0ha",
328 "ha0storage",
329 "ha_innodb",
330 "ha_innopart",
331 "ha_prototypes",
332 "handler0alter",
333 "hash0hash",
334 "i_s",
335 "ib0mutex",
336 "ibuf0ibuf",
337 "ibuf0types",
338 "lexyy",
339 "lob0lob",
340 "lock0iter",
341 "lock0lock",
342 "lock0prdt",
343 "lock0priv",
344 "lock0types",
345 "lock0wait",
346 "log0log",
347 "log0recv",
348 "log0write",
349 "mach0data",
350 "mem",
351 "mem0mem",
352 "memory",
353 "mtr0log",
354 "mtr0mtr",
355 "mtr0types",
356 "os0atomic",
357 "os0event",
358 "os0file",
359 "os0numa",
360 "os0once",
361 "os0proc",
362 "os0thread",
363 "page",
364 "page0cur",
365 "page0page",
366 "page0size",
367 "page0types",
368 "page0zip",
369 "pars0grm",
370 "pars0lex",
371 "pars0opt",
372 "pars0pars",
373 "pars0sym",
374 "pars0types",
375 "que0que",
376 "que0types",
377 "read0read",
378 "read0types",
379 "rec",
380 "rem0cmp",
381 "rem0rec",
382 "rem0types",
383 "row0ext",
384 "row0ft",
385 "row0import",
386 "row0ins",
387 "row0log",
388 "row0mysql",
389 "row0purge",
390 "row0quiesce",
391 "row0row",
392 "row0sel",
393 "row0types",
394 "row0uins",
395 "row0umod",
396 "row0undo",
397 "row0upd",
398 "row0vers",
399 "sess0sess",
400 "srv0conc",
401 "srv0mon",
402 "srv0srv",
403 "srv0start",
404 "srv0tmp",
405 "sync0arr",
406 "sync0debug",
407 "sync0policy",
408 "sync0sharded_rw",
409 "sync0rw",
410 "sync0sync",
411 "sync0types",
412 "trx0i_s",
413 "trx0purge",
414 "trx0rec",
415 "trx0roll",
416 "trx0rseg",
417 "trx0sys",
418 "trx0trx",
419 "trx0types",
420 "trx0undo",
421 "trx0xa",
422 "usr0sess",
423 "usr0types",
424 "ut",
425 "ut0byte",
426 "ut0counter",
427 "ut0crc32",
428 "ut0dbg",
429 "ut0link_buf",
430 "ut0list",
431 "ut0lock_free_hash",
432 "ut0lst",
433 "ut0mem",
434 "ut0mutex",
435 "ut0new",
436 "ut0object_cache",
437 "ut0pool",
438 "ut0rbt",
439 "ut0rnd",
440 "ut0sort",
441 "ut0stage",
442 "ut0ut",
443 "ut0vec",
444 "ut0wqueue",
445 "zipdecompress",
446};
447
448static constexpr size_t n_auto = UT_ARR_SIZE(auto_event_names);
451
452/** gcc 5 fails to evaluate costexprs at compile time. */
453#if defined(__GNUG__) && (__GNUG__ == 5)
454
455/** Compute whether a string begins with a given prefix, compile-time.
456@param[in] a first string, taken to be zero-terminated
457@param[in] b second string (prefix to search for)
458@param[in] b_len length in bytes of second string
459@param[in] index character index to start comparing at
460@return whether b is a prefix of a */
461constexpr bool ut_string_begins_with(const char *a, const char *b, size_t b_len,
462 size_t index = 0) {
463 return (index == b_len || (a[index] == b[index] &&
464 ut_string_begins_with(a, b, b_len, index + 1)));
465}
466
467/** Find the length of the filename without its file extension.
468@param[in] file filename, with extension but without directory
469@param[in] index character index to start scanning for extension
470 separator at
471@return length, in bytes */
472constexpr size_t ut_len_without_extension(const char *file, size_t index = 0) {
473 return ((file[index] == '\0' || file[index] == '.')
474 ? index
475 : ut_len_without_extension(file, index + 1));
476}
477
478/** Retrieve a memory key (registered with PFS), given the file name of the
479caller.
480@param[in] file portion of the filename - basename, with extension
481@param[in] len length of the filename to check for
482@param[in] index index of first PSI key to check
483@return registered memory key or PSI_NOT_INSTRUMENTED if not found */
485 size_t len,
486 size_t index = 0) {
487 return ((index == n_auto)
490 ? auto_event_keys[index]
491 : ut_new_get_key_by_base_file(file, len, index + 1)));
492}
493
494/** Retrieve a memory key (registered with PFS), given the file name of
495the caller.
496@param[in] file portion of the filename - basename, with extension
497@return registered memory key or PSI_NOT_INSTRUMENTED if not found */
498constexpr PSI_memory_key ut_new_get_key_by_file(const char *file) {
500}
501
502#define UT_NEW_THIS_FILE_PSI_KEY ut_new_get_key_by_file(MY_BASENAME)
503
504#else /* __GNUG__ == 5 */
505
506/** Compute whether a string begins with a given prefix, compile-time.
507@param[in] a first string, taken to be zero-terminated
508@param[in] b second string (prefix to search for)
509@param[in] b_len length in bytes of second string
510@return whether b is a prefix of a */
511constexpr bool ut_string_begins_with(const char *a, const char *b,
512 size_t b_len) {
513 for (size_t i = 0; i < b_len; ++i) {
514 if (a[i] != b[i]) {
515 return false;
516 }
517 }
518 return true;
519}
520
521/** Find the length of the filename without its file extension.
522@param[in] file filename, with extension but without directory
523@return length, in bytes */
524constexpr size_t ut_len_without_extension(const char *file) {
525 for (size_t i = 0;; ++i) {
526 if (file[i] == '\0' || file[i] == '.') {
527 return i;
528 }
529 }
530}
531
532/** Retrieve a memory key (registered with PFS), given the file name of the
533caller.
534@param[in] file portion of the filename - basename, with extension
535@param[in] len length of the filename to check for
536@return index to registered memory key or -1 if not found */
537constexpr int ut_new_get_key_by_base_file(const char *file, size_t len) {
538 for (size_t i = 0; i < n_auto; ++i) {
540 return static_cast<int>(i);
541 }
542 }
543 return -1;
544}
545
546/** Retrieve a memory key (registered with PFS), given the file name of
547the caller.
548@param[in] file portion of the filename - basename, with extension
549@return index to memory key or -1 if not found */
550constexpr int ut_new_get_key_by_file(const char *file) {
552}
553
554// Sending an expression through a template variable forces the compiler to
555// evaluate the expression at compile time (constexpr in itself has no such
556// guarantee, only that the compiler is allowed).
557template <int Value>
559 static constexpr int value = Value;
560};
561
562#define UT_NEW_THIS_FILE_PSI_INDEX \
563 (force_constexpr<ut_new_get_key_by_file(MY_BASENAME)>::value)
564
565#define UT_NEW_THIS_FILE_PSI_KEY \
566 (UT_NEW_THIS_FILE_PSI_INDEX == -1 \
567 ? ut::make_psi_memory_key(PSI_NOT_INSTRUMENTED) \
568 : ut::make_psi_memory_key(auto_event_keys[UT_NEW_THIS_FILE_PSI_INDEX]))
569
570#endif /* __GNUG__ == 5 */
571
572#else
573
574#define UT_NEW_THIS_FILE_PSI_KEY ut::make_psi_memory_key(PSI_NOT_INSTRUMENTED)
575
576#endif /* UNIV_PFS_MEMORY */
577
578namespace ut {
579
580#ifdef HAVE_PSI_MEMORY_INTERFACE
581constexpr bool WITH_PFS_MEMORY = true;
582#else
583constexpr bool WITH_PFS_MEMORY = false;
584#endif
585
586/** Dynamically allocates storage of given size. Instruments the memory with
587 given PSI memory key in case PFS memory support is enabled.
588
589 @param[in] key PSI memory key to be used for PFS memory instrumentation.
590 @param[in] size Size of storage (in bytes) requested to be allocated.
591 @return Pointer to the allocated storage. nullptr if dynamic storage
592 allocation failed.
593
594 Example:
595 int *x = static_cast<int*>(ut::malloc_withkey(key, 10*sizeof(int)));
596 */
597inline void *malloc_withkey(PSI_memory_key_t key, std::size_t size) noexcept {
599 using malloc_impl = detail::Alloc_<impl>;
600 return malloc_impl::alloc<false>(size, key());
601}
602
603/** Dynamically allocates storage of given size.
604
605 NOTE: Given that this function will _NOT_ be instrumenting the allocation
606 through PFS, observability for particular parts of the system which want to
607 use it will be lost or in best case inaccurate. Please have a strong reason
608 to do so.
609
610 @param[in] size Size of storage (in bytes) requested to be allocated.
611 @return Pointer to the allocated storage. nullptr if dynamic storage
612 allocation failed.
613
614 Example:
615 int *x = static_cast<int*>(ut::malloc_withkey(UT_NEW_THIS_FILE_PSI_KEY,
616 10*sizeof(int)));
617 */
618inline void *malloc(std::size_t size) noexcept {
620}
621
622/** Dynamically allocates zero-initialized storage of given size. Instruments
623 the memory with given PSI memory key in case PFS memory support is enabled.
624
625 @param[in] key PSI memory key to be used for PFS memory instrumentation.
626 @param[in] size Size of storage (in bytes) requested to be allocated.
627 @return Pointer to the zero-initialized allocated storage. nullptr if
628 dynamic storage allocation failed.
629
630 Example:
631 int *x = static_cast<int*>(ut::zalloc_withkey(key, 10*sizeof(int)));
632 */
633inline void *zalloc_withkey(PSI_memory_key_t key, std::size_t size) noexcept {
635 using malloc_impl = detail::Alloc_<impl>;
636 return malloc_impl::alloc<true>(size, key());
637}
638
639/** Dynamically allocates zero-initialized storage of given size.
640
641 NOTE: Given that this function will _NOT_ be instrumenting the allocation
642 through PFS, observability for particular parts of the system which want to
643 use it will be lost or in best case inaccurate. Please have a strong reason
644 to do so.
645
646 @param[in] size Size of storage (in bytes) requested to be allocated.
647 @return Pointer to the zero-initialized allocated storage. nullptr if
648 dynamic storage allocation failed.
649
650 Example:
651 int *x = static_cast<int*>(ut::zalloc_withkey(UT_NEW_THIS_FILE_PSI_KEY,
652 10*sizeof(int)));
653 */
654inline void *zalloc(std::size_t size) noexcept {
656}
657
658/** Upsizes or downsizes already dynamically allocated storage to the new size.
659 Instruments the memory with given PSI memory key in case PFS memory support
660 is enabled.
661
662 It also supports standard realloc() semantics by:
663 * allocating size bytes of memory when passed ptr is nullptr
664 * freeing the memory pointed by ptr if passed size is 0
665
666 @param[in] key PSI memory key to be used for PFS memory instrumentation.
667 @param[in] ptr Pointer to the memory area to be reallocated.
668 @param[in] size New size of storage (in bytes) requested to be reallocated.
669 @return Pointer to the reallocated storage. nullptr if dynamic storage
670 allocation failed.
671
672 Example:
673 int *x = static_cast<int*>(ut::malloc_withkey(key, 10*sizeof(int));
674 x = static_cast<int*>(ut::realloc_withkey(key, ptr, 100*sizeof(int)));
675 */
676inline void *realloc_withkey(PSI_memory_key_t key, void *ptr,
677 std::size_t size) noexcept {
679 using malloc_impl = detail::Alloc_<impl>;
680 return malloc_impl::realloc(ptr, size, key());
681}
682
683/** Upsizes or downsizes already dynamically allocated storage to the new size.
684
685 It also supports standard realloc() semantics by:
686 * allocating size bytes of memory when passed ptr is nullptr
687 * freeing the memory pointed by ptr if passed size is 0
688
689 NOTE: Given that this function will _NOT_ be instrumenting the allocation
690 through PFS, observability for particular parts of the system which want to
691 use it will be lost or in best case inaccurate. Please have a strong reason
692 to do so.
693
694 @param[in] ptr Pointer to the memory area to be reallocated.
695 @param[in] size New size of storage (in bytes) requested to be reallocated.
696 @return Pointer to the reallocated storage. nullptr if dynamic storage
697 allocation failed.
698
699 Example:
700 int *x = static_cast<int*>(ut::malloc_withkey(UT_NEW_THIS_FILE_PSI_KEY,
701 10*sizeof(int)); x = static_cast<int*>(ut::realloc(key, ptr,
702 100*sizeof(int)));
703 */
704inline void *realloc(void *ptr, std::size_t size) noexcept {
706 size);
707}
708
709/** Releases storage which has been dynamically allocated through any of
710 the ut::malloc*(), ut::realloc* or ut::zalloc*() variants.
711
712 @param[in] ptr Pointer which has been obtained through any of the
713 ut::malloc*(), ut::realloc* or ut::zalloc*() variants.
714
715 Example:
716 ut::free(ptr);
717 */
718inline void free(void *ptr) noexcept {
720 using malloc_impl = detail::Alloc_<impl>;
722}
723
724/** Dynamically allocates storage for an object of type T. Constructs the object
725 of type T with provided Args. Instruments the memory with given PSI memory
726 key in case PFS memory support is enabled.
727
728 @param[in] key PSI memory key to be used for PFS memory instrumentation.
729 @param[in] args Arguments one wishes to pass over to T constructor(s)
730 @return Pointer to the allocated storage. Throws std::bad_alloc exception
731 if dynamic storage allocation could not be fulfilled. Re-throws whatever
732 exception that may have occurred during the construction of T, in which case
733 it automatically cleans up the raw memory allocated for it.
734
735 Example 1:
736 int *ptr = ut::new_withkey<int>(key);
737
738 Example 2:
739 int *ptr = ut::new_withkey<int>(key, 10);
740 assert(*ptr == 10);
741
742 Example 3:
743 struct A {
744 A(int x, int y) : _x(x), _y(y) {}
745 int _x, _y;
746 };
747 A *ptr = ut::new_withkey<A>(key, 1, 2);
748 assert(ptr->_x == 1);
749 assert(ptr->_y == 2);
750 */
751template <typename T, typename... Args>
752inline T *new_withkey(PSI_memory_key_t key, Args &&... args) {
753 auto mem = ut::malloc_withkey(key, sizeof(T));
754 if (unlikely(!mem)) throw std::bad_alloc();
755 try {
756 new (mem) T(std::forward<Args>(args)...);
757 } catch (...) {
758 ut::free(mem);
759 throw;
760 }
761 return static_cast<T *>(mem);
762}
763
764/** Dynamically allocates storage for an object of type T. Constructs the object
765 of type T with provided Args.
766
767 NOTE: Given that this function will _NOT_ be instrumenting the allocation
768 through PFS, observability for particular parts of the system which want to
769 use it will be lost or in best case inaccurate. Please have a strong reason
770 to do so.
771
772 @param[in] args Arguments one wishes to pass over to T constructor(s)
773 @return Pointer to the allocated storage. Throws std::bad_alloc exception
774 if dynamic storage allocation could not be fulfilled. Re-throws whatever
775 exception that may have occurred during the construction of T, in which case
776 it automatically cleans up the raw memory allocated for it.
777
778 Example 1:
779 int *ptr = ut::new_withkey<int>(UT_NEW_THIS_FILE_PSI_KEY);
780
781 Example 2:
782 int *ptr = ut::new_withkey<int>(UT_NEW_THIS_FILE_PSI_KEY, 10);
783 assert(*ptr == 10);
784
785 Example 3:
786 struct A {
787 A(int x, int y) : _x(x), _y(y) {}
788 int _x, _y;
789 };
790 A *ptr = ut::new_withkey<A>(UT_NEW_THIS_FILE_PSI_KEY, 1, 2);
791 assert(ptr->_x == 1);
792 assert(ptr->_y == 2);
793 */
794template <typename T, typename... Args>
795inline T *new_(Args &&... args) {
796 return ut::new_withkey<T>(make_psi_memory_key(PSI_NOT_INSTRUMENTED),
797 std::forward<Args>(args)...);
798}
799
800/** Releases storage which has been dynamically allocated through any of
801 the ut::new*() variants. Destructs the object of type T.
802
803 @param[in] ptr Pointer which has been obtained through any of the
804 ut::new*() variants
805
806 Example:
807 ut::delete_(ptr);
808 */
809template <typename T>
810inline void delete_(T *ptr) noexcept {
811 if (unlikely(!ptr)) return;
812 ptr->~T();
813 ut::free(ptr);
814}
815
816/** Dynamically allocates storage for an array of T's. Constructs objects of
817 type T with provided Args. Arguments that are to be used to construct some
818 respective instance of T shall be wrapped into a std::tuple. See examples
819 down below. Instruments the memory with given PSI memory key in case PFS
820 memory support is enabled.
821
822 To create an array of default-intialized T's, one can use this function
823 template but for convenience purposes one can achieve the same by using
824 the ut::new_arr_withkey with ut::Count overload.
825
826 @param[in] key PSI memory key to be used for PFS memory instrumentation.
827 @param[in] args Tuples of arguments one wishes to pass over to T
828 constructor(s).
829 @return Pointer to the first element of allocated storage. Throws
830 std::bad_alloc exception if dynamic storage allocation could not be
831 fulfilled. Re-throws whatever exception that may have occurred during the
832 construction of any instance of T, in which case it automatically destroys
833 successfully constructed objects till that moment (if any), and finally
834 cleans up the raw memory allocated for T instances.
835
836 Example 1:
837 int *ptr = ut::new_arr_withkey<int>(key,
838 std::forward_as_tuple(1),
839 std::forward_as_tuple(2));
840 assert(ptr[0] == 1);
841 assert(ptr[1] == 2);
842
843 Example 2:
844 struct A {
845 A(int x, int y) : _x(x), _y(y) {}
846 int _x, _y;
847 };
848 A *ptr = ut::new_arr_withkey<A>(key,
849 std::forward_as_tuple(0, 1), std::forward_as_tuple(2, 3),
850 std::forward_as_tuple(4, 5), std::forward_as_tuple(6, 7),
851 std::forward_as_tuple(8, 9));
852 assert(ptr[0]->_x == 0 && ptr[0]->_y == 1);
853 assert(ptr[1]->_x == 2 && ptr[1]->_y == 3);
854 assert(ptr[2]->_x == 4 && ptr[2]->_y == 5);
855 assert(ptr[3]->_x == 6 && ptr[3]->_y == 7);
856 assert(ptr[4]->_x == 8 && ptr[4]->_y == 9);
857
858 Example 3:
859 struct A {
860 A() : _x(10), _y(100) {}
861 A(int x, int y) : _x(x), _y(y) {}
862 int _x, _y;
863 };
864 A *ptr = ut::new_arr_withkey<A>(key,
865 std::forward_as_tuple(0, 1), std::forward_as_tuple(2, 3),
866 std::forward_as_tuple(), std::forward_as_tuple(6, 7),
867 std::forward_as_tuple());
868 assert(ptr[0]->_x == 0 && ptr[0]->_y == 1);
869 assert(ptr[1]->_x == 2 && ptr[1]->_y == 3);
870 assert(ptr[2]->_x == 10 && ptr[2]->_y == 100);
871 assert(ptr[3]->_x == 6 && ptr[3]->_y == 7);
872 assert(ptr[4]->_x == 10 && ptr[4]->_y == 100);
873 */
874template <typename T, typename... Args>
875inline T *new_arr_withkey(PSI_memory_key_t key, Args &&... args) {
877 using malloc_impl = detail::Alloc_<impl>;
878 auto mem = malloc_impl::alloc<false>(sizeof(T) * sizeof...(args), key());
879 if (unlikely(!mem)) throw std::bad_alloc();
880
881 size_t idx = 0;
882 try {
883 (...,
884 detail::construct<T>(mem, sizeof(T) * idx++, std::forward<Args>(args)));
885 } catch (...) {
886 for (size_t offset = (idx - 1) * sizeof(T); offset != 0;
887 offset -= sizeof(T)) {
888 reinterpret_cast<T *>(reinterpret_cast<std::uintptr_t>(mem) + offset -
889 sizeof(T))
890 ->~T();
891 }
893 throw;
894 }
895 return static_cast<T *>(mem);
896}
897
898/** Dynamically allocates storage for an array of T's. Constructs objects of
899 type T with provided Args. Arguments that are to be used to construct some
900 respective instance of T shall be wrapped into a std::tuple. See examples
901 down below.
902
903 To create an array of default-intialized T's, one can use this function
904 template but for convenience purposes one can achieve the same by using
905 the ut::new_arr_withkey with ut::Count overload.
906
907 NOTE: Given that this function will _NOT_ be instrumenting the allocation
908 through PFS, observability for particular parts of the system which want to
909 use it will be lost or in best case inaccurate. Please have a strong reason
910 to do so.
911
912 @param[in] args Tuples of arguments one wishes to pass over to T
913 constructor(s).
914 @return Pointer to the first element of allocated storage. Throws
915 std::bad_alloc exception if dynamic storage allocation could not be
916 fulfilled. Re-throws whatever exception that may have occurred during the
917 construction of any instance of T, in which case it automatically destroys
918 successfully constructed objects till that moment (if any), and finally
919 cleans up the raw memory allocated for T instances.
920
921 Example 1:
922 int *ptr = ut::new_arr_withkey<int>(UT_NEW_THIS_FILE_PSI_KEY,
923 std::forward_as_tuple(1),
924 std::forward_as_tuple(2));
925 assert(ptr[0] == 1);
926 assert(ptr[1] == 2);
927
928 Example 2:
929 struct A {
930 A(int x, int y) : _x(x), _y(y) {}
931 int _x, _y;
932 };
933 A *ptr = ut::new_arr_withkey<A>(UT_NEW_THIS_FILE_PSI_KEY,
934 std::forward_as_tuple(0, 1), std::forward_as_tuple(2, 3),
935 std::forward_as_tuple(4, 5), std::forward_as_tuple(6, 7),
936 std::forward_as_tuple(8, 9));
937 assert(ptr[0]->_x == 0 && ptr[0]->_y == 1);
938 assert(ptr[1]->_x == 2 && ptr[1]->_y == 3);
939 assert(ptr[2]->_x == 4 && ptr[2]->_y == 5);
940 assert(ptr[3]->_x == 6 && ptr[3]->_y == 7);
941 assert(ptr[4]->_x == 8 && ptr[4]->_y == 9);
942
943 Example 3:
944 struct A {
945 A() : _x(10), _y(100) {}
946 A(int x, int y) : _x(x), _y(y) {}
947 int _x, _y;
948 };
949 A *ptr = ut::new_arr_withkey<A>(UT_NEW_THIS_FILE_PSI_KEY,
950 std::forward_as_tuple(0, 1), std::forward_as_tuple(2, 3),
951 std::forward_as_tuple(), std::forward_as_tuple(6, 7),
952 std::forward_as_tuple());
953 assert(ptr[0]->_x == 0 && ptr[0]->_y == 1);
954 assert(ptr[1]->_x == 2 && ptr[1]->_y == 3);
955 assert(ptr[2]->_x == 10 && ptr[2]->_y == 100);
956 assert(ptr[3]->_x == 6 && ptr[3]->_y == 7);
957 assert(ptr[4]->_x == 10 && ptr[4]->_y == 100);
958 */
959template <typename T, typename... Args>
960inline T *new_arr(Args &&... args) {
961 return ut::new_arr_withkey<T>(make_psi_memory_key(PSI_NOT_INSTRUMENTED),
962 std::forward<Args>(args)...);
963}
964
965/** Light-weight and type-safe wrapper which serves a purpose of
966 being able to select proper ut::new_arr* overload.
967
968 Without having a separate overload with this type, creating an array of
969 default-initialized instances of T through the ut::new_arr*(Args &&... args)
970 overload would have been impossible because:
971 int *ptr = ut::new_arr_withkey<int>(UT_NEW_THIS_FILE_PSI_KEY, 5);
972 wouldn't even compile and
973 int *ptr = ut::new_arr_withkey<int>(UT_NEW_THIS_FILE_PSI_KEY,
974 std::forward_as_tuple(5)); would compile but would not have intended effect.
975 It would create an array holding 1 integer element that is initialized to 5.
976
977 Given that function templates cannot be specialized, having an overload
978 crafted specifically for given case solves the problem:
979 int *ptr = ut::new_arr_withkey<int>(UT_NEW_THIS_FILE_PSI_KEY,
980 ut::Count{5});
981*/
982struct Count {
983 explicit Count(size_t count) : m_count(count) {}
984 size_t operator()() const { return m_count; }
985 size_t m_count;
986};
987
988/** Dynamically allocates storage for an array of T's. Constructs objects of
989 type T using default constructor. If T cannot be default-initialized (e.g.
990 default constructor does not exist), then this interface cannot be used for
991 constructing such an array. ut::new_arr_withkey overload with user-provided
992 initialization must be used then. Instruments the memory with given PSI
993 memory key in case PFS memory support is enabled.
994
995 @param[in] key PSI memory key to be used for PFS memory instrumentation.
996 @param[in] count Number of T elements in an array.
997 @return Pointer to the first element of allocated storage. Throws
998 std::bad_alloc exception if dynamic storage allocation could not be
999 fulfilled. Re-throws whatever exception that may have occurred during the
1000 construction of any instance of T, in which case it automatically destroys
1001 successfully constructed objects till that moment (if any), and finally
1002 cleans up the raw memory allocated for T instances.
1003
1004 Example 1:
1005 int *ptr = ut::new_arr_withkey<int>(key, ut::Count{2});
1006
1007 Example 2:
1008 struct A {
1009 A() : _x(10), _y(100) {}
1010 int _x, _y;
1011 };
1012 A *ptr = ut::new_arr_withkey<A>(key, ut::Count{5});
1013 assert(ptr[0]->_x == 10 && ptr[0]->_y == 100);
1014 assert(ptr[1]->_x == 10 && ptr[1]->_y == 100);
1015 assert(ptr[2]->_x == 10 && ptr[2]->_y == 100);
1016 assert(ptr[3]->_x == 10 && ptr[3]->_y == 100);
1017 assert(ptr[4]->_x == 10 && ptr[4]->_y == 100);
1018
1019 Example 3:
1020 struct A {
1021 A(int x, int y) : _x(x), _y(y) {}
1022 int _x, _y;
1023 };
1024 // Following cannot compile because A is not default-constructible
1025 A *ptr = ut::new_arr_withkey<A>(key, ut::Count{5});
1026 */
1027template <typename T>
1030 using malloc_impl = detail::Alloc_<impl>;
1031 auto mem = malloc_impl::alloc<false>(sizeof(T) * count(), key());
1032 if (unlikely(!mem)) throw std::bad_alloc();
1033
1034 size_t offset = 0;
1035 try {
1036 for (; offset < sizeof(T) * count(); offset += sizeof(T)) {
1037 new (reinterpret_cast<uint8_t *>(mem) + offset) T{};
1038 }
1039 } catch (...) {
1040 for (; offset != 0; offset -= sizeof(T)) {
1041 reinterpret_cast<T *>(reinterpret_cast<std::uintptr_t>(mem) + offset -
1042 sizeof(T))
1043 ->~T();
1044 }
1046 throw;
1047 }
1048 return static_cast<T *>(mem);
1049}
1050
1051/** Dynamically allocates storage for an array of T's. Constructs objects of
1052 type T using default constructor. If T cannot be default-initialized (e.g.
1053 default constructor does not exist), then this interface cannot be used for
1054 constructing such an array. ut::new_arr overload with user-provided
1055 initialization must be used then.
1056
1057 NOTE: Given that this function will _NOT_ be instrumenting the allocation
1058 through PFS, observability for particular parts of the system which want to
1059 use it will be lost or in best case inaccurate. Please have a strong reason
1060 to do so.
1061
1062 @param[in] count Number of T elements in an array.
1063 @return Pointer to the first element of allocated storage. Throws
1064 std::bad_alloc exception if dynamic storage allocation could not be
1065 fulfilled. Re-throws whatever exception that may have occurred during the
1066 construction of any instance of T, in which case it automatically destroys
1067 successfully constructed objects till that moment (if any), and finally
1068 cleans up the raw memory allocated for T instances.
1069
1070 Example 1:
1071 int *ptr = ut::new_arr_withkey<int>(UT_NEW_THIS_FILE_PSI_KEY,
1072 ut::Count{2});
1073
1074 Example 2:
1075 struct A {
1076 A() : _x(10), _y(100) {}
1077 int _x, _y;
1078 };
1079 A *ptr = ut::new_arr_withkey<A>(UT_NEW_THIS_FILE_PSI_KEY, ut::Count{5});
1080 assert(ptr[0]->_x == 10 && ptr[0]->_y == 100);
1081 assert(ptr[1]->_x == 10 && ptr[1]->_y == 100);
1082 assert(ptr[2]->_x == 10 && ptr[2]->_y == 100);
1083 assert(ptr[3]->_x == 10 && ptr[3]->_y == 100);
1084 assert(ptr[4]->_x == 10 && ptr[4]->_y == 100);
1085
1086 Example 3:
1087 struct A {
1088 A(int x, int y) : _x(x), _y(y) {}
1089 int _x, _y;
1090 };
1091 // Following cannot compile because A is not default-constructible
1092 A *ptr = ut::new_arr_withkey<A>(UT_NEW_THIS_FILE_PSI_KEY, ut::Count{5});
1093 */
1094template <typename T>
1095inline T *new_arr(Count count) {
1096 return ut::new_arr_withkey<T>(make_psi_memory_key(PSI_NOT_INSTRUMENTED),
1097 count);
1098}
1099
1100/** Releases storage which has been dynamically allocated through any of
1101 the ut::new_arr*() variants. Destructs all objects of type T.
1102
1103 @param[in] ptr Pointer which has been obtained through any of the
1104 ut::new_arr*() variants
1105
1106 Example:
1107 ut::delete_arr(ptr);
1108 */
1109template <typename T>
1110inline void delete_arr(T *ptr) noexcept {
1111 if (unlikely(!ptr)) return;
1113 using malloc_impl = detail::Alloc_<impl>;
1114 const auto data_len = malloc_impl::datalen(ptr);
1115 for (size_t offset = 0; offset < data_len; offset += sizeof(T)) {
1116 reinterpret_cast<T *>(reinterpret_cast<std::uintptr_t>(ptr) + offset)->~T();
1117 }
1118 malloc_impl::free(ptr);
1119}
1120
1121/** Returns number of bytes that ut::malloc_*, ut::zalloc_*, ut::realloc_* and
1122 ut::new_* variants will be using to store the necessary metadata for PFS.
1123
1124 @return Size of the PFS metadata.
1125*/
1126inline size_t pfs_overhead() noexcept {
1128 using malloc_impl = detail::Alloc_<impl>;
1130}
1131
1132/** Dynamically allocates system page-aligned storage of given size. Instruments
1133 the memory with given PSI memory key in case PFS memory support is enabled.
1134
1135 Actual page-alignment, and thus page-size, will depend on CPU architecture
1136 but in general page is traditionally mostly 4K large. In contrast to Unices,
1137 Windows do make an exception here and implement 64K granularity on top of
1138 regular page-size for some legacy reasons. For more details see:
1139 https://devblogs.microsoft.com/oldnewthing/20031008-00/?p=42223
1140
1141 @param[in] key PSI memory key to be used for PFS memory instrumentation.
1142 @param[in] size Size of storage (in bytes) requested to be allocated.
1143 @return Pointer to the page-aligned storage. nullptr if dynamic storage
1144 allocation failed.
1145
1146 Example:
1147 int *x = static_cast<int*>(ut::malloc_page_withkey(key, 10*sizeof(int)));
1148 */
1150 std::size_t size) noexcept {
1152 using page_alloc_impl = detail::Page_alloc_<impl>;
1153 return page_alloc_impl::alloc(size, key());
1154}
1155
1156/** Dynamically allocates system page-aligned storage of given size.
1157
1158 Actual page-alignment, and thus page-size, will depend on CPU architecture
1159 but in general page is traditionally mostly 4K large. In contrast to Unices,
1160 Windows do make an exception here and implement 64K granularity on top of
1161 regular page-size for some legacy reasons. For more details see:
1162 https://devblogs.microsoft.com/oldnewthing/20031008-00/?p=42223
1163
1164 NOTE: Given that this function will _NOT_ be instrumenting the allocation
1165 through PFS, observability for particular parts of the system which want to
1166 use it will be lost or in best case inaccurate. Please have a strong reason
1167 to do so.
1168
1169 @param[in] size Size of storage (in bytes) requested to be allocated.
1170 @return Pointer to the page-aligned storage. nullptr if dynamic storage
1171 allocation failed.
1172
1173 Example:
1174 int *x = static_cast<int*>(ut::malloc_page(10*sizeof(int)));
1175 */
1176inline void *malloc_page(std::size_t size) noexcept {
1178 size);
1179}
1180
1181/** Retrieves the total amount of bytes that are available for application code
1182 to use.
1183
1184 Amount of bytes returned does _not_ have to match bytes requested
1185 through ut::malloc_page*(). This is so because bytes requested will always
1186 be implicitly rounded up to the next regular page size (e.g. 4K).
1187
1188 @param[in] ptr Pointer which has been obtained through any of the
1189 ut::malloc_page*() variants.
1190 @return Number of bytes available.
1191
1192 Example:
1193 int *x = static_cast<int*>(ut::malloc_page(10*sizeof(int)));
1194 assert(page_allocation_size(x) == CPU_PAGE_SIZE);
1195 */
1196inline size_t page_allocation_size(void *ptr) noexcept {
1198 using page_alloc_impl = detail::Page_alloc_<impl>;
1199 return page_alloc_impl::datalen(ptr);
1200}
1201
1202/** Retrieves the pointer and size of the allocation provided by the OS. It is a
1203 low level information, and is needed only to call low level memory-related
1204 OS functions.
1205
1206 @param[in] ptr Pointer which has been obtained through any of the
1207 ut::malloc_page*() variants.
1208 @return Low level OS allocation info.
1209 */
1212 using page_alloc_impl = detail::Page_alloc_<impl>;
1213 return page_alloc_impl::low_level_info(ptr);
1214}
1215
1216/** Releases storage which has been dynamically allocated through any of
1217 the ut::malloc_page*() variants.
1218
1219 @param[in] ptr Pointer which has been obtained through any of the
1220 ut::malloc_page*() variants.
1221 @return True if releasing the page-aligned memory was successful.
1222
1223 Example:
1224 ut::free_page(ptr);
1225 */
1226inline bool free_page(void *ptr) noexcept {
1228 using page_alloc_impl = detail::Page_alloc_<impl>;
1229 return page_alloc_impl::free(ptr);
1230}
1231
1232/** Dynamically allocates memory backed up by large (huge) pages. Instruments
1233 the memory with given PSI memory key in case PFS memory support is enabled.
1234
1235 For large (huge) pages to be functional, usually some steps in system admin
1236 preparation is required. Exact steps vary from system to system.
1237
1238 @param[in] key PSI memory key to be used for PFS memory instrumentation.
1239 @param[in] size Size of storage (in bytes) requested to be allocated.
1240 @return Pointer to the page-aligned storage. nullptr if dynamic storage
1241 allocation failed.
1242
1243 Example:
1244 int *x = static_cast<int*>(
1245 ut::malloc_large_page_withkey(key, 10*sizeof(int))
1246 );
1247 */
1249 std::size_t size) noexcept {
1251 using large_page_alloc_impl = detail::Large_alloc_<impl>;
1252 return large_page_alloc_impl::alloc(size, key());
1253}
1254
1255/** Dynamically allocates memory backed up by large (huge) pages.
1256
1257 For large (huge) pages to be functional, usually some steps in system admin
1258 preparation is required. Exact steps vary from system to system.
1259
1260 NOTE: Given that this function will _NOT_ be instrumenting the allocation
1261 through PFS, observability for particular parts of the system which want to
1262 use it will be lost or in best case inaccurate. Please have a strong reason
1263 to do so.
1264
1265 @param[in] size Size of storage (in bytes) requested to be allocated.
1266 @return Pointer to the page-aligned storage. nullptr if dynamic storage
1267 allocation failed.
1268
1269 Example:
1270 int *x = static_cast<int*>(ut::malloc_large_page(10*sizeof(int)));
1271 */
1272inline void *malloc_large_page(std::size_t size) noexcept {
1275}
1276
1277/** Retrieves the total amount of bytes that are available for application code
1278 to use.
1279
1280 Amount of bytes returned does _not_ have to match bytes requested
1281 through ut::malloc_large_page*(). This is so because bytes requested will
1282 always be implicitly rounded up to the next multiple of huge-page size (e.g.
1283 2MiB). Exact huge-page size value that is going to be used will be stored
1284 in large_page_default_size.
1285
1286 @param[in] ptr Pointer which has been obtained through any of the
1287 ut::malloc_large_page*() variants.
1288 @return Number of bytes available.
1289
1290 Example:
1291 int *x = static_cast<int*>(ut::malloc_large_page(10*sizeof(int)));
1292 assert(large_page_allocation_size(x) == HUGE_PAGE_SIZE);
1293 */
1294inline size_t large_page_allocation_size(void *ptr) noexcept {
1296 using large_page_alloc_impl = detail::Large_alloc_<impl>;
1297 return large_page_alloc_impl::datalen(ptr);
1298}
1299
1300/** Retrieves the pointer and size of the allocation provided by the OS. It is a
1301 low level information, and is needed only to call low level memory-related
1302 OS functions.
1303
1304 @param[in] ptr Pointer which has been obtained through any of the
1305 ut::malloc_large_page*() variants.
1306 @return Low level OS allocation info.
1307 */
1310 using large_page_alloc_impl = detail::Large_alloc_<impl>;
1311 return large_page_alloc_impl::low_level_info(ptr);
1312}
1313
1314/** Releases storage which has been dynamically allocated through any of
1315 the ut::malloc_large_page*() variants.
1316
1317 @param[in] ptr Pointer which has been obtained through any of the
1318 ut::malloc_large_page*() variants.
1319 @return True if releasing the large (huge) page-aligned memory was
1320 successful.
1321
1322 Example:
1323 ut::free_large_page(ptr);
1324 */
1325inline bool free_large_page(void *ptr) noexcept {
1327 using large_page_alloc_impl = detail::Large_alloc_<impl>;
1328 return large_page_alloc_impl::free(ptr);
1329}
1330
1331/* Helper type for tag-dispatch */
1333
1334/** Dynamically allocates memory backed up by large (huge) pages. In the event
1335 that large (huge) pages are unavailable or disabled explicitly through
1336 os_use_large_pages, it will fallback to dynamic allocation backed by
1337 page-aligned memory. Instruments the memory with given PSI memory key in
1338 case PFS memory support is enabled.
1339
1340 @param[in] key PSI memory key to be used for PFS memory instrumentation.
1341 @param[in] size Size of storage (in bytes) requested to be allocated.
1342 @param[in] large_pages_enabled If true, the large pages will be tried to be
1343 used.
1344 @return Pointer to the page-aligned storage. nullptr if dynamic storage
1345 allocation failed.
1346
1347 Example:
1348 int *x = static_cast<int*>(
1349 ut::malloc_large_page_withkey(
1350 key,
1351 10*sizeof(int),
1352 fallback_to_normal_page_t{}
1353 )
1354 );
1355 */
1358 bool large_pages_enabled = os_use_large_pages) noexcept {
1359 void *large_page_mem = nullptr;
1360 if (large_pages_enabled) {
1361 large_page_mem = malloc_large_page_withkey(key, size);
1362 }
1363 return large_page_mem ? large_page_mem : malloc_page_withkey(key, size);
1364}
1365
1366/** Dynamically allocates memory backed up by large (huge) pages. In the event
1367 that large (huge) pages are unavailable or disabled explicitly through
1368 os_use_large_pages, it will fallback to dynamic allocation backed by
1369 page-aligned memory.
1370
1371 NOTE: Given that this function will _NOT_ be instrumenting the allocation
1372 through PFS, observability for particular parts of the system which want to
1373 use it will be lost or in best case inaccurate. Please have a strong reason
1374 to do so.
1375
1376 @param[in] size Size of storage (in bytes) requested to be allocated.
1377 @param[in] large_pages_enabled If true, the large pages will be tried to be
1378 used.
1379 @return Pointer to the page-aligned storage. nullptr if dynamic storage
1380 allocation failed.
1381
1382 Example:
1383 int *x = static_cast<int*>(
1384 ut::malloc_large_page(
1385 10*sizeof(int),
1386 fallback_to_normal_page_t{}
1387 )
1388 );
1389 */
1391 std::size_t size, fallback_to_normal_page_t,
1392 bool large_pages_enabled = os_use_large_pages) noexcept {
1395 fallback_to_normal_page_t{}, large_pages_enabled);
1396}
1397
1398/** Retrieves the total amount of bytes that are available for application code
1399 to use.
1400
1401 Amount of bytes returned does _not_ have to match bytes requested
1402 through ut::malloc_large_page*(fallback_to_normal_page_t). This is so
1403 because bytes requested will always be implicitly rounded up to the next
1404 multiple of either huge-page size (e.g. 2MiB) or regular page size (e.g.
1405 4K).
1406
1407 @param[in] ptr Pointer which has been obtained through any of the
1408 ut::malloc_large_page*(fallback_to_normal_page_t) variants.
1409 @return Number of bytes available for use.
1410 */
1411inline size_t large_page_allocation_size(void *ptr,
1412 fallback_to_normal_page_t) noexcept {
1413 assert(ptr);
1415 using large_page_alloc_impl = detail::Large_alloc_<impl>;
1416 if (large_page_alloc_impl::page_type(ptr) == detail::Page_type::system_page)
1417 return ut::page_allocation_size(ptr);
1418 ut_a(large_page_alloc_impl::page_type(ptr) == detail::Page_type::large_page);
1420}
1421
1422/** Retrieves the pointer and size of the allocation provided by the OS. It is a
1423 low level information, and is needed only to call low level memory-related
1424 OS functions.
1425
1426 @param[in] ptr Pointer which has been obtained through any of the
1427 ut::malloc_large_page*(fallback_to_normal_page_t) variants.
1428 @return Low level OS allocation info.
1429 */
1431 void *ptr, fallback_to_normal_page_t) noexcept {
1432 assert(ptr);
1434 using large_page_alloc_impl = detail::Large_alloc_<impl>;
1435 if (large_page_alloc_impl::page_type(ptr) == detail::Page_type::system_page)
1436 return ut::page_low_level_info(ptr);
1437 ut_a(large_page_alloc_impl::page_type(ptr) == detail::Page_type::large_page);
1439}
1440
1441/** Releases storage which has been dynamically allocated through any of
1442 the ut::malloc_large_page*(fallback_to_normal_page_t) variants.
1443
1444 Whether the pointer is representing area backed up by regular or huge-pages,
1445 this function will know the difference and therefore act accordingly.
1446
1447 @param[in] ptr Pointer which has been obtained through any of the
1448 ut::malloc_large_page*(fallback_to_normal_page_t) variants.
1449 @return True if releasing the memory was successful.
1450
1451 Example:
1452 ut::free_large_page(ptr);
1453 */
1454inline bool free_large_page(void *ptr, fallback_to_normal_page_t) noexcept {
1456 using large_page_alloc_impl = detail::Large_alloc_<impl>;
1457
1458 if (!ptr) return false;
1459
1460 bool success;
1461 if (large_page_alloc_impl::page_type(ptr) == detail::Page_type::system_page) {
1462 success = free_page(ptr);
1463 } else {
1464 ut_a(large_page_alloc_impl::page_type(ptr) ==
1466 success = free_large_page(ptr);
1467 }
1468 assert(success);
1469 return success;
1470}
1471
1472/** Dynamically allocates storage of given size and at the address aligned to
1473 the requested alignment. Instruments the memory with given PSI memory key
1474 in case PFS memory support is enabled.
1475
1476 @param[in] key PSI memory key to be used for PFS memory instrumentation.
1477 @param[in] size Size of storage (in bytes) requested to be allocated.
1478 @param[in] alignment Alignment requirement for storage to be allocated.
1479 @return Pointer to the allocated storage. nullptr if dynamic storage
1480 allocation failed.
1481
1482 Example:
1483 int* x = static_cast<int*>(aligned_alloc_withkey(key, 10*sizeof(int), 64));
1484 */
1486 std::size_t alignment) noexcept {
1488 using aligned_alloc_impl = detail::Aligned_alloc_<impl>;
1489 return aligned_alloc_impl::alloc<false>(size, alignment, key());
1490}
1491
1492/** Dynamically allocates storage of given size and at the address aligned to
1493 the requested alignment.
1494
1495 NOTE: Given that this function will _NOT_ be instrumenting the allocation
1496 through PFS, observability for particular parts of the system which want to
1497 use it will be lost or in best case inaccurate. Please have a strong reason
1498 to do so.
1499
1500 @param[in] size Size of storage (in bytes) requested to be allocated.
1501 @param[in] alignment Alignment requirement for storage to be allocated.
1502 @return Pointer to the allocated storage. nullptr if dynamic storage
1503 allocation failed.
1504
1505 Example:
1506 int* x = static_cast<int*>(aligned_alloc(10*sizeof(int), 64));
1507 */
1508inline void *aligned_alloc(std::size_t size, std::size_t alignment) noexcept {
1510 alignment);
1511}
1512
1513/** Dynamically allocates zero-initialized storage of given size and at the
1514 address aligned to the requested alignment. Instruments the memory with
1515 given PSI memory key in case PFS memory support is enabled.
1516
1517 @param[in] key PSI memory key to be used for PFS memory instrumentation.
1518 @param[in] size Size of storage (in bytes) requested to be allocated.
1519 @param[in] alignment Alignment requirement for storage to be allocated.
1520 @return Pointer to the zero-initialized allocated storage. nullptr if
1521 dynamic storage allocation failed.
1522
1523 Example:
1524 int* x =
1525 static_cast<int*>(aligned_zalloc_withkey(key, 10*sizeof(int), 64));
1526 */
1528 std::size_t alignment) noexcept {
1530 using aligned_alloc_impl = detail::Aligned_alloc_<impl>;
1531 return aligned_alloc_impl::alloc<true>(size, alignment, key());
1532}
1533
1534/** Dynamically allocates zero-initialized storage of given size and at the
1535 address aligned to the requested alignment.
1536
1537 NOTE: Given that this function will _NOT_ be instrumenting the allocation
1538 through PFS, observability for particular parts of the system which want to
1539 use it will be lost or in best case inaccurate. Please have a strong reason
1540 to do so.
1541
1542 @param[in] size Size of storage (in bytes) requested to be allocated.
1543 @param[in] alignment Alignment requirement for storage to be allocated.
1544 @return Pointer to the zero-initialized allocated storage. nullptr if
1545 dynamic storage allocation failed.
1546
1547 Example:
1548 int* x = static_cast<int*>(aligned_zalloc(10*sizeof(int), 64));
1549 */
1550inline void *aligned_zalloc(std::size_t size, std::size_t alignment) noexcept {
1552 alignment);
1553}
1554
1555/** Releases storage which has been dynamically allocated through any of
1556 the aligned_alloc_*() or aligned_zalloc_*() variants.
1557
1558 @param[in] ptr Pointer which has been obtained through any of the
1559 aligned_alloc_*() or aligned_zalloc_*() variants.
1560
1561 Example:
1562 aligned_free(ptr);
1563 */
1564inline void aligned_free(void *ptr) noexcept {
1566 using aligned_alloc_impl = detail::Aligned_alloc_<impl>;
1568}
1569
1570/** Dynamically allocates storage for an object of type T at address aligned
1571 to the requested alignment. Constructs the object of type T with provided
1572 Args. Instruments the memory with given PSI memory key in case PFS memory
1573 support is enabled.
1574
1575 @param[in] key PSI memory key to be used for PFS memory instrumentation.
1576 @param[in] alignment Alignment requirement for storage to be allocated.
1577 @param[in] args Arguments one wishes to pass over to T constructor(s)
1578 @return Pointer to the allocated storage. Throws std::bad_alloc exception
1579 if dynamic storage allocation could not be fulfilled.
1580
1581 Example 1:
1582 int *ptr = aligned_new_withkey<int>(key, 2);
1583
1584 Example 2:
1585 int *ptr = aligned_new_withkey<int>(key, 2, 10);
1586 assert(*ptr == 10);
1587
1588 Example 3:
1589 struct A { A(int x, int y) : _x(x), _y(y) {} int x, y; }
1590 A *ptr = aligned_new_withkey<A>(key, 2, 1, 2);
1591 assert(ptr->x == 1);
1592 assert(ptr->y == 2);
1593 */
1594template <typename T, typename... Args>
1595inline T *aligned_new_withkey(PSI_memory_key_t key, std::size_t alignment,
1596 Args &&... args) {
1597 auto mem = aligned_alloc_withkey(key, sizeof(T), alignment);
1598 if (unlikely(!mem)) throw std::bad_alloc();
1599 try {
1600 new (mem) T(std::forward<Args>(args)...);
1601 } catch (...) {
1603 throw;
1604 }
1605 return static_cast<T *>(mem);
1606}
1607
1608/** Dynamically allocates storage for an object of type T at address aligned
1609 to the requested alignment. Constructs the object of type T with provided
1610 Args.
1611
1612 NOTE: Given that this function will _NOT_ be instrumenting the allocation
1613 through PFS, observability for particular parts of the system which want to
1614 use it will be lost or in best case inaccurate. Please have a strong reason
1615 to do so.
1616
1617 @param[in] alignment Alignment requirement for storage to be allocated.
1618 @param[in] args Arguments one wishes to pass over to T constructor(s)
1619 @return Pointer to the allocated storage. Throws std::bad_alloc exception
1620 if dynamic storage allocation could not be fulfilled.
1621
1622 Example 1:
1623 int *ptr = aligned_new<int>(2);
1624
1625 Example 2:
1626 int *ptr = aligned_new<int>(2, 10);
1627 assert(*ptr == 10);
1628
1629 Example 3:
1630 struct A { A(int x, int y) : _x(x), _y(y) {} int x, y; }
1631 A *ptr = aligned_new<A>(2, 1, 2);
1632 assert(ptr->x == 1);
1633 assert(ptr->y == 2);
1634 */
1635template <typename T, typename... Args>
1636inline T *aligned_new(std::size_t alignment, Args &&... args) {
1637 return aligned_new_withkey<T>(make_psi_memory_key(PSI_NOT_INSTRUMENTED),
1638 alignment, std::forward<Args>(args)...);
1639}
1640
1641/** Releases storage which has been dynamically allocated through any of
1642 the aligned_new_*() variants. Destructs the object of type T.
1643
1644 @param[in] ptr Pointer which has been obtained through any of the
1645 aligned_new_*() variants
1646
1647 Example:
1648 aligned_delete(ptr);
1649 */
1650template <typename T>
1651inline void aligned_delete(T *ptr) noexcept {
1652 ptr->~T();
1653 aligned_free(ptr);
1654}
1655
1656/** Dynamically allocates storage for an array of T's at address aligned to the
1657 requested alignment. Constructs objects of type T with provided Args.
1658 Arguments that are to be used to construct some respective instance of T
1659 shall be wrapped into a std::tuple. See examples down below. Instruments the
1660 memory with given PSI memory key in case PFS memory support is enabled.
1661
1662 To create an array of default-initialized T's, one can use this function
1663 template but for convenience purposes one can achieve the same by using
1664 the ut::aligned_new_arr_withkey with ut::Count overload.
1665
1666 @param[in] key PSI memory key to be used for PFS memory instrumentation.
1667 @param[in] alignment Alignment requirement for storage to be allocated.
1668 @param[in] args Tuples of arguments one wishes to pass over to T
1669 constructor(s).
1670 @return Pointer to the first element of allocated storage. Throws
1671 std::bad_alloc exception if dynamic storage allocation could not be
1672 fulfilled. Re-throws whatever exception that may have occurred during the
1673 construction of any instance of T, in which case it automatically destroys
1674 successfully constructed objects till that moment (if any), and finally
1675 cleans up the raw memory allocated for T instances.
1676
1677 Example 1:
1678 int *ptr = ut::aligned_new_arr_withkey<int>(key, 32,
1679 std::forward_as_tuple(1),
1680 std::forward_as_tuple(2));
1681 assert(ptr[0] == 1);
1682 assert(ptr[1] == 2);
1683
1684 Example 2:
1685 struct A {
1686 A(int x, int y) : _x(x), _y(y) {}
1687 int _x, _y;
1688 };
1689 A *ptr = ut::aligned_new_arr_withkey<A>(key, 32,
1690 std::forward_as_tuple(0, 1), std::forward_as_tuple(2, 3),
1691 std::forward_as_tuple(4, 5), std::forward_as_tuple(6, 7),
1692 std::forward_as_tuple(8, 9));
1693 assert(ptr[0]->_x == 0 && ptr[0]->_y == 1);
1694 assert(ptr[1]->_x == 2 && ptr[1]->_y == 3);
1695 assert(ptr[2]->_x == 4 && ptr[2]->_y == 5);
1696 assert(ptr[3]->_x == 6 && ptr[3]->_y == 7);
1697 assert(ptr[4]->_x == 8 && ptr[4]->_y == 9);
1698
1699 Example 3:
1700 struct A {
1701 A() : _x(10), _y(100) {}
1702 A(int x, int y) : _x(x), _y(y) {}
1703 int _x, _y;
1704 };
1705 A *ptr = ut::aligned_new_arr_withkey<A>(key, 32,
1706 std::forward_as_tuple(0, 1), std::forward_as_tuple(2, 3),
1707 std::forward_as_tuple(), std::forward_as_tuple(6, 7),
1708 std::forward_as_tuple());
1709 assert(ptr[0]->_x == 0 && ptr[0]->_y == 1);
1710 assert(ptr[1]->_x == 2 && ptr[1]->_y == 3);
1711 assert(ptr[2]->_x == 10 && ptr[2]->_y == 100);
1712 assert(ptr[3]->_x == 6 && ptr[3]->_y == 7);
1713 assert(ptr[4]->_x == 10 && ptr[4]->_y == 100);
1714 */
1715template <typename T, typename... Args>
1716inline T *aligned_new_arr_withkey(PSI_memory_key_t key, std::size_t alignment,
1717 Args &&... args) {
1718 auto mem = aligned_alloc_withkey(key, sizeof(T) * sizeof...(args), alignment);
1719 if (unlikely(!mem)) throw std::bad_alloc();
1720
1721 size_t idx = 0;
1722 try {
1723 (...,
1724 detail::construct<T>(mem, sizeof(T) * idx++, std::forward<Args>(args)));
1725 } catch (...) {
1726 for (size_t offset = (idx - 1) * sizeof(T); offset != 0;
1727 offset -= sizeof(T)) {
1728 reinterpret_cast<T *>(reinterpret_cast<std::uintptr_t>(mem) + offset -
1729 sizeof(T))
1730 ->~T();
1731 }
1733 throw;
1734 }
1735 return static_cast<T *>(mem);
1736}
1737
1738/** Dynamically allocates storage for an array of T's at address aligned to the
1739 requested alignment. Constructs objects of type T using default constructor.
1740 If T cannot be default-initialized (e.g. default constructor does not
1741 exist), then this interface cannot be used for constructing such an array.
1742 ut::new_arr_withkey overload with user-provided initialization must be used
1743 then. Instruments the memory with given PSI memory key in case PFS memory
1744 support is enabled.
1745
1746 @param[in] key PSI memory key to be used for PFS memory instrumentation.
1747 @param[in] alignment Alignment requirement for storage to be allocated.
1748 @param[in] count Number of T elements in an array.
1749 @return Pointer to the first element of allocated storage. Throws
1750 std::bad_alloc exception if dynamic storage allocation could not be
1751 fulfilled. Re-throws whatever exception that may have occurred during the
1752 construction of any instance of T, in which case it automatically destroys
1753 successfully constructed objects till that moment (if any), and finally
1754 cleans up the raw memory allocated for T instances.
1755
1756 Example 1:
1757 int *ptr = ut::aligned_new_arr_withkey<int>(key, 32, ut::Count{2});
1758
1759 Example 2:
1760 struct A {
1761 A() : _x(10), _y(100) {}
1762 int _x, _y;
1763 };
1764 A *ptr = ut::aligned_new_arr_withkey<A>(key, 32, ut::Count{5});
1765 assert(ptr[0]->_x == 10 && ptr[0]->_y == 100);
1766 assert(ptr[1]->_x == 10 && ptr[1]->_y == 100);
1767 assert(ptr[2]->_x == 10 && ptr[2]->_y == 100);
1768 assert(ptr[3]->_x == 10 && ptr[3]->_y == 100);
1769 assert(ptr[4]->_x == 10 && ptr[4]->_y == 100);
1770
1771 Example 3:
1772 struct A {
1773 A(int x, int y) : _x(x), _y(y) {}
1774 int _x, _y;
1775 };
1776 // Following cannot compile because A is not default-constructible
1777 A *ptr = ut::aligned_new_arr_withkey<A>(key, 32, ut::Count{5});
1778 */
1779template <typename T>
1780inline T *aligned_new_arr_withkey(PSI_memory_key_t key, std::size_t alignment,
1781 Count count) {
1782 auto mem = aligned_alloc_withkey(key, sizeof(T) * count(), alignment);
1783 if (unlikely(!mem)) throw std::bad_alloc();
1784
1785 size_t offset = 0;
1786 try {
1787 for (; offset < sizeof(T) * count(); offset += sizeof(T)) {
1788 new (reinterpret_cast<uint8_t *>(mem) + offset) T{};
1789 }
1790 } catch (...) {
1791 for (; offset != 0; offset -= sizeof(T)) {
1792 reinterpret_cast<T *>(reinterpret_cast<std::uintptr_t>(mem) + offset -
1793 sizeof(T))
1794 ->~T();
1795 }
1797 throw;
1798 }
1799 return static_cast<T *>(mem);
1800}
1801
1802/** Dynamically allocates storage for an array of T's at address aligned to
1803 the requested alignment. Constructs objects of type T with provided Args.
1804
1805 NOTE: Given that this function will _NOT_ be instrumenting the allocation
1806 through PFS, observability for particular parts of the system which want to
1807 use it will be lost or in best case inaccurate. Please have a strong reason
1808 to do so.
1809
1810 @param[in] alignment Alignment requirement for storage to be allocated.
1811 @param[in] args Arguments one wishes to pass over to T constructor(s)
1812 @return Pointer to the first element of allocated storage. Throws
1813 std::bad_alloc exception if dynamic storage allocation could not be
1814 fulfilled.
1815
1816 Example 1:
1817 int *ptr = aligned_new_arr<int, 5>(2);
1818 ptr[0] ... ptr[4]
1819
1820 Example 2:
1821 int *ptr = aligned_new_arr<int, 5>(2, 1, 2, 3, 4, 5);
1822 assert(*ptr[0] == 1);
1823 assert(*ptr[1] == 2);
1824 ...
1825 assert(*ptr[4] == 5);
1826
1827 Example 3:
1828 struct A { A(int x, int y) : _x(x), _y(y) {} int x, y; }
1829 A *ptr = aligned_new_arr<A, 5>(2, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
1830 assert(ptr[0]->x == 1);
1831 assert(ptr[0]->y == 2);
1832 assert(ptr[1]->x == 3);
1833 assert(ptr[1]->y == 4);
1834 ...
1835 assert(ptr[4]->x == 9);
1836 assert(ptr[4]->y == 10);
1837 */
1838template <typename T, typename... Args>
1839inline T *aligned_new_arr(std::size_t alignment, Args &&... args) {
1840 return aligned_new_arr_withkey<T>(make_psi_memory_key(PSI_NOT_INSTRUMENTED),
1841 alignment, std::forward<Args>(args)...);
1842}
1843
1844/** Dynamically allocates storage for an array of T's at address aligned to
1845 the requested alignment. Constructs objects of type T using default
1846 constructor.
1847
1848 NOTE: Given that this function will _NOT_ be instrumenting the allocation
1849 through PFS, observability for particular parts of the system which want to
1850 use it will be lost or in best case inaccurate. Please have a strong reason
1851 to do so.
1852
1853 @param[in] alignment Alignment requirement for storage to be allocated.
1854 @param[in] count Number of T elements in an array.
1855 @return Pointer to the first element of allocated storage. Throws
1856 std::bad_alloc exception if dynamic storage allocation could not be
1857 fulfilled.
1858
1859 Example 1:
1860 int *ptr = aligned_new_arr<int>(2, 5);
1861 assert(*ptr[0] == 0);
1862 assert(*ptr[1] == 0);
1863 ...
1864 assert(*ptr[4] == 0);
1865
1866 Example 2:
1867 struct A { A) : x(1), y(2) {} int x, y; }
1868 A *ptr = aligned_new_arr<A>(2, 5);
1869 assert(ptr[0].x == 1);
1870 assert(ptr[0].y == 2);
1871 ...
1872 assert(ptr[4].x == 1);
1873 assert(ptr[4].y == 2);
1874
1875 Example 3:
1876 struct A { A(int x, int y) : _x(x), _y(y) {} int x, y; }
1877 A *ptr = aligned_new_arr<A>(2, 5);
1878 // will not compile, no default constructor
1879 */
1880template <typename T>
1881inline T *aligned_new_arr(std::size_t alignment, Count count) {
1882 return aligned_new_arr_withkey<T>(make_psi_memory_key(PSI_NOT_INSTRUMENTED),
1883 alignment, count);
1884}
1885
1886/** Releases storage which has been dynamically allocated through any of the
1887 aligned_new_arr_*() variants. Destructs all objects of type T.
1888
1889 @param[in] ptr Pointer which has been obtained through any of the
1890 aligned_new_arr_*() variants.
1891
1892 Example:
1893 aligned_delete_arr(ptr);
1894 */
1895template <typename T>
1896inline void aligned_delete_arr(T *ptr) noexcept {
1898 using aligned_alloc_impl = detail::Aligned_alloc_<impl>;
1899 const auto data_len = aligned_alloc_impl::datalen(ptr);
1900 for (size_t offset = 0; offset < data_len; offset += sizeof(T)) {
1901 reinterpret_cast<T *>(reinterpret_cast<std::uintptr_t>(ptr) + offset)->~T();
1902 }
1903 aligned_free(ptr);
1904}
1905
1906/** Lightweight convenience wrapper which manages dynamically allocated
1907 over-aligned type. Wrapper makes use of RAII to do the resource cleanup.
1908
1909 Example usage:
1910 struct My_fancy_type {
1911 My_fancy_type(int x, int y) : _x(x), _y(y) {}
1912 int _x, _y;
1913 };
1914
1915 aligned_pointer<My_fancy_type, 32> ptr;
1916 ptr.alloc(10, 5);
1917 My_fancy_type *p = ptr;
1918 assert(p->_x == 10 && p->_y == 5);
1919
1920 @tparam T Type to be managed.
1921 @tparam Alignment Number of bytes to align the type T to.
1922 */
1923template <typename T, size_t Alignment>
1925 T *ptr = nullptr;
1926
1927 public:
1928 /** Destructor. Invokes destructor of the underlying instance of
1929 type T. Releases dynamically allocated resources, if there had been
1930 left any.
1931 */
1933 if (ptr) dealloc();
1934 }
1935
1936 /** Allocates sufficiently large memory of dynamic storage duration to fit
1937 the instance of type T at the address which is aligned to Alignment bytes.
1938 Constructs the instance of type T with given Args.
1939
1940 Underlying instance of type T is accessed through the conversion operator.
1941
1942 @param[in] args Any number and type of arguments that type T can be
1943 constructed with.
1944 */
1945 template <typename... Args>
1946 void alloc(Args &&... args) {
1947 ut_ad(ptr == nullptr);
1948 ptr = ut::aligned_new<T>(Alignment, args...);
1949 }
1950
1951 /** Allocates sufficiently large memory of dynamic storage duration to fit
1952 the instance of type T at the address which is aligned to Alignment bytes.
1953 Constructs the instance of type T with given Args. Instruments the memory
1954 with given PSI memory key in case PFS memory support is enabled.
1955
1956 Underlying instance of type T is accessed through the conversion operator.
1957
1958 @param[in] key PSI memory key to be used for PFS memory instrumentation.
1959 @param[in] args Any number and type of arguments that type T can be
1960 constructed with.
1961 */
1962 template <typename... Args>
1963 void alloc_withkey(PSI_memory_key_t key, Args &&... args) {
1964 ut_ad(ptr == nullptr);
1965 ptr =
1966 ut::aligned_new_withkey<T>(key, Alignment, std::forward<Args>(args)...);
1967 }
1968
1969 /** Invokes the destructor of instance of type T, if applicable.
1970 Releases the resources previously allocated with alloc().
1971 */
1972 void dealloc() {
1973 ut_ad(ptr != nullptr);
1975 ptr = nullptr;
1976 }
1977
1978 /** Conversion operator. Used for accessing the underlying instance of
1979 type T.
1980 */
1981 operator T *() const {
1982 ut_ad(ptr != nullptr);
1983 return ptr;
1984 }
1985};
1986
1987/** Lightweight convenience wrapper which manages a dynamically
1988 allocated array of over-aligned types. Only the first element of an array is
1989 guaranteed to be aligned to the requested Alignment. Wrapper makes use of
1990 RAII to do the resource cleanup.
1991
1992 Example usage 1:
1993 struct My_fancy_type {
1994 My_fancy_type() : _x(0), _y(0) {}
1995 My_fancy_type(int x, int y) : _x(x), _y(y) {}
1996 int _x, _y;
1997 };
1998
1999 aligned_array_pointer<My_fancy_type, 32> ptr;
2000 ptr.alloc(3);
2001 My_fancy_type *p = ptr;
2002 assert(p[0]._x == 0 && p[0]._y == 0);
2003 assert(p[1]._x == 0 && p[1]._y == 0);
2004 assert(p[2]._x == 0 && p[2]._y == 0);
2005
2006 Example usage 2:
2007 aligned_array_pointer<My_fancy_type, 32> ptr;
2008 ptr.alloc<3>(1, 2, 3, 4, 5, 6);
2009 My_fancy_type *p = ptr;
2010 assert(p[0]._x == 1 && p[0]._y == 2);
2011 assert(p[1]._x == 3 && p[1]._y == 4);
2012 assert(p[2]._x == 5 && p[2]._y == 6);
2013
2014 @tparam T Type to be managed.
2015 @tparam Alignment Number of bytes to align the first element of array to.
2016 */
2017template <typename T, size_t Alignment>
2019 T *ptr = nullptr;
2020
2021 public:
2022 /** Destructor. Invokes destructors of the underlying instances of
2023 type T. Releases dynamically allocated resources, if there had been
2024 left any.
2025 */
2027 if (ptr) dealloc();
2028 }
2029
2030 /** Allocates sufficiently large memory of dynamic storage duration to fit
2031 the array of size number of elements of type T at the address which is
2032 aligned to Alignment bytes. Constructs the size number of instances of
2033 type T, each being initialized through the means of default constructor.
2034
2035 Underlying instances of type T are accessed through the conversion
2036 operator.
2037
2038 @param[in] count Number of T elements in an array.
2039 */
2041 ut_ad(ptr == nullptr);
2042 ptr = ut::aligned_new_arr<T>(Alignment, count);
2043 }
2044
2045 /** Allocates sufficiently large memory of dynamic storage duration to fit
2046 the array of size number of elements of type T at the address which is
2047 aligned to Alignment bytes. Constructs the size number of instances of
2048 type T, each being initialized through the means of provided Args and
2049 corresponding constructors.
2050
2051 Underlying instances of type T are accessed through the conversion
2052 operator.
2053
2054 @param[in] args Any number and type of arguments that type T can be
2055 constructed with.
2056 */
2057 template <typename... Args>
2058 void alloc(Args &&... args) {
2059 ut_ad(ptr == nullptr);
2060 ptr = ut::aligned_new_arr<T>(Alignment, std::forward<Args>(args)...);
2061 }
2062
2063 /** Allocates sufficiently large memory of dynamic storage duration to fit
2064 the array of size number of elements of type T at the address which is
2065 aligned to Alignment bytes. Constructs the size number of instances of
2066 type T, each being initialized through the means of default constructor.
2067 Instruments the memory with given PSI memory key in case PFS memory
2068 support is enabled.
2069
2070 Underlying instances of type T are accessed through the conversion
2071 operator.
2072
2073 @param[in] key PSI memory key to be used for PFS memory instrumentation.
2074 @param[in] count Number of T elements in an array.
2075 */
2077 ut_ad(ptr == nullptr);
2078 ptr = ut::aligned_new_arr_withkey<T>(key, Alignment, count);
2079 }
2080
2081 /** Allocates sufficiently large memory of dynamic storage duration to fit
2082 the array of size number of elements of type T at the address which is
2083 aligned to Alignment bytes. Constructs the size number of instances of
2084 type T, each being initialized through the means of provided Args and
2085 corresponding constructors. Instruments the memory with given PSI memory
2086 key in case PFS memory support is enabled.
2087
2088 Underlying instances of type T are accessed through the conversion
2089 operator.
2090
2091 @param[in] key PSI memory key to be used for PFS memory instrumentation.
2092 @param[in] args Any number and type of arguments that type T can be
2093 constructed with.
2094 */
2095 template <typename... Args>
2096 void alloc_withkey(PSI_memory_key_t key, Args &&... args) {
2097 ut_ad(ptr == nullptr);
2098 ptr = ut::aligned_new_arr_withkey<T>(key, Alignment,
2099 std::forward<Args>(args)...);
2100 }
2101
2102 /** Invokes destructors of instances of type T, if applicable.
2103 Releases the resources previously allocated with any variant of
2104 alloc().
2105 */
2106 void dealloc() {
2108 ptr = nullptr;
2109 }
2110
2111 /** Conversion operator. Used for accessing the underlying instances of
2112 type T.
2113 */
2114 operator T *() const {
2115 ut_ad(ptr != nullptr);
2116 return ptr;
2117 }
2118};
2119
2120namespace detail {
2121template <typename T>
2123 explicit allocator_base(PSI_memory_key /*key*/) {}
2124
2125 template <typename U>
2126 allocator_base(const allocator_base<U> & /*other*/) {}
2127
2128 void *allocate_impl(size_t n_bytes) { return ut::malloc(n_bytes); }
2129};
2130
2131template <typename T>
2134
2135 template <typename U>
2137 : allocator_base_pfs(other.get_mem_key()) {}
2138
2140
2141 void *allocate_impl(size_t n_bytes) {
2143 }
2144
2145 private:
2147};
2148} // namespace detail
2149
2150/** Allocator that allows std::* containers to manage their memory through
2151 ut::malloc* and ut::free library functions.
2152
2153 Main purpose of this custom allocator is to instrument all of the memory
2154 allocations and deallocations that are being done by std::* containers under
2155 the hood, and have them recorded through the PFS (memory) engine.
2156
2157 Other than std::* containers, this allocator is of course also suitable for
2158 use in any other allocator-aware containers and/or code.
2159
2160 Given that ut::malloc* and ut::free library functions already handle all
2161 the PFS and non-PFS implementation bits and pieces, this allocator is a mere
2162 wrapper around them.
2163
2164 Example which uses default PFS key (mem_key_std) to trace all std::vector
2165 allocations and deallocations:
2166 std::vector<int, ut::allocator<int>> vec;
2167 vec.push_back(...);
2168 ...
2169 vec.push_back(...);
2170
2171 Example which uses user-provided PFS key to trace std::vector allocations
2172 and deallocations:
2173 ut::allocator<int> allocator(some_other_psi_key);
2174 std::vector<int, ut::allocator<int>> vec(allocator);
2175 vec.push_back(...);
2176 ...
2177 vec.push_back(...);
2178 */
2179template <typename T, typename Allocator_base = std::conditional_t<
2182class allocator : public Allocator_base {
2183 public:
2184 using pointer = T *;
2185 using const_pointer = const T *;
2186 using reference = T &;
2187 using const_reference = const T &;
2188 using value_type = T;
2189 using size_type = size_t;
2190 using difference_type = ptrdiff_t;
2191
2192 static_assert(alignof(T) <= alignof(std::max_align_t),
2193 "ut::allocator does not support over-aligned types. Use "
2194 "ut::aligned_* API to handle such types.");
2195
2196 /** Default constructor.
2197 @param[in] key performance schema key.
2198 */
2199 explicit allocator(PSI_memory_key key = mem_key_std) : Allocator_base(key) {}
2200
2201 /* Rule-of-five */
2204 const allocator<T, Allocator_base> &) = default;
2207 default;
2208 ~allocator() = default;
2209
2210 /** Copy-construct a new instance of allocator with type T by using existing
2211 instance of allocator constructed with a different type U.
2212 @param[in] other the allocator to copy from.
2213 */
2214 template <typename U>
2216 : Allocator_base(other) {}
2217
2218 /* NOTE: rebind is deprecated in C++17 and to be removed in C++20 but one of
2219 our toolchains, when used in 32-bit setting, still does not support custom
2220 allocators that do not provide rebind support explicitly. In future, this
2221 part will become redundant and can be removed.
2222 */
2223 template <typename U>
2224 struct rebind {
2226 };
2227
2228 /** Equality of allocators instantiated with same types T. */
2230 return true;
2231 }
2232 /** Non-equality of allocators instantiated with same types T. */
2233 inline bool operator!=(const ut::allocator<T, Allocator_base> &other) const {
2234 return !(*this == other);
2235 }
2236
2237 /** Return the maximum number of objects that can be allocated by
2238 this allocator. This number is somewhat lower for PFS-enabled
2239 builds because of extra few bytes needed for PFS.
2240 */
2242 const size_type s_max = std::numeric_limits<size_type>::max();
2243 return (s_max - ut::pfs_overhead()) / sizeof(T);
2244 }
2245
2246 /** Allocates chunk of memory that can hold n_elements objects of
2247 type T. Returned pointer is always valid. In case underlying
2248 allocation function was not able to fulfill the allocation request,
2249 this function will throw std::bad_alloc exception. After successful
2250 allocation, returned pointer must be passed back to
2251 ut::allocator<T>::deallocate() when no longer needed.
2252
2253 @param[in] n_elements number of elements
2254 @param[in] hint pointer to a nearby memory location,
2255 not used by this implementation
2256 @return pointer to the allocated memory
2257 */
2259 const_pointer hint [[maybe_unused]] = nullptr) {
2260 if (unlikely(n_elements > max_size())) {
2261 throw std::bad_array_new_length();
2262 }
2263
2264 auto ptr = Allocator_base::allocate_impl(n_elements * sizeof(T));
2265
2266 if (unlikely(!ptr)) {
2267 throw std::bad_alloc();
2268 }
2269
2270 return static_cast<pointer>(ptr);
2271 }
2272
2273 /** Releases the memory allocated through ut::allocator<T>::allocate().
2274
2275 @param[in,out] ptr pointer to memory to free
2276 @param[in] n_elements number of elements allocated (unused)
2277 */
2278 void deallocate(pointer ptr, size_type n_elements [[maybe_unused]] = 0) {
2279 ut::free(ptr);
2280 }
2281};
2282
2283namespace detail {
2284template <typename>
2285constexpr bool is_unbounded_array_v = false;
2286template <typename T>
2287constexpr bool is_unbounded_array_v<T[]> = true;
2288
2289template <typename>
2290constexpr bool is_bounded_array_v = false;
2291template <typename T, std::size_t N>
2292constexpr bool is_bounded_array_v<T[N]> = true;
2293
2294template <typename>
2295constexpr size_t bounded_array_size_v = 0;
2296template <typename T, std::size_t N>
2298
2299template <typename T>
2300struct Deleter {
2301 void operator()(T *ptr) { ut::delete_(ptr); }
2302};
2303
2304template <typename T>
2306 void operator()(T *ptr) { ut::delete_arr(ptr); }
2307};
2308
2309template <typename T>
2311 void operator()(T *ptr) { ut::aligned_delete(ptr); }
2312};
2313
2314template <typename T>
2316 void operator()(T *ptr) { ut::aligned_delete_arr(ptr); }
2317};
2318
2319} // namespace detail
2320
2321/** Dynamically allocates storage for an object of type T. Constructs the object
2322 of type T with provided Args. Wraps the pointer to T instance into the
2323 std::unique_ptr.
2324
2325 This overload participates in overload resolution only if T
2326 is not an array type.
2327
2328 NOTE: Given that this function will _NOT_ be instrumenting the allocation
2329 through PFS, observability for particular parts of the system which want to
2330 use it will be lost or in best case inaccurate. Please have a strong reason
2331 to do so.
2332
2333 @param[in] args Arguments one wishes to pass over to T constructor(s) .
2334 @return std::unique_ptr holding a pointer to instance of T.
2335 */
2336template <typename T, typename Deleter = detail::Deleter<T>, typename... Args>
2337std::enable_if_t<!std::is_array<T>::value, std::unique_ptr<T, Deleter>>
2338make_unique(Args &&... args) {
2339 return std::unique_ptr<T, Deleter>(ut::new_<T>(std::forward<Args>(args)...));
2340}
2341
2342/** Dynamically allocates storage for an object of type T. Constructs the object
2343 of type T with provided Args. Wraps the pointer to T instance into the
2344 std::unique_ptr with custom deleter which knows how to handle PFS-enabled
2345 dynamic memory allocations. Instruments the memory with given PSI memory key
2346 in case PFS memory support is enabled.
2347
2348 This overload participates in overload resolution only if T
2349 is not an array type.
2350
2351 @param[in] key PSI memory key to be used for PFS memory instrumentation.
2352 @param[in] args Arguments one wishes to pass over to T constructor(s) .
2353 @return std::unique_ptr holding a pointer to instance of T.
2354 */
2355template <typename T, typename Deleter = detail::Deleter<T>, typename... Args>
2356std::enable_if_t<!std::is_array<T>::value, std::unique_ptr<T, Deleter>>
2358 return std::unique_ptr<T, Deleter>(
2359 ut::new_withkey<T>(key, std::forward<Args>(args)...));
2360}
2361
2362/** Dynamically allocates storage for an object of type T. Constructs the object
2363 of type T with provided Args. Wraps the pointer to an array of T instance
2364 into the std::unique_ptr.
2365
2366 This overload participates in overload resolution only if T
2367 is an array type with unknown compile-time bound.
2368
2369 NOTE: Given that this function will _NOT_ be instrumenting the allocation
2370 through PFS, observability for particular parts of the system which want to
2371 use it will be lost or in best case inaccurate. Please have a strong reason
2372 to do so.
2373
2374 @return std::unique_ptr holding a pointer to an array of size instances of
2375 T.
2376 */
2377template <typename T,
2378 typename Deleter = detail::Array_deleter<std::remove_extent_t<T>>>
2379std::enable_if_t<detail::is_unbounded_array_v<T>, std::unique_ptr<T, Deleter>>
2381 return std::unique_ptr<T, Deleter>(
2382 ut::new_arr<std::remove_extent_t<T>>(ut::Count{size}));
2383}
2384
2385/** Dynamically allocates storage for an object of type T. Constructs the object
2386 of type T with provided Args. Wraps the pointer to an array of T instances
2387 into the std::unique_ptr with custom deleter which knows how to handle
2388 PFS-enabled dynamic memory allocations. Instruments the memory with given
2389 PSI memory key in case PFS memory support is enabled.
2390
2391 This overload participates in overload resolution only if T
2392 is an array type with unknown compile-time bound.
2393
2394 @return std::unique_ptr holding a pointer to an array of size instances of
2395 T.
2396 */
2397template <typename T,
2398 typename Deleter = detail::Array_deleter<std::remove_extent_t<T>>>
2399std::enable_if_t<detail::is_unbounded_array_v<T>, std::unique_ptr<T, Deleter>>
2401 return std::unique_ptr<T, Deleter>(
2402 ut::new_arr_withkey<std::remove_extent_t<T>>(key, ut::Count{size}));
2403}
2404
2405/** std::unique_ptr for arrays of known compile-time bound are disallowed.
2406
2407 For more details see 4.3 paragraph from
2408 http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3588.txt
2409 */
2410template <typename T, typename... Args>
2411std::enable_if_t<detail::is_bounded_array_v<T>> make_unique(Args &&...) =
2412 delete;
2413
2414/** std::unique_ptr in PFS-enabled builds for arrays of known compile-time bound
2415 are disallowed.
2416
2417 For more details see 4.3 paragraph from
2418 http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3588.txt
2419 */
2420template <typename T, typename... Args>
2421std::enable_if_t<detail::is_bounded_array_v<T>> make_unique(
2422 PSI_memory_key_t key, Args &&...) = delete;
2423
2424/** The following is a common type that is returned by all the ut::make_unique
2425 (non-aligned) specializations listed above. This is effectively a if-ladder
2426 for the following list of conditions on the input type:
2427 !std::is_array<T>::value -> std::unique_ptr<T, detail::Deleter<T>>
2428 detail::is_unbounded_array_v<T> ->
2429 std::unique_ptr<T,detail::Array_deleter<std::remove_extent_t<T>>> else (or
2430 else if detail::is_bounded_array_v<T>) -> void (we do not support bounded
2431 array ut::make_unique)
2432 */
2433template <typename T>
2434using unique_ptr = std::conditional_t<
2435 !std::is_array<T>::value, std::unique_ptr<T, detail::Deleter<T>>,
2436 std::conditional_t<
2437 detail::is_unbounded_array_v<T>,
2438 std::unique_ptr<T, detail::Array_deleter<std::remove_extent_t<T>>>,
2439 void>>;
2440
2441/** Dynamically allocates storage for an object of type T at address aligned to
2442 the requested alignment. Constructs the object of type T with provided Args.
2443 Wraps the pointer to T instance into the std::unique_ptr.
2444
2445 This overload participates in overload resolution only if T
2446 is not an array type.
2447
2448 NOTE: Given that this function will _NOT_ be instrumenting the allocation
2449 through PFS, observability for particular parts of the system which want to
2450 use it will be lost or in best case inaccurate. Please have a strong reason
2451 to do so.
2452
2453 @param[in] alignment Alignment requirement for storage to be allocated.
2454 @param[in] args Arguments one wishes to pass over to T constructor(s) .
2455 @return std::unique_ptr holding a pointer to instance of T.
2456 */
2457template <typename T, typename Deleter = detail::Aligned_deleter<T>,
2458 typename... Args>
2459std::enable_if_t<!std::is_array<T>::value, std::unique_ptr<T, Deleter>>
2460make_unique_aligned(size_t alignment, Args &&... args) {
2461 return std::unique_ptr<T, Deleter>(
2462 ut::aligned_new<T>(alignment, std::forward<Args>(args)...));
2463}
2464
2465/** Dynamically allocates storage for an array of objects of type T at address
2466 aligned to the requested alignment. Constructs the object of type T with
2467 provided Args. Wraps the pointer to T instance into the std::unique_ptr with
2468 custom deleter which knows how to handle PFS-enabled dynamic memory
2469 allocations. Instruments the memory with given PSI memory key in case PFS
2470 memory support is enabled.
2471
2472 This overload participates in overload resolution only if T is not an array
2473 type.
2474
2475 @param[in] key PSI memory key to be used for PFS memory instrumentation.
2476 @param[in] alignment Alignment requirement for storage to be allocated.
2477 @param[in] args Arguments one wishes to pass over to T constructor(s) .
2478 @return std::unique_ptr holding a pointer to instance of T.
2479 */
2480template <typename T, typename Deleter = detail::Aligned_deleter<T>,
2481 typename... Args>
2482std::enable_if_t<!std::is_array<T>::value, std::unique_ptr<T, Deleter>>
2483make_unique_aligned(PSI_memory_key_t key, size_t alignment, Args &&... args) {
2484 return std::unique_ptr<T, Deleter>(
2485 ut::aligned_new_withkey<T>(key, alignment, std::forward<Args>(args)...));
2486}
2487
2488/** Dynamically allocates storage for an array of requested size of objects of
2489 type T at address aligned to the requested alignment. Constructs the object
2490 of type T with provided Args. Wraps the pointer to an array of T instance
2491 into the std::unique_ptr.
2492
2493 This overload participates in overload resolution only if T
2494 is an array type with unknown compile-time bound.
2495
2496 NOTE: Given that this function will _NOT_ be instrumenting the allocation
2497 through PFS, observability for particular parts of the system which want to
2498 use it will be lost or in best case inaccurate. Please have a strong reason
2499 to do so.
2500
2501 @param[in] alignment Alignment requirement for storage to be allocated.
2502 @param[in] size Size of the array of objects T to allocate.
2503 @return std::unique_ptr holding a pointer to an array of size instances of
2504 T.
2505 */
2506template <typename T, typename Deleter = detail::Aligned_array_deleter<
2507 std::remove_extent_t<T>>>
2508std::enable_if_t<detail::is_unbounded_array_v<T>, std::unique_ptr<T, Deleter>>
2509make_unique_aligned(size_t alignment, size_t size) {
2510 return std::unique_ptr<T, Deleter>(
2511 ut::aligned_new_arr<std::remove_extent_t<T>>(alignment, ut::Count{size}));
2512}
2513
2514/** Dynamically allocates storage for an array of requested size of objects of
2515 type T at address aligned to the requested alignment. Constructs the object
2516 of type T with provided Args. Wraps the pointer to an array of T instances
2517 into the std::unique_ptr with custom deleter which knows how to handle
2518 PFS-enabled dynamic memory allocations. Instruments the memory with given
2519 PSI memory key in case PFS memory support is enabled.
2520
2521 This overload participates in overload resolution only if T
2522 is an array type with unknown compile-time bound.
2523
2524 @param[in] key PSI memory key to be used for PFS memory instrumentation.
2525 @param[in] alignment Alignment requirement for storage to be allocated.
2526 @param[in] size Size of the array of objects T to allocate.
2527 @return std::unique_ptr holding a pointer to an array of size instances of
2528 T.
2529 */
2530template <typename T, typename Deleter = detail::Aligned_array_deleter<
2531 std::remove_extent_t<T>>>
2532std::enable_if_t<detail::is_unbounded_array_v<T>, std::unique_ptr<T, Deleter>>
2533make_unique_aligned(PSI_memory_key_t key, size_t alignment, size_t size) {
2534 return std::unique_ptr<T, Deleter>(
2535 ut::aligned_new_arr_withkey<std::remove_extent_t<T>>(key, alignment,
2536 ut::Count{size}));
2537}
2538
2539/** std::unique_ptr for arrays of known compile-time bound are disallowed.
2540
2541 For more details see 4.3 paragraph from
2542 http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3588.txt
2543 */
2544template <typename T, typename... Args>
2545std::enable_if_t<detail::is_bounded_array_v<T>> make_unique_aligned(
2546 Args &&...) = delete;
2547
2548/** std::unique_ptr in PFS-enabled builds for arrays of known compile-time bound
2549 are disallowed.
2550
2551 For more details see 4.3 paragraph from
2552 http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3588.txt
2553 */
2554template <typename T, typename... Args>
2555std::enable_if_t<detail::is_bounded_array_v<T>> make_unique_aligned(
2556 PSI_memory_key_t key, Args &&...) = delete;
2557
2558/** The following is a common type that is returned by all the
2559 ut::make_unique_aligned (non-aligned) specializations listed above. This is
2560 effectively a if-ladder for the following list of conditions on the input
2561 type: !std::is_array<T>::value -> std::unique_ptr<T,
2562 detail::Aligned_deleter<T>> detail::is_unbounded_array_v<T> ->
2563 std::unique_ptr<T,detail::Aligned_array_deleter<std::remove_extent_t<T>>>
2564 else (or else if detail::is_bounded_array_v<T>) -> void (we do not support
2565 bounded array ut::make_unique)
2566 */
2567template <typename T>
2568using unique_ptr_aligned = std::conditional_t<
2569 !std::is_array<T>::value, std::unique_ptr<T, detail::Aligned_deleter<T>>,
2570 std::conditional_t<detail::is_unbounded_array_v<T>,
2572 std::remove_extent_t<T>>>,
2573 void>>;
2574
2575/** Dynamically allocates storage for an object of type T. Constructs the object
2576 of type T with provided Args. Wraps the pointer to T instance into the
2577 std::shared_ptr.
2578
2579 This overload participates in overload resolution only if T
2580 is not an array type.
2581
2582 NOTE: Given that this function will _NOT_ be instrumenting the allocation
2583 through PFS, observability for particular parts of the system which want to
2584 use it will be lost or in best case inaccurate. Please have a strong reason
2585 to do so.
2586
2587 @param[in] args Arguments one wishes to pass over to T constructor(s) .
2588 @return std::shared_ptr holding a pointer to instance of T.
2589 */
2590template <typename T, typename Deleter = detail::Deleter<T>, typename... Args>
2591std::enable_if_t<!std::is_array<T>::value, std::shared_ptr<T>> make_shared(
2592 Args &&... args) {
2593 return std::shared_ptr<T>(ut::new_<T>(std::forward<Args>(args)...),
2594 Deleter{});
2595}
2596
2597/** Dynamically allocates storage for an object of type T. Constructs the object
2598 of type T with provided Args. Wraps the pointer to T instance into the
2599 std::shared_ptr with custom deleter which knows how to handle PFS-enabled
2600 dynamic memory allocations. Instruments the memory with given PSI memory key
2601 in case PFS memory support is enabled.
2602
2603 This overload participates in overload resolution only if T
2604 is not an array type.
2605
2606 @param[in] key PSI memory key to be used for PFS memory instrumentation.
2607 @param[in] args Arguments one wishes to pass over to T constructor(s) .
2608 @return std::shared_ptr holding a pointer to instance of T.
2609 */
2610template <typename T, typename Deleter = detail::Deleter<T>, typename... Args>
2611std::enable_if_t<!std::is_array<T>::value, std::shared_ptr<T>> make_shared(
2612 PSI_memory_key_t key, Args &&... args) {
2613 return std::shared_ptr<T>(
2614 ut::new_withkey<T>(key, std::forward<Args>(args)...), Deleter{});
2615}
2616
2617/** Dynamically allocates storage for an array of requested size of objects of
2618 type T. Constructs the object of type T with provided Args. Wraps the
2619 pointer to an array of T instance into the std::shared_ptr.
2620
2621 This overload participates in overload resolution only if T
2622 is an array type with unknown compile-time bound.
2623
2624 NOTE: Given that this function will _NOT_ be instrumenting the allocation
2625 through PFS, observability for particular parts of the system which want to
2626 use it will be lost or in best case inaccurate. Please have a strong reason
2627 to do so.
2628
2629 @param[in] size Size of the array of objects T to allocate.
2630 @return std::shared_ptr holding a pointer to an array of size instances of
2631 T.
2632 */
2633template <typename T,
2634 typename Deleter = detail::Array_deleter<std::remove_extent_t<T>>>
2635std::enable_if_t<detail::is_unbounded_array_v<T>, std::shared_ptr<T>>
2637 return std::shared_ptr<T>(
2638 ut::new_arr<std::remove_extent_t<T>>(ut::Count{size}), Deleter{});
2639}
2640
2641/** Dynamically allocates storage for an array of requested size of objects of
2642 type T. Constructs the object of type T with provided Args. Wraps the
2643 pointer to an array of T instances into the std::shared_ptr with custom
2644 deleter which knows how to handle PFS-enabled dynamic memory allocations.
2645 Instruments the memory with given PSI memory key in case PFS memory support
2646 is enabled.
2647
2648 This overload participates in overload resolution only if T
2649 is an array type with unknown compile-time bound.
2650
2651 @param[in] key PSI memory key to be used for PFS memory instrumentation.
2652 @param[in] size Size of the array of objects T to allocate.
2653 @return std::shared_ptr holding a pointer to an array of size instances of
2654 T.
2655 */
2656template <typename T,
2657 typename Deleter = detail::Array_deleter<std::remove_extent_t<T>>>
2658std::enable_if_t<detail::is_unbounded_array_v<T>, std::shared_ptr<T>>
2660 return std::shared_ptr<T>(
2661 ut::new_arr_withkey<std::remove_extent_t<T>>(key, ut::Count{size}),
2662 Deleter{});
2663}
2664
2665/** Dynamically allocates storage for an array of objects of type T. Constructs
2666 the object of type T with provided Args. Wraps the pointer to an array of T
2667 instance into the std::shared_ptr.
2668
2669 This overload participates in overload resolution only if T
2670 is an array type with known compile-time bound.
2671
2672 NOTE: Given that this function will _NOT_ be instrumenting the allocation
2673 through PFS, observability for particular parts of the system which want to
2674 use it will be lost or in best case inaccurate. Please have a strong reason
2675 to do so.
2676
2677 @return std::shared_ptr holding a pointer to an array of size instances of
2678 T.
2679 */
2680template <typename T,
2681 typename Deleter = detail::Array_deleter<std::remove_extent_t<T>>>
2682std::enable_if_t<detail::is_bounded_array_v<T>, std::shared_ptr<T>>
2684 return std::shared_ptr<T>(ut::new_arr<std::remove_extent_t<T>>(
2685 ut::Count{detail::bounded_array_size_v<T>}),
2686 Deleter{});
2687}
2688
2689/** Dynamically allocates storage for an array of objects of type T. Constructs
2690 the object of type T with provided Args. Wraps the pointer to an array of T
2691 instances into the std::shared_ptr with custom deleter which knows how to
2692 handle PFS-enabled dynamic memory allocations. Instruments the memory with
2693 given PSI memory key in case PFS memory support is enabled.
2694
2695 This overload participates in overload resolution only if T
2696 is an array type with known compile-time bound.
2697
2698 @param[in] key PSI memory key to be used for PFS memory instrumentation.
2699 @return std::shared_ptr holding a pointer to an array of size instances of
2700 T.
2701 */
2702template <typename T,
2703 typename Deleter = detail::Array_deleter<std::remove_extent_t<T>>>
2704std::enable_if_t<detail::is_bounded_array_v<T>, std::shared_ptr<T>> make_shared(
2706 return std::shared_ptr<T>(
2707 ut::new_arr_withkey<std::remove_extent_t<T>>(
2708 key, ut::Count{detail::bounded_array_size_v<T>}),
2709 Deleter{});
2710}
2711
2712/** Dynamically allocates storage for an object of type T at address aligned to
2713 the requested alignment. Constructs the object of type T with provided Args.
2714 Wraps the pointer to T instance into the std::shared_ptr.
2715
2716 This overload participates in overload resolution only if T
2717 is not an array type.
2718
2719 NOTE: Given that this function will _NOT_ be instrumenting the allocation
2720 through PFS, observability for particular parts of the system which want to
2721 use it will be lost or in best case inaccurate. Please have a strong reason
2722 to do so.
2723
2724 @param[in] alignment Alignment requirement for storage to be allocated.
2725 @param[in] args Arguments one wishes to pass over to T constructor(s) .
2726 @return std::shared_ptr holding a pointer to instance of T.
2727 */
2728template <typename T, typename Deleter = detail::Aligned_deleter<T>,
2729 typename... Args>
2730std::enable_if_t<!std::is_array<T>::value, std::shared_ptr<T>>
2731make_shared_aligned(size_t alignment, Args &&... args) {
2732 return std::shared_ptr<T>(
2733 ut::aligned_new<T>(alignment, std::forward<Args>(args)...), Deleter{});
2734}
2735
2736/** Dynamically allocates storage for an object of type T at address aligned to
2737 the requested alignment. Constructs the object of type T with provided Args.
2738 Wraps the pointer to T instance into the std::shared_ptr with custom deleter
2739 which knows how to handle PFS-enabled dynamic memory allocations.
2740 Instruments the memory with given PSI memory key in case PFS memory support
2741 is enabled.
2742
2743 This overload participates in overload resolution only if T
2744 is not an array type.
2745
2746 @param[in] key PSI memory key to be used for PFS memory instrumentation.
2747 @param[in] alignment Alignment requirement for storage to be allocated.
2748 @param[in] args Arguments one wishes to pass over to T constructor(s) .
2749 @return std::shared_ptr holding a pointer to instance of T.
2750 */
2751template <typename T, typename Deleter = detail::Aligned_deleter<T>,
2752 typename... Args>
2753std::enable_if_t<!std::is_array<T>::value, std::shared_ptr<T>>
2754make_shared_aligned(PSI_memory_key_t key, size_t alignment, Args &&... args) {
2755 return std::shared_ptr<T>(
2756 ut::aligned_new_withkey<T>(key, alignment, std::forward<Args>(args)...),
2757 Deleter{});
2758}
2759
2760/** Dynamically allocates storage for an array of requested size of objects of
2761 type T at address aligned to the requested alignment. Constructs the object
2762 of type T with provided Args. Wraps the pointer to an array of T instance
2763 into the std::shared_ptr.
2764
2765 This overload participates in overload resolution only if T
2766 is an array type with unknown compile-time bound.
2767
2768 NOTE: Given that this function will _NOT_ be instrumenting the allocation
2769 through PFS, observability for particular parts of the system which want to
2770 use it will be lost or in best case inaccurate. Please have a strong reason
2771 to do so.
2772
2773 @param[in] alignment Alignment requirement for storage to be allocated.
2774 @param[in] size Size of the array of objects T to allocate.
2775 @return std::shared_ptr holding a pointer to an array of size instances of
2776 T.
2777 */
2778template <typename T, typename Deleter = detail::Aligned_array_deleter<
2779 std::remove_extent_t<T>>>
2780std::enable_if_t<detail::is_unbounded_array_v<T>, std::shared_ptr<T>>
2781make_shared_aligned(size_t alignment, size_t size) {
2782 return std::shared_ptr<T>(
2783 ut::aligned_new_arr<std::remove_extent_t<T>>(alignment, ut::Count{size}),
2784 Deleter{});
2785}
2786
2787/** Dynamically allocates storage for an array of requested size of objects of
2788 type T at address aligned to the requested alignment. Constructs the object
2789 of type T with provided Args. Wraps the pointer to an array of T instances
2790 into the std::shared_ptr with custom deleter which knows how to handle
2791 PFS-enabled dynamic memory allocations. Instruments the memory with given
2792 PSI memory key in case PFS memory support is enabled.
2793
2794 This overload participates in overload resolution only if T
2795 is an array type with unknown compile-time bound.
2796
2797 @param[in] key PSI memory key to be used for PFS memory instrumentation.
2798 @param[in] alignment Alignment requirement for storage to be allocated.
2799 @param[in] size Size of the array of objects T to allocate.
2800 @return std::shared_ptr holding a pointer to an array of size instances of
2801 T.
2802 */
2803template <typename T, typename Deleter = detail::Aligned_array_deleter<
2804 std::remove_extent_t<T>>>
2805std::enable_if_t<detail::is_unbounded_array_v<T>, std::shared_ptr<T>>
2806make_shared_aligned(PSI_memory_key_t key, size_t alignment, size_t size) {
2807 return std::shared_ptr<T>(
2808 ut::aligned_new_arr_withkey<std::remove_extent_t<T>>(key, alignment,
2809 ut::Count{size}),
2810 Deleter{});
2811}
2812
2813/** Dynamically allocates storage for an array of objects of type T at address
2814 aligned to the requested alignment. Constructs the object of type T with
2815 provided Args. Wraps the pointer to an array of T instance into the
2816 std::shared_ptr.
2817
2818 This overload participates in overload resolution only if T
2819 is an array type with known compile-time bound.
2820
2821 NOTE: Given that this function will _NOT_ be instrumenting the allocation
2822 through PFS, observability for particular parts of the system which want to
2823 use it will be lost or in best case inaccurate. Please have a strong reason
2824 to do so.
2825
2826 @param[in] alignment Alignment requirement for storage to be allocated.
2827 @return std::shared_ptr holding a pointer to an array of size instances of
2828 T.
2829 */
2830template <typename T, typename Deleter = detail::Aligned_array_deleter<
2831 std::remove_extent_t<T>>>
2832std::enable_if_t<detail::is_bounded_array_v<T>, std::shared_ptr<T>>
2833make_shared_aligned(size_t alignment) {
2834 return std::shared_ptr<T>(
2835 ut::aligned_new_arr<std::remove_extent_t<T>>(
2836 alignment, ut::Count{detail::bounded_array_size_v<T>}),
2837 Deleter{});
2838}
2839
2840/** Dynamically allocates storage for an array of objects of type T at address
2841 aligned to the requested alignment. Constructs the object of type T with
2842 provided Args. Wraps the pointer to an array of T instances into the
2843 std::shared_ptr with custom deleter which knows how to handle PFS-enabled
2844 dynamic memory allocations. Instruments the memory with given PSI memory key
2845 in case PFS memory support is enabled.
2846
2847 This overload participates in overload resolution only if T
2848 is an array type with known compile-time bound.
2849
2850 @param[in] key PSI memory key to be used for PFS memory instrumentation.
2851 @param[in] alignment Alignment requirement for storage to be allocated.
2852 @return std::shared_ptr holding a pointer to an array of size instances of
2853 T.
2854 */
2855template <typename T, typename Deleter = detail::Aligned_array_deleter<
2856 std::remove_extent_t<T>>>
2857std::enable_if_t<detail::is_bounded_array_v<T>, std::shared_ptr<T>>
2859 return std::shared_ptr<T>(
2860 ut::aligned_new_arr_withkey<std::remove_extent_t<T>>(
2861 key, alignment, ut::Count{detail::bounded_array_size_v<T>}),
2862 Deleter{});
2863}
2864
2865/** Specialization of basic_ostringstream which uses ut::allocator. Please note
2866 that it's .str() method returns std::basic_string which is not std::string,
2867 so it has similar API (in particular .c_str()), but you can't assign it to
2868 regular, std::string.
2869 */
2871 std::basic_ostringstream<char, std::char_traits<char>, ut::allocator<char>>;
2872
2873/** Specialization of vector which uses allocator. */
2874template <typename T>
2875using vector = std::vector<T, ut::allocator<T>>;
2876
2877/** Specialization of list which uses ut_allocator. */
2878template <typename T>
2879using list = std::list<T, ut::allocator<T>>;
2880
2881/** Specialization of set which uses ut_allocator. */
2882template <typename Key, typename Compare = std::less<Key>>
2883using set = std::set<Key, Compare, ut::allocator<Key>>;
2884
2885template <typename Key>
2887 std::unordered_set<Key, std::hash<Key>, std::equal_to<Key>,
2889
2890/** Specialization of map which uses ut_allocator. */
2891template <typename Key, typename Value, typename Compare = std::less<Key>>
2892using map =
2893 std::map<Key, Value, Compare, ut::allocator<std::pair<const Key, Value>>>;
2894
2895template <typename Key, typename Value, typename Hash = std::hash<Key>,
2896 typename Key_equal = std::equal_to<Key>>
2898 std::unordered_map<Key, Value, Hash, Key_equal,
2900
2901} // namespace ut
2902
2903#endif /* ut0new_h */
Definition: tls_cipher.cc:37
Lightweight convenience wrapper which manages a dynamically allocated array of over-aligned types.
Definition: ut0new.h:2018
void dealloc()
Invokes destructors of instances of type T, if applicable.
Definition: ut0new.h:2106
void alloc(Count count)
Allocates sufficiently large memory of dynamic storage duration to fit the array of size number of el...
Definition: ut0new.h:2040
T * ptr
Definition: ut0new.h:2019
void alloc_withkey(PSI_memory_key_t key, Count count)
Allocates sufficiently large memory of dynamic storage duration to fit the array of size number of el...
Definition: ut0new.h:2076
void alloc_withkey(PSI_memory_key_t key, Args &&... args)
Allocates sufficiently large memory of dynamic storage duration to fit the array of size number of el...
Definition: ut0new.h:2096
~aligned_array_pointer()
Destructor.
Definition: ut0new.h:2026
void alloc(Args &&... args)
Allocates sufficiently large memory of dynamic storage duration to fit the array of size number of el...
Definition: ut0new.h:2058
Lightweight convenience wrapper which manages dynamically allocated over-aligned type.
Definition: ut0new.h:1924
~aligned_pointer()
Destructor.
Definition: ut0new.h:1932
void alloc(Args &&... args)
Allocates sufficiently large memory of dynamic storage duration to fit the instance of type T at the ...
Definition: ut0new.h:1946
void alloc_withkey(PSI_memory_key_t key, Args &&... args)
Allocates sufficiently large memory of dynamic storage duration to fit the instance of type T at the ...
Definition: ut0new.h:1963
T * ptr
Definition: ut0new.h:1925
void dealloc()
Invokes the destructor of instance of type T, if applicable.
Definition: ut0new.h:1972
Allocator that allows std::* containers to manage their memory through ut::malloc* and ut::free libra...
Definition: ut0new.h:2182
T & reference
Definition: ut0new.h:2186
void deallocate(pointer ptr, size_type n_elements=0)
Releases the memory allocated through ut::allocator<T>::allocate().
Definition: ut0new.h:2278
~allocator()=default
const T * const_pointer
Definition: ut0new.h:2185
ptrdiff_t difference_type
Definition: ut0new.h:2190
allocator< T, Allocator_base > & operator=(const allocator< T, Allocator_base > &)=default
allocator< T, Allocator_base > & operator=(allocator< T, Allocator_base > &&)=default
T value_type
Definition: ut0new.h:2188
allocator(const allocator< U, Allocator_base > &other)
Copy-construct a new instance of allocator with type T by using existing instance of allocator constr...
Definition: ut0new.h:2215
pointer allocate(size_type n_elements, const_pointer hint=nullptr)
Allocates chunk of memory that can hold n_elements objects of type T.
Definition: ut0new.h:2258
size_type max_size() const
Return the maximum number of objects that can be allocated by this allocator.
Definition: ut0new.h:2241
const T & const_reference
Definition: ut0new.h:2187
allocator(allocator< T, Allocator_base > &&)=default
bool operator!=(const ut::allocator< T, Allocator_base > &other) const
Non-equality of allocators instantiated with same types T.
Definition: ut0new.h:2233
allocator(PSI_memory_key key=mem_key_std)
Default constructor.
Definition: ut0new.h:2199
allocator(const allocator< T, Allocator_base > &)=default
size_t size_type
Definition: ut0new.h:2189
bool operator==(const ut::allocator< T, Allocator_base > &) const
Equality of allocators instantiated with same types T.
Definition: ut0new.h:2229
T * pointer
Definition: ut0new.h:2184
Implementation bits and pieces of include/ut0new.h.
unsigned int PSI_memory_key
Instrumented memory key.
Definition: psi_memory_bits.h:49
#define realloc(P, A)
Definition: lexyy.cc:916
#define free(A)
Definition: lexyy.cc:915
A macro that gives FILE without the directory name (e.g.
constexpr bool unlikely(bool expr)
Definition: my_compiler.h:58
static int count
Definition: myisam_ftdump.cc:45
Instrumentation helpers for memory allocation.
std::atomic< Type > N
Definition: ut0counter.h:225
std::unordered_map< Key, CHARSET_INFO * > Hash
Definition: collations_internal.cc:548
Definition: ut0tuple.h:57
Definition: os0file.h:89
std::string_view Key
The key type for the hash structure in HashJoinRowBuffer.
Definition: hash_join_buffer.h:102
Definition: http_server_component.cc:34
size_t size(const char *const c)
Definition: base64.h:46
Alignment
Enum class describing alignment-requirements.
Definition: lock_free_type.h:39
constexpr bool is_unbounded_array_v< T[]>
Definition: ut0new.h:2287
typename select_alloc_impl< Pfs_memory_instrumentation_on >::type select_alloc_impl_t
Just a small helper type which saves us some keystrokes.
Definition: aligned_alloc.h:691
constexpr size_t bounded_array_size_v< T[N]>
Definition: ut0new.h:2297
constexpr bool is_bounded_array_v
Definition: ut0new.h:2290
constexpr bool is_unbounded_array_v
Definition: ut0new.h:2285
typename select_large_page_alloc_impl< Pfs_memory_instrumentation_on >::type select_large_page_alloc_impl_t
Just a small helper type which saves us some keystrokes.
Definition: large_page_alloc.h:367
typename select_page_alloc_impl< Pfs_memory_instrumentation_on >::type select_page_alloc_impl_t
Just a small helper type which saves us some keystrokes.
Definition: page_alloc.h:428
typename select_malloc_impl< Pfs_memory_instrumentation_on, Array_specialization >::type select_malloc_impl_t
Just a small helper type which saves us some keystrokes.
Definition: alloc.h:429
constexpr size_t bounded_array_size_v
Definition: ut0new.h:2295
constexpr bool is_bounded_array_v< T[N]>
Definition: ut0new.h:2292
This file contains a set of libraries providing overloads for regular dynamic allocation routines whi...
Definition: aligned_alloc.h:48
void * aligned_zalloc_withkey(PSI_memory_key_t key, std::size_t size, std::size_t alignment) noexcept
Dynamically allocates zero-initialized storage of given size and at the address aligned to the reques...
Definition: ut0new.h:1527
std::unordered_map< Key, Value, Hash, Key_equal, ut::allocator< std::pair< const Key, Value > > > unordered_map
Definition: ut0new.h:2899
T * new_arr_withkey(PSI_memory_key_t key, Args &&... args)
Dynamically allocates storage for an array of T's.
Definition: ut0new.h:875
size_t pfs_overhead() noexcept
Returns number of bytes that ut::malloc_*, ut::zalloc_*, ut::realloc_* and ut::new_* variants will be...
Definition: ut0new.h:1126
T * aligned_new_withkey(PSI_memory_key_t key, std::size_t alignment, Args &&... args)
Dynamically allocates storage for an object of type T at address aligned to the requested alignment.
Definition: ut0new.h:1595
void * zalloc_withkey(PSI_memory_key_t key, std::size_t size) noexcept
Dynamically allocates zero-initialized storage of given size.
Definition: ut0new.h:633
void * malloc_withkey(PSI_memory_key_t key, std::size_t size) noexcept
Dynamically allocates storage of given size.
Definition: ut0new.h:597
std::enable_if_t<!std::is_array< T >::value, std::unique_ptr< T, Deleter > > make_unique(Args &&... args)
Dynamically allocates storage for an object of type T.
Definition: ut0new.h:2338
T * aligned_new_arr(std::size_t alignment, Args &&... args)
Dynamically allocates storage for an array of T's at address aligned to the requested alignment.
Definition: ut0new.h:1839
void * aligned_zalloc(std::size_t size, std::size_t alignment) noexcept
Dynamically allocates zero-initialized storage of given size and at the address aligned to the reques...
Definition: ut0new.h:1550
void * malloc_large_page(std::size_t size) noexcept
Dynamically allocates memory backed up by large (huge) pages.
Definition: ut0new.h:1272
std::unordered_set< Key, std::hash< Key >, std::equal_to< Key >, ut::allocator< Key > > unordered_set
Definition: ut0new.h:2888
std::basic_ostringstream< char, std::char_traits< char >, ut::allocator< char > > ostringstream
Specialization of basic_ostringstream which uses ut::allocator.
Definition: ut0new.h:2871
T * new_(Args &&... args)
Dynamically allocates storage for an object of type T.
Definition: ut0new.h:795
allocation_low_level_info page_low_level_info(void *ptr) noexcept
Retrieves the pointer and size of the allocation provided by the OS.
Definition: ut0new.h:1210
std::vector< T, ut::allocator< T > > vector
Specialization of vector which uses allocator.
Definition: ut0new.h:2875
void aligned_delete_arr(T *ptr) noexcept
Releases storage which has been dynamically allocated through any of the aligned_new_arr_*() variants...
Definition: ut0new.h:1896
void delete_(T *ptr) noexcept
Releases storage which has been dynamically allocated through any of the ut::new*() variants.
Definition: ut0new.h:810
std::set< Key, Compare, ut::allocator< Key > > set
Specialization of set which uses ut_allocator.
Definition: ut0new.h:2883
void * malloc_page(std::size_t size) noexcept
Dynamically allocates system page-aligned storage of given size.
Definition: ut0new.h:1176
void * realloc_withkey(PSI_memory_key_t key, void *ptr, std::size_t size) noexcept
Upsizes or downsizes already dynamically allocated storage to the new size.
Definition: ut0new.h:676
T * new_withkey(PSI_memory_key_t key, Args &&... args)
Dynamically allocates storage for an object of type T.
Definition: ut0new.h:752
void delete_arr(T *ptr) noexcept
Releases storage which has been dynamically allocated through any of the ut::new_arr*() variants.
Definition: ut0new.h:1110
allocation_low_level_info large_page_low_level_info(void *ptr) noexcept
Retrieves the pointer and size of the allocation provided by the OS.
Definition: ut0new.h:1308
std::enable_if_t<!std::is_array< T >::value, std::unique_ptr< T, Deleter > > make_unique_aligned(size_t alignment, Args &&... args)
Dynamically allocates storage for an object of type T at address aligned to the requested alignment.
Definition: ut0new.h:2460
T * new_arr(Args &&... args)
Dynamically allocates storage for an array of T's.
Definition: ut0new.h:960
bool free_page(void *ptr) noexcept
Releases storage which has been dynamically allocated through any of the ut::malloc_page*() variants.
Definition: ut0new.h:1226
void * malloc_large_page_withkey(PSI_memory_key_t key, std::size_t size) noexcept
Dynamically allocates memory backed up by large (huge) pages.
Definition: ut0new.h:1248
size_t large_page_allocation_size(void *ptr) noexcept
Retrieves the total amount of bytes that are available for application code to use.
Definition: ut0new.h:1294
std::enable_if_t<!std::is_array< T >::value, std::shared_ptr< T > > make_shared_aligned(size_t alignment, Args &&... args)
Dynamically allocates storage for an object of type T at address aligned to the requested alignment.
Definition: ut0new.h:2731
std::map< Key, Value, Compare, ut::allocator< std::pair< const Key, Value > > > map
Specialization of map which uses ut_allocator.
Definition: ut0new.h:2893
void * malloc(std::size_t size) noexcept
Dynamically allocates storage of given size.
Definition: ut0new.h:618
std::conditional_t< !std::is_array< T >::value, std::unique_ptr< T, detail::Deleter< T > >, std::conditional_t< detail::is_unbounded_array_v< T >, std::unique_ptr< T, detail::Array_deleter< std::remove_extent_t< T > > >, void > > unique_ptr
The following is a common type that is returned by all the ut::make_unique (non-aligned) specializati...
Definition: ut0new.h:2439
T * aligned_new(std::size_t alignment, Args &&... args)
Dynamically allocates storage for an object of type T at address aligned to the requested alignment.
Definition: ut0new.h:1636
std::list< T, ut::allocator< T > > list
Specialization of list which uses ut_allocator.
Definition: ut0new.h:2879
void free(void *ptr) noexcept
Releases storage which has been dynamically allocated through any of the ut::malloc*(),...
Definition: ut0new.h:718
PSI_memory_key_t make_psi_memory_key(PSI_memory_key key)
Convenience helper function to create type-safe representation of PSI_memory_key.
Definition: ut0new.h:190
void * aligned_alloc_withkey(PSI_memory_key_t key, std::size_t size, std::size_t alignment) noexcept
Dynamically allocates storage of given size and at the address aligned to the requested alignment.
Definition: ut0new.h:1485
constexpr bool WITH_PFS_MEMORY
Definition: ut0new.h:581
void aligned_delete(T *ptr) noexcept
Releases storage which has been dynamically allocated through any of the aligned_new_*() variants.
Definition: ut0new.h:1651
void * malloc_page_withkey(PSI_memory_key_t key, std::size_t size) noexcept
Dynamically allocates system page-aligned storage of given size.
Definition: ut0new.h:1149
std::conditional_t< !std::is_array< T >::value, std::unique_ptr< T, detail::Aligned_deleter< T > >, std::conditional_t< detail::is_unbounded_array_v< T >, std::unique_ptr< T, detail::Aligned_array_deleter< std::remove_extent_t< T > > >, void > > unique_ptr_aligned
The following is a common type that is returned by all the ut::make_unique_aligned (non-aligned) spec...
Definition: ut0new.h:2573
void * realloc(void *ptr, std::size_t size) noexcept
Upsizes or downsizes already dynamically allocated storage to the new size.
Definition: ut0new.h:704
std::enable_if_t<!std::is_array< T >::value, std::shared_ptr< T > > make_shared(Args &&... args)
Dynamically allocates storage for an object of type T.
Definition: ut0new.h:2591
size_t page_allocation_size(void *ptr) noexcept
Retrieves the total amount of bytes that are available for application code to use.
Definition: ut0new.h:1196
bool free_large_page(void *ptr) noexcept
Releases storage which has been dynamically allocated through any of the ut::malloc_large_page*() var...
Definition: ut0new.h:1325
T * aligned_new_arr_withkey(PSI_memory_key_t key, std::size_t alignment, Args &&... args)
Dynamically allocates storage for an array of T's at address aligned to the requested alignment.
Definition: ut0new.h:1716
void aligned_free(void *ptr) noexcept
Releases storage which has been dynamically allocated through any of the aligned_alloc_*() or aligned...
Definition: ut0new.h:1564
void * aligned_alloc(std::size_t size, std::size_t alignment) noexcept
Dynamically allocates storage of given size and at the address aligned to the requested alignment.
Definition: ut0new.h:1508
void * zalloc(std::size_t size) noexcept
Dynamically allocates zero-initialized storage of given size.
Definition: ut0new.h:654
The interface to the operating system process control primitives.
bool os_use_large_pages
Whether to use large pages in the buffer pool.
Definition: os0proc.cc:51
The interface to the operating system process and thread control primitives.
Performance schema instrumentation interface.
Performance schema instrumentation interface.
required string key
Definition: replication_asynchronous_connection_failover.proto:60
static MEM_ROOT mem
Definition: sql_servers.cc:100
Memory instrument information.
Definition: psi_memory_bits.h:58
Definition: ut0new.h:558
static constexpr int value
Definition: ut0new.h:559
Light-weight and type-safe wrapper which serves a purpose of being able to select proper ut::new_arr*...
Definition: ut0new.h:982
Count(size_t count)
Definition: ut0new.h:983
size_t m_count
Definition: ut0new.h:985
size_t operator()() const
Definition: ut0new.h:984
Light-weight and type-safe wrapper around the PSI_memory_key that eliminates the possibility of intro...
Definition: ut0new.h:178
PSI_memory_key operator()() const
Definition: ut0new.h:180
PSI_memory_key m_key
Definition: ut0new.h:181
PSI_memory_key_t(PSI_memory_key key)
Definition: ut0new.h:179
Can be used to extract pointer and size of the allocation provided by the OS.
Definition: ut0new.h:140
void * base_ptr
A pointer returned by the OS allocator.
Definition: ut0new.h:142
size_t allocation_size
The size of allocation that OS performed.
Definition: ut0new.h:144
Definition: ut0new.h:2224
Small wrapper which utilizes SFINAE to dispatch the call to appropriate aligned allocator implementat...
Definition: aligned_alloc.h:697
Definition: ut0new.h:2315
void operator()(T *ptr)
Definition: ut0new.h:2316
Definition: ut0new.h:2310
void operator()(T *ptr)
Definition: ut0new.h:2311
Small wrapper which utilizes SFINAE to dispatch the call to appropriate allocator implementation.
Definition: alloc.h:435
Definition: ut0new.h:2305
void operator()(T *ptr)
Definition: ut0new.h:2306
Definition: ut0new.h:2300
void operator()(T *ptr)
Definition: ut0new.h:2301
Small wrapper which utilizes SFINAE to dispatch the call to appropriate aligned allocator implementat...
Definition: large_page_alloc.h:373
Small wrapper which utilizes SFINAE to dispatch the call to appropriate aligned allocator implementat...
Definition: page_alloc.h:434
Definition: ut0new.h:2132
void * allocate_impl(size_t n_bytes)
Definition: ut0new.h:2141
const PSI_memory_key m_key
Definition: ut0new.h:2146
PSI_memory_key get_mem_key() const
Definition: ut0new.h:2139
allocator_base_pfs(PSI_memory_key key)
Definition: ut0new.h:2133
allocator_base_pfs(const allocator_base_pfs< U > &other)
Definition: ut0new.h:2136
Definition: ut0new.h:2122
allocator_base(const allocator_base< U > &)
Definition: ut0new.h:2126
void * allocate_impl(size_t n_bytes)
Definition: ut0new.h:2128
allocator_base(PSI_memory_key)
Definition: ut0new.h:2123
Definition: ut0new.h:1332
Version control for database, common definitions, and include files.
#define UT_ARR_SIZE(a)
Definition: univ.i:524
Utilities for byte operations.
Utilities related to CPU cache.
Debug utilities for Innobase.
#define ut_ad(EXPR)
Debug assertion.
Definition: ut0dbg.h:105
#define ut_a(EXPR)
Abort execution if EXPR does not evaluate to nonzero.
Definition: ut0dbg.h:93
PSI_memory_key mem_key_ddl
Definition: ut0new.cc:60
void ut_new_boot_safe()
Setup the internal objects needed for ut::*_withkey() to operate.
Definition: ut0new.cc:137
PSI_memory_key mem_key_redo_log_archive_queue_element
PSI_memory_key mem_key_dict_stats_index_map_t
Definition: ut0new.cc:54
PSI_memory_key mem_key_buf_stat_per_index_t
Definition: ut0new.cc:50
PSI_memory_key mem_key_other
Definition: ut0new.cc:57
PSI_memory_info pfs_info_auto[n_auto]
PSI_memory_key auto_event_keys[n_auto]
constexpr int ut_new_get_key_by_base_file(const char *file, size_t len)
Retrieve a memory key (registered with PFS), given the file name of the caller.
Definition: ut0new.h:537
PSI_memory_key mem_key_fil_space_t
Definition: ut0new.cc:56
constexpr bool ut_string_begins_with(const char *a, const char *b, size_t b_len)
gcc 5 fails to evaluate costexprs at compile time.
Definition: ut0new.h:511
constexpr int ut_new_get_key_by_file(const char *file)
Retrieve a memory key (registered with PFS), given the file name of the caller.
Definition: ut0new.h:550
PSI_memory_key mem_key_ahi
Keys for registering allocations with performance schema.
Definition: ut0new.cc:47
void ut_new_boot()
Setup the internal objects needed for ut::*_withkey() to operate.
Definition: ut0new.cc:118
PSI_memory_key mem_key_partitioning
Definition: ut0new.cc:58
PSI_memory_key mem_key_archive
Definition: ut0new.cc:48
static constexpr const char * auto_event_names[]
List of filenames that allocate memory and are instrumented via PFS.
Definition: ut0new.h:246
PSI_memory_key mem_key_std
Definition: ut0new.cc:61
const size_t alloc_max_retries
Maximum number of retries to allocate memory.
Definition: ut0new.cc:43
PSI_memory_key mem_key_row_log_buf
Definition: ut0new.cc:59
PSI_memory_key mem_key_trx_sys_t_rw_trx_ids
Definition: ut0new.cc:62
static constexpr size_t n_auto
Definition: ut0new.h:448
PSI_memory_key mem_key_buf_buf_pool
Definition: ut0new.cc:49
constexpr size_t ut_len_without_extension(const char *file)
Find the length of the filename without its file extension.
Definition: ut0new.h:524
PSI_memory_key mem_key_undo_spaces
Definition: ut0new.cc:63
PSI_memory_key mem_key_ut_lock_free_hash_t
Definition: ut0new.cc:64
PSI_memory_key mem_key_clone
Memory key for clone.
Definition: ut0new.cc:52
PSI_memory_key mem_key_dict_stats_n_diff_on_level
Definition: ut0new.cc:55
PSI_memory_key mem_key_dict_stats_bg_recalc_pool_t
Definition: ut0new.cc:53
Various utilities.
#define PSI_NOT_INSTRUMENTED
Definition: validate_password_imp.cc:42