Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Mark some internal symbols as hidden on ELF in xbt
[simgrid.git] / src / xbt / mmalloc / mm_legacy.c
1 /* Copyright (c) 2010-2015. The SimGrid Team.
2  * All rights reserved.                                                     */
3
4 /* This program is free software; you can redistribute it and/or modify it
5  * under the terms of the license (GNU LGPL) which comes with this package. */
6
7 /* Redefine the classical malloc/free/realloc functions so that they fit well in the mmalloc framework */
8 #define _GNU_SOURCE
9
10 #include <stdlib.h>
11
12 #include <dlfcn.h>
13
14 #include "../../mc/mc_base.h"
15 #include "mmprivate.h"
16 #include "xbt_modinter.h"
17 #include "internal_config.h"
18 #include <math.h>
19 #include "../mc/mc_protocol.h"
20
21 /* ***** Whether to use `mmalloc` of the undrlying malloc ***** */
22
23 static int __malloc_use_mmalloc;
24
25 int malloc_use_mmalloc(void)
26 {
27   return __malloc_use_mmalloc;
28 }
29
30 /* ***** Current heap ***** */
31
32 /* The mmalloc() package can use a single implicit malloc descriptor
33    for mmalloc/mrealloc/mfree operations which do not supply an explicit
34    descriptor.  This allows mmalloc() to provide
35    backwards compatibility with the non-mmap'd version. */
36 xbt_mheap_t __mmalloc_default_mdp = NULL;
37
38 /* The heap we are currently using. */
39 static xbt_mheap_t __mmalloc_current_heap = NULL;
40
41 xbt_mheap_t mmalloc_get_current_heap(void)
42 {
43   return __mmalloc_current_heap;
44 }
45
46 xbt_mheap_t mmalloc_set_current_heap(xbt_mheap_t new_heap)
47 {
48   xbt_mheap_t heap = __mmalloc_current_heap;
49   __mmalloc_current_heap = new_heap;
50   return heap;
51 }
52
53 #ifdef MMALLOC_WANT_OVERRIDE_LEGACY
54
55 /* ***** Temporary allocator
56  *
57  * This is used before we have found the real malloc implementation with dlsym.
58  */
59
60 #define BUFFER_SIZE 32
61 static size_t fake_alloc_index;
62 static uint64_t buffer[BUFFER_SIZE];
63
64 /* Fake implementations, they are used to fool dlsym:
65  * dlsym used calloc and falls back to some other mechanism
66  * if this fails.
67  */
68 static void* mm_fake_malloc(size_t n)
69 {
70   // How many uint64_t do w need?
71   size_t count = n / sizeof(uint64_t);
72   if (n % sizeof(uint64_t))
73     count++;
74   // Check that we have enough availabel memory:
75   if (fake_alloc_index + count >= BUFFER_SIZE)
76     exit(127);
77   // Allocate it:
78   uint64_t* res = buffer + fake_alloc_index;
79   fake_alloc_index += count;
80   return res;
81 }
82
83 static void* mm_fake_calloc(size_t nmemb, size_t size)
84 {
85   // This is fresh .bss data, we don't need to clear it:
86   size_t n = nmemb * size;
87   return mm_fake_malloc(n);
88 }
89
90 static void* mm_fake_realloc(void *p, size_t s)
91 {
92   return mm_fake_malloc(s);
93 }
94
95 static void mm_fake_free(void *p)
96 {
97 }
98
99 /* Function signatures for the main malloc functions: */
100 typedef void* (*mm_malloc_t)(size_t size);
101 typedef void  (*mm_free_t)(void*);
102 typedef void* (*mm_calloc_t)(size_t nmemb, size_t size);
103 typedef void* (*mm_realloc_t)(void *ptr, size_t size);
104
105 /* Function pointers to the real/next implementations: */
106 static mm_malloc_t mm_real_malloc;
107 static mm_free_t mm_real_free;
108 static mm_calloc_t mm_real_calloc;
109 static mm_realloc_t mm_real_realloc;
110
111 static int mm_initializing;
112 static int mm_initialized;
113
114 /** Constructor functions used to initialize the malloc implementation
115  */
116 static void __attribute__((constructor(101))) mm_legacy_constructor()
117 {
118   if (mm_initialized)
119     return;
120   mm_initializing = 1;
121   __malloc_use_mmalloc = getenv(MC_ENV_VARIABLE) ? 1 : 0;
122   if (__malloc_use_mmalloc) {
123     __mmalloc_current_heap = mmalloc_preinit();
124   } else {
125     mm_real_realloc  = dlsym(RTLD_NEXT, "realloc");
126     mm_real_malloc   = dlsym(RTLD_NEXT, "malloc");
127     mm_real_free     = dlsym(RTLD_NEXT, "free");
128     mm_real_calloc   = dlsym(RTLD_NEXT, "calloc");
129   }
130   mm_initializing = 0;
131   mm_initialized = 1;
132 }
133
134 /* ***** malloc/free implementation
135  *
136  * They call either the underlying/native/RTLD_NEXT implementation (non MC mode)
137  * or the mm implementation (MC mode).
138  *
139  * If we are initializing the malloc subsystem, we call the fake/dummy `malloc`
140  * implementation. This is necessary because `dlsym` calls `malloc` and friends.
141  */
142
143 #define GET_HEAP() __mmalloc_current_heap
144
145 void* malloc_no_memset(size_t n)
146 {
147   if (!mm_initialized) {
148     if (mm_initializing)
149       return mm_fake_malloc(n);
150     mm_legacy_constructor();
151   }
152
153   if (!__malloc_use_mmalloc) {
154     return mm_real_malloc(n);
155   }
156
157   xbt_mheap_t mdp = GET_HEAP();
158   if (!mdp)
159     return NULL;
160
161   LOCK(mdp);
162   void *ret = mmalloc_no_memset(mdp, n);
163   UNLOCK(mdp);
164   return ret;
165 }
166
167 void *malloc(size_t n)
168 {
169   if (!mm_initialized) {
170     if (mm_initializing)
171       return mm_fake_malloc(n);
172     mm_legacy_constructor();
173   }
174
175   if (!__malloc_use_mmalloc) {
176     return mm_real_malloc(n);
177   }
178
179   xbt_mheap_t mdp = GET_HEAP();
180   if (!mdp)
181     return NULL;
182
183   LOCK(mdp);
184   void *ret = mmalloc(mdp, n);
185   UNLOCK(mdp);
186   return ret;
187 }
188
189 void *calloc(size_t nmemb, size_t size)
190 {
191   if (!mm_initialized) {
192     if (mm_initializing)
193       return mm_fake_calloc(nmemb, size);
194     mm_legacy_constructor();
195   }
196
197   if (!__malloc_use_mmalloc) {
198     return mm_real_calloc(nmemb, size);
199   }
200
201   xbt_mheap_t mdp = GET_HEAP();
202   if (!mdp)
203     return NULL;
204
205   LOCK(mdp);
206   void *ret = mmalloc(mdp, nmemb*size);
207   UNLOCK(mdp);
208   // This was already done in the callee:
209   if(!(mdp->options & XBT_MHEAP_OPTION_MEMSET)) {
210     memset(ret, 0, nmemb * size);
211   }
212   return ret;
213 }
214
215 void *realloc(void *p, size_t s)
216 {
217   if (!mm_initialized) {
218     if (mm_initializing)
219       return mm_fake_realloc(p, s);
220     mm_legacy_constructor();
221   }
222
223   if (!__malloc_use_mmalloc) {
224     return mm_real_realloc(p, s);
225   }
226
227   xbt_mheap_t mdp = GET_HEAP();
228   if (!mdp)
229     return NULL;
230
231   LOCK(mdp);
232   void* ret = mrealloc(mdp, p, s);
233   UNLOCK(mdp);
234   return ret;
235 }
236
237 void free(void *p)
238 {
239   if (!mm_initialized) {
240     if (mm_initializing)
241       return mm_fake_free(p);
242     mm_legacy_constructor();
243   }
244
245   if (!__malloc_use_mmalloc) {
246     mm_real_free(p);
247     return;
248   }
249
250   if (!p)
251     return;
252
253   xbt_mheap_t mdp = GET_HEAP();
254   LOCK(mdp);
255   mfree(mdp, p);
256   UNLOCK(mdp);
257 }
258 #endif /* WANT_MALLOC_OVERRIDE */