From: Brian Norris <banorris@uci.edu>
Date: Tue, 4 Dec 2012 02:30:18 +0000 (-0800)
Subject: model: add process_fence()
X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=53f0d3f9d56fd6341ef725ce8651661d6d9d906e;p=cdsspec-compiler.git

model: add process_fence()

process_fence() will only handle fence-acquire. Fence-relaxed is a
no-op; fence-release is only logged for later use; and fence-seq-cst
takes release/acquire semantics, plus some mo-graph rules which apply to
reads/reads (see {r,w}_modification_order).
---

diff --git a/model.cc b/model.cc
index dbca58e..6120f4d 100644
--- a/model.cc
+++ b/model.cc
@@ -858,6 +858,54 @@ bool ModelChecker::process_write(ModelAction *curr)
 	return updated_mod_order || updated_promises;
 }
 
+/**
+ * Process a fence ModelAction
+ * @param curr The ModelAction to process
+ * @return True if synchronization was updated
+ */
+bool ModelChecker::process_fence(ModelAction *curr)
+{
+	/*
+	 * fence-relaxed: no-op
+	 * fence-release: only log the occurence (not in this function), for
+	 *   use in later synchronization
+	 * fence-acquire (this function): search for hypothetical release
+	 *   sequences
+	 */
+	bool updated = false;
+	if (curr->is_acquire()) {
+		action_list_t *list = action_trace;
+		action_list_t::reverse_iterator rit;
+		/* Find X : is_read(X) && X --sb-> curr */
+		for (rit = list->rbegin(); rit != list->rend(); rit++) {
+			ModelAction *act = *rit;
+			if (act->get_tid() != curr->get_tid())
+				continue;
+			/* Stop at the beginning of the thread */
+			if (act->is_thread_start())
+				break;
+			/* Stop once we reach a prior fence-acquire */
+			if (act->is_fence() && act->is_acquire())
+				break;
+			if (!act->is_read())
+				continue;
+			/* read-acquire will find its own release sequences */
+			if (act->is_acquire())
+				continue;
+
+			/* Establish hypothetical release sequences */
+			rel_heads_list_t release_heads;
+			get_release_seq_heads(curr, act, &release_heads);
+			for (unsigned int i = 0; i < release_heads.size(); i++)
+				if (!act->synchronize_with(release_heads[i]))
+					set_bad_synchronization();
+			if (release_heads.size() != 0)
+				updated = true;
+		}
+	}
+	return updated;
+}
+
 /**
  * @brief Process the current action for thread-related activity
  *
@@ -1173,6 +1221,9 @@ Thread * ModelChecker::check_current_action(ModelAction *curr)
 			if (act->is_write() && process_write(act))
 				update = true;
 
+			if (act->is_fence() && process_fence(act))
+				update_all = true;
+
 			if (act->is_mutex_op() && process_mutex(act))
 				update_all = true;
 
diff --git a/model.h b/model.h
index b078939..5543eb8 100644
--- a/model.h
+++ b/model.h
@@ -152,6 +152,7 @@ private:
 	bool initialize_curr_action(ModelAction **curr);
 	bool process_read(ModelAction *curr, bool second_part_of_rmw);
 	bool process_write(ModelAction *curr);
+	bool process_fence(ModelAction *curr);
 	bool process_mutex(ModelAction *curr);
 	bool process_thread_action(ModelAction *curr);
 	void process_relseq_fixup(ModelAction *curr, work_queue_t *work_queue);