From 6bf0a5cb5034a7e684dcc3500e841785237ce2dd Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 7 Apr 2024 19:32:43 +0200 Subject: Adding upstream version 1:115.7.0. Signed-off-by: Daniel Baumann --- comm/mailnews/base/src/nsStopwatch.cpp | 164 +++++++++++++++++++++++++++++++++ 1 file changed, 164 insertions(+) create mode 100644 comm/mailnews/base/src/nsStopwatch.cpp (limited to 'comm/mailnews/base/src/nsStopwatch.cpp') diff --git a/comm/mailnews/base/src/nsStopwatch.cpp b/comm/mailnews/base/src/nsStopwatch.cpp new file mode 100644 index 0000000000..585450d113 --- /dev/null +++ b/comm/mailnews/base/src/nsStopwatch.cpp @@ -0,0 +1,164 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "nsStopwatch.h" + +#include +#include +#if defined(XP_UNIX) +# include +# include +# include +# include +#elif defined(XP_WIN) +# include "windows.h" +#endif // elif defined(XP_WIN) + +#include "nsMemory.h" +/* + * This basis for the logic in this file comes from (will used to come from): + * (mozilla/)modules/libutil/public/stopwatch.cpp. + * + * It was no longer used in the mozilla tree, and is being migrated to + * comm-central where we actually have a need for it. ("Being" in the sense + * that it will not be removed immediately from mozilla-central.) + * + * Simplification and general clean-up has been performed and the fix for + * bug 96669 has been integrated. + */ + +NS_IMPL_ISUPPORTS(nsStopwatch, nsIStopwatch) + +#if defined(XP_UNIX) +/** the number of ticks per second */ +static double gTicks = 0; +# define MICRO_SECONDS_TO_SECONDS_MULT static_cast(1.0e-6) +#elif defined(WIN32) +# ifdef DEBUG +# include "nsPrintfCString.h" +# endif +// 1 tick per 100ns = 10 per us = 10 * 1,000 per ms = 10 * 1,000 * 1,000 per +// sec. +# define WIN32_TICK_RESOLUTION static_cast(1.0e-7) +// subtract off to get to the unix epoch +# define UNIX_EPOCH_IN_FILE_TIME 116444736000000000L +#endif // elif defined(WIN32) + +nsStopwatch::nsStopwatch() + : fTotalRealTimeSecs(0.0), fTotalCpuTimeSecs(0.0), fRunning(false) { +#if defined(XP_UNIX) + // idempotent in the event of a race under all coherency models + if (!gTicks) { + // we need to clear errno because sysconf's spec says it leaves it the same + // on success and only sets it on failure. + errno = 0; + gTicks = (clock_t)sysconf(_SC_CLK_TCK); + // in event of failure, pick an arbitrary value so we don't divide by zero. + if (errno) gTicks = 1000000L; + } +#endif +} + +nsStopwatch::~nsStopwatch() {} + +NS_IMETHODIMP nsStopwatch::Start() { + fTotalRealTimeSecs = 0.0; + fTotalCpuTimeSecs = 0.0; + return Resume(); +} + +NS_IMETHODIMP nsStopwatch::Stop() { + fStopRealTimeSecs = GetRealTime(); + fStopCpuTimeSecs = GetCPUTime(); + if (fRunning) { + fTotalCpuTimeSecs += fStopCpuTimeSecs - fStartCpuTimeSecs; + fTotalRealTimeSecs += fStopRealTimeSecs - fStartRealTimeSecs; + } + fRunning = false; + return NS_OK; +} + +NS_IMETHODIMP nsStopwatch::Resume() { + if (!fRunning) { + fStartRealTimeSecs = GetRealTime(); + fStartCpuTimeSecs = GetCPUTime(); + } + fRunning = true; + return NS_OK; +} + +NS_IMETHODIMP nsStopwatch::GetCpuTimeSeconds(double* result) { + NS_ENSURE_ARG_POINTER(result); + *result = fTotalCpuTimeSecs; + return NS_OK; +} + +NS_IMETHODIMP nsStopwatch::GetRealTimeSeconds(double* result) { + NS_ENSURE_ARG_POINTER(result); + *result = fTotalRealTimeSecs; + return NS_OK; +} + +double nsStopwatch::GetRealTime() { +#if defined(XP_UNIX) + struct timeval t; + gettimeofday(&t, NULL); + return t.tv_sec + t.tv_usec * MICRO_SECONDS_TO_SECONDS_MULT; +#elif defined(WIN32) + union { + FILETIME ftFileTime; + __int64 ftInt64; + } ftRealTime; // time the process has spent in kernel mode + SYSTEMTIME st; + GetSystemTime(&st); + SystemTimeToFileTime(&st, &ftRealTime.ftFileTime); + return (ftRealTime.ftInt64 - UNIX_EPOCH_IN_FILE_TIME) * WIN32_TICK_RESOLUTION; +#else +# error "nsStopwatch not supported on this platform." +#endif +} + +double nsStopwatch::GetCPUTime() { +#if defined(XP_UNIX) + struct tms cpt; + times(&cpt); + return (double)(cpt.tms_utime + cpt.tms_stime) / gTicks; +#elif defined(WIN32) + FILETIME ftCreate, // when the process was created + ftExit; // when the process exited + + union { + FILETIME ftFileTime; + __int64 ftInt64; + } ftKernel; // time the process has spent in kernel mode + + union { + FILETIME ftFileTime; + __int64 ftInt64; + } ftUser; // time the process has spent in user mode + + HANDLE hProcess = GetCurrentProcess(); +# ifdef DEBUG + BOOL ret = +# endif + GetProcessTimes(hProcess, &ftCreate, &ftExit, &ftKernel.ftFileTime, + &ftUser.ftFileTime); +# ifdef DEBUG + if (!ret) + NS_ERROR(nsPrintfCString("GetProcessTimes() failed, error=0x%lx.", + GetLastError()) + .get()); +# endif + + /* + * Process times are returned in a 64-bit structure, as the number of + * 100 nanosecond ticks since 1 January 1601. User mode and kernel mode + * times for this process are in separate 64-bit structures. + * Add them and convert the result to seconds. + */ + return (ftKernel.ftInt64 + ftUser.ftInt64) * WIN32_TICK_RESOLUTION; +#else +# error "nsStopwatch not supported on this platform." +#endif +} -- cgit v1.2.3