Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
7f9aa05e4e6f82bdba464bb889b9234b6d4baaeb
[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 HEAP_OFFSET   20480000    /* Safety gap from the heap's break adress */
13 #define STD_HEAP_SIZE   20480000  /* Maximum size of the system's heap */
14
15 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(mc_memory, mc,
16                                 "Logging specific to MC (memory)");
17
18 /* Pointers to each of the heap regions to use */
19 void *std_heap;
20 void *raw_heap;
21 void *actual_heap;
22
23 /* Pointers to the begining and end of the .data and .bss segment of libsimgrid */
24 /* They are initialized once at memory_init */
25 void *libsimgrid_data_addr_start = NULL;
26 size_t libsimgrid_data_size = 0;
27
28 /* Initialize the model-checker memory subsystem */
29 /* It creates the heap regions and set the default one */
30 void MC_memory_init()
31 {
32 /* Create the first region HEAP_OFFSET bytes after the heap break address */
33   std_heap = mmalloc_attach(-1, (char *)sbrk(0) + HEAP_OFFSET);
34   xbt_assert(std_heap != NULL);
35
36 /* Create the sencond region a page after the first one ends */  
37 /* FIXME: do not hardcode the page size to 4096 */
38   raw_heap = mmalloc_attach(-1, (char *)(std_heap) + STD_HEAP_SIZE + 4096);
39   xbt_assert(raw_heap != NULL);
40
41   MC_SET_RAW_MEM;
42
43 /* Get the start address and size of libsimgrid's data segment */
44 /* CAVEAT: Here we are assuming several things, first that get_memory_map() */
45 /* returns an array with the maps sorted from lower addresses to higher */
46 /* ones. Second, that libsimgrid's data takes ONLY ONE page. */
47   int i;
48   char *libname, *tmp;
49
50   /* Get memory map */
51   memory_map_t maps;
52   maps = get_memory_map();
53   
54   for(i=0; i < maps->mapsize; i++){
55  
56     if(maps->regions[i].inode != 0){
57  
58       tmp = xbt_strdup(maps->regions[i].pathname);
59       libname = basename(tmp);
60  
61       if( strncmp("libsimgrid.so.2.0.0", libname, 18) == 0 && maps->regions[i].perms & MAP_WRITE){
62         libsimgrid_data_addr_start = maps->regions[i].start_addr;
63         libsimgrid_data_size = (size_t)((char *)maps->regions[i+1].end_addr - (char *)maps->regions[i].start_addr);
64         xbt_free(tmp);
65         break;
66       }        
67       xbt_free(tmp);
68     }
69   }
70   
71   xbt_assert0(libsimgrid_data_addr_start != NULL, 
72              "Cannot determine libsimgrid's .data segment address");
73              
74   MC_UNSET_RAW_MEM;
75 }
76
77 /* Finish the memory subsystem */
78 void MC_memory_exit()
79 {
80   mmalloc_detach(std_heap);
81   mmalloc_detach(raw_heap);
82   actual_heap = NULL;
83 }
84
85 void *malloc(size_t n)
86 {
87   void *ret = mmalloc(actual_heap, n);
88    
89   DEBUG2("%zu bytes were allocated at %p",n, ret);
90   return ret;
91 }
92
93 void *calloc(size_t nmemb, size_t size)
94 {
95   size_t total_size = nmemb * size;
96   void *ret = mmalloc(actual_heap, total_size);
97    
98 /* Fill the allocated memory with zeroes to mimic calloc behaviour */
99   memset(ret,'\0', total_size);
100
101   DEBUG2("%zu bytes were mallocated and zeroed at %p",total_size, ret);
102   return ret;
103 }
104   
105 void *realloc(void *p, size_t s)
106 {
107   void *ret = NULL;
108         
109   if (s) {
110     if (p)
111       ret = mrealloc(actual_heap, p,s);
112     else
113       ret = malloc(s);
114   } else {
115     if (p) {
116       free(p);
117     }
118   }
119
120   DEBUG2("%zu bytes were reallocated at %p",s,ret);
121   return ret;
122 }
123
124 void free(void *p)
125 {
126   DEBUG1("%p was freed",p);
127   xbt_assert(actual_heap != NULL);
128   return mfree(actual_heap, p);
129 }
130
131 /* FIXME: Horrible hack! because the mmalloc library doesn't provide yet of */
132 /* an API to query about the status of a heap, we simply call mmstats and */
133 /* because I now how does structure looks like, then I redefine it here */
134
135 struct mstats
136   {
137     size_t bytes_total;         /* Total size of the heap. */
138     size_t chunks_used;         /* Chunks allocated by the user. */
139     size_t bytes_used;          /* Byte total of user-allocated chunks. */
140     size_t chunks_free;         /* Chunks in the free list. */
141     size_t bytes_free;          /* Byte total of chunks in the free list. */
142   };
143
144 extern struct mstats mmstats(void *);
145
146 /* Copy std_heap to "to_heap" allocating the required space for it */
147 size_t MC_save_heap(void **to_heap)
148 {  
149   size_t heap_size = mmstats(std_heap).bytes_total;
150   
151   *to_heap = calloc(heap_size, 1);
152
153   xbt_assert(*to_heap != NULL);
154   
155   memcpy(*to_heap, std_heap, heap_size);
156   
157   return heap_size;
158 }
159
160 /* Copy the data segment of libsimgrid to "data" allocating the space for it */
161 size_t MC_save_dataseg(void **data)
162 {
163   *data = calloc(libsimgrid_data_size, 1);
164   memcpy(*data, libsimgrid_data_addr_start, libsimgrid_data_size);
165   return libsimgrid_data_size;
166 }
167
168 /* Restore std_heap from "src_heap" */
169 void MC_restore_heap(void *src_heap, size_t size)
170 {  
171   memcpy(std_heap, src_heap, size);
172 }
173
174 /* Restore the data segment of libsimgrid from "src_data" */
175 void MC_restore_dataseg(void *src_data, size_t size)
176 {
177   memcpy(libsimgrid_data_addr_start, src_data, size);
178 }
179
180
181
182
183