ASSERT(0);
}
+#include <signal.h>
+
+#define SIGSTACKSIZE 65536
+static void mprot_handle_pf(int sig, siginfo_t *si, void *unused)
+{
+ model_print("Segmentation fault at %p\n", si->si_addr);
+ model_print("For debugging, place breakpoint at: %s:%d\n",
+ __FILE__, __LINE__);
+ print_trace(); // Trace printing may cause dynamic memory allocation
+ while(1)
+ ;
+}
+
+void install_handler() {
+ stack_t ss;
+ ss.ss_sp = model_malloc(SIGSTACKSIZE);
+ ss.ss_size = SIGSTACKSIZE;
+ ss.ss_flags = 0;
+ sigaltstack(&ss, NULL);
+ struct sigaction sa;
+ sa.sa_flags = SA_SIGINFO | SA_NODEFER | SA_RESTART | SA_ONSTACK;
+ sigemptyset(&sa.sa_mask);
+ sa.sa_sigaction = mprot_handle_pf;
+
+ if (sigaction(SIGSEGV, &sa, NULL) == -1) {
+ perror("sigaction(SIGSEGV)");
+ exit(EXIT_FAILURE);
+ }
+
+}
+
/** @brief Constructor */
ModelChecker::ModelChecker() :
/* Initialize default scheduler */
params(),
- restart_flag(false),
scheduler(new Scheduler()),
history(new ModelHistory()),
execution(new ModelExecution(this, scheduler)),
trace_analyses(),
inspect_plugin(NULL)
{
- printf("C11Tester\n"
- "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");
+ model_print("C11Tester\n"
+ "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_thread = new Thread(execution->get_next_id(), (thrd_t *) model_malloc(sizeof(thrd_t)), &placeholder, NULL, NULL);
#ifdef TLS
initRaceDetector();
/* Configure output redirection for the model-checker */
redirect_output();
- install_trace_analyses(model->get_execution());
+ install_trace_analyses(get_execution());
+ install_handler();
}
/** @brief Destructor */
for (unsigned int i = 0;i < get_num_threads();i++)
delete get_thread(int_to_id(i))->get_pending();
- snapshot_backtrack_before(0);
+ snapshot_roll_back(snapshot);
}
/** @return the number of user threads created during this execution */
* @return If there are more executions to explore, return true. Otherwise,
* return false.
*/
-bool ModelChecker::next_execution()
+void ModelChecker::finish_execution(bool more_executions)
{
DBG();
/* Is this execution a feasible execution that's worth bug-checking? */
else
clear_program_output();
- if (restart_flag) {
- do_restart();
- return true;
- }
// test code
execution_number ++;
- reset_to_initial_state();
+ if (more_executions)
+ reset_to_initial_state();
history->set_new_exec_flag();
- return false;
}
/** @brief Run trace analyses on complete trace */
void ModelChecker::startChecker() {
startExecution(get_system_context(), runChecker);
- snapshot_stack_init();
- snapshot_record(0);
+ snapshot = take_snapshot();
+ initMainThread();
}
bool ModelChecker::should_terminate_execution()
return false;
}
-/** @brief Restart ModelChecker upon returning to the run loop of the
- * model checker. */
-void ModelChecker::restart()
-{
- restart_flag = true;
-}
-
-void ModelChecker::do_restart()
-{
- restart_flag = false;
- reset_to_initial_state();
- memset(&stats,0,sizeof(struct execution_stats));
- execution_number = 1;
-}
-
-void ModelChecker::startMainThread() {
- init_thread->set_state(THREAD_RUNNING);
- scheduler->set_current_thread(init_thread);
- main_thread_startup();
-}
-
/** @brief Run ModelChecker for the user program */
void ModelChecker::run()
{
//Need to initial random number generator state to avoid resets on rollback
char random_state[256];
initstate(423121, random_state, sizeof(random_state));
-
+ modelclock_t checkfree = params.checkthreshold;
for(int exec = 0;exec < params.maxexecutions;exec++) {
Thread * t = init_thread;
do {
+ /* Check whether we need to free model actions. */
+
+ if (params.traceminsize != 0 &&
+ execution->get_curr_seq_num() > checkfree) {
+ checkfree += params.checkthreshold;
+ execution->collectActions();
+ }
+
/*
* Stash next pending action(s) for thread(s). There
* should only need to stash one thread's action--the
t->set_pending(NULL);
t = execution->take_step(curr);
} while (!should_terminate_execution());
- next_execution();
+ finish_execution((exec+1) < params.maxexecutions);
//restore random number generator state after rollback
setstate(random_state);
}