num_executions(0),
num_feasible_executions(0),
diverge(NULL),
+ earliest_diverge(NULL),
action_trace(new action_list_t()),
thread_map(new HashTable<int, Thread *, int>()),
obj_map(new HashTable<const void *, action_list_t, uintptr_t, 4>()),
ModelAction *next = node_stack->get_next()->get_action();
if (next == diverge) {
+ if (earliest_diverge == NULL || *diverge < *earliest_diverge)
+ earliest_diverge=diverge;
+
Node *nextnode = next->get_node();
/* Reached divergence point */
if (nextnode->increment_promise()) {
Node *node = nextnode->get_parent();
tid = node->get_next_backtrack();
node_stack->pop_restofstack(1);
+ if (diverge==earliest_diverge) {
+ earliest_diverge=node->get_action();
+ }
}
DEBUG("*** Divergence point ***\n");
+
diverge = NULL;
} else {
tid = next->get_tid();
DBG();
num_executions++;
- if (isfinalfeasible())
+ if (isfinalfeasible()) {
+ printf("Earliest divergence point since last feasible execution:\n");
+ if (earliest_diverge)
+ earliest_diverge->print();
+ else
+ printf("(Not set)\n");
+
+ earliest_diverge = NULL;
num_feasible_executions++;
+ }
if (isfinalfeasible() || DBG_ENABLED())
print_summary();
/* Discard duplicate ModelAction; use action from NodeStack */
delete curr;
- /* If we have diverged, we need to reset the clock vector. */
- if (diverge == NULL) {
- newcurr->create_cv(get_parent_action(newcurr->get_tid()));
- }
+ /* Always compute new clock vector */
+ newcurr->create_cv(get_parent_action(newcurr->get_tid()));
} else {
newcurr = curr;
+
+ /* Always compute new clock vector */
+ newcurr->create_cv(get_parent_action(newcurr->get_tid()));
/*
* Perform one-time actions when pushing new ModelAction onto
* NodeStack
*/
- curr->create_cv(get_parent_action(curr->get_tid()));
- if (curr->is_write())
- compute_promises(curr);
+ if (newcurr->is_write())
+ compute_promises(newcurr);
}
return newcurr;
}
bool updated = false;
if (act->is_read()) {
- if (r_modification_order(act, act->get_reads_from()))
+ const ModelAction *rf = act->get_reads_from();
+ if (rf != NULL && r_modification_order(act, rf))
updated = true;
}
if (act->is_write()) {
action_list_t::reverse_iterator rit;
ModelAction *lastact = NULL;
- /* Find last action that happens after curr */
+ /* Find last action that happens after curr that is either not curr or a rmw */
for (rit = list->rbegin(); rit != list->rend(); rit++) {
ModelAction *act = *rit;
- if (curr->happens_before(act)) {
+ if (curr->happens_before(act) && (curr != act || curr->is_rmw())) {
lastact = act;
} else
break;
/* Include at most one act per-thread that "happens before" curr */
if (lastact != NULL) {
- if (lastact->is_read()) {
+ if (lastact==curr) {
+ //Case 1: The resolved read is a RMW, and we need to make sure
+ //that the write portion of the RMW mod order after rf
+
+ mo_graph->addEdge(rf, lastact);
+ } else if (lastact->is_read()) {
+ //Case 2: The resolved read is a normal read and the next
+ //operation is a read, and we need to make sure the value read
+ //is mod ordered after rf
+
const ModelAction *postreadfrom = lastact->get_reads_from();
if (postreadfrom != NULL&&rf != postreadfrom)
mo_graph->addEdge(rf, postreadfrom);
- } else if (rf != lastact) {
- mo_graph->addEdge(rf, lastact);
+ } else {
+ //Case 3: The resolved read is a normal read and the next
+ //operation is a write, and we need to make sure that the
+ //write is mod ordered after rf
+ if (lastact!=rf)
+ mo_graph->addEdge(rf, lastact);
}
break;
}
printf("---------------------------------------------------------------------\n");
}
+#if SUPPORT_MOD_ORDER_DUMP
+void ModelChecker::dumpGraph(char *filename) {
+ char buffer[200];
+ sprintf(buffer, "%s.dot",filename);
+ FILE *file=fopen(buffer, "w");
+ fprintf(file, "digraph %s {\n",filename);
+ mo_graph->dumpNodes(file);
+ ModelAction ** thread_array=(ModelAction **)model_calloc(1, sizeof(ModelAction *)*get_num_threads());
+
+ for (action_list_t::iterator it = action_trace->begin(); it != action_trace->end(); it++) {
+ ModelAction *action=*it;
+ if (action->is_read()) {
+ fprintf(file, "N%u [label=\"%u, T%u\"];\n", action->get_seq_number(),action->get_seq_number(), action->get_tid());
+ fprintf(file, "N%u -> N%u[label=\"rf\", color=red];\n", action->get_seq_number(), action->get_reads_from()->get_seq_number());
+ }
+ if (thread_array[action->get_tid()] != NULL) {
+ fprintf(file, "N%u -> N%u[label=\"sb\", color=blue];\n", thread_array[action->get_tid()]->get_seq_number(), action->get_seq_number());
+ }
+
+ thread_array[action->get_tid()]=action;
+ }
+ fprintf(file,"}\n");
+ model_free(thread_array);
+ fclose(file);
+}
+#endif
+
void ModelChecker::print_summary()
{
printf("\n");
char buffername[100];
sprintf(buffername, "exec%04u", num_executions);
mo_graph->dumpGraphToFile(buffername);
+ sprintf(buffername, "graph%04u", num_executions);
+ dumpGraph(buffername);
#endif
if (!isfinalfeasible())