+ std::vector<action_list_t> *thrd_lists = &(*obj_thrd_map)[curr->get_location()];
+ unsigned int i;
+ ASSERT(curr->is_read());
+
+ ModelAction *last_seq_cst = NULL;
+
+ /* Track whether this object has been initialized */
+ bool initialized = false;
+
+ if (curr->is_seqcst()) {
+ last_seq_cst = get_last_seq_cst(curr->get_location());
+ /* We have to at least see the last sequentially consistent write,
+ so we are initialized. */
+ if (last_seq_cst != NULL)
+ initialized = true;
+ }
+
+ /* Iterate over all threads */
+ for (i = 0; i < thrd_lists->size(); i++) {
+ /* Iterate over actions in thread, starting from most recent */
+ action_list_t *list = &(*thrd_lists)[i];
+ action_list_t::reverse_iterator rit;
+ for (rit = list->rbegin(); rit != list->rend(); rit++) {
+ ModelAction *act = *rit;
+
+ /* Only consider 'write' actions */
+ if (!act->is_write())
+ continue;
+
+ /* Don't consider more than one seq_cst write if we are a seq_cst read. */
+ if (!act->is_seqcst() || !curr->is_seqcst() || act == last_seq_cst) {
+ DEBUG("Adding action to may_read_from:\n");
+ if (DBG_ENABLED()) {
+ act->print();
+ curr->print();
+ }
+ curr->get_node()->add_read_from(act);
+ }
+
+ /* Include at most one act per-thread that "happens before" curr */
+ if (act->happens_before(curr)) {
+ initialized = true;
+ break;
+ }
+ }
+ }
+
+ if (!initialized) {
+ /* TODO: need a more informative way of reporting errors */
+ printf("ERROR: may read from uninitialized atomic\n");