Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Remove unused bits from mmalloc.
[simgrid.git] / src / xbt / mmalloc / mm_legacy.c
1 /* Copyright (c) 2010-2019. 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 "mmprivate.h"
15 #include "src/internal_config.h"
16 #include "src/mc/mc_base.h"
17 #include "src/mc/remote/mc_protocol.h"
18 #include "src/xbt_modinter.h"
19 #include <math.h>
20
21 /* ***** Whether to use `mmalloc` of the underlying 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 /* Override the malloc-like functions if MC is activated at compile time */
47 #if SIMGRID_HAVE_MC
48
49 /* ***** Temporary allocator
50  *
51  * This is used before we have found the real malloc implementation with dlsym.
52  */
53
54 #ifdef __FreeBSD__ /* FreeBSD require more memory, other might */
55 # define BUFFER_SIZE 256
56 #else /* Valid on: Linux */
57 # define BUFFER_SIZE 32
58 #endif
59 static size_t fake_alloc_index;
60 static uint64_t buffer[BUFFER_SIZE];
61
62 /* Fake implementations, they are used to fool dlsym:
63  * dlsym used calloc and falls back to some other mechanism
64  * if this fails.
65  */
66 static void* mm_fake_malloc(size_t n)
67 {
68   // How many uint64_t do w need?
69   size_t count = n / sizeof(uint64_t);
70   if (n % sizeof(uint64_t))
71     count++;
72   // Check that we have enough available memory:
73   if (fake_alloc_index + count >= BUFFER_SIZE)
74     exit(127);
75   // Allocate it:
76   uint64_t* res = buffer + fake_alloc_index;
77   fake_alloc_index += count;
78   return res;
79 }
80
81 static void* mm_fake_calloc(size_t nmemb, size_t size)
82 {
83   // This is fresh .bss data, we don't need to clear it:
84   size_t n = nmemb * size;
85   return mm_fake_malloc(n);
86 }
87
88 static void* mm_fake_realloc(XBT_ATTRIB_UNUSED void* p, size_t s)
89 {
90   return mm_fake_malloc(s);
91 }
92
93 static void mm_fake_free(XBT_ATTRIB_UNUSED void* p)
94 {
95   // Nothing to do
96 }
97
98 /* Function signatures for the main malloc functions: */
99 typedef void* (*mm_malloc_t)(size_t size);
100 typedef void  (*mm_free_t)(void*);
101 typedef void* (*mm_calloc_t)(size_t nmemb, size_t size);
102 typedef void* (*mm_realloc_t)(void *ptr, size_t size);
103
104 /* Function pointers to the real/next implementations: */
105 static mm_malloc_t mm_real_malloc;
106 static mm_free_t mm_real_free;
107 static mm_calloc_t mm_real_calloc;
108 static mm_realloc_t mm_real_realloc;
109
110 static int mm_initializing;
111 static int mm_initialized;
112
113 /** Constructor functions used to initialize the malloc implementation
114  */
115 XBT_ATTRIB_CONSTRUCTOR(101) static void mm_legacy_constructor()
116 {
117   if (mm_initialized)
118     return;
119   mm_initializing = 1;
120   __malloc_use_mmalloc = getenv(MC_ENV_VARIABLE) ? 1 : 0;
121   if (__malloc_use_mmalloc) {
122     __mmalloc_current_heap = mmalloc_preinit();
123   } else {
124 #if HAVE_DLFUNC
125     mm_real_realloc  = (void *(*)(void *, size_t))dlfunc(RTLD_NEXT, "realloc");
126     mm_real_malloc   = (void *(*)(size_t))dlfunc(RTLD_NEXT, "malloc");
127     mm_real_free     = (void (*)(void *))dlfunc(RTLD_NEXT, "free");
128     mm_real_calloc   = (void *(*)(size_t, size_t))dlfunc(RTLD_NEXT, "calloc");
129 #else
130     mm_real_realloc  = dlsym(RTLD_NEXT, "realloc");
131     mm_real_malloc   = dlsym(RTLD_NEXT, "malloc");
132     mm_real_free     = dlsym(RTLD_NEXT, "free");
133     mm_real_calloc   = dlsym(RTLD_NEXT, "calloc");
134 #endif
135   }
136   mm_initializing = 0;
137   mm_initialized = 1;
138 }
139
140 /* ***** malloc/free implementation
141  *
142  * They call either the underlying/native/RTLD_NEXT implementation (non MC mode)
143  * or the mm implementation (MC mode).
144  *
145  * If we are initializing the malloc subsystem, we call the fake/dummy `malloc`
146  * implementation. This is necessary because `dlsym` calls `malloc` and friends.
147  */
148
149 #define GET_HEAP() __mmalloc_current_heap
150
151 void *malloc(size_t n)
152 {
153   if (!mm_initialized) {
154     if (mm_initializing)
155       return mm_fake_malloc(n);
156     mm_legacy_constructor();
157   }
158
159   if (!__malloc_use_mmalloc) {
160     return mm_real_malloc(n);
161   }
162
163   xbt_mheap_t mdp = GET_HEAP();
164   if (!mdp)
165     return NULL;
166
167   LOCK(mdp);
168   void *ret = mmalloc(mdp, n);
169   UNLOCK(mdp);
170   return ret;
171 }
172
173 void *calloc(size_t nmemb, size_t size)
174 {
175   if (!mm_initialized) {
176     if (mm_initializing)
177       return mm_fake_calloc(nmemb, size);
178     mm_legacy_constructor();
179   }
180
181   if (!__malloc_use_mmalloc) {
182     return mm_real_calloc(nmemb, size);
183   }
184
185   xbt_mheap_t mdp = GET_HEAP();
186   if (!mdp)
187     return NULL;
188
189   LOCK(mdp);
190   void *ret = mmalloc(mdp, nmemb*size);
191   UNLOCK(mdp);
192   // This was already done in the callee:
193   if(!(mdp->options & XBT_MHEAP_OPTION_MEMSET)) {
194     memset(ret, 0, nmemb * size);
195   }
196   return ret;
197 }
198
199 void *realloc(void *p, size_t s)
200 {
201   if (!mm_initialized) {
202     if (mm_initializing)
203       return mm_fake_realloc(p, s);
204     mm_legacy_constructor();
205   }
206
207   if (!__malloc_use_mmalloc) {
208     return mm_real_realloc(p, s);
209   }
210
211   xbt_mheap_t mdp = GET_HEAP();
212   if (!mdp)
213     return NULL;
214
215   LOCK(mdp);
216   void* ret = mrealloc(mdp, p, s);
217   UNLOCK(mdp);
218   return ret;
219 }
220
221 void free(void *p)
222 {
223   if (!mm_initialized) {
224     if (mm_initializing)
225       return mm_fake_free(p);
226     mm_legacy_constructor();
227   }
228
229   if (!__malloc_use_mmalloc) {
230     mm_real_free(p);
231     return;
232   }
233
234   if (!p)
235     return;
236
237   xbt_mheap_t mdp = GET_HEAP();
238   LOCK(mdp);
239   mfree(mdp, p);
240   UNLOCK(mdp);
241 }
242 #endif /* SIMGRID_HAVE_MC */