Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
20a609a3e041f7c5efb6dfa3c74d9d0c1048a8ab
[simgrid.git] / src / xbt / mmalloc / mm_legacy.c
1 /* Copyright (c) 2010-2014. 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
9 #include "mmprivate.h"
10 #include "xbt_modinter.h"
11 #include "internal_config.h"
12 #include <math.h>
13
14 //#define MM_LEGACY_VERBOSE 1 /* define this to see which version of malloc gets used */
15
16 /* The mmalloc() package can use a single implicit malloc descriptor
17    for mmalloc/mrealloc/mfree operations which do not supply an explicit
18    descriptor.  This allows mmalloc() to provide
19    backwards compatibility with the non-mmap'd version. */
20 xbt_mheap_t __mmalloc_default_mdp = NULL;
21
22
23 static xbt_mheap_t __mmalloc_current_heap = NULL;     /* The heap we are currently using. */
24
25 xbt_mheap_t mmalloc_get_current_heap(void)
26 {
27   return __mmalloc_current_heap;
28 }
29
30 void mmalloc_set_current_heap(xbt_mheap_t new_heap)
31 {
32   __mmalloc_current_heap = new_heap;
33 }
34
35
36 #ifdef MMALLOC_WANT_OVERRIDE_LEGACY
37 #ifdef HAVE_GNU_LD
38
39 #undef _GNU_SOURCE
40 #define _GNU_SOURCE 1
41 #include <dlfcn.h>
42
43 static void * (*real_malloc) (size_t) = NULL;
44 static void * (*real_realloc) (void*,size_t) = NULL;
45 static void * (*real_free) (void*) = NULL;
46
47 static void mm_gnuld_legacy_init(void) { /* This function is called from mmalloc_preinit(); it works even if it's static because all mm is in mm.c */
48   real_malloc = (void * (*) (size_t)) dlsym(RTLD_NEXT, "malloc");
49   real_realloc = (void * (*) (void*,size_t)) dlsym(RTLD_NEXT, "realloc");
50   real_free = (void * (*) (void*)) dlsym(RTLD_NEXT, "free");
51   __mmalloc_current_heap = __mmalloc_default_mdp;
52 }
53
54 /* Hello pimple!
55  * DL needs some memory while resolving the malloc symbol, that is somehow problematic
56  * To that extend, we have a little area here living in .BSS that we return if asked for memory before the malloc is resolved.
57  */
58 static int allocated_junk = 0; /* keep track of many blocks of our little area was already given to someone */
59 #define JUNK_SIZE 8
60 #define MAX_JUNK_AREAS (64 * 1024 / JUNK_SIZE)
61 static char junkareas[MAX_JUNK_AREAS][JUNK_SIZE];
62
63 /* This version use mmalloc if there is a current heap, or the legacy implem if not */
64 static void *malloc_or_calloc(size_t n, int setzero) {
65   xbt_mheap_t mdp = __mmalloc_current_heap;
66   void *ret;
67 #ifdef MM_LEGACY_VERBOSE
68   static int warned_raw = 0;
69   static int warned_mmalloc = 0;
70 #endif
71
72   if (mdp) {
73     LOCK(mdp);
74     ret = mmalloc(mdp, n);
75     UNLOCK(mdp);
76     // This was already done by mmalloc:
77     if (mdp->options & XBT_MHEAP_OPTION_MEMSET) {
78       setzero = 0;
79     }
80 #ifdef MM_LEGACY_VERBOSE
81     if (!warned_mmalloc) {
82       fprintf(stderr,"Using mmalloc; enabling the model-checker in cmake may have a bad impact on your simulation performance\n");
83       warned_mmalloc = 1;
84     }
85 #endif
86   } else if (!real_malloc) {
87       size_t needed_areas = n / JUNK_SIZE;
88       if(needed_areas * JUNK_SIZE != n) needed_areas++;
89       if (allocated_junk+needed_areas>=MAX_JUNK_AREAS) {
90         fprintf(stderr,
91           "Panic: real malloc symbol not resolved yet, and I already gave my little private memory chunk away.\n");
92         exit(1);
93       } else {
94         size_t i = allocated_junk;
95         allocated_junk += needed_areas;
96         ret = junkareas[i];
97       }
98     }
99   else {
100 #ifdef MM_LEGACY_VERBOSE
101     if (!warned_raw) {
102       fprintf(stderr,"Using system malloc after interception; you seem to be currently model-checking\n");
103       warned_raw = 1;
104     }
105 #endif
106     ret = real_malloc(n);
107   }
108   if (ret && setzero) {
109     memset(ret, 0, n);
110   }
111   return ret;
112 }
113
114 void *malloc(size_t n)
115 {
116   return malloc_or_calloc(n, 0);
117 }
118
119 void *calloc(size_t nmemb, size_t size)
120 {
121   return malloc_or_calloc(nmemb*size, 1);
122 }
123
124 void *realloc(void *p, size_t s)
125 {
126   xbt_mheap_t mdp = __mmalloc_current_heap;
127   void *ret;
128
129   if (mdp) {
130     LOCK(mdp);
131     ret = mrealloc(mdp, p, s);
132     UNLOCK(mdp);
133   } else {
134     ret = real_realloc(p,s);
135   }
136
137   return ret;
138 }
139
140 void free(void *p)
141 {
142   if (p==NULL)
143     return;
144   if (p<(void*)junkareas || p>=(void*)(junkareas[MAX_JUNK_AREAS]) ) {
145     // main use case
146
147     xbt_mheap_t mdp = __mmalloc_current_heap;
148
149     if (mdp) {
150       LOCK(mdp);
151       mfree(mdp, p);
152       UNLOCK(mdp);
153     } else {
154       real_free(p);
155     }
156   } else {
157     // We are in the junkarea.
158     // This area is used to allocate memory at initilization time.
159
160     if(allocated_junk && p==junkareas[allocated_junk-1]) {
161       // Last junkarea. We can reuse it.
162       allocated_junk--;
163     } else {
164       // We currently cannot reuse freed junkareas in the general case.
165     }
166   }
167 }
168
169
170 #else /* NO GNU_LD */
171 void *malloc(size_t n)
172 {
173   xbt_mheap_t mdp = __mmalloc_current_heap ?: (xbt_mheap_t) mmalloc_preinit();
174
175   LOCK(mdp);
176   void *ret = mmalloc(mdp, n);
177   UNLOCK(mdp);
178
179   return ret;
180 }
181
182 void *calloc(size_t nmemb, size_t size)
183 {
184   xbt_mheap_t mdp = __mmalloc_current_heap ?: (xbt_mheap_t) mmalloc_preinit();
185
186   LOCK(mdp);
187   void *ret = mmalloc(mdp, nmemb*size);
188   UNLOCK(mdp);
189   memset(ret, 0, nmemb * size);
190
191
192   return ret;
193 }
194
195 void *realloc(void *p, size_t s)
196 {
197   void *ret = NULL;
198   xbt_mheap_t mdp = __mmalloc_current_heap ?: (xbt_mheap_t) mmalloc_preinit();
199
200   LOCK(mdp);
201   ret = mrealloc(mdp, p, s);
202   UNLOCK(mdp);
203
204   return ret;
205 }
206
207 void free(void *p)
208 {
209   if (p != NULL) {
210     xbt_mheap_t mdp = __mmalloc_current_heap ?: (xbt_mheap_t) mmalloc_preinit();
211
212     LOCK(mdp);
213     mfree(mdp, p);
214     UNLOCK(mdp);
215   }
216 }
217 #endif /* NO GNU_LD */
218 #endif /* WANT_MALLOC_OVERRIDE */
219
220