malloc.cpp
Go to the documentation of this file.
1 /*********************************************************************
2 * Software License Agreement (BSD License)
3 *
4 * Copyright (c) 2010, Willow Garage, Inc.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 *
11 * * Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * * Redistributions in binary form must reproduce the above
14 * copyright notice, this list of conditions and the following
15 * disclaimer in the documentation and/or other materials provided
16 * with the distribution.
17 * * Neither the name of the Willow Garage nor the names of its
18 * contributors may be used to endorse or promote products derived
19 * from this software without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
31 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32 * POSSIBILITY OF SUCH DAMAGE.
33 *********************************************************************/
34 
35 #include <rosrt/malloc_wrappers.h>
36 
37 #include <ros/assert.h>
38 #include <ros/atomic.h>
39 
40 #include "boost/thread.hpp"
41 
42 #include <iostream>
43 #include <dlfcn.h>
44 
45 #if defined(WIN32)
46 #define STATIC_TLS_KW __declspec(thread)
47 #define HAS_TLS_KW 1
48 #elif defined(__APPLE__)
49 #define HAS_TLS_KW 0
50 #else
51 #define STATIC_TLS_KW __thread
52 #define HAS_TLS_KW 1
53 #endif
54 
55 #if !HAS_TLS_KW
56 #include <pthread.h>
57 #define MAX_ALLOC_INFO 1000
58 #endif
59 
60 namespace rosrt
61 {
62 namespace detail
63 {
64 
65 #if HAS_TLS_KW
66 STATIC_TLS_KW uint64_t g_mallocs = 0;
68 STATIC_TLS_KW uint64_t g_callocs = 0;
70 STATIC_TLS_KW uint64_t g_frees = 0;
74 #else // HAS_TLS_KW
75 
76 pthread_key_t g_tls_key;
77 bool g_tls_key_initialized = false;
78 
79 AllocInfo g_thread_alloc_info[MAX_ALLOC_INFO];
80 ros::atomic_bool g_alloc_info_used[MAX_ALLOC_INFO];
81 
82 void tlsDestructor(void* mem)
83 {
84  AllocInfo* info = reinterpret_cast<AllocInfo*>(mem);
85  uint32_t index = info - g_thread_alloc_info;
86  ROS_ASSERT(index < MAX_ALLOC_INFO);
87  g_alloc_info_used[index].store(false);
88 }
89 
90 struct MallocTLSInit
91 {
92  MallocTLSInit()
93  {
94  int ret = pthread_key_create(&g_tls_key, tlsDestructor);
95  ROS_ASSERT_MSG(!ret, "Failed to create TLS");
96 
97  for (size_t i = 0; i < MAX_ALLOC_INFO; ++i)
98  {
99  g_alloc_info_used[i].store(false);
100  }
101 
102  g_tls_key_initialized = true;
103  }
104 
105  ~MallocTLSInit()
106  {
107  g_tls_key_initialized = false;
108 
109  pthread_key_delete(g_tls_key);
110  }
111 };
112 MallocTLSInit g_malloc_tls_init;
113 
114 AllocInfo* allocateAllocInfo()
115 {
116  if (!g_tls_key_initialized)
117  {
118  return 0;
119  }
120 
121  void* info = pthread_getspecific(g_tls_key);
122  if (!info)
123  {
124  for (size_t i = 0; i < MAX_ALLOC_INFO; ++i)
125  {
126  if (g_alloc_info_used[i].exchange(true) == false)
127  {
128  info = g_thread_alloc_info + i;
129  pthread_setspecific(g_tls_key, info);
130  break;
131  }
132  }
133  }
134 
135  return reinterpret_cast<AllocInfo*>(info);
136 }
137 
138 #endif // !HAS_TLS_KW
139 
140 } // namespace malloc_tls
141 
143 {
144  AllocInfo info;
145 
146 #if HAS_TLS_KW
147  info.mallocs = detail::g_mallocs;
148  info.callocs = detail::g_callocs;
151  info.frees = detail::g_frees;
155 #else
156  AllocInfo* tls = detail::allocateAllocInfo();
157  if (tls)
158  {
159  info = *tls;
160  }
161 #endif
162  return info;
163 }
164 
166 {
167 #if HAS_TLS_KW
168  detail::g_mallocs = 0;
169  detail::g_reallocs = 0;
170  detail::g_callocs = 0;
172  detail::g_frees = 0;
175 #else
176  AllocInfo* info = detail::allocateAllocInfo();
177  if (info)
178  {
179  *info = AllocInfo();
180  }
181 #endif
182 }
183 
185 {
186 #if HAS_TLS_KW
188 #else
189  AllocInfo* info = detail::allocateAllocInfo();
190  if (info)
191  {
192  info->break_on_alloc_or_free = b;
193  }
194 #endif
195 }
196 
197 } // namespace rosrt
198 
199 extern "C"
200 {
201 
202 typedef void* (*MallocType)(size_t size);
203 typedef void* (*CallocType)(size_t nmemb, size_t size);
204 typedef void* (*ReallocType)(void *ptr, size_t size);
205 typedef void* (*MemalignType)(size_t boundary, size_t size);
206 typedef int (*PosixMemalignType)(void **memptr, size_t alignment, size_t size);
207 typedef void (*FreeType)(void* ptr);
208 
209 #if HAS_TLS_KW
210 #define UPDATE_ALLOC_INFO(result, size, type) \
211  if (result) \
212  { \
213  rosrt::detail::g_total_memory_allocated += size; \
214  } \
215 \
216  ++rosrt::detail::g_##type; \
217  ++rosrt::detail::g_total_ops; \
218 \
219  if (rosrt::detail::g_break_on_alloc_or_free) \
220  { \
221  std::cerr << "Issuing break due to break_on_alloc_or_free being set" << std::endl; \
222  ROS_ISSUE_BREAK(); \
223  }
224 #else
225 #define UPDATE_ALLOC_INFO(result, size, type) \
226  rosrt::AllocInfo* tls = rosrt::detail::allocateAllocInfo(); \
227  if (tls) \
228  { \
229  if (result) \
230  { \
231  tls->total_memory_allocated += size; \
232  } \
233  \
234  ++tls->type; \
235  ++tls->total_ops; \
236  \
237  if (tls->break_on_alloc_or_free) \
238  { \
239  std::cerr << "Issuing break due to break_on_alloc_or_free being set" << std::endl; \
240  ROS_ISSUE_BREAK(); \
241  } \
242  }
243 #endif
244 
245 void* malloc(size_t size)
246 {
247  static MallocType original_function = reinterpret_cast<MallocType>(dlsym(RTLD_NEXT, "malloc"));
248 
249  void* result = original_function(size);
250 
251  UPDATE_ALLOC_INFO(result, size, mallocs);
252 
253  return result;
254 }
255 
256 void* __libc_malloc(size_t size)
257 {
258  return malloc(size);
259 }
260 
261 void* realloc(void* ptr, size_t size)
262 {
263  static ReallocType original_function = reinterpret_cast<ReallocType>(dlsym(RTLD_NEXT, "realloc"));
264 
265  void* result = original_function(ptr, size);
266 
267  UPDATE_ALLOC_INFO(result, size, reallocs);
268 
269  return result;
270 }
271 
272 void* __libc_realloc(void* ptr, size_t size)
273 {
274  return realloc(ptr, size);
275 }
276 
277 void* memalign(size_t boundary, size_t size)
278 {
279  static MemalignType original_function = reinterpret_cast<MemalignType>(dlsym(RTLD_NEXT, "memalign"));
280 
281  void* result = original_function(boundary, size);
282 
283  UPDATE_ALLOC_INFO(result, size, memaligns);
284 
285  return result;
286 }
287 
288 void* __libc_memalign(size_t boundary, size_t size)
289 {
290  return memalign(boundary, size);
291 }
292 
293 void free(void *ptr)
294 {
295  static FreeType original_function = reinterpret_cast<FreeType>(dlsym(RTLD_NEXT, "free"));
296 
297  original_function(ptr);
298 
299  uint32_t size = 0;
300  void* result = 0;
301  UPDATE_ALLOC_INFO(result, size, frees);
302 }
303 
304 void __libc_free(void* ptr)
305 {
306  return free(ptr);
307 }
308 
309 // dlsym uses calloc so it has to be treated specially. Solution found at http://crbug.com/28244
310 static void* nullCalloc(size_t nmemb, size_t size)
311 {
312  return 0;
313 }
314 
315 void* calloc(size_t nmemb, size_t size)
316 {
317  static CallocType original_function = 0;
318  if (original_function == 0)
319  {
320  original_function = nullCalloc;
321  original_function = reinterpret_cast<CallocType>(dlsym(RTLD_NEXT, "calloc"));
322  }
323 
324  void* result = original_function(nmemb, size);
325 
326  UPDATE_ALLOC_INFO(result, size * nmemb, callocs);
327 
328  return result;
329 }
330 
331 void* __libc_calloc(size_t nmemb, size_t size)
332 {
333  return calloc(nmemb, size);
334 }
335 
336 int posix_memalign(void** ptr, size_t alignment, size_t size) {
337  static PosixMemalignType original_function = reinterpret_cast<PosixMemalignType>(dlsym(RTLD_NEXT, "posix_memalign"));
338 
339  int result = original_function(ptr, alignment, size);
340 
341  UPDATE_ALLOC_INFO(!result, size, memaligns);
342 
343  return result;
344 }
345 
346 
347 } // extern "C"
348 
349 
void setThreadBreakOnAllocOrFree(bool b)
Definition: malloc.cpp:184
#define STATIC_TLS_KW
Definition: malloc.cpp:51
void(* FreeType)(void *ptr)
Definition: malloc.cpp:207
AllocInfo getThreadAllocInfo()
Definition: malloc.cpp:142
void __libc_free(void *ptr)
Definition: malloc.cpp:304
void * malloc(size_t size)
Definition: malloc.cpp:245
STATIC_TLS_KW bool g_break_on_alloc_or_free
Definition: malloc.cpp:73
STATIC_TLS_KW uint64_t g_total_memory_allocated
Definition: malloc.cpp:72
int posix_memalign(void **ptr, size_t alignment, size_t size)
Definition: malloc.cpp:336
STATIC_TLS_KW uint64_t g_mallocs
Definition: malloc.cpp:66
STATIC_TLS_KW uint64_t g_memaligns
Definition: malloc.cpp:69
STATIC_TLS_KW uint64_t g_reallocs
Definition: malloc.cpp:67
Definition: managers.h:38
void * __libc_realloc(void *ptr, size_t size)
Definition: malloc.cpp:272
void *(* MemalignType)(size_t boundary, size_t size)
Definition: malloc.cpp:205
void * __libc_malloc(size_t size)
Definition: malloc.cpp:256
static void * nullCalloc(size_t nmemb, size_t size)
Definition: malloc.cpp:310
#define ROS_ASSERT_MSG(cond,...)
STATIC_TLS_KW uint64_t g_total_ops
Definition: malloc.cpp:71
void free(void *ptr)
Definition: malloc.cpp:293
void * realloc(void *ptr, size_t size)
Definition: malloc.cpp:261
void * calloc(size_t nmemb, size_t size)
Definition: malloc.cpp:315
STATIC_TLS_KW uint64_t g_callocs
Definition: malloc.cpp:68
void resetThreadAllocInfo()
Definition: malloc.cpp:165
void *(* ReallocType)(void *ptr, size_t size)
Definition: malloc.cpp:204
void *(* MallocType)(size_t size)
Definition: malloc.cpp:202
uint64_t total_memory_allocated
void * __libc_memalign(size_t boundary, size_t size)
Definition: malloc.cpp:288
void *(* CallocType)(size_t nmemb, size_t size)
Definition: malloc.cpp:203
#define ROS_ASSERT(cond)
#define UPDATE_ALLOC_INFO(result, size, type)
Definition: malloc.cpp:210
int(* PosixMemalignType)(void **memptr, size_t alignment, size_t size)
Definition: malloc.cpp:206
STATIC_TLS_KW uint64_t g_frees
Definition: malloc.cpp:70
void * memalign(size_t boundary, size_t size)
Definition: malloc.cpp:277
void * __libc_calloc(size_t nmemb, size_t size)
Definition: malloc.cpp:331


rosrt
Author(s): Josh Faust
autogenerated on Mon Jun 10 2019 14:44:46