1/*****************************************************************************
2
3Copyright (c) 2014, 2015, Oracle and/or its affiliates. All Rights Reserved.
4Copyright (c) 2017, MariaDB Corporation.
5
6This program is free software; you can redistribute it and/or modify it under
7the terms of the GNU General Public License as published by the Free Software
8Foundation; version 2 of the License.
9
10This program is distributed in the hope that it will be useful, but WITHOUT
11ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
12FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
13
14You should have received a copy of the GNU General Public License along with
15this program; if not, write to the Free Software Foundation, Inc.,
1651 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
17
18*****************************************************************************/
19
20/**************************************************//**
21@file ut/ut0new.h
22Instrumented memory allocator.
23
24Created May 26, 2014 Vasil Dimov
25*******************************************************/
26
27/** Dynamic memory allocation within InnoDB guidelines.
28All dynamic (heap) memory allocations (malloc(3), strdup(3), etc, "new",
29various std:: containers that allocate memory internally), that are done
30within InnoDB are instrumented. This means that InnoDB uses a custom set
31of functions for allocating memory, rather than calling e.g. "new" directly.
32
33Here follows a cheat sheet on what InnoDB functions to use whenever a
34standard one would have been used.
35
36Creating new objects with "new":
37--------------------------------
38Standard:
39 new expression
40 or
41 new(std::nothrow) expression
42InnoDB, default instrumentation:
43 UT_NEW_NOKEY(expression)
44InnoDB, custom instrumentation, preferred:
45 UT_NEW(expression, key)
46
47Destroying objects, created with "new":
48---------------------------------------
49Standard:
50 delete ptr
51InnoDB:
52 UT_DELETE(ptr)
53
54Creating new arrays with "new[]":
55---------------------------------
56Standard:
57 new type[num]
58 or
59 new(std::nothrow) type[num]
60InnoDB, default instrumentation:
61 UT_NEW_ARRAY_NOKEY(type, num)
62InnoDB, custom instrumentation, preferred:
63 UT_NEW_ARRAY(type, num, key)
64
65Destroying arrays, created with "new[]":
66----------------------------------------
67Standard:
68 delete[] ptr
69InnoDB:
70 UT_DELETE_ARRAY(ptr)
71
72Declaring a type with a std:: container, e.g. std::vector:
73----------------------------------------------------------
74Standard:
75 std::vector<t>
76InnoDB:
77 std::vector<t, ut_allocator<t> >
78
79Declaring objects of some std:: type:
80-------------------------------------
81Standard:
82 std::vector<t> v
83InnoDB, default instrumentation:
84 std::vector<t, ut_allocator<t> > v
85InnoDB, custom instrumentation, preferred:
86 std::vector<t, ut_allocator<t> > v(ut_allocator<t>(key))
87
88Raw block allocation (as usual in C++, consider whether using "new" would
89not be more appropriate):
90-------------------------------------------------------------------------
91Standard:
92 malloc(num)
93InnoDB, default instrumentation:
94 ut_malloc_nokey(num)
95InnoDB, custom instrumentation, preferred:
96 ut_malloc(num, key)
97
98Raw block resize:
99-----------------
100Standard:
101 realloc(ptr, new_size)
102InnoDB:
103 ut_realloc(ptr, new_size)
104
105Raw block deallocation:
106-----------------------
107Standard:
108 free(ptr)
109InnoDB:
110 ut_free(ptr)
111
112Note: the expression passed to UT_NEW() or UT_NEW_NOKEY() must always end
113with (), thus:
114Standard:
115 new int
116InnoDB:
117 UT_NEW_NOKEY(int())
118*/
119
120#ifndef ut0new_h
121#define ut0new_h
122
123#include <algorithm> /* std::min() */
124#include <limits> /* std::numeric_limits */
125#include <map> /* std::map */
126
127#include <stddef.h>
128#include <stdlib.h> /* malloc() */
129#include <string.h> /* strlen(), strrchr(), strncmp() */
130
131#include "my_global.h" /* needed for headers from mysql/psi/ */
132#if !defined(DBUG_OFF) && defined(HAVE_MADVISE)
133#include <sys/mman.h>
134#endif
135
136/* JAN: TODO: missing 5.7 header */
137#ifdef HAVE_MYSQL_MEMORY_H
138#include "mysql/psi/mysql_memory.h" /* PSI_MEMORY_CALL() */
139#endif
140
141#include "mysql/psi/psi_memory.h" /* PSI_memory_key, PSI_memory_info */
142
143#include "univ.i"
144
145#include "os0proc.h" /* os_mem_alloc_large() */
146#include "os0thread.h" /* os_thread_sleep() */
147#include "ut0ut.h" /* ut_strcmp_functor, ut_basename_noext() */
148
149#define OUT_OF_MEMORY_MSG \
150 "Check if you should increase the swap file or ulimits of your" \
151 " operating system. Note that on most 32-bit computers the process" \
152 " memory space is limited to 2 GB or 4 GB."
153
154/** Maximum number of retries to allocate memory. */
155extern const size_t alloc_max_retries;
156
157/** Keys for registering allocations with performance schema.
158Pointers to these variables are supplied to PFS code via the pfs_info[]
159array and the PFS code initializes them via PSI_MEMORY_CALL(register_memory)().
160mem_key_other and mem_key_std are special in the following way (see also
161ut_allocator::get_mem_key()):
162* If the caller has not provided a key and the file name of the caller is
163 unknown, then mem_key_std will be used. This happens only when called from
164 within std::* containers.
165* If the caller has not provided a key and the file name of the caller is
166 known, but is not amongst the predefined names (see ut_new_boot()) then
167 mem_key_other will be used. Generally this should not happen and if it
168 happens then that means that the list of predefined names must be extended.
169Keep this list alphabetically sorted. */
170extern PSI_memory_key mem_key_ahi;
171extern PSI_memory_key mem_key_buf_buf_pool;
172extern PSI_memory_key mem_key_dict_stats_bg_recalc_pool_t;
173extern PSI_memory_key mem_key_dict_stats_index_map_t;
174extern PSI_memory_key mem_key_dict_stats_n_diff_on_level;
175extern PSI_memory_key mem_key_other;
176extern PSI_memory_key mem_key_row_log_buf;
177extern PSI_memory_key mem_key_row_merge_sort;
178extern PSI_memory_key mem_key_std;
179extern PSI_memory_key mem_key_partitioning;
180
181/** Setup the internal objects needed for UT_NEW() to operate.
182This must be called before the first call to UT_NEW(). */
183void
184ut_new_boot();
185
186#ifdef UNIV_PFS_MEMORY
187
188/** Retrieve a memory key (registered with PFS), given a portion of the file
189name of the caller.
190@param[in] file portion of the filename - basename without an extension
191@return registered memory key or PSI_NOT_INSTRUMENTED if not found */
192PSI_memory_key
193ut_new_get_key_by_file(
194 const char* file);
195
196#endif /* UNIV_PFS_MEMORY */
197
198/** A structure that holds the necessary data for performance schema
199accounting. An object of this type is put in front of each allocated block
200of memory when allocation is done by ut_allocator::allocate(). This is
201because the data is needed even when freeing the memory. Users of
202ut_allocator::allocate_large() are responsible for maintaining this
203themselves. */
204struct ut_new_pfx_t {
205
206#ifdef UNIV_PFS_MEMORY
207
208 /** Performance schema key. Assigned to a name at startup via
209 PSI_MEMORY_CALL(register_memory)() and later used for accounting
210 allocations and deallocations with
211 PSI_MEMORY_CALL(memory_alloc)(key, size, owner) and
212 PSI_MEMORY_CALL(memory_free)(key, size, owner). */
213 PSI_memory_key m_key;
214
215 /**
216 Thread owner.
217 Instrumented thread that owns the allocated memory.
218 This state is used by the performance schema to maintain
219 per thread statistics,
220 when memory is given from thread A to thread B.
221 */
222 struct PSI_thread *m_owner;
223
224#endif /* UNIV_PFS_MEMORY */
225
226 /** Size of the allocated block in bytes, including this prepended
227 aux structure (for ut_allocator::allocate()). For example if InnoDB
228 code requests to allocate 100 bytes, and sizeof(ut_new_pfx_t) is 16,
229 then 116 bytes are allocated in total and m_size will be 116.
230 ut_allocator::allocate_large() does not prepend this struct to the
231 allocated block and its users are responsible for maintaining it
232 and passing it later to ut_allocator::deallocate_large(). */
233 size_t m_size;
234#if SIZEOF_VOIDP == 4
235 /** Pad the header size to a multiple of 64 bits on 32-bit systems,
236 so that the payload will be aligned to 64 bits. */
237 size_t pad;
238#endif
239};
240
241static inline void ut_allocate_trace_dontdump(void *ptr, size_t bytes,
242 bool
243#if defined(DBUG_OFF) && defined(HAVE_MADVISE) && defined(MADV_DONTDUMP)
244 dontdump
245#endif
246 , ut_new_pfx_t* pfx,
247 const char*
248#ifdef UNIV_PFS_MEMORY
249 file
250#endif
251
252 )
253{
254 ut_a(ptr != NULL);
255
256#if defined(DBUG_OFF) && defined(HAVE_MADVISE) && defined(MADV_DONTDUMP)
257 if (dontdump && madvise(ptr, bytes, MADV_DONTDUMP)) {
258 ib::warn() << "Failed to set memory to DONTDUMP: "
259 << strerror(errno)
260 << " ptr " << ptr
261 << " size " << bytes;
262 }
263#endif
264 if (pfx != NULL) {
265#ifdef UNIV_PFS_MEMORY
266 allocate_trace(bytes, file, pfx);
267#endif /* UNIV_PFS_MEMORY */
268 pfx->m_size = bytes;
269 }
270}
271
272#if defined(DBUG_OFF) && defined(HAVE_MADVISE) && defined(MADV_DODUMP)
273static inline void ut_dodump(void* ptr, size_t m_size)
274{
275 if (ptr && madvise(ptr, m_size, MADV_DODUMP)) {
276 ib::warn() << "Failed to set memory to DODUMP: "
277 << strerror(errno)
278 << " ptr " << ptr
279 << " size " << m_size;
280 }
281}
282#else
283static inline void ut_dodump(void*, size_t) {}
284#endif
285
286/** Allocator class for allocating memory from inside std::* containers.
287@tparam T type of allocated object
288@tparam oom_fatal whether to commit suicide when running out of memory */
289template <class T, bool oom_fatal = true>
290class ut_allocator {
291public:
292 typedef T* pointer;
293 typedef const T* const_pointer;
294 typedef T& reference;
295 typedef const T& const_reference;
296 typedef T value_type;
297 typedef size_t size_type;
298 typedef ptrdiff_t difference_type;
299
300#ifdef UNIV_PFS_MEMORY
301 /** Default constructor. */
302 explicit
303 ut_allocator(PSI_memory_key key = PSI_NOT_INSTRUMENTED)
304 : m_key(key)
305 {
306 }
307#else
308 ut_allocator() {}
309 ut_allocator(PSI_memory_key) {}
310#endif /* UNIV_PFS_MEMORY */
311
312 /** Constructor from allocator of another type. */
313 template <class U>
314 ut_allocator(const ut_allocator<U>&
315#ifdef UNIV_PFS_MEMORY
316 other
317#endif
318 )
319#ifdef UNIV_PFS_MEMORY
320 : m_key(other.m_key)
321#endif /* UNIV_PFS_MEMORY */
322 {
323 }
324
325 /** Return the maximum number of objects that can be allocated by
326 this allocator. */
327 size_type
328 max_size() const
329 {
330 const size_type s_max = std::numeric_limits<size_type>::max();
331
332#ifdef UNIV_PFS_MEMORY
333 return((s_max - sizeof(ut_new_pfx_t)) / sizeof(T));
334#else
335 return(s_max / sizeof(T));
336#endif /* UNIV_PFS_MEMORY */
337 }
338
339 pointer allocate(size_type n) { return allocate(n, NULL, NULL); }
340
341 /** Allocate a chunk of memory that can hold 'n_elements' objects of
342 type 'T' and trace the allocation.
343 If the allocation fails this method may throw an exception. This
344 is mandated by the standard and if it returns NULL instead, then
345 STL containers that use it (e.g. std::vector) may get confused.
346 After successfull allocation the returned pointer must be passed
347 to ut_allocator::deallocate() when no longer needed.
348 @param[in] n_elements number of elements
349 @param[in] set_to_zero if true, then the returned memory is
350 initialized with 0x0 bytes.
351 @param[in] throw_on_error if true, raize exception if too big
352 @return pointer to the allocated memory */
353 pointer
354 allocate(
355 size_type n_elements,
356 const_pointer,
357 const char*
358#ifdef UNIV_PFS_MEMORY
359 file /*!< file name of the caller */
360#endif
361 ,
362 bool set_to_zero = false,
363 bool throw_on_error = true)
364 {
365 if (n_elements == 0) {
366 return(NULL);
367 }
368
369 if (n_elements > max_size()) {
370 if (throw_on_error) {
371 throw(std::bad_alloc());
372 } else {
373 return(NULL);
374 }
375 }
376
377 void* ptr;
378 size_t total_bytes = n_elements * sizeof(T);
379
380#ifdef UNIV_PFS_MEMORY
381 /* The header size must not ruin the 64-bit alignment
382 on 32-bit systems. Some allocated structures use
383 64-bit fields. */
384 ut_ad((sizeof(ut_new_pfx_t) & 7) == 0);
385 total_bytes += sizeof(ut_new_pfx_t);
386#endif /* UNIV_PFS_MEMORY */
387
388 for (size_t retries = 1; ; retries++) {
389
390 if (set_to_zero) {
391 ptr = calloc(1, total_bytes);
392 } else {
393 ptr = malloc(total_bytes);
394 }
395
396 if (ptr != NULL || retries >= alloc_max_retries) {
397 break;
398 }
399
400 os_thread_sleep(1000000 /* 1 second */);
401 }
402
403 if (ptr == NULL) {
404 ib::fatal_or_error(oom_fatal)
405 << "Cannot allocate " << total_bytes
406 << " bytes of memory after "
407 << alloc_max_retries << " retries over "
408 << alloc_max_retries << " seconds. OS error: "
409 << strerror(errno) << " (" << errno << "). "
410 << OUT_OF_MEMORY_MSG;
411 if (throw_on_error) {
412 throw(std::bad_alloc());
413 } else {
414 return(NULL);
415 }
416 }
417
418#ifdef UNIV_PFS_MEMORY
419 ut_new_pfx_t* pfx = static_cast<ut_new_pfx_t*>(ptr);
420
421 allocate_trace(total_bytes, file, pfx);
422
423 return(reinterpret_cast<pointer>(pfx + 1));
424#else
425 return(reinterpret_cast<pointer>(ptr));
426#endif /* UNIV_PFS_MEMORY */
427 }
428
429 /** Free a memory allocated by allocate() and trace the deallocation.
430 @param[in,out] ptr pointer to memory to free */
431 void deallocate(pointer ptr, size_type)
432 {
433#ifdef UNIV_PFS_MEMORY
434 if (ptr == NULL) {
435 return;
436 }
437
438 ut_new_pfx_t* pfx = reinterpret_cast<ut_new_pfx_t*>(ptr) - 1;
439
440 deallocate_trace(pfx);
441
442 free(pfx);
443#else
444 free(ptr);
445#endif /* UNIV_PFS_MEMORY */
446 }
447
448 /** Create an object of type 'T' using the value 'val' over the
449 memory pointed by 'p'. */
450 void
451 construct(
452 pointer p,
453 const T& val)
454 {
455 new(p) T(val);
456 }
457
458 /** Destroy an object pointed by 'p'. */
459 void
460 destroy(
461 pointer p)
462 {
463 p->~T();
464 }
465
466 /** Return the address of an object. */
467 pointer
468 address(
469 reference x) const
470 {
471 return(&x);
472 }
473
474 /** Return the address of a const object. */
475 const_pointer
476 address(
477 const_reference x) const
478 {
479 return(&x);
480 }
481
482 template <class U>
483 struct rebind {
484 typedef ut_allocator<U> other;
485 };
486
487 /* The following are custom methods, not required by the standard. */
488
489#ifdef UNIV_PFS_MEMORY
490
491 /** realloc(3)-like method.
492 The passed in ptr must have been returned by allocate() and the
493 pointer returned by this method must be passed to deallocate() when
494 no longer needed.
495 @param[in,out] ptr old pointer to reallocate
496 @param[in] n_elements new number of elements to allocate
497 @param[in] file file name of the caller
498 @return newly allocated memory */
499 pointer
500 reallocate(
501 void* ptr,
502 size_type n_elements,
503 const char* file)
504 {
505 if (n_elements == 0) {
506 deallocate(static_cast<pointer>(ptr));
507 return(NULL);
508 }
509
510 if (ptr == NULL) {
511 return(allocate(n_elements, NULL, file, false, false));
512 }
513
514 if (n_elements > max_size()) {
515 return(NULL);
516 }
517
518 ut_new_pfx_t* pfx_old;
519 ut_new_pfx_t* pfx_new;
520 size_t total_bytes;
521
522 pfx_old = reinterpret_cast<ut_new_pfx_t*>(ptr) - 1;
523
524 total_bytes = n_elements * sizeof(T) + sizeof(ut_new_pfx_t);
525
526 for (size_t retries = 1; ; retries++) {
527
528 pfx_new = static_cast<ut_new_pfx_t*>(
529 realloc(pfx_old, total_bytes));
530
531 if (pfx_new != NULL || retries >= alloc_max_retries) {
532 break;
533 }
534
535 os_thread_sleep(1000000 /* 1 second */);
536 }
537
538 if (pfx_new == NULL) {
539 ib::fatal_or_error(oom_fatal)
540 << "Cannot reallocate " << total_bytes
541 << " bytes of memory after "
542 << alloc_max_retries << " retries over "
543 << alloc_max_retries << " seconds. OS error: "
544 << strerror(errno) << " (" << errno << "). "
545 << OUT_OF_MEMORY_MSG;
546 return(NULL);
547 }
548
549 /* pfx_new still contains the description of the old block
550 that was presumably freed by realloc(). */
551 deallocate_trace(pfx_new);
552
553 /* pfx_new is set here to describe the new block. */
554 allocate_trace(total_bytes, file, pfx_new);
555
556 return(reinterpret_cast<pointer>(pfx_new + 1));
557 }
558
559 /** Allocate, trace the allocation and construct 'n_elements' objects
560 of type 'T'. If the allocation fails or if some of the constructors
561 throws an exception, then this method will return NULL. It does not
562 throw exceptions. After successfull completion the returned pointer
563 must be passed to delete_array() when no longer needed.
564 @param[in] n_elements number of elements to allocate
565 @param[in] file file name of the caller
566 @return pointer to the first allocated object or NULL */
567 pointer
568 new_array(
569 size_type n_elements,
570 const char* file)
571 {
572 T* p = allocate(n_elements, NULL, file, false, false);
573
574 if (p == NULL) {
575 return(NULL);
576 }
577
578 T* first = p;
579 size_type i;
580
581 try {
582 for (i = 0; i < n_elements; i++) {
583 new(p) T;
584 ++p;
585 }
586 } catch (...) {
587 for (size_type j = 0; j < i; j++) {
588 --p;
589 p->~T();
590 }
591
592 deallocate(first);
593
594 throw;
595 }
596
597 return(first);
598 }
599
600 /** Destroy, deallocate and trace the deallocation of an array created
601 by new_array().
602 @param[in,out] ptr pointer to the first object in the array */
603 void
604 delete_array(
605 T* ptr)
606 {
607 if (ptr == NULL) {
608 return;
609 }
610
611 const size_type n_elements = n_elements_allocated(ptr);
612
613 T* p = ptr + n_elements - 1;
614
615 for (size_type i = 0; i < n_elements; i++) {
616 p->~T();
617 --p;
618 }
619
620 deallocate(ptr);
621 }
622
623#endif /* UNIV_PFS_MEMORY */
624
625 /** Allocate a large chunk of memory that can hold 'n_elements'
626 objects of type 'T' and trace the allocation.
627 @param[in] n_elements number of elements
628 @param[in] dontdump if true, advise the OS is not to core
629 dump this memory.
630 @param[out] pfx storage for the description of the
631 allocated memory. The caller must provide space for this one and keep
632 it until the memory is no longer needed and then pass it to
633 deallocate_large().
634 @return pointer to the allocated memory or NULL */
635 pointer
636 allocate_large(
637 size_type n_elements,
638 ut_new_pfx_t* pfx,
639 bool dontdump = false)
640 {
641 if (n_elements == 0 || n_elements > max_size()) {
642 return(NULL);
643 }
644
645 ulint n_bytes = n_elements * sizeof(T);
646
647 pointer ptr = reinterpret_cast<pointer>(
648 os_mem_alloc_large(&n_bytes));
649
650 if (ptr == NULL) {
651 return NULL;
652 }
653
654 ut_allocate_trace_dontdump(ptr, n_bytes, dontdump, pfx, NULL);
655
656 return(ptr);
657 }
658
659 /** Free a memory allocated by allocate_large() and trace the
660 deallocation.
661 @param[in,out] ptr pointer to memory to free
662 @param[in] pfx descriptor of the memory, as returned by
663 allocate_large().
664 @param[in] dodump if true, advise the OS to include this
665 memory again if a core dump occurs. */
666 void
667 deallocate_large(
668 pointer ptr,
669 const ut_new_pfx_t*
670#ifdef UNIV_PFS_MEMORY
671 pfx
672#endif
673 ,
674 size_t size,
675 bool dodump = false)
676 {
677 if (dodump) {
678 ut_dodump(ptr, size);
679 }
680#ifdef UNIV_PFS_MEMORY
681 if (pfx) {
682 deallocate_trace(pfx);
683 }
684#endif /* UNIV_PFS_MEMORY */
685
686 os_mem_free_large(ptr, size);
687 }
688
689#ifdef UNIV_PFS_MEMORY
690
691 /** Get the performance schema key to use for tracing allocations.
692 @param[in] file file name of the caller or NULL if unknown
693 @return performance schema key */
694 PSI_memory_key
695 get_mem_key(
696 const char* file) const
697 {
698 if (m_key != PSI_NOT_INSTRUMENTED) {
699 return(m_key);
700 }
701
702 if (file == NULL) {
703 return(mem_key_std);
704 }
705
706 /* e.g. "btr0cur", derived from "/path/to/btr0cur.cc" */
707 char keyname[FILENAME_MAX];
708 const size_t len = ut_basename_noext(file, keyname,
709 sizeof(keyname));
710 /* If sizeof(keyname) was not enough then the output would
711 be truncated, assert that this did not happen. */
712 ut_a(len < sizeof(keyname));
713
714 const PSI_memory_key key = ut_new_get_key_by_file(keyname);
715
716 if (key != PSI_NOT_INSTRUMENTED) {
717 return(key);
718 }
719
720 return(mem_key_other);
721 }
722
723private:
724
725 /** Retrieve the size of a memory block allocated by new_array().
726 @param[in] ptr pointer returned by new_array().
727 @return size of memory block */
728 size_type
729 n_elements_allocated(
730 const_pointer ptr)
731 {
732 const ut_new_pfx_t* pfx
733 = reinterpret_cast<const ut_new_pfx_t*>(ptr) - 1;
734
735 const size_type user_bytes
736 = pfx->m_size - sizeof(ut_new_pfx_t);
737
738 ut_ad(user_bytes % sizeof(T) == 0);
739
740 return(user_bytes / sizeof(T));
741 }
742
743 /** Trace a memory allocation.
744 After the accounting, the data needed for tracing the deallocation
745 later is written into 'pfx'.
746 The PFS event name is picked on the following criteria:
747 1. If key (!= PSI_NOT_INSTRUMENTED) has been specified when constructing
748 this ut_allocator object, then the name associated with that key will
749 be used (this is the recommended approach for new code)
750 2. Otherwise, if "file" is NULL, then the name associated with
751 mem_key_std will be used
752 3. Otherwise, if an entry is found by ut_new_get_key_by_file(), that
753 corresponds to "file", that will be used (see ut_new_boot())
754 4. Otherwise, the name associated with mem_key_other will be used.
755 @param[in] size number of bytes that were allocated
756 @param[in] file file name of the caller or NULL if unknown
757 @param[out] pfx placeholder to store the info which will be
758 needed when freeing the memory */
759 void
760 allocate_trace(
761 size_t size,
762 const char* file,
763 ut_new_pfx_t* pfx)
764 {
765 const PSI_memory_key key = get_mem_key(file);
766
767 pfx->m_key = PSI_MEMORY_CALL(memory_alloc)(key, size, & pfx->m_owner);
768 pfx->m_size = size;
769 }
770
771 /** Trace a memory deallocation.
772 @param[in] pfx info for the deallocation */
773 void
774 deallocate_trace(
775 const ut_new_pfx_t* pfx)
776 {
777 PSI_MEMORY_CALL(memory_free)(pfx->m_key, pfx->m_size, pfx->m_owner);
778 }
779
780 /** Performance schema key. */
781 PSI_memory_key m_key;
782
783#endif /* UNIV_PFS_MEMORY */
784
785private:
786
787 /** Assignment operator, not used, thus disabled (private). */
788 template <class U>
789 void
790 operator=(
791 const ut_allocator<U>&);
792};
793
794/** Compare two allocators of the same type.
795As long as the type of A1 and A2 is the same, a memory allocated by A1
796could be freed by A2 even if the pfs mem key is different. */
797template <typename T>
798inline
799bool
800operator==(const ut_allocator<T>&, const ut_allocator<T>&) { return(true); }
801
802/** Compare two allocators of the same type. */
803template <typename T>
804inline
805bool
806operator!=(
807 const ut_allocator<T>& lhs,
808 const ut_allocator<T>& rhs)
809{
810 return(!(lhs == rhs));
811}
812
813#ifdef UNIV_PFS_MEMORY
814
815/** Allocate, trace the allocation and construct an object.
816Use this macro instead of 'new' within InnoDB.
817For example: instead of
818 Foo* f = new Foo(args);
819use:
820 Foo* f = UT_NEW(Foo(args), mem_key_some);
821Upon failure to allocate the memory, this macro may return NULL. It
822will not throw exceptions. After successfull allocation the returned
823pointer must be passed to UT_DELETE() when no longer needed.
824@param[in] expr any expression that could follow "new"
825@param[in] key performance schema memory tracing key
826@return pointer to the created object or NULL */
827#define UT_NEW(expr, key) \
828 /* Placement new will return NULL and not attempt to construct an
829 object if the passed in pointer is NULL, e.g. if allocate() has
830 failed to allocate memory and has returned NULL. */ \
831 ::new(ut_allocator<byte>(key).allocate( \
832 sizeof expr, NULL, __FILE__, false, false)) expr
833
834/** Allocate, trace the allocation and construct an object.
835Use this macro instead of 'new' within InnoDB and instead of UT_NEW()
836when creating a dedicated memory key is not feasible.
837For example: instead of
838 Foo* f = new Foo(args);
839use:
840 Foo* f = UT_NEW_NOKEY(Foo(args));
841Upon failure to allocate the memory, this macro may return NULL. It
842will not throw exceptions. After successfull allocation the returned
843pointer must be passed to UT_DELETE() when no longer needed.
844@param[in] expr any expression that could follow "new"
845@return pointer to the created object or NULL */
846#define UT_NEW_NOKEY(expr) UT_NEW(expr, PSI_NOT_INSTRUMENTED)
847
848/** Destroy, deallocate and trace the deallocation of an object created by
849UT_NEW() or UT_NEW_NOKEY().
850We can't instantiate ut_allocator without having the type of the object, thus
851we redirect this to a templated function. */
852#define UT_DELETE(ptr) ut_delete(ptr)
853
854/** Destroy and account object created by UT_NEW() or UT_NEW_NOKEY().
855@param[in,out] ptr pointer to the object */
856template <typename T>
857inline
858void
859ut_delete(
860 T* ptr)
861{
862 if (ptr == NULL) {
863 return;
864 }
865
866 ut_allocator<T> allocator;
867
868 allocator.destroy(ptr);
869 allocator.deallocate(ptr);
870}
871
872/** Allocate and account 'n_elements' objects of type 'type'.
873Use this macro to allocate memory within InnoDB instead of 'new[]'.
874The returned pointer must be passed to UT_DELETE_ARRAY().
875@param[in] type type of objects being created
876@param[in] n_elements number of objects to create
877@param[in] key performance schema memory tracing key
878@return pointer to the first allocated object or NULL */
879#define UT_NEW_ARRAY(type, n_elements, key) \
880 ut_allocator<type>(key).new_array(n_elements, __FILE__)
881
882/** Allocate and account 'n_elements' objects of type 'type'.
883Use this macro to allocate memory within InnoDB instead of 'new[]' and
884instead of UT_NEW_ARRAY() when it is not feasible to create a dedicated key.
885@param[in] type type of objects being created
886@param[in] n_elements number of objects to create
887@return pointer to the first allocated object or NULL */
888#define UT_NEW_ARRAY_NOKEY(type, n_elements) \
889 UT_NEW_ARRAY(type, n_elements, PSI_NOT_INSTRUMENTED)
890
891/** Destroy, deallocate and trace the deallocation of an array created by
892UT_NEW_ARRAY() or UT_NEW_ARRAY_NOKEY().
893We can't instantiate ut_allocator without having the type of the object, thus
894we redirect this to a templated function. */
895#define UT_DELETE_ARRAY(ptr) ut_delete_array(ptr)
896
897/** Destroy and account objects created by UT_NEW_ARRAY() or
898UT_NEW_ARRAY_NOKEY().
899@param[in,out] ptr pointer to the first object in the array */
900template <typename T>
901inline
902void
903ut_delete_array(
904 T* ptr)
905{
906 ut_allocator<T>().delete_array(ptr);
907}
908
909#define ut_malloc(n_bytes, key) static_cast<void*>( \
910 ut_allocator<byte>(key).allocate( \
911 n_bytes, NULL, __FILE__, false, false))
912
913#define ut_malloc_dontdump(n_bytes) static_cast<void*>( \
914 ut_allocator<byte>(PSI_NOT_INSTRUMENTED).allocate_large( \
915 n_bytes, true))
916
917#define ut_zalloc(n_bytes, key) static_cast<void*>( \
918 ut_allocator<byte>(key).allocate( \
919 n_bytes, NULL, __FILE__, true, false))
920
921#define ut_malloc_nokey(n_bytes) static_cast<void*>( \
922 ut_allocator<byte>(PSI_NOT_INSTRUMENTED).allocate( \
923 n_bytes, NULL, __FILE__, false, false))
924
925#define ut_zalloc_nokey(n_bytes) static_cast<void*>( \
926 ut_allocator<byte>(PSI_NOT_INSTRUMENTED).allocate( \
927 n_bytes, NULL, __FILE__, true, false))
928
929#define ut_zalloc_nokey_nofatal(n_bytes) static_cast<void*>( \
930 ut_allocator<byte, false>(PSI_NOT_INSTRUMENTED).allocate( \
931 n_bytes, NULL, __FILE__, true, false))
932
933#define ut_realloc(ptr, n_bytes) static_cast<void*>( \
934 ut_allocator<byte>(PSI_NOT_INSTRUMENTED).reallocate( \
935 ptr, n_bytes, __FILE__))
936
937#define ut_free(ptr) ut_allocator<byte>(PSI_NOT_INSTRUMENTED).deallocate( \
938 reinterpret_cast<byte*>(ptr))
939
940#define ut_free_dodump(ptr, size) static_cast<void*>( \
941 ut_allocator<byte>(PSI_NOT_INSTRUMENTED).deallocate_large( \
942 ptr, NULL, size, true))
943
944#else /* UNIV_PFS_MEMORY */
945
946/* Fallbacks when memory tracing is disabled at compile time. */
947
948#define UT_NEW(expr, key) ::new(std::nothrow) expr
949#define UT_NEW_NOKEY(expr) ::new(std::nothrow) expr
950#define UT_DELETE(ptr) ::delete ptr
951
952#define UT_NEW_ARRAY(type, n_elements, key) \
953 ::new(std::nothrow) type[n_elements]
954
955#define UT_NEW_ARRAY_NOKEY(type, n_elements) \
956 ::new(std::nothrow) type[n_elements]
957
958#define UT_DELETE_ARRAY(ptr) ::delete[] ptr
959
960#define ut_malloc(n_bytes, key) ::malloc(n_bytes)
961
962#define ut_zalloc(n_bytes, key) ::calloc(1, n_bytes)
963
964#define ut_malloc_nokey(n_bytes) ::malloc(n_bytes)
965
966static inline void *ut_malloc_dontdump(size_t n_bytes)
967{
968 void *ptr = os_mem_alloc_large(&n_bytes);
969
970 ut_allocate_trace_dontdump(ptr, n_bytes, true, NULL, NULL);
971 return ptr;
972}
973
974#define ut_zalloc_nokey(n_bytes) ::calloc(1, n_bytes)
975
976#define ut_zalloc_nokey_nofatal(n_bytes) ::calloc(1, n_bytes)
977
978#define ut_realloc(ptr, n_bytes) ::realloc(ptr, n_bytes)
979
980#define ut_free(ptr) ::free(ptr)
981
982static inline void ut_free_dodump(void *ptr, size_t size)
983{
984 ut_dodump(ptr, size);
985 os_mem_free_large(ptr, size);
986}
987
988#endif /* UNIV_PFS_MEMORY */
989
990#endif /* ut0new_h */
991