Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
[mc] Support for reading heap state from another process
[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 #define _GNU_SOURCE
9
10 #include <stdlib.h>
11
12 #include <dlfcn.h>
13
14 #include "mmprivate.h"
15 #include "xbt_modinter.h"
16 #include "internal_config.h"
17 #include <math.h>
18
19 //#define MM_LEGACY_VERBOSE 1 /* define this to see which version of malloc gets used */
20
21 /* The mmalloc() package can use a single implicit malloc descriptor
22    for mmalloc/mrealloc/mfree operations which do not supply an explicit
23    descriptor.  This allows mmalloc() to provide
24    backwards compatibility with the non-mmap'd version. */
25 xbt_mheap_t __mmalloc_default_mdp = NULL;
26
27
28 static xbt_mheap_t __mmalloc_current_heap = NULL;     /* The heap we are currently using. */
29
30 xbt_mheap_t mmalloc_get_current_heap(void)
31 {
32   return __mmalloc_current_heap;
33 }
34
35 void mmalloc_set_current_heap(xbt_mheap_t new_heap)
36 {
37   __mmalloc_current_heap = new_heap;
38 }
39
40 #ifdef MMALLOC_WANT_OVERRIDE_LEGACY
41
42 /* Fake implementations, they are used to fool dlsym:
43  * dlsym used calloc and falls back to some other mechanism
44  * if this fails.
45  */
46 static void* mm_fake_calloc(size_t nmemb, size_t size) { return NULL; }
47 static void* mm_fake_malloc(size_t n)                  { return NULL; }
48 static void* mm_fake_realloc(void *p, size_t s)        { return NULL; }
49
50 /* Function signatures for the main malloc functions: */
51 typedef void* (*mm_malloc_t)(size_t size);
52 typedef void  (*mm_free_t)(void*);
53 typedef void* (*mm_calloc_t)(size_t nmemb, size_t size);
54 typedef void* (*mm_realloc_t)(void *ptr, size_t size);
55
56 /* Function pointers to the real/next implementations: */
57 static mm_malloc_t mm_real_malloc   = mm_fake_malloc;
58 static mm_free_t mm_real_free;
59 static mm_calloc_t mm_real_calloc   = mm_fake_calloc;
60 static mm_realloc_t mm_real_realloc = mm_fake_realloc;
61
62 #define GET_HEAP() __mmalloc_current_heap
63
64 static const char* env_name = "SIMGRID_MALLOC_USE_MM";
65
66 int mmalloc_exec_using_mm(int argc, const char** argv)
67 {
68   char** argv2 = (char**) malloc(sizeof(char*) * (argc+1));
69   memcpy(argv2, argv, sizeof(char*) * argc);
70   argv2[argc] = NULL;
71   if (setenv(env_name, "1", 1) >= 0) {
72     execv(argv[0], argv2);
73   }
74   unsetenv(env_name);
75   fprintf(stderr, "Could not restart with mm malloc\n");
76   free(argv2);
77   return -1;
78 }
79
80 void mmalloc_ensure_using_mm(int argc, const char** argv)
81 {
82   if (!__mmalloc_default_mdp) {
83     mmalloc_exec_using_mm(argc, argv);
84   }
85 }
86
87 /** Constructor functions used to initialize the malloc implementation
88  */
89 static void __attribute__((constructor(101))) mm_legacy_constructor()
90 {
91   bool use_mm = getenv(env_name);
92   if (use_mm) {
93     __mmalloc_current_heap = mmalloc_preinit();
94   } else {
95     mm_real_realloc  = (mm_realloc_t) dlsym(RTLD_NEXT, "realloc");
96     mm_real_malloc   = (mm_malloc_t)  dlsym(RTLD_NEXT, "malloc");
97     mm_real_free     = (mm_free_t)    dlsym(RTLD_NEXT, "free");
98     mm_real_calloc   = (mm_calloc_t)  dlsym(RTLD_NEXT, "calloc");
99   }
100 }
101
102 void *malloc(size_t n)
103 {
104   if (!__mmalloc_current_heap) {
105     return mm_real_malloc(n);
106   }
107
108   xbt_mheap_t mdp = GET_HEAP();
109   if (!mdp)
110     return NULL;
111
112   LOCK(mdp);
113   void *ret = mmalloc(mdp, n);
114   UNLOCK(mdp);
115   return ret;
116 }
117
118 void *calloc(size_t nmemb, size_t size)
119 {
120   if (!__mmalloc_current_heap) {
121     return mm_real_calloc(nmemb, size);
122   }
123
124   xbt_mheap_t mdp = GET_HEAP();
125   if (!mdp)
126     return NULL;
127
128   LOCK(mdp);
129   void *ret = mmalloc(mdp, nmemb*size);
130   UNLOCK(mdp);
131   // This was already done in the callee:
132   if(!(mdp->options & XBT_MHEAP_OPTION_MEMSET)) {
133     memset(ret, 0, nmemb * size);
134   }
135   return ret;
136 }
137
138 void *realloc(void *p, size_t s)
139 {
140   if (!__mmalloc_current_heap) {
141     return mm_real_realloc(p, s);
142   }
143
144   xbt_mheap_t mdp = GET_HEAP();
145   if (!mdp)
146     return NULL;
147
148   LOCK(mdp);
149   void* ret = mrealloc(mdp, p, s);
150   UNLOCK(mdp);
151   return ret;
152 }
153
154 void free(void *p)
155 {
156   if (!p)
157     return;
158
159   if (!__mmalloc_current_heap) {
160     mm_real_free(p);
161     return;
162   }
163
164   xbt_mheap_t mdp = GET_HEAP();
165   LOCK(mdp);
166   mfree(mdp, p);
167   UNLOCK(mdp);
168 }
169 #endif /* WANT_MALLOC_OVERRIDE */