Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
get rid of simix_global and smx_private.hpp
[simgrid.git] / src / kernel / actor / SimcallObserver.cpp
1 /* Copyright (c) 2019-2021. The SimGrid Team. All rights reserved.          */
2
3 /* This program is free software; you can redistribute it and/or modify it
4  * under the terms of the license (GNU LGPL) which comes with this package. */
5
6 #include "src/kernel/actor/SimcallObserver.hpp"
7 #include "simgrid/s4u/Host.hpp"
8 #include "src/kernel/activity/MutexImpl.hpp"
9 #include "src/kernel/actor/ActorImpl.hpp"
10
11 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(mc_observer, mc, "Logging specific to MC simcall observation");
12
13 namespace simgrid {
14 namespace kernel {
15 namespace actor {
16
17 bool SimcallObserver::depends(SimcallObserver* other)
18 {
19   THROW_UNIMPLEMENTED;
20 }
21 /* Random is only dependent when issued by the same actor (ie, always independent) */
22 bool RandomSimcall::depends(SimcallObserver* other)
23 {
24   return get_issuer() == other->get_issuer();
25 }
26 bool MutexSimcall::depends(SimcallObserver* other)
27 {
28   if (dynamic_cast<RandomSimcall*>(other) != nullptr)
29     return other->depends(this); /* Other is random, that is very permissive. Use that relation instead. */
30
31 #if 0 /* This code is currently broken and shouldn't be used. We must implement asynchronous locks before */
32   MutexSimcall* that = dynamic_cast<MutexSimcall*>(other);
33   if (that == nullptr)
34     return true; // Depends on anything we don't know
35
36   /* Theorem 4.4.7: Any pair of synchronization actions of distinct actors concerning distinct mutexes are independent */
37   if (this->get_issuer() != that->get_issuer() && this->get_mutex() != that->get_mutex())
38     return false;
39
40   /* Theorem 4.4.8 An AsyncMutexLock is independent with a MutexUnlock of another actor */
41   if (((dynamic_cast<MutexLockSimcall*>(this) != nullptr && dynamic_cast<MutexUnlockSimcall*>(that)) ||
42        (dynamic_cast<MutexLockSimcall*>(that) != nullptr && dynamic_cast<MutexUnlockSimcall*>(this))) &&
43       get_issuer() != other->get_issuer())
44     return false;
45 #endif
46   return true; // Depend on things we don't know for sure that they are independent
47 }
48
49 std::string SimcallObserver::to_string(int /*times_considered*/) const
50 {
51   return simgrid::xbt::string_printf("[(%ld)%s (%s)] ", issuer_->get_pid(), issuer_->get_host()->get_cname(),
52                                      issuer_->get_cname());
53 }
54
55 std::string SimcallObserver::dot_label() const
56 {
57   if (issuer_->get_host())
58     return xbt::string_printf("[(%ld)%s] ", issuer_->get_pid(), issuer_->get_cname());
59   return xbt::string_printf("[(%ld)] ", issuer_->get_pid());
60 }
61
62 std::string RandomSimcall::to_string(int times_considered) const
63 {
64   return SimcallObserver::to_string(times_considered) + "MC_RANDOM(" + std::to_string(times_considered) + ")";
65 }
66
67 std::string RandomSimcall::dot_label() const
68 {
69   return SimcallObserver::dot_label() + "MC_RANDOM(" + std::to_string(next_value_) + ")";
70 }
71
72 void RandomSimcall::prepare(int times_considered)
73 {
74   next_value_ = min_ + times_considered;
75   XBT_DEBUG("MC_RANDOM(%d, %d) will return %d after %d times", min_, max_, next_value_, times_considered);
76 }
77
78 int RandomSimcall::get_max_consider() const
79 {
80   return max_ - min_ + 1;
81 }
82
83 std::string MutexUnlockSimcall::to_string(int times_considered) const
84 {
85   return SimcallObserver::to_string(times_considered) + "Mutex UNLOCK";
86 }
87
88 std::string MutexUnlockSimcall::dot_label() const
89 {
90   return SimcallObserver::dot_label() + "Mutex UNLOCK";
91 }
92
93 std::string MutexLockSimcall::to_string(int times_considered) const
94 {
95   auto mutex      = get_mutex();
96   std::string res = SimcallObserver::to_string(times_considered) + (blocking_ ? "Mutex LOCK" : "Mutex TRYLOCK");
97   res += "(locked = " + std::to_string(mutex->is_locked());
98   res += ", owner = " + std::to_string(mutex->get_owner() ? mutex->get_owner()->get_pid() : -1);
99   res += ", sleeping = n/a)";
100   return res;
101 }
102
103 std::string MutexLockSimcall::dot_label() const
104 {
105   return SimcallObserver::dot_label() + (blocking_ ? "Mutex LOCK" : "Mutex TRYLOCK");
106 }
107
108 bool MutexLockSimcall::is_enabled() const
109 {
110   return not blocking_ || get_mutex()->get_owner() == nullptr || get_mutex()->get_owner() == get_issuer();
111 }
112
113 std::string ConditionWaitSimcall::to_string(int times_considered) const
114 {
115   std::string res = SimcallObserver::to_string(times_considered) + "Condition WAIT";
116   res += "(" + (timeout_ == -1.0 ? "" : std::to_string(timeout_)) + ")";
117   return res;
118 }
119
120 std::string ConditionWaitSimcall::dot_label() const
121 {
122   return SimcallObserver::dot_label() + "Condition WAIT";
123 }
124
125 bool ConditionWaitSimcall::is_enabled() const
126 {
127   static bool warned = false;
128   if (not warned) {
129     XBT_INFO("Using condition variables in model-checked code is still experimental. Use at your own risk");
130     warned = true;
131   }
132   return true;
133 }
134
135 std::string SemAcquireSimcall::to_string(int times_considered) const
136 {
137   std::string res = SimcallObserver::to_string(times_considered) + "Sem ACQUIRE";
138   res += "(" + (timeout_ == -1.0 ? "" : std::to_string(timeout_)) + ")";
139   return res;
140 }
141
142 std::string SemAcquireSimcall::dot_label() const
143 {
144   return SimcallObserver::dot_label() + "Sem ACQUIRE";
145 }
146
147 bool SemAcquireSimcall::is_enabled() const
148 {
149   static bool warned = false;
150   if (not warned) {
151     XBT_INFO("Using semaphore in model-checked code is still experimental. Use at your own risk");
152     warned = true;
153   }
154   return true;
155 }
156
157 std::string ExecutionWaitanySimcall::to_string(int times_considered) const
158 {
159   std::string res = SimcallObserver::to_string(times_considered) + "Execution WAITANY";
160   res += "(" + (timeout_ == -1.0 ? "" : std::to_string(timeout_)) + ")";
161   return res;
162 }
163
164 std::string ExecutionWaitanySimcall::dot_label() const
165 {
166   return SimcallObserver::dot_label() + "Execution WAITANY";
167 }
168
169 std::string IoWaitanySimcall::to_string(int times_considered) const
170 {
171   std::string res = SimcallObserver::to_string(times_considered) + "I/O WAITANY";
172   res += "(" + (timeout_ == -1.0 ? "" : std::to_string(timeout_)) + ")";
173   return res;
174 }
175
176 std::string IoWaitanySimcall::dot_label() const
177 {
178   return SimcallObserver::dot_label() + "I/O WAITANY";
179 }
180
181 } // namespace actor
182 } // namespace kernel
183 } // namespace simgrid