+ read_map->put(location, read_from_val);
+
+ /* Store the memory locations where atomic reads happen */
+ bool push_loc = true;
+ ModelList<void *>::iterator it;
+ for (it = read_locations.begin();it != read_locations.end();it++) {
+ if (location == *it) {
+ push_loc = false;
+ break;
+ }
+ }
+
+ if (push_loc)
+ read_locations.push_back(location);
+}
+
+uint64_t FuncNode::query_last_read(ModelAction * act, uint32_t tid)
+{
+ if (thrd_read_map.size() <= tid)
+ return 0xdeadbeef;
+
+ read_map_t * read_map = thrd_read_map[tid];
+ void * location = act->get_location();
+
+ /* last read value not found */
+ if ( !read_map->contains(location) )
+ return 0xdeadbeef;
+
+ uint64_t read_val = read_map->get(location);
+ return read_val;
+}
+
+/* @param tid thread id
+ * Reset read map for a thread. This function shall only be called
+ * when a thread exits a function
+ */
+void FuncNode::clear_read_map(uint32_t tid)
+{
+ if (thrd_read_map.size() <= tid)
+ return;
+
+ thrd_read_map[tid]->reset();
+}
+
+/* @param tid thread id
+ * Print the values read by the last read actions for each memory location
+ */
+void FuncNode::print_last_read(uint32_t tid)
+{
+ ASSERT(thrd_read_map.size() > tid);
+ read_map_t * read_map = thrd_read_map[tid];
+
+ ModelList<void *>::iterator it;
+ for (it = read_locations.begin();it != read_locations.end();it++) {
+ if ( !read_map->contains(*it) )
+ break;
+
+ uint64_t read_val = read_map->get(*it);
+ model_print("last read of thread %d at %p: 0x%x\n", tid, *it, read_val);
+ }