Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
[travis] detect linux as we should
[simgrid.git] / src / mc / mcer_ignore.cpp
1 /* Copyright (c) 2008-2015. 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/mc_private.h"
10 #include "smpi/private.h"
11 #include "mc/mc_snapshot.h"
12 #include "mc/mc_ignore.h"
13 #include "mc/mc_protocol.h"
14 #include "mc/mc_client.h"
15
16 #include "mc/Frame.hpp"
17 #include "mc/Variable.hpp"
18 #include "mc/ObjectInformation.hpp"
19
20 extern "C" {
21
22 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(mcer_ignore, mc,
23                                 "Logging specific to MC ignore mechanism");
24
25 // ***** Ignore heap chunks
26
27 extern xbt_dynar_t mc_heap_comparison_ignore;
28
29 void heap_ignore_region_free(mc_heap_ignore_region_t r)
30 {
31   xbt_free(r);
32 }
33
34 void heap_ignore_region_free_voidp(void *r)
35 {
36   heap_ignore_region_free((mc_heap_ignore_region_t) * (void **) r);
37 }
38
39
40 void MC_heap_region_ignore_insert(mc_heap_ignore_region_t region)
41 {
42   if (mc_heap_comparison_ignore == NULL) {
43     mc_heap_comparison_ignore =
44         xbt_dynar_new(sizeof(mc_heap_ignore_region_t),
45                       heap_ignore_region_free_voidp);
46     xbt_dynar_push(mc_heap_comparison_ignore, &region);
47     return;
48   }
49
50   unsigned int cursor = 0;
51   mc_heap_ignore_region_t current_region = NULL;
52   int start = 0;
53   int end = xbt_dynar_length(mc_heap_comparison_ignore) - 1;
54
55   // Find the position where we want to insert the mc_heap_ignore_region_t:
56   while (start <= end) {
57     cursor = (start + end) / 2;
58     current_region =
59         (mc_heap_ignore_region_t) xbt_dynar_get_as(mc_heap_comparison_ignore,
60                                                    cursor,
61                                                    mc_heap_ignore_region_t);
62     if (current_region->address == region->address) {
63       heap_ignore_region_free(region);
64       return;
65     } else if (current_region->address < region->address) {
66       start = cursor + 1;
67     } else {
68       end = cursor - 1;
69     }
70   }
71
72   // Insert it mc_heap_ignore_region_t:
73   if (current_region->address < region->address)
74     xbt_dynar_insert_at(mc_heap_comparison_ignore, cursor + 1, &region);
75   else
76     xbt_dynar_insert_at(mc_heap_comparison_ignore, cursor, &region);
77 }
78
79 void MC_heap_region_ignore_remove(void *address, size_t size)
80 {
81   unsigned int cursor = 0;
82   int start = 0;
83   int end = xbt_dynar_length(mc_heap_comparison_ignore) - 1;
84   mc_heap_ignore_region_t region;
85   int ignore_found = 0;
86
87   while (start <= end) {
88     cursor = (start + end) / 2;
89     region =
90         (mc_heap_ignore_region_t) xbt_dynar_get_as(mc_heap_comparison_ignore,
91                                                    cursor,
92                                                    mc_heap_ignore_region_t);
93     if (region->address == address) {
94       ignore_found = 1;
95       break;
96     } else if (region->address < address) {
97       start = cursor + 1;
98     } else {
99       if ((char *) region->address <= ((char *) address + size)) {
100         ignore_found = 1;
101         break;
102       } else {
103         end = cursor - 1;
104       }
105     }
106   }
107
108   if (ignore_found == 1) {
109     xbt_dynar_remove_at(mc_heap_comparison_ignore, cursor, NULL);
110     MC_remove_ignore_heap(address, size);
111   }
112 }
113
114 // ***** Ignore global variables
115
116 void MCer_ignore_global_variable(const char *name)
117 {
118   simgrid::mc::Process* process = &mc_model_checker->process();
119   xbt_assert(!process->object_infos.empty(), "MC subsystem not initialized");
120
121   for (std::shared_ptr<simgrid::mc::ObjectInformation> const& info : process->object_infos) {
122
123     // Binary search:
124     int start = 0;
125     int end = info->global_variables.size() - 1;
126     while (start <= end) {
127       unsigned int cursor = (start + end) / 2;
128       simgrid::mc::Variable* current_var = &info->global_variables[cursor];
129       int cmp = strcmp(current_var->name.c_str(), name);
130       if (cmp == 0) {
131         info->global_variables.erase(
132           info->global_variables.begin() + cursor);
133         start = 0;
134         end = info->global_variables.size() - 1;
135       } else if (cmp < 0) {
136         start = cursor + 1;
137       } else {
138         end = cursor - 1;
139       }
140     }
141   }
142 }
143
144 // ***** Ignore local variables
145
146 static void mc_ignore_local_variable_in_scope(const char *var_name,
147                                               const char *subprogram_name,
148                                               simgrid::mc::Frame* subprogram,
149                                               simgrid::mc::Frame* scope);
150 static void MC_ignore_local_variable_in_object(const char *var_name,
151                                                const char *subprogram_name,
152                                                simgrid::mc::ObjectInformation* info);
153
154 void MC_ignore_local_variable(const char *var_name, const char *frame_name)
155 {
156   simgrid::mc::Process* process = &mc_model_checker->process();
157   if (strcmp(frame_name, "*") == 0)
158     frame_name = NULL;
159
160   for (std::shared_ptr<simgrid::mc::ObjectInformation> const& info : process->object_infos)
161     MC_ignore_local_variable_in_object(var_name, frame_name, info.get());
162 }
163
164 static void MC_ignore_local_variable_in_object(const char *var_name,
165                                                const char *subprogram_name,
166                                                simgrid::mc::ObjectInformation* info)
167 {
168   for (auto& entry : info->subprograms)
169     mc_ignore_local_variable_in_scope(
170       var_name, subprogram_name, &entry.second, &entry.second);
171 }
172
173 /** \brief Ignore a local variable in a scope
174  *
175  *  Ignore all instances of variables with a given name in
176  *  any (possibly inlined) subprogram with a given namespaced
177  *  name.
178  *
179  *  \param var_name        Name of the local variable (or parameter to ignore)
180  *  \param subprogram_name Name of the subprogram fo ignore (NULL for any)
181  *  \param subprogram      (possibly inlined) Subprogram of the scope
182  *  \param scope           Current scope
183  */
184 static void mc_ignore_local_variable_in_scope(const char *var_name,
185                                               const char *subprogram_name,
186                                               simgrid::mc::Frame* subprogram,
187                                               simgrid::mc::Frame* scope)
188 {
189   // Processing of direct variables:
190
191   // If the current subprogram matches the given name:
192   if (subprogram_name == nullptr ||
193       (!subprogram->name.empty()
194         && subprogram->name == subprogram_name)) {
195
196     // Try to find the variable and remove it:
197     int start = 0;
198     int end = scope->variables.size() - 1;
199
200     // Dichotomic search:
201     while (start <= end) {
202       int cursor = (start + end) / 2;
203       simgrid::mc::Variable* current_var = &scope->variables[cursor];
204
205       int compare = strcmp(current_var->name.c_str(), var_name);
206       if (compare == 0) {
207         // Variable found, remove it:
208         scope->variables.erase(scope->variables.begin() + cursor);
209
210         // and start again:
211         start = 0;
212         end = scope->variables.size() - 1;
213       } else if (compare < 0) {
214         start = cursor + 1;
215       } else {
216         end = cursor - 1;
217       }
218     }
219
220   }
221   // And recursive processing in nested scopes:
222   for (simgrid::mc::Frame& nested_scope : scope->scopes) {
223     // The new scope may be an inlined subroutine, in this case we want to use its
224     // namespaced name in recursive calls:
225     simgrid::mc::Frame* nested_subprogram =
226         nested_scope.tag ==
227         DW_TAG_inlined_subroutine ? &nested_scope : subprogram;
228
229     mc_ignore_local_variable_in_scope(var_name, subprogram_name,
230                                       nested_subprogram, &nested_scope);
231   }
232 }
233
234 extern xbt_dynar_t stacks_areas;
235
236 void MC_stack_area_add(stack_region_t stack_area)
237 {
238   if (stacks_areas == NULL)
239     stacks_areas = xbt_dynar_new(sizeof(stack_region_t), NULL);
240   xbt_dynar_push(stacks_areas, &stack_area);
241 }
242
243 }