about summary refs log tree commit diff homepage
path: root/lib/Core/ExecutorTimers.cpp
blob: 8ebe5aed2e8c6fe2ea7e0f0edce77a42e37b2802 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
//===-- ExecutorTimers.cpp ------------------------------------------------===//
//
//                     The KLEE Symbolic Virtual Machine
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "CoreStats.h"
#include "Executor.h"
#include "ExecutorTimerInfo.h"
#include "PTree.h"
#include "StatsTracker.h"

#include "klee/ExecutionState.h"
#include "klee/Internal/Module/InstructionInfoTable.h"
#include "klee/Internal/Module/KInstruction.h"
#include "klee/Internal/Module/KModule.h"
#include "klee/Internal/Support/ErrorHandling.h"
#include "klee/Internal/System/Time.h"
#include "klee/OptionCategories.h"

#include "llvm/IR/Function.h"
#include "llvm/Support/CommandLine.h"

#include <math.h>
#include <signal.h>
#include <string>
#include <sys/time.h>
#include <unistd.h>

using namespace llvm;
using namespace klee;

namespace klee {
cl::opt<std::string>
    MaxTime("max-time",
            cl::desc("Halt execution after the specified number of seconds.  "
                     "Set to 0s to disable (default=0s)"),
            cl::init("0s"),
            cl::cat(TerminationCat));

cl::opt<std::string>
    TimerInterval("timer-interval",
                  cl::desc("Minimum interval to check timers (default=1s)"),
                  cl::init("1s"),
                  cl::cat(TerminationCat)); // StatsCat?
}

///

class HaltTimer : public Executor::Timer {
  Executor *executor;

public:
  HaltTimer(Executor *_executor) : executor(_executor) {}
  ~HaltTimer() {}

  void run() {
    klee_message("HaltTimer invoked");
    executor->setHaltExecution(true);
  }
};

///

void Executor::initTimers() {
  const time::Span maxTime(MaxTime);
  if (maxTime) {
    addTimer(new HaltTimer(this), maxTime);
  }
}

///

void Executor::addTimer(Timer *timer, time::Span rate) {
  timers.push_back(new TimerInfo(timer, rate));
}

void Executor::processTimers(ExecutionState *current,
                             time::Span maxInstTime) {
  const static time::Span minInterval(TimerInterval);
  static time::Point lastCheckedTime;
  const auto currentTime = time::getWallTime();
  const auto duration = currentTime - lastCheckedTime;

  if (duration < minInterval) return;

  // check max instruction time
  if (maxInstTime && current &&
      std::find(removedStates.begin(), removedStates.end(), current) == removedStates.end() &&
      duration > maxInstTime) {
    klee_warning("max-instruction-time exceeded: %.2fs", duration.toSeconds());
    terminateStateEarly(*current, "max-instruction-time exceeded");
  }


  // check timers
  for (auto &timerInfo : timers) {
    if (currentTime >= timerInfo->nextFireTime) {
      timerInfo->timer->run();
      timerInfo->nextFireTime = currentTime + timerInfo->rate;
    }
  }

  lastCheckedTime = currentTime;
}