ExecutorTimers.cpp

Go to the documentation of this file.
00001 //===-- ExecutorTimers.cpp ------------------------------------------------===//
00002 //
00003 //                     The KLEE Symbolic Virtual Machine
00004 //
00005 // This file is distributed under the University of Illinois Open Source
00006 // License. See LICENSE.TXT for details.
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 // XXX hack
00061 extern "C" unsigned dumpStates, dumpPTree;
00062 unsigned dumpStates = 0, dumpPTree = 0;
00063 
00064 static void onAlarm(int) {
00065   ++timerTicks;
00066 }
00067 
00068 // oooogalay
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 

Generated on Fri Jun 5 03:31:31 2009 for klee by  doxygen 1.5.8