Logo AND Algorithmique Numérique Distribuée

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