1 /* Copyright (c) 2011-2015. The SimGrid Team.
2 * All rights reserved. */
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. */
12 #include <xbt/automaton.h>
14 #include <xbt/sysdep.h>
15 #include <xbt/dynar.h>
18 #include "src/mc/mc_comm_pattern.h"
19 #include "src/mc/mc_safety.h"
20 #include "src/mc/mc_liveness.h"
21 #include "src/mc/mc_private.h"
22 #include "src/mc/Process.hpp"
23 #include "src/mc/mc_smx.h"
25 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(mc_visited, mc,
26 "Logging specific to state equaity detection mechanisms");
31 std::vector<std::unique_ptr<simgrid::mc::VisitedState>> visited_states;
33 static int is_exploration_stack_state(simgrid::mc::VisitedState* state){
34 xbt_fifo_item_t item = xbt_fifo_get_first_item(mc_stack);
36 if (((mc_state_t)xbt_fifo_get_item_content(item))->num == state->num){
37 ((mc_state_t)xbt_fifo_get_item_content(item))->in_visited_states = 0;
40 item = xbt_fifo_get_next_item(item);
46 * \brief Save the current state
47 * \return Snapshot of the current state.
49 VisitedState::VisitedState()
51 simgrid::mc::Process* process = &(mc_model_checker->process());
52 this->heap_bytes_used = mmalloc_get_bytes_used_remote(
53 process->get_heap()->heaplimit,
54 process->get_malloc_info());
57 mc_model_checker->process().simix_processes().size();
59 this->system_state = simgrid::mc::take_snapshot(mc_stats->expanded_states);
60 this->num = mc_stats->expanded_states;
64 VisitedState::~VisitedState()
66 if(!is_exploration_stack_state(this))
67 delete this->system_state;
70 VisitedPair::VisitedPair(int pair_num, xbt_automaton_state_t automaton_state, xbt_dynar_t atomic_propositions, mc_state_t graph_state)
72 simgrid::mc::Process* process = &(mc_model_checker->process());
74 this->graph_state = graph_state;
75 if(this->graph_state->system_state == nullptr)
76 this->graph_state->system_state = simgrid::mc::take_snapshot(pair_num);
77 this->heap_bytes_used = mmalloc_get_bytes_used_remote(
78 process->get_heap()->heaplimit,
79 process->get_malloc_info());
82 mc_model_checker->process().simix_processes().size();
84 this->automaton_state = automaton_state;
87 this->acceptance_removed = 0;
88 this->visited_removed = 0;
89 this->acceptance_pair = 0;
90 this->atomic_propositions = simgrid::xbt::unique_ptr<s_xbt_dynar_t>(
91 xbt_dynar_new(sizeof(int), nullptr));
93 unsigned int cursor = 0;
95 xbt_dynar_foreach(atomic_propositions, cursor, value)
96 xbt_dynar_push_as(this->atomic_propositions.get(), int, value);
99 static int is_exploration_stack_pair(simgrid::mc::VisitedPair* pair){
100 xbt_fifo_item_t item = xbt_fifo_get_first_item(mc_stack);
102 if (((simgrid::mc::Pair*)xbt_fifo_get_item_content(item))->num == pair->num){
103 ((simgrid::mc::Pair*)xbt_fifo_get_item_content(item))->visited_pair_removed = 1;
106 item = xbt_fifo_get_next_item(item);
111 VisitedPair::~VisitedPair()
113 if( !is_exploration_stack_pair(this))
114 MC_state_delete(this->graph_state, 1);
121 bool some_communications_are_not_finished()
123 for (size_t current_process = 1; current_process < MC_smx_get_maxpid(); current_process++) {
124 xbt_dynar_t pattern = xbt_dynar_get_as(
125 incomplete_communications_pattern, current_process, xbt_dynar_t);
126 if (!xbt_dynar_is_empty(pattern)) {
127 XBT_DEBUG("Some communications are not finished, cannot stop the exploration ! State not visited.");
138 * \brief Checks whether a given state has already been visited by the algorithm.
140 std::unique_ptr<simgrid::mc::VisitedState> is_visited_state(mc_state_t graph_state)
142 if (_sg_mc_visited == 0)
145 /* If comm determinism verification, we cannot stop the exploration if some
146 communications are not finished (at least, data are transfered). These communications
147 are incomplete and they cannot be analyzed and compared with the initial pattern. */
148 int partial_comm = (_sg_mc_comms_determinism || _sg_mc_send_determinism) &&
149 some_communications_are_not_finished();
151 std::unique_ptr<simgrid::mc::VisitedState> new_state =
152 std::unique_ptr<simgrid::mc::VisitedState>(new VisitedState());
153 graph_state->system_state = new_state->system_state;
154 graph_state->in_visited_states = 1;
155 XBT_DEBUG("Snapshot %p of visited state %d (exploration stack state %d)", new_state->system_state, new_state->num, graph_state->num);
157 if (visited_states.empty()) {
158 visited_states.push_back(std::move(new_state));
162 int min = -1, max = -1, index;
164 index = simgrid::mc::get_search_interval(
165 visited_states.data(), visited_states.size(),
166 new_state.get(), &min, &max);
168 if (min != -1 && max != -1) {
170 if (_sg_mc_safety || (!partial_comm
171 && initial_global_state->initial_communications_pattern_done)) {
174 while (cursor <= max) {
175 if (snapshot_compare(visited_states[cursor].get(), new_state.get()) == 0) {
176 // The state has been visited:
178 std::unique_ptr<simgrid::mc::VisitedState> old_state =
179 std::move(visited_states[cursor]);
181 if (old_state->other_num == -1)
182 new_state->other_num = old_state->num;
184 new_state->other_num = old_state->other_num;
186 if (dot_output == nullptr)
187 XBT_DEBUG("State %d already visited ! (equal to state %d)",
188 new_state->num, old_state->num);
191 "State %d already visited ! (equal to state %d (state %d in dot_output))",
192 new_state->num, old_state->num, new_state->other_num);
194 /* Replace the old state with the new one (with a bigger num)
195 (when the max number of visited states is reached, the oldest
196 one is removed according to its number (= with the min number) */
197 XBT_DEBUG("Replace visited state %d with the new visited state %d",
198 old_state->num, new_state->num);
200 simgrid::mc::visited_states[cursor] = std::move(new_state);
201 return std::move(old_state);
207 XBT_DEBUG("Insert new visited state %d (total : %lu)", new_state->num, (unsigned long) visited_states.size());
208 visited_states.insert(visited_states.begin() + min, std::move(new_state));
212 // The state has not been visited: insert the state in the dynamic array.
213 visited_states.insert(visited_states.begin() + index, std::move(new_state));
214 XBT_DEBUG("Insert new visited state %d (total : %lu)",
215 visited_states[index]->num,
216 (unsigned long) visited_states.size());
220 if (visited_states.size() <= (std::size_t) _sg_mc_visited)
223 // We have reached the maximum number of stored states;
225 XBT_DEBUG("Try to remove visited state (maximum number of stored states reached)");
227 // Find the (index of the) older state (with the smallest num):
228 int min2 = mc_stats->expanded_states;
229 unsigned int index2 = 0;
231 for (std::size_t cursor2 = 0; cursor2 != visited_states.size(); ++cursor2)
232 if (!mc_model_checker->is_important_snapshot(
233 *visited_states[cursor2]->system_state)
234 && visited_states[cursor2]->num < min2) {
236 min2 = visited_states[cursor2]->num;
240 visited_states.erase(visited_states.begin() + index2);
241 XBT_DEBUG("Remove visited state (maximum number of stored states reached)");