diff options
Diffstat (limited to 'lib/Support')
-rw-r--r-- | lib/Support/Process.cpp | 25 | ||||
-rw-r--r-- | lib/Support/Unix/Process.inc | 62 | ||||
-rw-r--r-- | lib/Support/Windows/Process.inc | 51 |
3 files changed, 103 insertions, 35 deletions
diff --git a/lib/Support/Process.cpp b/lib/Support/Process.cpp index 64a1fa237e..2c0d37bb32 100644 --- a/lib/Support/Process.cpp +++ b/lib/Support/Process.cpp @@ -50,6 +50,31 @@ self_process::~self_process() { llvm_unreachable("This destructor must never be executed!"); } +/// \brief A helper function to compute the elapsed wall-time since the program +/// started. +/// +/// Note that this routine actually computes the elapsed wall time since the +/// first time it was called. However, we arrange to have it called during the +/// startup of the process to get approximately correct results. +static TimeValue getElapsedWallTime() { + static TimeValue &StartTime = *new TimeValue(TimeValue::now()); + return TimeValue::now() - StartTime; +} + +/// \brief A special global variable to ensure we call \c getElapsedWallTime +/// during global initialization of the program. +/// +/// Note that this variable is never referenced elsewhere. Doing so could +/// create race conditions during program startup or shutdown. +static volatile TimeValue DummyTimeValue = getElapsedWallTime(); + +// Implement this routine by using the static helpers above. They're already +// portable. +TimeValue self_process::get_wall_time() const { + return getElapsedWallTime(); +} + + #if defined(_MSC_VER) #pragma warning(pop) #endif diff --git a/lib/Support/Unix/Process.inc b/lib/Support/Unix/Process.inc index 9ad6272bab..a525538f78 100644 --- a/lib/Support/Unix/Process.inc +++ b/lib/Support/Unix/Process.inc @@ -49,6 +49,43 @@ process::id_type self_process::get_id() { return getpid(); } +static std::pair<TimeValue, TimeValue> getRUsageTimes() { +#if defined(HAVE_GETRUSAGE) + struct rusage RU; + ::getrusage(RUSAGE_SELF, &RU); + return std::make_pair( + TimeValue( + static_cast<TimeValue::SecondsType>(RU.ru_utime.tv_sec), + static_cast<TimeValue::NanoSecondsType>( + RU.ru_utime.tv_usec * TimeValue::NANOSECONDS_PER_MICROSECOND)), + TimeValue( + static_cast<TimeValue::SecondsType>(RU.ru_stime.tv_sec), + static_cast<TimeValue::NanoSecondsType>( + RU.ru_stime.tv_usec * TimeValue::NANOSECONDS_PER_MICROSECOND))); +#else +#warning Cannot get usage times on this platform + return std::make_pair(TimeValue(), TimeValue()); +#endif +} + +TimeValue self_process::get_user_time() const { +#ifdef _POSIX_CPUTIME + // Try to get a high resolution CPU timer. + struct timespec TS; + if (::clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &TS) == 0) + return TimeValue(static_cast<TimeValue::SecondsType>(TS.tv_sec), + static_cast<TimeValue::NanoSecondsType>(TS.tv_nsec)); +#endif + + // Otherwise fall back to rusage based timing. + return getRUsageTimes().first; +} + +TimeValue self_process::get_system_time() const { + // We can only collect system time by inspecting the results of getrusage. + return getRUsageTimes().second; +} + static unsigned getPageSize() { #if defined(__CYGWIN__) // On Cygwin, getpagesize() returns 64k but the page size for the purposes of @@ -95,29 +132,10 @@ size_t Process::GetMallocUsage() { #endif } -void -Process::GetTimeUsage(TimeValue& elapsed, TimeValue& user_time, - TimeValue& sys_time) -{ +void Process::GetTimeUsage(TimeValue &elapsed, TimeValue &user_time, + TimeValue &sys_time) { elapsed = TimeValue::now(); -#if defined(HAVE_GETRUSAGE) - struct rusage usage; - ::getrusage(RUSAGE_SELF, &usage); - user_time = TimeValue( - static_cast<TimeValue::SecondsType>( usage.ru_utime.tv_sec ), - static_cast<TimeValue::NanoSecondsType>( usage.ru_utime.tv_usec * - TimeValue::NANOSECONDS_PER_MICROSECOND ) ); - sys_time = TimeValue( - static_cast<TimeValue::SecondsType>( usage.ru_stime.tv_sec ), - static_cast<TimeValue::NanoSecondsType>( usage.ru_stime.tv_usec * - TimeValue::NANOSECONDS_PER_MICROSECOND ) ); -#else -#warning Cannot get usage times on this platform - user_time.seconds(0); - user_time.microseconds(0); - sys_time.seconds(0); - sys_time.microseconds(0); -#endif + llvm::tie(user_time, sys_time) = getRUsageTimes(); } int Process::GetCurrentUserId() { diff --git a/lib/Support/Windows/Process.inc b/lib/Support/Windows/Process.inc index 9eb611be87..789ae7ddce 100644 --- a/lib/Support/Windows/Process.inc +++ b/lib/Support/Windows/Process.inc @@ -43,6 +43,36 @@ process::id_type self_process::get_id() { return GetCurrentProcess(); } +static TimeValue getTimeValueFromFILETIME(FILETIME Time) { + ULARGE_INTEGER TimeInteger; + TimeInteger.LowPart = Time.dwLowDateTime; + TimeInteger.HighPart = Time.dwHighDateTime; + + // FILETIME's are # of 100 nanosecond ticks (1/10th of a microsecond) + return TimeValue( + static_cast<TimeValue::SecondsType>(TimeInteger.QuadPart / 10000000), + static_cast<TimeValue::NanoSecondsType>( + (TimeInteger.QuadPart % 10000000) * 100)); +} + +TimeValue self_process::get_user_time() const { + FILETIME ProcCreate, ProcExit, KernelTime, UserTime; + if (GetProcessTimes(GetCurrentProcess(), &ProcCreate, &ProcExit, &KernelTime, + &UserTime) == 0) + return TimeValue(); + + return getTimeValueFromFILETIME(UserTime); +} + +TimeValue self_process::get_system_time() const { + FILETIME ProcCreate, ProcExit, KernelTime, UserTime; + if (GetProcessTimes(GetCurrentProcess(), &ProcCreate, &ProcExit, &KernelTime, + &UserTime) == 0) + return TimeValue(); + + return getTimeValueFromFILETIME(KernelTime); +} + // This function retrieves the page size using GetSystemInfo and is present // solely so it can be called once to initialize the self_process member below. static unsigned getPageSize() { @@ -76,22 +106,17 @@ Process::GetMallocUsage() return size; } -void -Process::GetTimeUsage( - TimeValue& elapsed, TimeValue& user_time, TimeValue& sys_time) -{ +void Process::GetTimeUsage(TimeValue &elapsed, TimeValue &user_time, + TimeValue &sys_time) { elapsed = TimeValue::now(); - uint64_t ProcCreate, ProcExit, KernelTime, UserTime; - GetProcessTimes(GetCurrentProcess(), (FILETIME*)&ProcCreate, - (FILETIME*)&ProcExit, (FILETIME*)&KernelTime, - (FILETIME*)&UserTime); + FILETIME ProcCreate, ProcExit, KernelTime, UserTime; + if (GetProcessTimes(GetCurrentProcess(), &ProcCreate, &ProcExit, &KernelTime, + &UserTime) == 0) + return; - // FILETIME's are # of 100 nanosecond ticks (1/10th of a microsecond) - user_time.seconds( UserTime / 10000000 ); - user_time.nanoseconds( unsigned(UserTime % 10000000) * 100 ); - sys_time.seconds( KernelTime / 10000000 ); - sys_time.nanoseconds( unsigned(KernelTime % 10000000) * 100 ); + user_time = getTimeValueFromFILETIME(UserTime); + sys_time = getTimeValueFromFILETIME(SystemTime); } int Process::GetCurrentUserId() |