X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=model.cc;h=e4b6431336050c89043f45851214c632b2e943ce;hb=fc32611957cecd106751b62bc4de4aeddc9af56c;hp=715a2584f36a1538528489d60f987142ad0f2a77;hpb=9bdbedb24f7c16c4941ec6b711fc8065e0cee9d3;p=model-checker.git diff --git a/model.cc b/model.cc index 715a258..e4b6431 100644 --- a/model.cc +++ b/model.cc @@ -1,6 +1,7 @@ #include #include #include +#include #include "model.h" #include "action.h" @@ -128,19 +129,21 @@ ModelChecker::~ModelChecker() delete priv; } -static action_list_t * get_safe_ptr_action(HashTable * hash, void * ptr) { - action_list_t * tmp=hash->get(ptr); - if (tmp==NULL) { - tmp=new action_list_t(); +static action_list_t * get_safe_ptr_action(HashTable * hash, void * ptr) +{ + action_list_t *tmp = hash->get(ptr); + if (tmp == NULL) { + tmp = new action_list_t(); hash->put(ptr, tmp); } return tmp; } -static std::vector * get_safe_ptr_vect_action(HashTable *, uintptr_t, 4> * hash, void * ptr) { - std::vector * tmp=hash->get(ptr); - if (tmp==NULL) { - tmp=new std::vector(); +static std::vector * get_safe_ptr_vect_action(HashTable *, uintptr_t, 4> * hash, void * ptr) +{ + std::vector *tmp = hash->get(ptr); + if (tmp == NULL) { + tmp = new std::vector(); hash->put(ptr, tmp); } return tmp; @@ -207,7 +210,7 @@ Thread * ModelChecker::get_next_thread(ModelAction *curr) { thread_id_t tid; - if (curr!=NULL) { + if (curr != NULL) { /* Do not split atomic actions. */ if (curr->is_rmwr()) return thread_current(); @@ -282,12 +285,12 @@ Thread * ModelChecker::get_next_thread(ModelAction *curr) * the corresponding thread object's pending action. */ -void ModelChecker::execute_sleep_set() { - for(unsigned int i=0;iget_enabled(thr) == THREAD_SLEEP_SET && - thr->get_pending() == NULL ) { +void ModelChecker::execute_sleep_set() +{ + for (unsigned int i = 0; i < get_num_threads(); i++) { + thread_id_t tid = int_to_id(i); + Thread *thr = get_thread(tid); + if (scheduler->is_sleep_set(thr) && thr->get_pending() == NULL) { thr->set_state(THREAD_RUNNING); scheduler->next_thread(thr); Thread::swap(&system_context, thr); @@ -298,16 +301,15 @@ void ModelChecker::execute_sleep_set() { priv->current_action = NULL; } -void ModelChecker::wake_up_sleeping_actions(ModelAction * curr) { - for(unsigned int i=0;iget_enabled(thr) == THREAD_SLEEP_SET ) { - ModelAction *pending_act=thr->get_pending(); - if ((!curr->is_rmwr())&&pending_act->could_synchronize_with(curr)) { +void ModelChecker::wake_up_sleeping_actions(ModelAction *curr) +{ + for (unsigned int i = 0; i < get_num_threads(); i++) { + Thread *thr = get_thread(int_to_id(i)); + if (scheduler->is_sleep_set(thr)) { + ModelAction *pending_act = thr->get_pending(); + if ((!curr->is_rmwr()) && pending_act->could_synchronize_with(curr)) //Remove this thread from sleep set scheduler->remove_sleep(thr); - } } } } @@ -603,11 +605,11 @@ ModelAction * ModelChecker::get_last_conflict(ModelAction *act) void ModelChecker::set_backtracking(ModelAction *act) { Thread *t = get_thread(act); - ModelAction * prev = get_last_conflict(act); + ModelAction *prev = get_last_conflict(act); if (prev == NULL) return; - Node * node = prev->get_node()->get_parent(); + Node *node = prev->get_node()->get_parent(); int low_tid, high_tid; if (node->is_enabled(t)) { @@ -714,7 +716,7 @@ bool ModelChecker::process_read(ModelAction *curr, bool second_part_of_rmw) /* Read from future value */ value = curr->get_node()->get_future_value(); modelclock_t expiration = curr->get_node()->get_future_value_expiration(); - read_from(curr, NULL); + curr->set_read_from(NULL); Promise *valuepromise = new Promise(curr, value, expiration); promises->push_back(valuepromise); } @@ -1137,8 +1139,8 @@ bool ModelChecker::read_from(ModelAction *act, const ModelAction *rf) */ bool ModelChecker::check_action_enabled(ModelAction *curr) { if (curr->is_lock()) { - std::mutex * lock = (std::mutex *)curr->get_location(); - struct std::mutex_state * state = lock->get_state(); + std::mutex *lock = (std::mutex *)curr->get_location(); + struct std::mutex_state *state = lock->get_state(); if (state->islocked) { //Stick the action in the appropriate waiting queue get_safe_ptr_action(lock_waiters_map, curr->get_location())->push_back(curr); @@ -1272,7 +1274,8 @@ Thread * ModelChecker::check_current_action(ModelAction *curr) return get_next_thread(curr); } -void ModelChecker::check_curr_backtracking(ModelAction * curr) { +void ModelChecker::check_curr_backtracking(ModelAction *curr) +{ Node *currnode = curr->get_node(); Node *parnode = currnode->get_parent(); @@ -1384,9 +1387,9 @@ ModelAction * ModelChecker::process_rmw(ModelAction *act) { * * If so, we decide that the execution is no longer feasible. */ -void ModelChecker::check_recency(ModelAction *curr, const ModelAction *rf) { +void ModelChecker::check_recency(ModelAction *curr, const ModelAction *rf) +{ if (params.maxreads != 0) { - if (curr->get_node()->get_read_from_size() <= 1) return; //Must make sure that execution is currently feasible... We could @@ -1412,7 +1415,7 @@ void ModelChecker::check_recency(ModelAction *curr, const ModelAction *rf) { //See if we have enough reads from the same value int count = 0; for (; count < params.maxreads; rit++,count++) { - if (rit==list->rend()) + if (rit == list->rend()) return; ModelAction *act = *rit; if (!act->is_read()) @@ -1423,12 +1426,12 @@ void ModelChecker::check_recency(ModelAction *curr, const ModelAction *rf) { if (act->get_node()->get_read_from_size() <= 1) return; } - for (int i = 0; iget_node()->get_read_from_size(); i++) { - //Get write - const ModelAction * write = curr->get_node()->get_read_from_at(i); + for (int i = 0; i < curr->get_node()->get_read_from_size(); i++) { + /* Get write */ + const ModelAction *write = curr->get_node()->get_read_from_at(i); - //Need a different write - if (write==rf) + /* Need a different write */ + if (write == rf) continue; /* Test to see whether this is a feasible write to read from*/ @@ -1445,7 +1448,7 @@ void ModelChecker::check_recency(ModelAction *curr, const ModelAction *rf) { //new we need to see if this write works for everyone for (int loop = count; loop>0; loop--,rit++) { - ModelAction *act=*rit; + ModelAction *act = *rit; bool foundvalue = false; for (int j = 0; jget_node()->get_read_from_size(); j++) { if (act->get_node()->get_read_from_at(j)==write) { @@ -1763,7 +1766,8 @@ bool ModelChecker::w_modification_order(ModelAction *curr) /** Arbitrary reads from the future are not allowed. Section 29.3 * part 9 places some constraints. This method checks one result of constraint * constraint. Others require compiler support. */ -bool ModelChecker::thin_air_constraint_may_allow(const ModelAction * writer, const ModelAction *reader) { +bool ModelChecker::thin_air_constraint_may_allow(const ModelAction *writer, const ModelAction *reader) +{ if (!writer->is_rmw()) return true; @@ -2103,18 +2107,32 @@ bool ModelChecker::resolve_release_sequences(void *location, work_queue_t *work_ void ModelChecker::add_action_to_lists(ModelAction *act) { int tid = id_to_int(act->get_tid()); - action_trace->push_back(act); + ModelAction *uninit = NULL; + int uninit_id = -1; + action_list_t *list = get_safe_ptr_action(obj_map, act->get_location()); + if (list->empty() && act->is_atomic_var()) { + uninit = new_uninitialized_action(act->get_location()); + uninit_id = id_to_int(uninit->get_tid()); + list->push_back(uninit); + } + list->push_back(act); - get_safe_ptr_action(obj_map, act->get_location())->push_back(act); + action_trace->push_back(act); + if (uninit) + action_trace->push_front(uninit); std::vector *vec = get_safe_ptr_vect_action(obj_thrd_map, act->get_location()); if (tid >= (int)vec->size()) vec->resize(priv->next_thread_id); (*vec)[tid].push_back(act); + if (uninit) + (*vec)[uninit_id].push_front(uninit); if ((int)thrd_last_action->size() <= tid) thrd_last_action->resize(get_num_threads()); (*thrd_last_action)[tid] = act; + if (uninit) + (*thrd_last_action)[uninit_id] = uninit; if (act->is_fence() && act->is_release()) { if ((int)thrd_last_fence_release->size() <= tid) @@ -2364,14 +2382,14 @@ void ModelChecker::check_promises_thread_disabled() { * cannot perform a future write that will resolve the promise due to * modificatin order constraints. * - * @parem tid The thread that either read from the model action + * @param tid The thread that either read from the model action * write, or actually did the model action write. * - * @parem write The ModelAction representing the relevant write. + * @param write The ModelAction representing the relevant write. */ - -void ModelChecker::mo_check_promises(thread_id_t tid, const ModelAction *write) { - void * location = write->get_location(); +void ModelChecker::mo_check_promises(thread_id_t tid, const ModelAction *write) +{ + void *location = write->get_location(); for (unsigned int i = 0; i < promises->size(); i++) { Promise *promise = (*promises)[i]; const ModelAction *act = promise->get_action(); @@ -2449,16 +2467,8 @@ void ModelChecker::build_reads_from_past(ModelAction *curr) ModelAction *last_sc_write = NULL; - /* Track whether this object has been initialized */ - bool initialized = false; - - if (curr->is_seqcst()) { + if (curr->is_seqcst()) last_sc_write = get_last_seq_cst_write(curr); - /* We have to at least see the last sequentially consistent write, - so we are initialized. */ - if (last_sc_write != NULL) - initialized = true; - } /* Iterate over all threads */ for (i = 0; i < thrd_lists->size(); i++) { @@ -2490,17 +2500,12 @@ void ModelChecker::build_reads_from_past(ModelAction *curr) } /* Include at most one act per-thread that "happens before" curr */ - if (act->happens_before(curr)) { - initialized = true; + if (act->happens_before(curr)) break; - } } } - if (!initialized) - assert_bug("May read from uninitialized atomic"); - - if (DBG_ENABLED() || !initialized) { + if (DBG_ENABLED()) { model_print("Reached read action:\n"); curr->print(); model_print("Printing may_read_from\n"); @@ -2509,22 +2514,39 @@ void ModelChecker::build_reads_from_past(ModelAction *curr) } } -bool ModelChecker::sleep_can_read_from(ModelAction * curr, const ModelAction *write) { - while(true) { - Node *prevnode=write->get_node()->get_parent(); +bool ModelChecker::sleep_can_read_from(ModelAction *curr, const ModelAction *write) +{ + while (true) { + /* UNINIT actions don't have a Node, and they never sleep */ + if (write->is_uninitialized()) + return true; + Node *prevnode = write->get_node()->get_parent(); - bool thread_sleep=prevnode->enabled_status(curr->get_tid())==THREAD_SLEEP_SET; - if (write->is_release()&&thread_sleep) + bool thread_sleep = prevnode->enabled_status(curr->get_tid()) == THREAD_SLEEP_SET; + if (write->is_release() && thread_sleep) return true; if (!write->is_rmw()) { return false; } - if (write->get_reads_from()==NULL) + if (write->get_reads_from() == NULL) return true; write=write->get_reads_from(); } } +/** + * @brief Create a new action representing an uninitialized atomic + * @param location The memory location of the atomic object + * @return A pointer to a new ModelAction + */ +ModelAction * ModelChecker::new_uninitialized_action(void *location) const +{ + ModelAction *act = (ModelAction *)snapshot_malloc(sizeof(class ModelAction)); + act = new (act) ModelAction(ATOMIC_UNINIT, std::memory_order_relaxed, location, 0, model_thread); + act->create_cv(NULL); + return act; +} + static void print_list(action_list_t *list, int exec_num = -1) { action_list_t::iterator it;