TimeoutChecker.cpp [plain text]
#include "config.h"
#include "TimeoutChecker.h"
#include "CallFrame.h"
#include "JSGlobalObject.h"
#if OS(DARWIN)
#include <mach/mach.h>
#elif OS(WINDOWS)
#include <windows.h>
#else
#include <wtf/CurrentTime.h>
#endif
using namespace std;
namespace JSC {
static const int ticksUntilFirstCheck = 1024;
static const int intervalBetweenChecks = 1000;
static inline unsigned getCPUTime()
{
#if OS(DARWIN)
mach_msg_type_number_t infoCount = THREAD_BASIC_INFO_COUNT;
thread_basic_info_data_t info;
mach_port_t threadPort = mach_thread_self();
thread_info(threadPort, THREAD_BASIC_INFO, reinterpret_cast<thread_info_t>(&info), &infoCount);
mach_port_deallocate(mach_task_self(), threadPort);
unsigned time = info.user_time.seconds * 1000 + info.user_time.microseconds / 1000;
time += info.system_time.seconds * 1000 + info.system_time.microseconds / 1000;
return time;
#elif OS(WINDOWS)
union {
FILETIME fileTime;
unsigned long long fileTimeAsLong;
} userTime, kernelTime;
FILETIME creationTime, exitTime;
GetThreadTimes(GetCurrentThread(), &creationTime, &exitTime, &kernelTime.fileTime, &userTime.fileTime);
return userTime.fileTimeAsLong / 10000 + kernelTime.fileTimeAsLong / 10000;
#else
static double firstTime = currentTime();
return static_cast<unsigned> ((currentTime() - firstTime) * 1000);
#endif
}
TimeoutChecker::TimeoutChecker()
: m_timeoutInterval(0)
, m_startCount(0)
{
reset();
}
void TimeoutChecker::reset()
{
m_ticksUntilNextCheck = ticksUntilFirstCheck;
m_timeAtLastCheck = 0;
m_timeExecuting = 0;
}
bool TimeoutChecker::didTimeOut(ExecState* exec)
{
unsigned currentTime = getCPUTime();
if (!m_timeAtLastCheck) {
m_timeAtLastCheck = currentTime;
return false;
}
unsigned timeDiff = currentTime - m_timeAtLastCheck;
if (timeDiff == 0)
timeDiff = 1;
m_timeExecuting += timeDiff;
m_timeAtLastCheck = currentTime;
m_ticksUntilNextCheck = static_cast<unsigned>((static_cast<float>(intervalBetweenChecks) / timeDiff) * m_ticksUntilNextCheck);
if (m_ticksUntilNextCheck == 0)
m_ticksUntilNextCheck = ticksUntilFirstCheck;
if (exec->dynamicGlobalObject()->globalObjectMethodTable()->shouldInterruptScriptBeforeTimeout(exec->dynamicGlobalObject()))
return true;
if (m_timeoutInterval && m_timeExecuting > m_timeoutInterval) {
if (exec->dynamicGlobalObject()->globalObjectMethodTable()->shouldInterruptScript(exec->dynamicGlobalObject()))
return true;
reset();
}
return false;
}
}