Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
implement CommTestTransition
[simgrid.git] / src / kernel / actor / SimcallObserver.hpp
1 /* Copyright (c) 2019-2022. 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 #ifndef SIMGRID_MC_SIMCALL_OBSERVER_HPP
7 #define SIMGRID_MC_SIMCALL_OBSERVER_HPP
8
9 #include "simgrid/forward.h"
10 #include "src/mc/api/Transition.hpp"
11 #include "xbt/asserts.h"
12
13 #include <string>
14
15 namespace simgrid {
16 namespace kernel {
17 namespace actor {
18
19 class SimcallObserver {
20   ActorImpl* const issuer_;
21
22 public:
23   explicit SimcallObserver(ActorImpl* issuer) : issuer_(issuer) {}
24   ActorImpl* get_issuer() const { return issuer_; }
25   /** Whether this transition can currently be taken without blocking.
26    *
27    * For example, a mutex_lock is not enabled when the mutex is not free.
28    * A comm_receive is not enabled before the corresponding send has been issued.
29    */
30   virtual bool is_enabled() const { return true; }
31
32   /** Returns the amount of time that this transition can be used.
33    *
34    * If it's 1 (as with send/wait), there is no need to fork the state space exploration on this point.
35    * If it's more than one (as with mc_random or waitany), we need to consider this transition several times to start
36    * differing branches
37    */
38   virtual int get_max_consider() const { return 1; }
39
40   /** Prepares the simcall to be used.
41    *
42    * For most simcalls, this does nothing. Once enabled, there is nothing to do to prepare a send().
43    *
44    * It is useful only for the simcalls that can be used several times, such as waitany() or random().
45    * For them, prepare() selects the right outcome for the time being considered.
46    *
47    * The first time a simcall is considered, times_considered is 0, not 1.
48    */
49   virtual void prepare(int times_considered)
50   { /* Nothing to do by default */
51   }
52
53   /** Computes the dependency relation */
54   virtual bool depends(SimcallObserver* other);
55
56   /** Serialize to the given string buffer */
57   virtual void serialize(mc::Transition::Type& type, std::stringstream& stream)
58   {
59     type = mc::Transition::Type::UNKNOWN;
60   }
61
62   /** Some simcalls may only be observable under some conditions.
63    * Most simcalls are not visible from the MC because they don't have an observer at all. */
64   virtual bool is_visible() const { return true; }
65 };
66
67 template <class T> class ResultingSimcall : public SimcallObserver {
68   T result_;
69
70 public:
71   ResultingSimcall() = default;
72   ResultingSimcall(ActorImpl* actor, T default_result) : SimcallObserver(actor), result_(default_result) {}
73   void set_result(T res) { result_ = res; }
74   T get_result() const { return result_; }
75 };
76
77 class RandomSimcall : public SimcallObserver {
78   const int min_;
79   const int max_;
80   int next_value_ = 0;
81
82 public:
83   RandomSimcall(ActorImpl* actor, int min, int max) : SimcallObserver(actor), min_(min), max_(max)
84   {
85     xbt_assert(min < max);
86   }
87   void serialize(mc::Transition::Type& type, std::stringstream& stream) override;
88   int get_max_consider() const override;
89   void prepare(int times_considered) override;
90   int get_value() const { return next_value_; }
91   bool depends(SimcallObserver* other) override;
92 };
93
94 class MutexSimcall : public SimcallObserver {
95   activity::MutexImpl* const mutex_;
96
97 public:
98   MutexSimcall(ActorImpl* actor, activity::MutexImpl* mutex) : SimcallObserver(actor), mutex_(mutex) {}
99   activity::MutexImpl* get_mutex() const { return mutex_; }
100   bool depends(SimcallObserver* other) override;
101 };
102
103 class MutexUnlockSimcall : public MutexSimcall {
104   using MutexSimcall::MutexSimcall;
105 };
106
107 class MutexLockSimcall : public MutexSimcall {
108   const bool blocking_;
109
110 public:
111   MutexLockSimcall(ActorImpl* actor, activity::MutexImpl* mutex, bool blocking = true)
112       : MutexSimcall(actor, mutex), blocking_(blocking)
113   {
114   }
115   bool is_enabled() const override;
116 };
117
118 class ConditionWaitSimcall : public ResultingSimcall<bool> {
119   activity::ConditionVariableImpl* const cond_;
120   activity::MutexImpl* const mutex_;
121   const double timeout_;
122
123 public:
124   ConditionWaitSimcall(ActorImpl* actor, activity::ConditionVariableImpl* cond, activity::MutexImpl* mutex,
125                        double timeout = -1.0)
126       : ResultingSimcall(actor, false), cond_(cond), mutex_(mutex), timeout_(timeout)
127   {
128   }
129   bool is_enabled() const override;
130   bool is_visible() const override { return false; }
131   activity::ConditionVariableImpl* get_cond() const { return cond_; }
132   activity::MutexImpl* get_mutex() const { return mutex_; }
133   double get_timeout() const { return timeout_; }
134 };
135
136 class SemAcquireSimcall : public ResultingSimcall<bool> {
137   activity::SemaphoreImpl* const sem_;
138   const double timeout_;
139
140 public:
141   SemAcquireSimcall(ActorImpl* actor, activity::SemaphoreImpl* sem, double timeout = -1.0)
142       : ResultingSimcall(actor, false), sem_(sem), timeout_(timeout)
143   {
144   }
145   bool is_enabled() const override;
146   bool is_visible() const override { return false; }
147   activity::SemaphoreImpl* get_sem() const { return sem_; }
148   double get_timeout() const { return timeout_; }
149 };
150
151 class ActivityTestSimcall : public ResultingSimcall<bool> {
152   activity::ActivityImpl* const activity_;
153
154 public:
155   ActivityTestSimcall(ActorImpl* actor, activity::ActivityImpl* activity)
156       : ResultingSimcall(actor, true), activity_(activity)
157   {
158   }
159   bool is_visible() const override { return true; }
160   activity::ActivityImpl* get_activity() const { return activity_; }
161   void serialize(mc::Transition::Type& type, std::stringstream& stream) override;
162 };
163
164 class ActivityTestanySimcall : public ResultingSimcall<ssize_t> {
165   const std::vector<activity::ActivityImpl*>& activities_;
166   int next_value_ = 0;
167
168 public:
169   ActivityTestanySimcall(ActorImpl* actor, const std::vector<activity::ActivityImpl*>& activities)
170       : ResultingSimcall(actor, -1), activities_(activities)
171   {
172   }
173   bool is_visible() const override { return true; }
174   int get_max_consider() const override;
175   void prepare(int times_considered) override;
176   const std::vector<activity::ActivityImpl*>& get_activities() const { return activities_; }
177   int get_value() const { return next_value_; }
178 };
179
180 class ActivityWaitSimcall : public ResultingSimcall<bool> {
181   activity::ActivityImpl* activity_;
182   const double timeout_;
183
184 public:
185   ActivityWaitSimcall(ActorImpl* actor, activity::ActivityImpl* activity, double timeout)
186       : ResultingSimcall(actor, false), activity_(activity), timeout_(timeout)
187   {
188   }
189   void serialize(mc::Transition::Type& type, std::stringstream& stream) override;
190   bool is_visible() const override { return true; }
191   bool is_enabled() const override;
192   activity::ActivityImpl* get_activity() const { return activity_; }
193   void set_activity(activity::ActivityImpl* activity) { activity_ = activity; }
194   double get_timeout() const { return timeout_; }
195 };
196
197 class ActivityWaitanySimcall : public ResultingSimcall<ssize_t> {
198   const std::vector<activity::ActivityImpl*>& activities_;
199   const double timeout_;
200   int next_value_ = 0;
201
202 public:
203   ActivityWaitanySimcall(ActorImpl* actor, const std::vector<activity::ActivityImpl*>& activities, double timeout)
204       : ResultingSimcall(actor, -1), activities_(activities), timeout_(timeout)
205   {
206   }
207   bool is_enabled() const override;
208   bool is_visible() const override { return true; }
209   void prepare(int times_considered) override;
210   int get_max_consider() const override;
211   const std::vector<activity::ActivityImpl*>& get_activities() const { return activities_; }
212   double get_timeout() const { return timeout_; }
213   int get_value() const { return next_value_; }
214 };
215
216 class CommIsendSimcall : public SimcallObserver {
217   activity::MailboxImpl* mbox_;
218   double payload_size_;
219   double rate_;
220   unsigned char* src_buff_;
221   size_t src_buff_size_;
222   void* payload_;
223   bool detached_;
224
225 public:
226   bool (*match_fun_)(void*, void*, activity::CommImpl*);
227   void (*clean_fun_)(void*); // used to free the synchro in case of problem after a detached send
228   void (*copy_data_fun_)(activity::CommImpl*, void*, size_t); // used to copy data if not default one
229
230   CommIsendSimcall(ActorImpl* actor, activity::MailboxImpl* mbox, double payload_size, double rate,
231                    unsigned char* src_buff, size_t src_buff_size, bool (*match_fun)(void*, void*, activity::CommImpl*),
232                    void (*clean_fun)(void*), // used to free the synchro in case of problem after a detached send
233                    void (*copy_data_fun)(activity::CommImpl*, void*, size_t), // used to copy data if not default one
234                    void* payload, bool detached)
235       : SimcallObserver(actor)
236       , mbox_(mbox)
237       , payload_size_(payload_size)
238       , rate_(rate)
239       , src_buff_(src_buff)
240       , src_buff_size_(src_buff_size)
241       , payload_(payload)
242       , detached_(detached)
243       , match_fun_(match_fun)
244       , clean_fun_(clean_fun)
245       , copy_data_fun_(copy_data_fun)
246   {
247   }
248   void serialize(mc::Transition::Type& type, std::stringstream& stream) override;
249   bool is_visible() const override { return true; }
250   activity::MailboxImpl* get_mailbox() const { return mbox_; }
251   double get_payload_size() const { return payload_size_; }
252   double get_rate() const { return rate_; }
253   unsigned char* get_src_buff() const { return src_buff_; }
254   size_t get_src_buff_size() const { return src_buff_size_; }
255   void* get_payload() const { return payload_; }
256   bool is_detached() const { return detached_; }
257 };
258
259 class CommIrecvSimcall : public SimcallObserver {
260   activity::MailboxImpl* mbox_;
261   unsigned char* dst_buff_;
262   size_t* dst_buff_size_;
263   void* payload_;
264   double rate_;
265
266 public:
267   bool (*match_fun_)(void*, void*, activity::CommImpl*);
268   void (*copy_data_fun_)(activity::CommImpl*, void*, size_t); // used to copy data if not default one
269
270   CommIrecvSimcall(ActorImpl* actor, activity::MailboxImpl* mbox, unsigned char* dst_buff, size_t* dst_buff_size,
271                    bool (*match_fun)(void*, void*, activity::CommImpl*),
272                    void (*copy_data_fun)(activity::CommImpl*, void*, size_t), void* payload, double rate)
273       : SimcallObserver(actor)
274       , mbox_(mbox)
275       , dst_buff_(dst_buff)
276       , dst_buff_size_(dst_buff_size)
277       , payload_(payload)
278       , rate_(rate)
279       , match_fun_(match_fun)
280       , copy_data_fun_(copy_data_fun)
281   {
282   }
283   void serialize(mc::Transition::Type& type, std::stringstream& stream) override;
284   bool is_visible() const override { return true; }
285   activity::MailboxImpl* get_mailbox() const { return mbox_; }
286   double get_rate() const { return rate_; }
287   unsigned char* get_dst_buff() const { return dst_buff_; }
288   size_t* get_dst_buff_size() const { return dst_buff_size_; }
289   void* get_payload() const { return payload_; }
290 };
291
292 } // namespace actor
293 } // namespace kernel
294 } // namespace simgrid
295
296 #endif