#include <stdint.h>
#include <sys/time.h>
#include <time.h>
#include <unistd.h>
#include <optional>
#include "base/check.h"
#include "base/notreached.h"
#include "base/numerics/safe_math.h"
#include "base/time/time.h"
#include "base/time/time_override.h"
#include "build/build_config.h"
#if BUILDFLAG(IS_ANDROID) && !defined(__LP64__)
#include <time64.h>
#endif
#if BUILDFLAG(IS_FUCHSIA) || BUILDFLAG(IS_APPLE)
#error "This implementation is for POSIX platforms other than Fuchsia or Mac."
#endif
namespace {
int64_t ConvertTimespecToMicros(const struct timespec& ts) {
if (sizeof(ts.tv_sec) <= 4 && sizeof(ts.tv_nsec) <= 8) {
int64_t result = ts.tv_sec;
result *= base::Time::kMicrosecondsPerSecond;
result += (ts.tv_nsec / base::Time::kNanosecondsPerMicrosecond);
return result;
}
base::CheckedNumeric<int64_t> result(ts.tv_sec);
result *= base::Time::kMicrosecondsPerSecond;
result += (ts.tv_nsec / base::Time::kNanosecondsPerMicrosecond);
return result.ValueOrDie();
}
#if (BUILDFLAG(IS_POSIX) && defined(_POSIX_MONOTONIC_CLOCK) && \
_POSIX_MONOTONIC_CLOCK >= 0) || \
BUILDFLAG(IS_BSD) || BUILDFLAG(IS_ANDROID)
int64_t ClockNow(clockid_t clk_id) {
struct timespec ts;
CHECK(clock_gettime(clk_id, &ts) == 0);
return ConvertTimespecToMicros(ts);
}
std::optional<int64_t> MaybeClockNow(clockid_t clk_id) {
struct timespec ts;
int res = clock_gettime(clk_id, &ts);
if (res == 0) {
return ConvertTimespecToMicros(ts);
}
return std::nullopt;
}
#else
#error No usable tick clock function on this platform.
#endif
}
namespace base {
namespace subtle {
Time TimeNowIgnoringOverride() {
struct timeval tv;
struct timezone tz = {0, 0};
CHECK(gettimeofday(&tv, &tz) == 0);
return Time() +
Microseconds((tv.tv_sec * Time::kMicrosecondsPerSecond + tv.tv_usec) +
Time::kTimeTToMicrosecondsOffset);
}
Time TimeNowFromSystemTimeIgnoringOverride() {
return TimeNowIgnoringOverride();
}
}
namespace subtle {
TimeTicks TimeTicksNowIgnoringOverride() {
return TimeTicks() + Microseconds(ClockNow(CLOCK_MONOTONIC));
}
std::optional<TimeTicks> MaybeTimeTicksNowIgnoringOverride() {
std::optional<int64_t> now = MaybeClockNow(CLOCK_MONOTONIC);
if (now.has_value()) {
return TimeTicks() + Microseconds(now.value());
}
return std::nullopt;
}
TimeTicks TimeTicksLowResolutionNowIgnoringOverride() {
return TimeTicks() + Microseconds(ClockNow(CLOCK_MONOTONIC_COARSE));
}
}
TimeTicks::Clock TimeTicks::GetClock() {
return Clock::LINUX_CLOCK_MONOTONIC;
}
bool TimeTicks::IsHighResolution() {
return true;
}
bool TimeTicks::IsConsistentAcrossProcesses() {
return true;
}
namespace subtle {
ThreadTicks ThreadTicksNowIgnoringOverride() {
#if (defined(_POSIX_THREAD_CPUTIME) && (_POSIX_THREAD_CPUTIME >= 0)) || \
BUILDFLAG(IS_ANDROID)
return ThreadTicks() + Microseconds(ClockNow(CLOCK_THREAD_CPUTIME_ID));
#else
NOTREACHED();
#endif
}
}
}