crashpad/util/misc/time.h
Joshua Peraza 6dadd492b8 linux: fix proc stat reader flakiness
ProcStatReader.Threads is flaky because it relies on an internal,
imprecise measurement of boot time. The flaky test asserts that a
thread started after the main thread should have a start time >= the
main thread. The start time is returned in a timeval, with microsecond
precision, but the measurement of boot time requires two system calls
and the time between those system calls can be approximately a
microsecond. An unlucky event such as a change in system time could
make this imprecision arbitrarily bad.

This patch lets the caller of ProcStatReader.StartTime() inject the
boot time, allowing ProcStatReader to guarantee that threads have
correctly ordered time, given the same input boot time.

Bug: 1016765
Change-Id: I6e4a944a1d58c3916090bab6a4b99573e71a89fc
Reviewed-on: https://chromium-review.googlesource.com/c/crashpad/crashpad/+/1891588
Reviewed-by: Mark Mentovai <mark@chromium.org>
Commit-Queue: Joshua Peraza <jperaza@chromium.org>
2019-11-07 16:54:17 +00:00

83 lines
2.9 KiB
C++

// Copyright 2015 The Crashpad Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef CRASHPAD_UTIL_MISC_TIME_H_
#define CRASHPAD_UTIL_MISC_TIME_H_
#include <stdint.h>
#include <sys/time.h>
#include <time.h>
#include "build/build_config.h"
#if defined(OS_WIN)
#include <windows.h>
#endif
namespace crashpad {
constexpr uint64_t kNanosecondsPerSecond = static_cast<uint64_t>(1E9);
//! \brief Add `timespec` \a ts1 and \a ts2 and return the result in \a result.
void AddTimespec(const timespec& ts1, const timespec& ts2, timespec* result);
//! \brief Subtract `timespec` \a ts2 from \a ts1 and return the result in \a
//! result.
void SubtractTimespec(const timespec& ts1,
const timespec& ts2,
timespec* result);
//! \brief Convert the timespec \a ts to a timeval \a tv.
//! \return `true` if the assignment is possible without truncation.
bool TimespecToTimeval(const timespec& ts, timeval* tv);
//! \brief Convert the timeval \a tv to a timespec \a ts.
void TimevalToTimespec(const timeval& tv, timespec* ts);
#if defined(OS_WIN) || DOXYGEN
//! \brief Convert a `timespec` to a Windows `FILETIME`, converting from POSIX
//! epoch to Windows epoch.
FILETIME TimespecToFiletimeEpoch(const timespec& ts);
//! \brief Convert a Windows `FILETIME` to `timespec`, converting from Windows
//! epoch to POSIX epoch.
timespec FiletimeToTimespecEpoch(const FILETIME& filetime);
//! \brief Convert Windows `FILETIME` to `timeval`, converting from Windows
//! epoch to POSIX epoch.
timeval FiletimeToTimevalEpoch(const FILETIME& filetime);
//! \brief Convert Windows `FILETIME` to `timeval`, treating the values as
//! an interval of elapsed time.
timeval FiletimeToTimevalInterval(const FILETIME& filetime);
//! \brief Similar to POSIX `gettimeofday()`, gets the current system time in
//! UTC.
void GetTimeOfDay(timeval* tv);
#endif // OS_WIN
#if defined(OS_LINUX) || defined(OS_ANDROID) || DOXYGEN
//! \brief Get the kernel boot time. Subsequent calls to this function may
//! return different results due to the system clock being changed or
//! imprecision in measuring the boot time.
//! \return `true` on success. Otherwise, `false` with a message logged.
bool GetBootTime(timespec* ts);
#endif // OS_LINUX || OS_ANDROID || DOXYGEN
} // namespace crashpad
#endif // CRASHPAD_UTIL_MISC_TIME_H_