1 /**
2  * @file   heap_memory.cc
3  *
4  * @section LICENSE
5  *
6  * The MIT License
7  *
8  * @copyright Copyright (c) 2021 TileDB, Inc.
9  *
10  * Permission is hereby granted, free of charge, to any person obtaining a copy
11  * of this software and associated documentation files (the "Software"), to deal
12  * in the Software without restriction, including without limitation the rights
13  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14  * copies of the Software, and to permit persons to whom the Software is
15  * furnished to do so, subject to the following conditions:
16  *
17  * The above copyright notice and this permission notice shall be included in
18  * all copies or substantial portions of the Software.
19  *
20  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
26  * THE SOFTWARE.
27  *
28  * @section DESCRIPTION
29  *
30  * Implements TileDB-variants of dynamic (heap) memory allocation routines.
31  */
32 
33 #include <cstdlib>
34 
35 #include "tiledb/common/heap_memory.h"
36 #include "tiledb/common/heap_profiler.h"
37 
38 namespace tiledb {
39 namespace common {
40 
41 // Protects against races between memory management APIs
42 // and the HeapProfiler API.
43 std::recursive_mutex __tdb_heap_mem_lock;
44 
tiledb_malloc(const size_t size,const std::string & label)45 void* tiledb_malloc(const size_t size, const std::string& label) {
46   if (!heap_profiler.enabled()) {
47     return std::malloc(size);
48   }
49 
50   std::unique_lock<std::recursive_mutex> ul(__tdb_heap_mem_lock);
51 
52   void* const p = std::malloc(size);
53 
54   if (!p)
55     heap_profiler.dump_and_terminate();
56 
57   heap_profiler.record_alloc(p, size, label);
58 
59   return p;
60 }
61 
tiledb_calloc(const size_t num,const size_t size,const std::string & label)62 void* tiledb_calloc(
63     const size_t num, const size_t size, const std::string& label) {
64   if (!heap_profiler.enabled()) {
65     return std::calloc(num, size);
66   }
67 
68   std::unique_lock<std::recursive_mutex> ul(__tdb_heap_mem_lock);
69 
70   void* const p = std::calloc(num, size);
71 
72   if (!p)
73     heap_profiler.dump_and_terminate();
74 
75   heap_profiler.record_alloc(p, num * size, label);
76 
77   return p;
78 }
79 
tiledb_realloc(void * const p,const size_t size,const std::string & label)80 void* tiledb_realloc(
81     void* const p, const size_t size, const std::string& label) {
82   if (!heap_profiler.enabled()) {
83     return std::realloc(p, size);
84   }
85 
86   std::unique_lock<std::recursive_mutex> ul(__tdb_heap_mem_lock);
87 
88   void* const p_realloc = std::realloc(p, size);
89 
90   if (!p_realloc)
91     heap_profiler.dump_and_terminate();
92 
93   heap_profiler.record_dealloc(p);
94   heap_profiler.record_alloc(p_realloc, size, label);
95 
96   return p_realloc;
97 }
98 
tiledb_free(void * const p)99 void tiledb_free(void* const p) {
100   if (!heap_profiler.enabled()) {
101     free(p);
102     return;
103   }
104 
105   std::unique_lock<std::recursive_mutex> ul(__tdb_heap_mem_lock);
106 
107   free(p);
108   heap_profiler.record_dealloc(p);
109 }
110 
111 }  // namespace common
112 }  // namespace tiledb
113