Some edits
[c11tester.git] / waitobj.cc
1 #include "waitobj.h"
2 #include "threads-model.h"
3 #include "funcnode.h"
4
5 WaitObj::WaitObj(thread_id_t tid) :
6         tid(tid),
7         waiting_for(32),
8         waited_by(32),
9         thrd_dist_maps(),
10         thrd_target_nodes(),
11         thrd_action_counters()
12 {}
13
14 WaitObj::~WaitObj()
15 {
16         for (uint i = 0; i < thrd_dist_maps.size(); i++)
17                 delete thrd_dist_maps[i];
18
19         for (uint i = 0; i < thrd_target_nodes.size(); i++)
20                 delete thrd_target_nodes[i];
21 }
22
23 void WaitObj::add_waiting_for(thread_id_t other, FuncNode * node, int dist)
24 {
25         waiting_for.add(other);
26
27         dist_map_t * dist_map = getDistMap(other);
28         dist_map->put(node, dist);
29
30         node_set_t * target_nodes = getTargetNodes(other);
31         target_nodes->add(node);
32 }
33
34 void WaitObj::add_waited_by(thread_id_t other)
35 {
36         waited_by.add(other);
37 }
38
39 /**
40  * Stop waiting for the thread to reach the target node
41  *
42  * @param other The thread to be removed
43  * @param node The target node
44  * @return true if "other" is removed from waiting_for set
45  *         false if only a target node of "other" is removed
46  */
47 bool WaitObj::remove_waiting_for_node(thread_id_t other, FuncNode * node)
48 {
49         dist_map_t * dist_map = getDistMap(other);
50         dist_map->remove(node);
51
52         node_set_t * target_nodes = getTargetNodes(other);
53         target_nodes->remove(node);
54
55         /* The thread has no nodes to reach */
56         if (target_nodes->isEmpty()) {
57                 int index = id_to_int(other);
58                 thrd_action_counters[index] = 0;
59                 waiting_for.remove(other);
60
61                 return true;
62         }
63
64         return false;
65 }
66
67 /* Stop waiting for the thread */
68 void WaitObj::remove_waiting_for(thread_id_t other)
69 {
70         waiting_for.remove(other);
71
72         // TODO: clear dist_map or not?
73         /* dist_map_t * dist_map = getDistMap(other);
74            dist_map->reset(); */
75
76         node_set_t * target_nodes = getTargetNodes(other);
77         target_nodes->reset();
78
79         int index = id_to_int(other);
80         thrd_action_counters[index] = 0;
81 }
82
83 void WaitObj::remove_waited_by(thread_id_t other)
84 {
85         waited_by.remove(other);
86 }
87
88 int WaitObj::lookup_dist(thread_id_t tid, FuncNode * target)
89 {
90         dist_map_t * map = getDistMap(tid);
91         node_set_t * node_set = getTargetNodes(tid);
92
93         /* thrd_dist_maps is not reset when clear_waiting_for is called,
94          * so node_set should be checked */
95         if (node_set->contains(target) && map->contains(target))
96                 return map->get(target);
97
98         return -1;
99 }
100
101 dist_map_t * WaitObj::getDistMap(thread_id_t tid)
102 {
103         int thread_id = id_to_int(tid);
104         int old_size = thrd_dist_maps.size();
105
106         if (old_size <= thread_id) {
107                 thrd_dist_maps.resize(thread_id + 1);
108                 for (int i = old_size; i < thread_id + 1; i++) {
109                         thrd_dist_maps[i] = new dist_map_t(16);
110                 }
111         }
112
113         return thrd_dist_maps[thread_id];
114 }
115
116 node_set_t * WaitObj::getTargetNodes(thread_id_t tid)
117 {
118         int thread_id = id_to_int(tid);
119         int old_size = thrd_target_nodes.size();
120
121         if (old_size <= thread_id) {
122                 thrd_target_nodes.resize(thread_id + 1);
123                 for (int i = old_size; i < thread_id + 1; i++) {
124                         thrd_target_nodes[i] = new node_set_t(16);
125                 }
126         }
127
128         return thrd_target_nodes[thread_id];
129 }
130
131 /**
132  * Increment action counter for thread tid
133  * @return true if the counter for tid expires
134  */
135 bool WaitObj::incr_counter(thread_id_t tid)
136 {
137         int thread_id = id_to_int(tid);
138
139         /* thrd_action_counters.resize does not work here */
140         while (thrd_action_counters.size() <= (uint) thread_id) {
141                 thrd_action_counters.push_back(0);
142         }
143
144         thrd_action_counters[thread_id]++;
145         if (thrd_action_counters[thread_id] > 1000)
146                 return true;
147
148         return false;
149 }
150
151 void WaitObj::clear_waiting_for()
152 {
153         thrd_id_set_iter * iter = waiting_for.iterator();
154         while (iter->hasNext()) {
155                 thread_id_t tid = iter->next();
156                 int index = id_to_int(tid);
157                 thrd_action_counters[index] = 0;
158
159                 /* thrd_dist_maps are not reset because distances
160                  * will be overwritten when node targets are added
161                  * thrd_dist_maps[index]->reset(); */
162
163                 node_set_t * target_nodes = getTargetNodes(tid);
164                 target_nodes->reset();
165         }
166
167         waiting_for.reset();
168         /* waited_by relation should be kept */
169 }
170
171 void WaitObj::print_waiting_for(bool verbose)
172 {
173         if (waiting_for.getSize() == 0)
174                 return;
175
176         model_print("thread %d is waiting for: ", tid);
177         thrd_id_set_iter * it = waiting_for.iterator();
178
179         while (it->hasNext()) {
180                 thread_id_t waiting_for_id = it->next();
181                 model_print("%d ", waiting_for_id);
182         }
183         model_print("\n");
184
185         if (verbose) {
186                 /* Print out the distances from each thread to target nodes */
187                 model_print("\t");
188                 for (uint i = 0; i < thrd_target_nodes.size(); i++) {
189                         dist_map_t * dist_map = getDistMap(i);
190                         node_set_t * node_set = getTargetNodes(i);
191                         node_set_iter * node_iter = node_set->iterator();
192
193                         if (!node_set->isEmpty()) {
194                                 model_print("[thread %d](", int_to_id(i));
195
196                                 while (node_iter->hasNext()){
197                                         FuncNode * node = node_iter->next();
198                                         int dist = dist_map->get(node);
199                                         model_print("node %d: %d, ", node->get_func_id(), dist);
200                                 }
201                                 model_print(") ");
202                         }
203                 }
204                 model_print("\n");
205         }
206 }
207
208 void WaitObj::print_waited_by()
209 {
210         if (waited_by.getSize() == 0)
211                 return;
212
213         model_print("thread %d is waited by: ", tid);
214         thrd_id_set_iter * it = waited_by.iterator();
215
216         while (it->hasNext()) {
217                 thread_id_t thread_id = it->next();
218                 model_print("%d ", thread_id);
219         }
220         model_print("\n");
221 }