Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Improve the integration of mmalloc and mc_memory into the mess.
[simgrid.git] / src / mc / mc_memory.c
1 #include <stdlib.h>
2 #include <stdio.h>
3 #include "mc/mc.h"
4 #include "xbt/sysdep.h"
5 #include "private.h"
6 #include "xbt/log.h"
7 #include <unistd.h>
8 #define _GNU_SOURCE
9
10 extern char *basename (__const char *__filename);
11
12 #define STD_HEAP_SIZE   20480000  /* Maximum size of the system's heap */
13
14 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(mc_memory, mc,
15                                 "Logging specific to MC (memory)");
16
17 /* Pointers to each of the heap regions to use */
18 void *std_heap=NULL; /* memory erased each time the MC stuff rollbacks to the beginning. Almost everything goes here */
19 void *raw_heap=NULL; /* memory persistent over the MC rollbacks. Only MC stuff should go there */
20 void *actual_heap=NULL; /* The heap we are currently using. Either std_heap or raw_heap. Controlled by macros MC_SET_RAW_MEM/MC_UNSET_RAW_MEM */
21
22 /* Pointers to the beginning and end of the .data and .bss segment of libsimgrid */
23 /* They are initialized once at memory_init */
24 void *libsimgrid_data_addr_start = NULL;
25 size_t libsimgrid_data_size = 0;
26
27 /* Initialize the model-checker memory subsystem */
28 /* It creates the heap regions and set the default one */
29 void MC_memory_init()
30 {
31 /* Create the first region HEAP_OFFSET bytes after the heap break address */
32   std_heap = mmalloc_get_default_md();
33   xbt_assert(std_heap != NULL);
34
35 /* Create the second region a page after the first one ends */
36   raw_heap = mmalloc_attach(-1, (char *)(std_heap) + STD_HEAP_SIZE + getpagesize());
37   xbt_assert(raw_heap != NULL);
38
39   MC_SET_RAW_MEM;
40
41 /* Get the start address and size of libsimgrid's data segment */
42 /* CAVEAT: Here we are assuming that get_memory_map() */
43 /* returns an array with the maps sorted from lower addresses to higher ones.  */
44   int i;
45   char *libname, *tmp;
46
47   /* Get memory map */
48   memory_map_t maps;
49   maps = get_memory_map();
50   
51   for(i=0; i < maps->mapsize; i++){
52  
53     if(maps->regions[i].inode != 0){
54  
55       tmp = xbt_strdup(maps->regions[i].pathname);
56       libname = basename(tmp);
57  
58 #if 0
59       if (maps->regions[i].perms & MAP_WRITE &&
60           maps->regions[i].pathname[0] != '\0' &&  /* do not take anonymous segments: what are they? */
61           strcmp("[heap]",maps->regions[i].pathname) && /* do not take standard heap: mmalloc saves it already */
62           strcmp("[stack]",maps->regions[i].pathname) /* this is maestro's stack. No need to save it */
63           ) {
64         /* FIXME: we should save the data of more segments, in a list of block to save */
65       }
66 #endif
67       /* for now, we only save the data of libsimgrid (FIXME) */
68       if( strncmp("libsimgrid.so.", libname, 14) == 0 && maps->regions[i].perms & MAP_WRITE){
69         libsimgrid_data_addr_start = maps->regions[i].start_addr;
70         libsimgrid_data_size = (size_t)((char *)maps->regions[i+1].start_addr - (char *)maps->regions[i].start_addr);
71         xbt_free(tmp);
72         break;
73       }        
74       xbt_free(tmp);
75     }
76   }
77   
78   xbt_assert0(libsimgrid_data_addr_start != NULL, 
79              "Cannot determine libsimgrid's .data segment address");
80              
81   MC_UNSET_RAW_MEM;
82 }
83
84 /* Finish the memory subsystem */
85 void MC_memory_exit()
86 {
87   mmalloc_detach(std_heap);
88   mmalloc_detach(raw_heap);
89   actual_heap = NULL;
90 }
91
92 void *malloc(size_t n) {
93   void *ret = mmalloc(actual_heap, n);
94    
95   DEBUG2("%zu bytes were allocated at %p",n, ret);
96   return ret;
97 }
98
99 void *calloc(size_t nmemb, size_t size)
100 {
101   size_t total_size = nmemb * size;
102
103   void *ret = mmalloc(actual_heap, total_size);
104    
105 /* Fill the allocated memory with zeroes to mimic calloc behaviour */
106   memset(ret,'\0', total_size);
107
108   DEBUG2("%zu bytes were mallocated and zeroed at %p",total_size, ret);
109   return ret;
110 }
111   
112 void *realloc(void *p, size_t s)
113 {
114   void *ret = NULL;
115         
116   if (s) {
117     if (p)
118       ret = mrealloc(actual_heap, p,s);
119     else
120       ret = malloc(s); /* FIXME: shouldn't this be mmalloc? */
121   } else {
122     if (p) {
123       free(p);
124     }
125   }
126
127   DEBUG2("%zu bytes were reallocated at %p",s,ret);
128   return ret;
129 }
130
131 void free(void *p)
132 {
133   DEBUG1("%p was freed",p);
134 //  xbt_assert(actual_heap != NULL); FIXME: I had to comment this
135   return mfree(actual_heap, p);
136 }
137
138 /* FIXME: Horrible hack! because the mmalloc library doesn't provide yet of */
139 /* an API to query about the status of a heap, we simply call mmstats and */
140 /* because I now how does structure looks like, then I redefine it here */
141
142 struct mstats
143   {
144     size_t bytes_total;         /* Total size of the heap. */
145     size_t chunks_used;         /* Chunks allocated by the user. */
146     size_t bytes_used;          /* Byte total of user-allocated chunks. */
147     size_t chunks_free;         /* Chunks in the free list. */
148     size_t bytes_free;          /* Byte total of chunks in the free list. */
149   };
150
151 extern struct mstats mmstats(void *);
152
153 /* Copy std_heap to "to_heap" allocating the required space for it */
154 size_t MC_save_heap(void **to_heap)
155 {  
156   size_t heap_size = mmstats(std_heap).bytes_total;
157   
158   *to_heap = calloc(heap_size, 1);
159
160   xbt_assert(*to_heap != NULL);
161   
162   memcpy(*to_heap, std_heap, heap_size);
163   
164   return heap_size;
165 }
166
167 /* Copy the data segment of libsimgrid to "data" allocating the space for it */
168 size_t MC_save_dataseg(void **data)
169 {
170   *data = calloc(libsimgrid_data_size, 1);
171   memcpy(*data, libsimgrid_data_addr_start, libsimgrid_data_size);
172   return libsimgrid_data_size;
173 }
174
175 /* Restore std_heap from "src_heap" */
176 void MC_restore_heap(void *src_heap, size_t size)
177 {  
178   memcpy(std_heap, src_heap, size);
179 }
180
181 /* Restore the data segment of libsimgrid from "src_data" */
182 void MC_restore_dataseg(void *src_data, size_t size)
183 {
184   memcpy(libsimgrid_data_addr_start, src_data, size);
185 }
186
187
188
189
190