X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=model.cc;h=c190e38cacb8c7ccb842957ef07c1c231f3c9bfe;hb=HEAD;hp=c2de31304f577187d538075de45504a94f7019b9;hpb=db17cfb8915ef5b6b2977360c05a92b1b7e01a3e;p=c11tester.git diff --git a/model.cc b/model.cc index c2de3130..c190e38c 100644 --- a/model.cc +++ b/model.cc @@ -15,12 +15,20 @@ #include "output.h" #include "traceanalysis.h" #include "execution.h" -#include "history.h" #include "bugmessage.h" #include "params.h" #include "plugins.h" ModelChecker *model = NULL; +int inside_model = 0; + +uint64_t get_nanotime() +{ + struct timespec currtime; + clock_gettime(CLOCK_MONOTONIC, &currtime); + + return currtime.tv_nsec; +} void placeholder(void *) { ASSERT(0); @@ -54,7 +62,16 @@ void install_handler() { perror("sigaction(SIGSEGV)"); exit(EXIT_FAILURE); } +} +void createModelIfNotExist() { + if (!model) { + ENTER_MODEL_FLAG; + snapshot_system_init(100000); + model = new ModelChecker(); + model->startChecker(); + EXIT_MODEL_FLAG; + } } /** @brief Constructor */ @@ -62,9 +79,9 @@ ModelChecker::ModelChecker() : /* Initialize default scheduler */ params(), scheduler(new Scheduler()), - history(new ModelHistory()), execution(new ModelExecution(this, scheduler)), execution_number(1), + curr_thread_num(MAIN_THREAD_ID), trace_analyses(), inspect_plugin(NULL) { @@ -72,7 +89,8 @@ ModelChecker::ModelChecker() : "Copyright (c) 2013 and 2019 Regents of the University of California. All rights reserved.\n" "Distributed under the GPLv2\n" "Written by Weiyu Luo, Brian Norris, and Brian Demsky\n\n"); - memset(&stats,0,sizeof(struct execution_stats)); + init_memory_ops(); + real_memset(&stats,0,sizeof(struct execution_stats)); init_thread = new Thread(execution->get_next_id(), (thrd_t *) model_malloc(sizeof(thrd_t)), &placeholder, NULL, NULL); #ifdef TLS init_thread->setTLS((char *)get_tls_addr()); @@ -134,6 +152,18 @@ Thread * ModelChecker::get_current_thread() const return scheduler->get_current_thread(); } +/** + * Must be called from user-thread context (e.g., through the global + * thread_current_id() interface) + * + * @return The id of the currently executing Thread. + */ +thread_id_t ModelChecker::get_current_thread_id() const +{ + ASSERT(int_to_id(curr_thread_num) == get_current_thread()->get_id()); + return int_to_id(curr_thread_num); +} + /** * @brief Choose the next thread to execute. * @@ -256,7 +286,9 @@ void ModelChecker::print_execution(bool printbugs) const } model_print("\n"); +#ifdef PRINT_TRACE execution->print_summary(); +#endif } /** @@ -289,7 +321,6 @@ void ModelChecker::finish_execution(bool more_executions) clear_program_output(); execution_number ++; - history->set_new_exec_flag(); if (more_executions) reset_to_initial_state(); @@ -329,13 +360,11 @@ void ModelChecker::startRunExecution(Thread *old) { execution->collectActions(); } - thread_chosen = false; - curr_thread_num = 1; - - Thread *thr = getNextThread(); + curr_thread_num = MAIN_THREAD_ID; + Thread *thr = getNextThread(old); if (thr != nullptr) { scheduler->set_current_thread(thr); - + EXIT_MODEL_FLAG; if (Thread::swap(old, thr) < 0) { perror("swap threads"); exit(EXIT_FAILURE); @@ -343,53 +372,52 @@ void ModelChecker::startRunExecution(Thread *old) { return; } - if (execution->has_asserted()) { - finishRunExecution(old); - return; - } - if (!chosen_thread) - chosen_thread = get_next_thread(); - if (!chosen_thread || chosen_thread->is_model_thread()) { - finishRunExecution(old); - return; - } - if (chosen_thread->just_woken_up()) { - chosen_thread->set_wakeup_state(false); - chosen_thread->set_pending(NULL); - chosen_thread = NULL; - // Allow this thread to stash the next pending action - continue; - } - - /* Consume the next action for a Thread */ - consumeAction(); - - if (should_terminate_execution()) { - finishRunExecution(old); + if (!handleChosenThread(old)) { return; } } } -Thread* ModelChecker::getNextThread() +Thread* ModelChecker::getNextThread(Thread *old) { Thread *nextThread = nullptr; for (unsigned int i = curr_thread_num;i < get_num_threads();i++) { thread_id_t tid = int_to_id(i); Thread *thr = get_thread(tid); - if (!thr->is_complete() && !thr->get_pending()) { - curr_thread_num = i; - nextThread = thr; - break; + if (!thr->is_complete()) { + if (!thr->get_pending()) { + curr_thread_num = i; + nextThread = thr; + break; + } + } else if (thr != old && !thr->is_freed()) { + thr->freeResources(); } - /* Don't schedule threads which should be disabled */ ModelAction *act = thr->get_pending(); - if (act && execution->is_enabled(thr) && !execution->check_action_enabled(act)) { - scheduler->sleep(thr); + if (act && scheduler->is_enabled(tid)){ + /* Don't schedule threads which should be disabled */ + if (!execution->check_action_enabled(act)) { + scheduler->sleep(thr); + } + + /* Allow pending relaxed/release stores or thread actions to perform first */ + else if (!chosen_thread) { + if (act->is_write()) { + std::memory_order order = act->get_mo(); + if (order == std::memory_order_relaxed || \ + order == std::memory_order_release) { + chosen_thread = thr; + } + } else if (act->get_type() == THREAD_CREATE || \ + act->get_type() == PTHREAD_CREATE || \ + act->get_type() == THREAD_START || \ + act->get_type() == THREAD_FINISH) { + chosen_thread = thr; + } + } } - chooseThread(act, thr); } return nextThread; } @@ -399,6 +427,9 @@ void ModelChecker::finishRunExecution(Thread *old) { scheduler->set_current_thread(NULL); + /** Reset curr_thread_num to initial value for next execution. */ + curr_thread_num = MAIN_THREAD_ID; + /** If we have more executions, we won't make it past this call. */ finish_execution(execution_number < params.maxexecutions); @@ -420,34 +451,6 @@ void ModelChecker::finishRunExecution(Thread *old) _Exit(0); } -void ModelChecker::consumeAction() -{ - ModelAction *curr = chosen_thread->get_pending(); - chosen_thread->set_pending(NULL); - chosen_thread = execution->take_step(curr); -} - -/* Allow pending relaxed/release stores or thread actions to perform first */ -void ModelChecker::chooseThread(ModelAction *act, Thread *thr) -{ - if (!thread_chosen && act && execution->is_enabled(thr) && (thr->get_state() != THREAD_BLOCKED) ) { - if (act->is_write()) { - std::memory_order order = act->get_mo(); - if (order == std::memory_order_relaxed || \ - order == std::memory_order_release) { - chosen_thread = thr; - thread_chosen = true; - } - } else if (act->get_type() == THREAD_CREATE || \ - act->get_type() == PTHREAD_CREATE || \ - act->get_type() == THREAD_START || \ - act->get_type() == THREAD_FINISH) { - chosen_thread = thr; - thread_chosen = true; - } - } -} - uint64_t ModelChecker::switch_thread(ModelAction *act) { if (modellock) { @@ -460,6 +463,8 @@ uint64_t ModelChecker::switch_thread(ModelAction *act) delete act; return 0; } + ENTER_MODEL_FLAG; + DBG(); Thread *old = thread_current(); old->set_state(THREAD_READY); @@ -475,65 +480,68 @@ uint64_t ModelChecker::switch_thread(ModelAction *act) if (old->is_waiting_on(old)) assert_bug("Deadlock detected (thread %u)", curr_thread_num); - if (act && execution->is_enabled(old) && !execution->check_action_enabled(act)) { - scheduler->sleep(old); - } - chooseThread(act, old); - - curr_thread_num++; - Thread* next = getNextThread(); + Thread* next = getNextThread(old); if (next != nullptr) { scheduler->set_current_thread(next); if (Thread::swap(old, next) < 0) { perror("swap threads"); exit(EXIT_FAILURE); } - } else - handleChosenThread(old); - + } else { + if (handleChosenThread(old)) { + startRunExecution(old); + } + } return old->get_return_value(); } -void ModelChecker::handleChosenThread(Thread *old) +bool ModelChecker::handleChosenThread(Thread *old) { if (execution->has_asserted()) { finishRunExecution(old); - return; + return false; } - if (!chosen_thread) + if (!chosen_thread) { chosen_thread = get_next_thread(); - if (!chosen_thread || chosen_thread->is_model_thread()) { + } + if (!chosen_thread) { finishRunExecution(old); - return; + return false; } if (chosen_thread->just_woken_up()) { chosen_thread->set_wakeup_state(false); chosen_thread->set_pending(NULL); chosen_thread = NULL; // Allow this thread to stash the next pending action - startRunExecution(old); - return; + return true; } // Consume the next action for a Thread - consumeAction(); + ModelAction *curr = chosen_thread->get_pending(); + chosen_thread->set_pending(NULL); + chosen_thread = execution->take_step(curr); if (should_terminate_execution()) { finishRunExecution(old); - return; - } else - startRunExecution(old); + return false; + } else { + return true; + } } void ModelChecker::startChecker() { startExecution(); //Need to initial random number generator state to avoid resets on rollback - initstate(423121, random_state, sizeof(random_state)); + //initstate(423121, random_state, sizeof(random_state)); + uint64_t seed = get_nanotime(); + srandom(seed); snapshot = take_snapshot(); //reset random number generator state - setstate(random_state); + //setstate(random_state); + seed = get_nanotime(); + srandom(seed); install_trace_analyses(get_execution()); redirect_output();