Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
[mc] Enable the custom mm malloc only in MC
[simgrid.git] / src / mc / mc_ignore.c
1 /* Copyright (c) 2008-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 #include "internal_config.h"
8 #include "mc_object_info.h"
9 #include "mc_private.h"
10 #include "smpi/private.h"
11 #include "mc/mc_snapshot.h"
12
13 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(mc_ignore, mc,
14                                 "Logging specific to MC ignore mechanism");
15
16
17 /**************************** Global variables ******************************/
18 xbt_dynar_t mc_checkpoint_ignore;
19 extern xbt_dynar_t mc_heap_comparison_ignore;
20 extern xbt_dynar_t stacks_areas;
21
22 /**************************** Structures ******************************/
23 typedef struct s_mc_stack_ignore_variable {
24   char *var_name;
25   char *frame;
26 } s_mc_stack_ignore_variable_t, *mc_stack_ignore_variable_t;
27
28 /**************************** Free functions ******************************/
29
30 static void stack_ignore_variable_free(mc_stack_ignore_variable_t v)
31 {
32   xbt_free(v->var_name);
33   xbt_free(v->frame);
34   xbt_free(v);
35 }
36
37 static void stack_ignore_variable_free_voidp(void *v)
38 {
39   stack_ignore_variable_free((mc_stack_ignore_variable_t) * (void **) v);
40 }
41
42 void heap_ignore_region_free(mc_heap_ignore_region_t r)
43 {
44   xbt_free(r);
45 }
46
47 void heap_ignore_region_free_voidp(void *r)
48 {
49   heap_ignore_region_free((mc_heap_ignore_region_t) * (void **) r);
50 }
51
52 static void checkpoint_ignore_region_free(mc_checkpoint_ignore_region_t r)
53 {
54   xbt_free(r);
55 }
56
57 static void checkpoint_ignore_region_free_voidp(void *r)
58 {
59   checkpoint_ignore_region_free((mc_checkpoint_ignore_region_t) * (void **) r);
60 }
61
62 /***********************************************************************/
63
64 void MC_ignore_heap(void *address, size_t size)
65 {
66   if(!std_heap)
67     return;
68
69   int raw_mem_set = (mmalloc_get_current_heap() == mc_heap);
70
71   MC_SET_MC_HEAP;
72
73   mc_heap_ignore_region_t region = NULL;
74   region = xbt_new0(s_mc_heap_ignore_region_t, 1);
75   region->address = address;
76   region->size = size;
77
78   region->block =
79       ((char *) address -
80        (char *) std_heap->heapbase) / BLOCKSIZE + 1;
81
82   if (std_heap->heapinfo[region->block].type == 0) {
83     region->fragment = -1;
84     std_heap->heapinfo[region->block].busy_block.ignore++;
85   } else {
86     region->fragment =
87         ((uintptr_t) (ADDR2UINT(address) % (BLOCKSIZE))) >> std_heap->
88         heapinfo[region->block].type;
89     std_heap->heapinfo[region->block].busy_frag.ignore[region->fragment]++;
90   }
91
92   if (mc_heap_comparison_ignore == NULL) {
93     mc_heap_comparison_ignore =
94         xbt_dynar_new(sizeof(mc_heap_ignore_region_t),
95                       heap_ignore_region_free_voidp);
96     xbt_dynar_push(mc_heap_comparison_ignore, &region);
97     if (!raw_mem_set)
98       MC_SET_STD_HEAP;
99     return;
100   }
101
102   unsigned int cursor = 0;
103   mc_heap_ignore_region_t current_region = NULL;
104   int start = 0;
105   int end = xbt_dynar_length(mc_heap_comparison_ignore) - 1;
106
107   while (start <= end) {
108     cursor = (start + end) / 2;
109     current_region =
110         (mc_heap_ignore_region_t) xbt_dynar_get_as(mc_heap_comparison_ignore,
111                                                    cursor,
112                                                    mc_heap_ignore_region_t);
113     if (current_region->address == address) {
114       heap_ignore_region_free(region);
115       if (!raw_mem_set)
116         MC_SET_STD_HEAP;
117       return;
118     } else if (current_region->address < address) {
119       start = cursor + 1;
120     } else {
121       end = cursor - 1;
122     }
123   }
124
125   if (current_region->address < address)
126     xbt_dynar_insert_at(mc_heap_comparison_ignore, cursor + 1, &region);
127   else
128     xbt_dynar_insert_at(mc_heap_comparison_ignore, cursor, &region);
129
130   if (!raw_mem_set)
131     MC_SET_STD_HEAP;
132 }
133
134 void MC_remove_ignore_heap(void *address, size_t size)
135 {
136
137   int raw_mem_set = (mmalloc_get_current_heap() == mc_heap);
138
139   MC_SET_MC_HEAP;
140
141   unsigned int cursor = 0;
142   int start = 0;
143   int end = xbt_dynar_length(mc_heap_comparison_ignore) - 1;
144   mc_heap_ignore_region_t region;
145   int ignore_found = 0;
146
147   while (start <= end) {
148     cursor = (start + end) / 2;
149     region =
150         (mc_heap_ignore_region_t) xbt_dynar_get_as(mc_heap_comparison_ignore,
151                                                    cursor,
152                                                    mc_heap_ignore_region_t);
153     if (region->address == address) {
154       ignore_found = 1;
155       break;
156     } else if (region->address < address) {
157       start = cursor + 1;
158     } else {
159       if ((char *) region->address <= ((char *) address + size)) {
160         ignore_found = 1;
161         break;
162       } else {
163         end = cursor - 1;
164       }
165     }
166   }
167
168   if (ignore_found == 1) {
169     xbt_dynar_remove_at(mc_heap_comparison_ignore, cursor, NULL);
170     MC_remove_ignore_heap(address, size);
171   }
172
173   if (!raw_mem_set)
174     MC_SET_STD_HEAP;
175
176 }
177
178 void MC_ignore_global_variable(const char *name)
179 {
180   mc_process_t process = &mc_model_checker->process;
181   int raw_mem_set = (mmalloc_get_current_heap() == mc_heap);
182
183   MC_SET_MC_HEAP;
184
185   xbt_assert(process->object_infos, "MC subsystem not initialized");
186
187   size_t n = process->object_infos_size;
188   for (size_t i=0; i!=n; ++i) {
189     mc_object_info_t info = process->object_infos[i];
190
191     // Binary search:
192     int start = 0;
193     int end = xbt_dynar_length(info->global_variables) - 1;
194     while (start <= end) {
195       unsigned int cursor = (start + end) / 2;
196       dw_variable_t current_var =
197           (dw_variable_t) xbt_dynar_get_as(info->global_variables,
198                                            cursor, dw_variable_t);
199       if (strcmp(current_var->name, name) == 0) {
200         xbt_dynar_remove_at(info->global_variables, cursor, NULL);
201         start = 0;
202         end = xbt_dynar_length(info->global_variables) - 1;
203       } else if (strcmp(current_var->name, name) < 0) {
204         start = cursor + 1;
205       } else {
206         end = cursor - 1;
207       }
208     }
209   }
210
211   if (!raw_mem_set)
212     MC_SET_STD_HEAP;
213 }
214
215 /** \brief Ignore a local variable in a scope
216  *
217  *  Ignore all instances of variables with a given name in
218  *  any (possibly inlined) subprogram with a given namespaced
219  *  name.
220  *
221  *  \param var_name        Name of the local variable (or parameter to ignore)
222  *  \param subprogram_name Name of the subprogram fo ignore (NULL for any)
223  *  \param subprogram      (possibly inlined) Subprogram of the scope
224  *  \param scope           Current scope
225  */
226 static void mc_ignore_local_variable_in_scope(const char *var_name,
227                                               const char *subprogram_name,
228                                               dw_frame_t subprogram,
229                                               dw_frame_t scope)
230 {
231   // Processing of direct variables:
232
233   // If the current subprogram matche the given name:
234   if (!subprogram_name ||
235       (subprogram->name && strcmp(subprogram_name, subprogram->name) == 0)) {
236
237     // Try to find the variable and remove it:
238     int start = 0;
239     int end = xbt_dynar_length(scope->variables) - 1;
240
241     // Dichotomic search:
242     while (start <= end) {
243       int cursor = (start + end) / 2;
244       dw_variable_t current_var =
245           (dw_variable_t) xbt_dynar_get_as(scope->variables, cursor,
246                                            dw_variable_t);
247
248       int compare = strcmp(current_var->name, var_name);
249       if (compare == 0) {
250         // Variable found, remove it:
251         xbt_dynar_remove_at(scope->variables, cursor, NULL);
252
253         // and start again:
254         start = 0;
255         end = xbt_dynar_length(scope->variables) - 1;
256       } else if (compare < 0) {
257         start = cursor + 1;
258       } else {
259         end = cursor - 1;
260       }
261     }
262
263   }
264   // And recursive processing in nested scopes:
265   unsigned cursor = 0;
266   dw_frame_t nested_scope = NULL;
267   xbt_dynar_foreach(scope->scopes, cursor, nested_scope) {
268     // The new scope may be an inlined subroutine, in this case we want to use its
269     // namespaced name in recursive calls:
270     dw_frame_t nested_subprogram =
271         nested_scope->tag ==
272         DW_TAG_inlined_subroutine ? nested_scope : subprogram;
273
274     mc_ignore_local_variable_in_scope(var_name, subprogram_name,
275                                       nested_subprogram, nested_scope);
276   }
277 }
278
279 static void MC_ignore_local_variable_in_object(const char *var_name,
280                                                const char *subprogram_name,
281                                                mc_object_info_t info)
282 {
283   xbt_dict_cursor_t cursor2;
284   dw_frame_t frame;
285   char *key;
286   xbt_dict_foreach(info->subprograms, cursor2, key, frame) {
287     mc_ignore_local_variable_in_scope(var_name, subprogram_name, frame, frame);
288   }
289 }
290
291 void MC_ignore_local_variable(const char *var_name, const char *frame_name)
292 {
293   mc_process_t process = &mc_model_checker->process;
294
295
296   int raw_mem_set = (mmalloc_get_current_heap() == mc_heap);
297
298   if (strcmp(frame_name, "*") == 0)
299     frame_name = NULL;
300
301   MC_SET_MC_HEAP;
302
303   size_t n = process->object_infos_size;
304   size_t i;
305   for (i=0; i!=n; ++i) {
306     MC_ignore_local_variable_in_object(var_name, frame_name, process->object_infos[i]);
307   }
308
309   if (!raw_mem_set)
310     MC_SET_STD_HEAP;
311
312 }
313
314 /** @brief Register a stack in the model checker
315  *
316  *  The stacks are allocated in the heap. The MC handle them especially
317  *  when we analyse/compare the content of theap so it must be told where
318  *  they are with this function.
319  *
320  *  @param stack
321  *  @param process Process owning the stack
322  *  @param context
323  *  @param size    Size of the stack
324  */
325 void MC_new_stack_area(void *stack, smx_process_t process, void *context, size_t size)
326 {
327
328   int raw_mem_set = (mmalloc_get_current_heap() == mc_heap);
329
330   MC_SET_MC_HEAP;
331
332   if (stacks_areas == NULL)
333     stacks_areas = xbt_dynar_new(sizeof(stack_region_t), NULL);
334
335   stack_region_t region = NULL;
336   region = xbt_new0(s_stack_region_t, 1);
337   region->address = stack;
338   region->process_name = process && process->name ? strdup(process->name) : NULL;
339   region->context = context;
340   region->size = size;
341   region->block =
342       ((char *) stack -
343        (char *) std_heap->heapbase) / BLOCKSIZE + 1;
344 #ifdef HAVE_SMPI
345   if (smpi_privatize_global_variables && process) {
346     region->process_index = smpi_process_index_of_smx_process(process);
347   } else
348 #endif
349   region->process_index = -1;
350
351   xbt_dynar_push(stacks_areas, &region);
352
353   if (!raw_mem_set)
354     MC_SET_STD_HEAP;
355 }
356
357 void MC_ignore(void *addr, size_t size)
358 {
359
360   int raw_mem_set = (mmalloc_get_current_heap() == mc_heap);
361
362   MC_SET_MC_HEAP;
363
364   if (mc_checkpoint_ignore == NULL)
365     mc_checkpoint_ignore =
366         xbt_dynar_new(sizeof(mc_checkpoint_ignore_region_t),
367                       checkpoint_ignore_region_free_voidp);
368
369   mc_checkpoint_ignore_region_t region =
370       xbt_new0(s_mc_checkpoint_ignore_region_t, 1);
371   region->addr = addr;
372   region->size = size;
373
374   if (xbt_dynar_is_empty(mc_checkpoint_ignore)) {
375     xbt_dynar_push(mc_checkpoint_ignore, &region);
376   } else {
377
378     unsigned int cursor = 0;
379     int start = 0;
380     int end = xbt_dynar_length(mc_checkpoint_ignore) - 1;
381     mc_checkpoint_ignore_region_t current_region = NULL;
382
383     while (start <= end) {
384       cursor = (start + end) / 2;
385       current_region =
386           (mc_checkpoint_ignore_region_t) xbt_dynar_get_as(mc_checkpoint_ignore,
387                                                            cursor,
388                                                            mc_checkpoint_ignore_region_t);
389       if (current_region->addr == addr) {
390         if (current_region->size == size) {
391           checkpoint_ignore_region_free(region);
392           if (!raw_mem_set)
393             MC_SET_STD_HEAP;
394           return;
395         } else if (current_region->size < size) {
396           start = cursor + 1;
397         } else {
398           end = cursor - 1;
399         }
400       } else if (current_region->addr < addr) {
401         start = cursor + 1;
402       } else {
403         end = cursor - 1;
404       }
405     }
406
407     if (current_region->addr == addr) {
408       if (current_region->size < size) {
409         xbt_dynar_insert_at(mc_checkpoint_ignore, cursor + 1, &region);
410       } else {
411         xbt_dynar_insert_at(mc_checkpoint_ignore, cursor, &region);
412       }
413     } else if (current_region->addr < addr) {
414       xbt_dynar_insert_at(mc_checkpoint_ignore, cursor + 1, &region);
415     } else {
416       xbt_dynar_insert_at(mc_checkpoint_ignore, cursor, &region);
417     }
418   }
419
420   if (!raw_mem_set)
421     MC_SET_STD_HEAP;
422 }