snapshotObject->backTrackBeforeStep(0);
}
-/** @returns a thread ID for a new Thread */
+/** @return a thread ID for a new Thread */
thread_id_t ModelChecker::get_next_id()
{
return priv->next_thread_id++;
}
-/** @returns the number of user threads created during this execution */
+/** @return the number of user threads created during this execution */
int ModelChecker::get_num_threads()
{
return priv->next_thread_id;
}
-/** @returns a sequence number for a new ModelAction */
+/** @return a sequence number for a new ModelAction */
modelclock_t ModelChecker::get_next_seq_num()
{
return ++priv->used_sequence_numbers;
}
}
+/**
+ * Processes a lock, trylock, or unlock model action. @param curr is
+ * the read model action to process.
+ *
+ * The try lock operation checks whether the lock is taken. If not,
+ * it falls to the normal lock operation case. If so, it returns
+ * fail.
+ *
+ * The lock operation has already been checked that it is enabled, so
+ * it just grabs the lock and synchronizes with the previous unlock.
+ *
+ * The unlock operation has to re-enable all of the threads that are
+ * waiting on the lock.
+ */
+
void ModelChecker::process_mutex(ModelAction *curr) {
std::mutex * mutex=(std::mutex *) curr->get_location();
struct std::mutex_state * state=mutex->get_state();
action_list_t * waiters = lock_waiters_map->get_safe_ptr(curr->get_location());
//activate all the waiting threads
for(action_list_t::iterator rit = waiters->begin(); rit!=waiters->end(); rit++) {
- add_thread(get_thread((*rit)->get_tid()));
+ scheduler->add_thread(get_thread((*rit)->get_tid()));
}
waiters->clear();
break;
return newcurr;
}
+/**
+ * This method checks whether a model action is enabled at the given point.
+ * At this point, it checks whether a lock operation would be successful at this point.
+ * If not, it puts the thread in a waiter list.
+ * @param curr is the ModelAction to check whether it is enabled.
+ * @return a bool that indicates whether the action is enabled.
+ */
+
bool ModelChecker::check_action_enabled(ModelAction *curr) {
if (curr->is_lock()) {
std::mutex * lock=(std::mutex *) curr->get_location();
return false;
}
-/** @returns whether the current partial trace must be a prefix of a
+/** @return whether the current partial trace must be a prefix of a
* feasible trace. */
bool ModelChecker::isfeasibleprefix() {
return promises->size() == 0 && *lazy_sync_size == 0;
}
-/** @returns whether the current partial trace is feasible. */
+/** @return whether the current partial trace is feasible. */
bool ModelChecker::isfeasible() {
return !mo_graph->checkForRMWViolation() && isfeasibleotherthanRMW();
}
-/** @returns whether the current partial trace is feasible other than
+/** @return whether the current partial trace is feasible other than
* multiple RMW reading from the same store. */
bool ModelChecker::isfeasibleotherthanRMW() {
if (DBG_ENABLED()) {
* the release seq? */
bool future_ordered = false;
+ ModelAction *last = get_last_action(int_to_id(i));
+ if (last && rf->happens_before(last))
+ future_ordered = true;
+
for (rit = list->rbegin(); rit != list->rend(); rit++) {
const ModelAction *act = *rit;
- if (!act->is_write())
- continue;
/* Reach synchronization -> this thread is complete */
if (act->happens_before(release))
break;
continue;
}
+ /* Only writes can break release sequences */
+ if (!act->is_write())
+ continue;
+
/* Check modification order */
if (mo_graph->checkReachable(rf, act)) {
/* rf --mo--> act */
(*thrd_last_action)[tid] = act;
}
-ModelAction * ModelChecker::get_last_action(thread_id_t tid)
+/**
+ * @brief Get the last action performed by a particular Thread
+ * @param tid The thread ID of the Thread in question
+ * @return The last action in the thread
+ */
+ModelAction * ModelChecker::get_last_action(thread_id_t tid) const
{
- int threadid=id_to_int(tid);
- if (threadid<(int)thrd_last_action->size())
+ int threadid = id_to_int(tid);
+ if (threadid < (int)thrd_last_action->size())
return (*thrd_last_action)[id_to_int(tid)];
else
return NULL;
* check
* @return The last seq_cst write
*/
-ModelAction * ModelChecker::get_last_seq_cst(ModelAction *curr)
+ModelAction * ModelChecker::get_last_seq_cst(ModelAction *curr) const
{
void *location = curr->get_location();
action_list_t *list = obj_map->get_safe_ptr(location);
return NULL;
}
-ModelAction * ModelChecker::get_last_unlock(ModelAction *curr)
+/**
+ * Gets the last unlock operation performed on a particular mutex (i.e., memory
+ * location). This function identifies the mutex according to the current
+ * action, which is presumed to perform on the same mutex.
+ * @param curr The current ModelAction; also denotes the object location to
+ * check
+ * @return The last unlock operation
+ */
+ModelAction * ModelChecker::get_last_unlock(ModelAction *curr) const
{
void *location = curr->get_location();
action_list_t *list = obj_map->get_safe_ptr(location);
- /* Find: max({i in dom(S) | seq_cst(t_i) && isWrite(t_i) && samevar(t_i, t)}) */
+ /* Find: max({i in dom(S) | isUnlock(t_i) && samevar(t_i, t)}) */
action_list_t::reverse_iterator rit;
for (rit = list->rbegin(); rit != list->rend(); rit++)
if ((*rit)->is_unlock())
#if SUPPORT_MOD_ORDER_DUMP
scheduler->print();
char buffername[100];
- sprintf(buffername, "exec%u",num_executions);
+ sprintf(buffername, "exec%04u", num_executions);
mo_graph->dumpGraphToFile(buffername);
#endif