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