141 lines · c
1//===-- DNBTimer.h ----------------------------------------------*- C++ -*-===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8//9// Created by Greg Clayton on 12/13/07.10//11//===----------------------------------------------------------------------===//12 13#ifndef LLDB_TOOLS_DEBUGSERVER_SOURCE_DNBTIMER_H14#define LLDB_TOOLS_DEBUGSERVER_SOURCE_DNBTIMER_H15 16#include "DNBDefs.h"17#include <cstdint>18#include <mutex>19#include <optional>20#include <sys/time.h>21 22class DNBTimer {23public:24 // Constructors and Destructors25 DNBTimer(bool threadSafe) {26 if (threadSafe)27 m_mutex.emplace();28 Reset();29 }30 31 DNBTimer(const DNBTimer &rhs) {32 // Create a new mutex to make this timer thread safe as well if33 // the timer we are copying is thread safe34 if (rhs.IsThreadSafe())35 m_mutex.emplace();36 m_timeval = rhs.m_timeval;37 }38 39 DNBTimer &operator=(const DNBTimer &rhs) {40 // Create a new mutex to make this timer thread safe as well if41 // the timer we are copying is thread safe42 if (rhs.IsThreadSafe())43 m_mutex.emplace();44 m_timeval = rhs.m_timeval;45 return *this;46 }47 48 ~DNBTimer() {}49 50 bool IsThreadSafe() const { return m_mutex.has_value(); }51 // Reset the time value to now52 void Reset() {53 auto lock = m_mutex ? std::unique_lock<std::recursive_mutex>(*m_mutex)54 : std::unique_lock<std::recursive_mutex>();55 gettimeofday(&m_timeval, NULL);56 }57 // Get the total microseconds since Jan 1, 197058 uint64_t TotalMicroSeconds() const {59 std::unique_lock<std::recursive_mutex> lock =60 m_mutex ? std::unique_lock<std::recursive_mutex>(*m_mutex)61 : std::unique_lock<std::recursive_mutex>();62 return (uint64_t)(m_timeval.tv_sec) * 1000000ull +63 (uint64_t)m_timeval.tv_usec;64 }65 66 void GetTime(uint64_t &sec, uint32_t &usec) const {67 auto lock = m_mutex ? std::unique_lock<std::recursive_mutex>(*m_mutex)68 : std::unique_lock<std::recursive_mutex>();69 sec = m_timeval.tv_sec;70 usec = m_timeval.tv_usec;71 }72 // Return the number of microseconds elapsed between now and the73 // m_timeval74 uint64_t ElapsedMicroSeconds(bool update) {75 std::unique_lock<std::recursive_mutex> lock =76 m_mutex ? std::unique_lock<std::recursive_mutex>(*m_mutex)77 : std::unique_lock<std::recursive_mutex>();78 struct timeval now;79 gettimeofday(&now, NULL);80 uint64_t now_usec =81 (uint64_t)(now.tv_sec) * 1000000ull + (uint64_t)now.tv_usec;82 uint64_t this_usec =83 (uint64_t)(m_timeval.tv_sec) * 1000000ull + (uint64_t)m_timeval.tv_usec;84 uint64_t elapsed = now_usec - this_usec;85 // Update the timer time value if requeseted86 if (update)87 m_timeval = now;88 return elapsed;89 }90 91 static uint64_t GetTimeOfDay() {92 struct timeval now;93 gettimeofday(&now, NULL);94 uint64_t now_usec =95 (uint64_t)(now.tv_sec) * 1000000ull + (uint64_t)now.tv_usec;96 return now_usec;97 }98 99 static void OffsetTimeOfDay(struct timespec *ts,100 __darwin_time_t sec_offset = 0,101 long nsec_offset = 0) {102 if (ts == NULL)103 return;104 // Get the current time in a timeval structure105 struct timeval now;106 gettimeofday(&now, NULL);107 // Morph it into a timespec108 TIMEVAL_TO_TIMESPEC(&now, ts);109 // Offset the timespec if requested110 if (sec_offset != 0 || nsec_offset != 0) {111 // Offset the nano seconds112 ts->tv_nsec += nsec_offset;113 // Offset the seconds taking into account a nano-second overflow114 ts->tv_sec = ts->tv_sec + ts->tv_nsec / 1000000000 + sec_offset;115 // Trim the nanoseconds back there was an overflow116 ts->tv_nsec = ts->tv_nsec % 1000000000;117 }118 }119 static bool TimeOfDayLaterThan(struct timespec &ts) {120 struct timespec now;121 OffsetTimeOfDay(&now);122 if (now.tv_sec > ts.tv_sec)123 return true;124 else if (now.tv_sec < ts.tv_sec)125 return false;126 else {127 if (now.tv_nsec > ts.tv_nsec)128 return true;129 else130 return false;131 }132 }133 134protected:135 // Classes that inherit from DNBTimer can see and modify these136 mutable std::optional<std::recursive_mutex> m_mutex;137 struct timeval m_timeval;138};139 140#endif // LLDB_TOOLS_DEBUGSERVER_SOURCE_DNBTIMER_H141