move write_history to funcnode.cc and do experiment
[c11tester.git] / funcnode.cc
1 #include "funcnode.h"
2 #include "predicate.h"
3
4 FuncNode::FuncNode() :
5         func_inst_map(),
6         inst_list(),
7         entry_insts(),
8         thrd_read_map(),
9         write_history(),
10         write_locations()
11 {}
12
13 /* Check whether FuncInst with the same type, position, and location
14  * as act has been added to func_inst_map or not. If so, return it;
15  * if not, add it and return it.
16  *
17  * @return FuncInst with the same type, position, and location as act */
18 FuncInst * FuncNode::get_or_add_action(ModelAction *act)
19 {
20         ASSERT(act);
21         const char * position = act->get_position();
22
23         /* Actions THREAD_CREATE, THREAD_START, THREAD_YIELD, THREAD_JOIN,
24          * THREAD_FINISH, PTHREAD_CREATE, PTHREAD_JOIN,
25          * ATOMIC_LOCK, ATOMIC_TRYLOCK, and ATOMIC_UNLOCK are not tagged with their
26          * source line numbers
27          */
28         if (position == NULL)
29                 return NULL;
30
31         if ( func_inst_map.contains(position) ) {
32                 FuncInst * inst = func_inst_map.get(position);
33
34                 if (inst->get_type() != act->get_type() ) {
35                         // model_print("action with a different type occurs at line number %s\n", position);
36                         FuncInst * func_inst = inst->search_in_collision(act);
37
38                         if (func_inst != NULL) {
39                                 // return the FuncInst found in the collision list
40                                 return func_inst;
41                         }
42
43                         func_inst = new FuncInst(act, this);
44                         inst->get_collisions()->push_back(func_inst);
45                         inst_list.push_back(func_inst); // delete?
46
47                         return func_inst;
48                 }
49
50                 return inst;
51         }
52
53         FuncInst * func_inst = new FuncInst(act, this);
54
55         func_inst_map.put(position, func_inst);
56         inst_list.push_back(func_inst);
57
58         return func_inst;
59 }
60
61 void FuncNode::add_entry_inst(FuncInst * inst)
62 {
63         if (inst == NULL)
64                 return;
65
66         func_inst_list_mt::iterator it;
67         for (it = entry_insts.begin();it != entry_insts.end();it++) {
68                 if (inst == *it)
69                         return;
70         }
71
72         entry_insts.push_back(inst);
73 }
74
75 /* @param inst_list a list of FuncInsts; this argument comes from ModelExecution
76  * Link FuncInsts in a list - add one FuncInst to another's predecessors and successors
77  */
78 void FuncNode::link_insts(func_inst_list_t * inst_list)
79 {
80         if (inst_list == NULL)
81                 return;
82
83         func_inst_list_t::iterator it = inst_list->begin();
84         func_inst_list_t::iterator prev;
85
86         if (inst_list->size() == 0)
87                 return;
88
89         /* add the first instruction to the list of entry insts */
90         FuncInst * entry_inst = *it;
91         add_entry_inst(entry_inst);
92
93         it++;
94         while (it != inst_list->end()) {
95                 prev = it;
96                 prev--;
97
98                 FuncInst * prev_inst = *prev;
99                 FuncInst * curr_inst = *it;
100
101                 prev_inst->add_succ(curr_inst);
102                 curr_inst->add_pred(prev_inst);
103
104                 it++;
105         }
106 }
107
108 /* @param tid thread id
109  * Store the values read by atomic read actions into thrd_read_map */
110 void FuncNode::store_read(ModelAction * act, uint32_t tid)
111 {
112         ASSERT(act);
113
114         void * location = act->get_location();
115         uint64_t read_from_val = act->get_reads_from_value();
116
117         /* resize and initialize */
118         uint32_t old_size = thrd_read_map.size();
119         if (old_size <= tid) {
120                 thrd_read_map.resize(tid + 1);
121                 for (uint32_t i = old_size; i < tid + 1; i++)
122                         thrd_read_map[i] = new read_map_t();
123         }
124
125         read_map_t * read_map = thrd_read_map[tid];
126         read_map->put(location, read_from_val);
127
128         /* Store the memory locations where atomic reads happen */
129         // read_locations.add(location);
130 }
131
132 uint64_t FuncNode::query_last_read(void * location, uint32_t tid)
133 {
134         if (thrd_read_map.size() <= tid)
135                 return 0xdeadbeef;
136
137         read_map_t * read_map = thrd_read_map[tid];
138
139         /* last read value not found */
140         if ( !read_map->contains(location) )
141                 return 0xdeadbeef;
142
143         uint64_t read_val = read_map->get(location);
144         return read_val;
145 }
146
147 /* @param tid thread id
148  * Reset read map for a thread. This function shall only be called
149  * when a thread exits a function
150  */
151 void FuncNode::clear_read_map(uint32_t tid)
152 {
153         if (thrd_read_map.size() <= tid)
154                 return;
155
156         thrd_read_map[tid]->reset();
157 }
158
159 void FuncNode::add_to_write_history(void * location, uint64_t write_val)
160 {
161         write_set_t * write_set = write_history.get(location);
162
163         if (write_set == NULL) {
164                 write_set = new write_set_t();
165                 write_history.put(location, write_set);
166         }
167
168         write_set->add(write_val);
169         write_locations.add(location);
170 }
171
172 void FuncNode::generate_predicate(FuncInst *func_inst)
173 {
174         
175 }
176
177 /* @param tid thread id
178  * Print the values read by the last read actions for each memory location
179  */
180 void FuncNode::print_last_read(uint32_t tid)
181 {
182         ASSERT(thrd_read_map.size() > tid);
183         read_map_t * read_map = thrd_read_map[tid];
184 /*
185         ModelList<void *>::iterator it;
186         for (it = read_locations.begin();it != read_locations.end();it++) {
187                 if ( !read_map->contains(*it) )
188                         break;
189
190                 uint64_t read_val = read_map->get(*it);
191                 model_print("last read of thread %d at %p: 0x%x\n", tid, *it, read_val);
192         }
193 */
194 }
195
196 void FuncNode::print_write()
197 {
198         HSIterator<void *, uintptr_t, 4, model_malloc, model_calloc, model_free> * iter;
199         HSIterator<uint64_t, uint64_t, 0, model_malloc, model_calloc, model_free> * write_iter;
200         iter = write_locations.iterator();
201
202         if (write_locations.getSize() > 10) {
203                 while (iter->hasNext()) {
204                         void * location = iter->next();
205                         write_set_t * write_set = write_history.get(location);
206
207 //                      model_print("location: %p contains %d writes\n", location, write_set->getSize());
208                         if (write_set->getSize() > 5) {
209                                 model_print("location %p has writes: ", location);
210                                 write_iter = write_set->iterator();
211
212                                 while (write_iter->hasNext()) {
213                                         uint64_t val = write_iter->next();
214                                         model_print("%lx ", val);
215                                 }
216                                 model_print("\n");
217                         }
218                 }
219         } else {
220                 model_print("\n");
221         }
222         delete iter;
223 }