TimeoutChecker.cpp [plain text]
#include "config.h"
#include "TimeoutChecker.h"
#include "CallFrame.h"
#include "JSGlobalObject.h"
#if PLATFORM(DARWIN)
#include <mach/mach.h>
#endif
#if HAVE(SYS_TIME_H)
#include <sys/time.h>
#endif
#if PLATFORM(WIN_OS)
#include <windows.h>
#endif
#if PLATFORM(QT)
#include <QDateTime>
#endif
using namespace std;
namespace JSC {
static const int ticksUntilFirstCheck = 1024;
static const int intervalBetweenChecks = 1000;
static inline unsigned getCPUTime()
{
#if PLATFORM(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 HAVE(SYS_TIME_H)
struct timeval tv;
gettimeofday(&tv, 0);
return tv.tv_sec * 1000 + tv.tv_usec / 1000;
#elif PLATFORM(QT)
QDateTime t = QDateTime::currentDateTime();
return t.toTime_t() * 1000 + t.time().msec();
#elif PLATFORM(WIN_OS)
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
#error Platform does not have getCurrentTime function
#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()->shouldInterruptScriptBeforeTimeout())
return true;
if (m_timeoutInterval && m_timeExecuting > m_timeoutInterval) {
if (exec->dynamicGlobalObject()->shouldInterruptScript())
return true;
reset();
}
return false;
}
}