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