model: correct the "no valid reads" assertion
[model-checker.git] / promise.cc
1 #define __STDC_FORMAT_MACROS
2 #include <inttypes.h>
3
4 #include "promise.h"
5 #include "model.h"
6 #include "schedule.h"
7 #include "action.h"
8 #include "threads-model.h"
9
10 /**
11  * @brief Promise constructor
12  * @param read The read which reads from a promised future value
13  * @param fv The future value that is promised
14  */
15 Promise::Promise(ModelAction *read, struct future_value fv) :
16         num_available_threads(0),
17         fv(fv),
18         read(read),
19         write(NULL)
20 {
21         add_thread(fv.tid);
22         eliminate_thread(read->get_tid());
23 }
24
25 /**
26  * Eliminate a thread which no longer can satisfy this promise. Once all
27  * enabled threads have been eliminated, this promise is unresolvable.
28  *
29  * @param tid The thread ID of the thread to eliminate
30  * @return True, if this elimination has invalidated the promise; false
31  * otherwise
32  */
33 bool Promise::eliminate_thread(thread_id_t tid)
34 {
35         unsigned int id = id_to_int(tid);
36         if (!thread_is_available(tid))
37                 return false;
38
39         available_thread[id] = false;
40         num_available_threads--;
41         return has_failed();
42 }
43
44 /**
45  * Add a thread which may resolve this promise
46  *
47  * @param tid The thread ID
48  */
49 void Promise::add_thread(thread_id_t tid)
50 {
51         unsigned int id = id_to_int(tid);
52         if (id >= available_thread.size())
53                 available_thread.resize(id + 1, false);
54         if (!available_thread[id]) {
55                 available_thread[id] = true;
56                 num_available_threads++;
57         }
58 }
59
60 /**
61  * Check if a thread is available for resolving this promise. That is, the
62  * thread must have been previously marked for resolving this promise, and it
63  * cannot have been eliminated due to synchronization, etc.
64  *
65  * @param tid Thread ID of the thread to check
66  * @return True if the thread is available; false otherwise
67  */
68 bool Promise::thread_is_available(thread_id_t tid) const
69 {
70         unsigned int id = id_to_int(tid);
71         if (id >= available_thread.size())
72                 return false;
73         return available_thread[id];
74 }
75
76 /** @brief Print debug info about the Promise */
77 void Promise::print() const
78 {
79         model_print("Promised value %#" PRIx64 ", read from thread %d, available threads to resolve: ", fv.value, id_to_int(read->get_tid()));
80         for (unsigned int i = 0; i < available_thread.size(); i++)
81                 if (available_thread[i])
82                         model_print("[%d]", i);
83         model_print("\n");
84 }
85
86 /**
87  * Check if this promise has failed. A promise can fail when all threads which
88  * could possibly satisfy the promise have been eliminated.
89  *
90  * @return True, if this promise has failed; false otherwise
91  */
92 bool Promise::has_failed() const
93 {
94         return num_available_threads == 0;
95 }
96
97 /**
98  * @brief Check if an action's thread and location are compatible for resolving
99  * this promise
100  * @param act The action to check against
101  * @return True if we are compatible; false otherwise
102  */
103 bool Promise::is_compatible(const ModelAction *act) const
104 {
105         return thread_is_available(act->get_tid()) && read->same_var(act);
106 }
107
108 /**
109  * @brief Check if an action's thread and location are compatible for resolving
110  * this promise, and that the promise is thread-exclusive
111  * @param act The action to check against
112  * @return True if we are compatible and exclusive; false otherwise
113  */
114 bool Promise::is_compatible_exclusive(const ModelAction *act) const
115 {
116         return get_num_available_threads() == 1 && is_compatible(act);
117 }