spot 2.16
Loading...
Searching...
No Matches
mc_instanciator.hh
1// -*- coding: utf-8 -*-
2// Copyright (C) by the Spot authors, see the AUTHORS file for details.
3//
4// This file is part of Spot, a model checking library.
5//
6// Spot is free software; you can redistribute it and/or modify it
7// under the terms of the GNU General Public License as published by
8// the Free Software Foundation; either version 3 of the License, or
9// (at your option) any later version.
10//
11// Spot is distributed in the hope that it will be useful, but WITHOUT
12// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
14// License for more details.
15//
16// You should have received a copy of the GNU General Public License
17// along with this program. If not, see <http://www.gnu.org/licenses/>.
18
19#pragma once
20
21#include <spot/misc/common.hh>
22#include <spot/misc/_config.h>
23#include <string>
24#include <thread>
25#include <vector>
26#include <utility>
27#include <atomic>
28#include <spot/kripke/kripke.hh>
29#include <spot/mc/mc.hh>
30#include <spot/mc/lpar13.hh>
31#include <spot/mc/deadlock.hh>
32#include <spot/mc/cndfs.hh>
33#include <spot/mc/bloemen.hh>
34#include <spot/mc/bloemen_ec.hh>
35#include <spot/misc/timer.hh>
36
37namespace spot
38{
39
40#if defined(__cpp_concepts) && __cpp_concepts >= 201907L
44 template<typename T>
45 concept is_a_mc_algorithm = requires(T u)
46 {
47 u->setup();
48 u->run();
49 u->finalize();
50 { u->finisher() } -> std::same_as<bool>;
51 { u->states() } -> std::same_as<unsigned>;
52 { u->transitions() } -> std::same_as<unsigned>;
53 { u->walltime() } -> std::same_as<unsigned>;
54 { u->name() } -> std::same_as<std::string>;
55 { u->sccs() } -> std::same_as<int>;
56 { u->result() } -> std::same_as<mc_rvalue>;
57 { u->trace() } -> std::same_as<std::string>;
58 };
59#endif
60
61
62 template<typename algo_name, typename kripke_ptr, typename State,
63 typename Iterator, typename Hash, typename Equal>
64 static ec_stats instanciate(kripke_ptr sys,
65 spot::twacube_ptr prop = nullptr,
66 bool trace = false)
67 {
69 std::atomic<bool> stop(false);
70 unsigned nbth = sys->get_threads();
71
72 typename algo_name::shared_map map;
73 std::vector<algo_name*> swarmed(nbth);
74
75 // The shared structure requires sometimes one instance per thread
76 using struct_name = typename algo_name::shared_struct;
77 std::vector<struct_name*> ss(nbth);
78
79 tm.start("Initialisation");
80 for (unsigned i = 0; i < nbth; ++i)
81 {
82 ss[i] = algo_name::make_shared_structure(map, i);
83 swarmed[i] = new algo_name(*sys, prop, map, ss[i], i, stop);
84
85#if defined(__cpp_concepts) && __cpp_concepts >= 201907L
86 static_assert(spot::is_a_mc_algorithm<decltype(&*swarmed[i])>,
87 "error: does not match the mc_algorithm requirements");
88#endif
89
90 }
91 tm.stop("Initialisation");
92
93 // Spawn Threads
94 std::mutex iomutex;
95 std::atomic<bool> barrier(true);
96 std::vector<std::thread> threads(nbth);
97 for (unsigned i = 0; i < nbth; ++i)
98 {
99 threads[i] = std::thread ([&swarmed, &iomutex, i, &barrier]
100 {
101#ifdef SPOT_HAVE_SCHED_GETCPU
102 {
103 std::lock_guard<std::mutex> iolock(iomutex);
104 std::cout << "Thread #" << i
105 << ": on CPU " << sched_getcpu() << '\n';
106 }
107#endif
108
109 // Wait all threads to be instantiated.
110 while (barrier)
111 continue;
112 swarmed[i]->run();
113 });
114
115#ifdef SPOT_PTHREAD_SETAFFINITY_NP
116 // Pin threads to a dedicated core.
117 cpu_set_t cpuset;
118 CPU_ZERO(&cpuset);
119 CPU_SET(i, &cpuset);
120 int rc = pthread_setaffinity_np(threads[i].native_handle(),
121 sizeof(cpu_set_t), &cpuset);
122 if (rc != 0)
123 {
124 std::lock_guard<std::mutex> iolock(iomutex);
125 std::cerr << "Error calling pthread_setaffinity_np: " << rc << '\n';
126 }
127#endif
128 }
129
130 tm.start("Run");
131 barrier.store(false);
132
133 for (auto& t: threads)
134 t.join();
135 tm.stop("Run");
136
137 // Build the result
138 ec_stats result;
139 for (unsigned i = 0; i < nbth; ++i)
140 {
141 result.name.emplace_back(swarmed[i]->name());
142 result.walltime.emplace_back(swarmed[i]->walltime());
143 result.states.emplace_back(swarmed[i]->states());
144 result.transitions.emplace_back(swarmed[i]->transitions());
145 result.sccs.emplace_back(swarmed[i]->sccs());
146 result.value.emplace_back(swarmed[i]->result());
147 result.finisher.emplace_back(swarmed[i]->finisher());
148 }
149
150 if (trace)
151 {
152 bool go_on = true;
153 for (unsigned i = 0; i < nbth && go_on; ++i)
154 {
155 // Enumerate cases where a trace can be extracted
156 // Here we use a switch so that adding new algorithm
157 // with new return status will trigger an error that
158 // should then be fixed here.
159 switch (result.value[i])
160 {
161 // A (partial?) trace has been computed
164 result.trace = swarmed[i]->trace();
165 go_on = false;
166 break;
167
168 // Nothing to do here.
170 case mc_rvalue::EMPTY:
173 break;
174 }
175 }
176 }
177
178 for (unsigned i = 0; i < nbth; ++i)
179 {
180 delete swarmed[i];
181 delete ss[i];
182 }
183
184 return result;
185 }
186
187 template<typename kripke_ptr, typename State,
188 typename Iterator, typename Hash, typename Equal>
189 static ec_stats ec_instanciator(const mc_algorithm algo, kripke_ptr sys,
190 spot::twacube_ptr prop = nullptr,
191 bool trace = false)
192 {
193 if (algo == mc_algorithm::BLOEMEN_EC || algo == mc_algorithm::CNDFS ||
195 {
196 SPOT_ASSERT(prop != nullptr);
197 SPOT_ASSERT(sys->ap().size() == prop->ap().size());
198 for (unsigned int i = 0; i < sys->ap().size(); ++i)
199 SPOT_ASSERT(sys->ap()[i].compare(prop->ap()[i]) == 0);
200 }
201
202 switch (algo)
203 {
205 return instanciate<spot::swarmed_bloemen<State, Iterator, Hash, Equal>,
206 kripke_ptr, State, Iterator, Hash, Equal> (sys, prop, trace);
207
209 return
210 instanciate<spot::swarmed_bloemen_ec<State, Iterator, Hash, Equal>,
211 kripke_ptr, State, Iterator, Hash, Equal> (sys, prop, trace);
212
214 return instanciate<spot::swarmed_cndfs<State, Iterator, Hash, Equal>,
215 kripke_ptr, State, Iterator, Hash, Equal> (sys, prop, trace);
216
218 return instanciate
220 kripke_ptr, State, Iterator, Hash, Equal> (sys, prop, trace);
221
223 return instanciate
225 kripke_ptr, State, Iterator, Hash, Equal> (sys, prop, trace);
226
228 return instanciate<spot::lpar13<State, Iterator, Hash, Equal>,
229 kripke_ptr, State, Iterator, Hash, Equal> (sys, prop, trace);
230 }
231 SPOT_UNREACHABLE();
232 }
233}
This class aims to explore a model to detect whether it contains a deadlock. This deadlock detection ...
Definition deadlock.hh:47
A map of timer, where each timer has a name.
Definition timer.hh:231
void stop(const std::string &name)
Stop timer name.
Definition timer.hh:251
void start(const std::string &name)
Start a timer with name name.
Definition timer.hh:240
std::shared_ptr< kripke > kripke_ptr
Definition fwd.hh:36
std::shared_ptr< twacube > twacube_ptr
Definition fwd.hh:28
Definition automata.hh:26
mc_algorithm
The list of parallel model-checking algorithms available.
Definition mc.hh:39
@ CNDFS
Evangelista.12.atva emptiness check.
@ REACHABILITY
Only perform a reachability algorithm.
@ SWARMING
Holzmann.11.ieee applied to renault.13.lpar.
@ DEADLOCK
Check whether there is a deadlock.
@ BLOEMEN_SCC
Bloemen.16.ppopp SCC computation.
@ BLOEMEN_EC
Bloemen.16.hvc emptiness check.
@ NOT_EMPTY
The product is not empty.
@ NO_DEADLOCK
No deadlock has been found.
@ FAILURE
The algorithm finished abnormally.
@ DEADLOCK
A deadlock has been found.
@ EMPTY
The product is empty.
@ SUCCESS
The algorithm finished normally.

Please direct any question, comment, or bug report to the Spot mailing list at spot@lrde.epita.fr.
Generated on Fri Feb 27 2015 10:00:07 for spot by doxygen 1.9.8