ExecutorTimers.cpp
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 #include "Common.h"
00011
00012 #include "CoreStats.h"
00013 #include "Executor.h"
00014 #include "PTree.h"
00015 #include "StatsTracker.h"
00016
00017 #include "klee/ExecutionState.h"
00018 #include "klee/Internal/Module/InstructionInfoTable.h"
00019 #include "klee/Internal/Module/KInstruction.h"
00020 #include "klee/Internal/Module/KModule.h"
00021 #include "klee/Internal/System/Time.h"
00022
00023 #include "llvm/Function.h"
00024 #include "llvm/Support/CommandLine.h"
00025
00026 #include <unistd.h>
00027 #include <signal.h>
00028 #include <sys/time.h>
00029 #include <math.h>
00030
00031
00032 using namespace llvm;
00033 using namespace klee;
00034
00035 cl::opt<double>
00036 MaxTime("max-time",
00037 cl::desc("Halt execution after the specified number of seconds (0=off)"),
00038 cl::init(0));
00039
00041
00042 class HaltTimer : public Executor::Timer {
00043 Executor *executor;
00044
00045 public:
00046 HaltTimer(Executor *_executor) : executor(_executor) {}
00047 ~HaltTimer() {}
00048
00049 void run() {
00050 llvm::cerr << "KLEE: HaltTimer invoked\n";
00051 executor->setHaltExecution(true);
00052 }
00053 };
00054
00056
00057 static const double kSecondsPerTick = .1;
00058 static volatile unsigned timerTicks = 0;
00059
00060
00061 extern "C" unsigned dumpStates, dumpPTree;
00062 unsigned dumpStates = 0, dumpPTree = 0;
00063
00064 static void onAlarm(int) {
00065 ++timerTicks;
00066 }
00067
00068
00069 static void setupHandler() {
00070 struct itimerval t;
00071 struct timeval tv;
00072
00073 tv.tv_sec = (long) kSecondsPerTick;
00074 tv.tv_usec = (long) (fmod(kSecondsPerTick, 1.)*1000000);
00075
00076 t.it_interval = t.it_value = tv;
00077
00078 ::setitimer(ITIMER_REAL, &t, 0);
00079 ::signal(SIGALRM, onAlarm);
00080 }
00081
00082 void Executor::initTimers() {
00083 static bool first = true;
00084
00085 if (first) {
00086 first = false;
00087 setupHandler();
00088 }
00089
00090 if (MaxTime) {
00091 addTimer(new HaltTimer(this), MaxTime);
00092 }
00093 }
00094
00096
00097 Executor::Timer::Timer() {}
00098
00099 Executor::Timer::~Timer() {}
00100
00101 class Executor::TimerInfo {
00102 public:
00103 Timer *timer;
00104
00106 double rate;
00108 double nextFireTime;
00109
00110 public:
00111 TimerInfo(Timer *_timer, double _rate)
00112 : timer(_timer),
00113 rate(_rate),
00114 nextFireTime(util::getWallTime() + rate) {}
00115 ~TimerInfo() { delete timer; }
00116 };
00117
00118 void Executor::addTimer(Timer *timer, double rate) {
00119 timers.push_back(new TimerInfo(timer, rate));
00120 }
00121
00122 void Executor::processTimers(ExecutionState *current,
00123 double maxInstTime) {
00124 static unsigned callsWithoutCheck = 0;
00125 unsigned ticks = timerTicks;
00126
00127 if (!ticks && ++callsWithoutCheck > 1000) {
00128 setupHandler();
00129 ticks = 1;
00130 }
00131
00132 if (ticks || dumpPTree || dumpStates) {
00133 if (dumpPTree) {
00134 char name[32];
00135 sprintf(name, "ptree%08d.dot", (int) stats::instructions);
00136 std::ostream *os = interpreterHandler->openOutputFile(name);
00137 if (os) {
00138 processTree->dump(*os);
00139 delete os;
00140 }
00141
00142 dumpPTree = 0;
00143 }
00144
00145 if (dumpStates) {
00146 std::ostream *os = interpreterHandler->openOutputFile("states.txt");
00147
00148 if (os) {
00149 for (std::set<ExecutionState*>::const_iterator it = states.begin(),
00150 ie = states.end(); it != ie; ++it) {
00151 ExecutionState *es = *it;
00152 *os << "(" << es << ",";
00153 *os << "[";
00154 ExecutionState::stack_ty::iterator next = es->stack.begin();
00155 ++next;
00156 for (ExecutionState::stack_ty::iterator sfIt = es->stack.begin(),
00157 sf_ie = es->stack.end(); sfIt != sf_ie; ++sfIt) {
00158 *os << "('" << sfIt->kf->function->getName() << "',";
00159 if (next == es->stack.end()) {
00160 *os << es->prevPC->info->line << "), ";
00161 } else {
00162 *os << next->caller->info->line << "), ";
00163 ++next;
00164 }
00165 }
00166 *os << "], ";
00167
00168 StackFrame &sf = es->stack.back();
00169 uint64_t md2u = computeMinDistToUncovered(es->pc,
00170 sf.minDistToUncoveredOnReturn);
00171 uint64_t icnt = theStatisticManager->getIndexedValue(stats::instructions,
00172 es->pc->info->id);
00173 uint64_t cpicnt = sf.callPathNode->statistics.getValue(stats::instructions);
00174
00175 *os << "{";
00176 *os << "'depth' : " << es->depth << ", ";
00177 *os << "'weight' : " << es->weight << ", ";
00178 *os << "'queryCost' : " << es->queryCost << ", ";
00179 *os << "'coveredNew' : " << es->coveredNew << ", ";
00180 *os << "'instsSinceCovNew' : " << es->instsSinceCovNew << ", ";
00181 *os << "'md2u' : " << md2u << ", ";
00182 *os << "'icnt' : " << icnt << ", ";
00183 *os << "'CPicnt' : " << cpicnt << ", ";
00184 *os << "}";
00185 *os << ")\n";
00186 }
00187
00188 delete os;
00189 }
00190
00191 dumpStates = 0;
00192 }
00193
00194 if (maxInstTime>0 && current && !removedStates.count(current)) {
00195 if (timerTicks*kSecondsPerTick > maxInstTime) {
00196 klee_warning("max-instruction-time exceeded: %.2fs",
00197 timerTicks*kSecondsPerTick);
00198 terminateStateEarly(*current, "max-instruction-time exceeded");
00199 }
00200 }
00201
00202 if (!timers.empty()) {
00203 double time = util::getWallTime();
00204
00205 for (std::vector<TimerInfo*>::iterator it = timers.begin(),
00206 ie = timers.end(); it != ie; ++it) {
00207 TimerInfo *ti = *it;
00208
00209 if (time >= ti->nextFireTime) {
00210 ti->timer->run();
00211 ti->nextFireTime = time + ti->rate;
00212 }
00213 }
00214 }
00215
00216 timerTicks = 0;
00217 callsWithoutCheck = 0;
00218 }
00219 }
00220