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-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // Created by Greg Clayton on 12/13/07. 10 // 11 //===----------------------------------------------------------------------===// 12 13 #ifndef LLDB_TOOLS_DEBUGSERVER_SOURCE_DNBTIMER_H 14 #define LLDB_TOOLS_DEBUGSERVER_SOURCE_DNBTIMER_H 15 16 #include "DNBDefs.h" 17 #include "PThreadMutex.h" 18 #include <memory> 19 #include <stdint.h> 20 #include <sys/time.h> 21 22 class DNBTimer { 23 public: 24 // Constructors and Destructors DNBTimer(bool threadSafe)25 DNBTimer(bool threadSafe) : m_mutexAP() { 26 if (threadSafe) 27 m_mutexAP.reset(new PThreadMutex(PTHREAD_MUTEX_RECURSIVE)); 28 Reset(); 29 } 30 DNBTimer(const DNBTimer & rhs)31 DNBTimer(const DNBTimer &rhs) : m_mutexAP() { 32 // Create a new mutex to make this timer thread safe as well if 33 // the timer we are copying is thread safe 34 if (rhs.IsThreadSafe()) 35 m_mutexAP.reset(new PThreadMutex(PTHREAD_MUTEX_RECURSIVE)); 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 if 41 // the timer we are copying is thread safe 42 if (rhs.IsThreadSafe()) 43 m_mutexAP.reset(new PThreadMutex(PTHREAD_MUTEX_RECURSIVE)); 44 m_timeval = rhs.m_timeval; 45 return *this; 46 } 47 ~DNBTimer()48 ~DNBTimer() {} 49 IsThreadSafe()50 bool IsThreadSafe() const { return m_mutexAP.get() != NULL; } 51 // Reset the time value to now Reset()52 void Reset() { 53 PTHREAD_MUTEX_LOCKER(locker, m_mutexAP.get()); 54 gettimeofday(&m_timeval, NULL); 55 } 56 // Get the total mircoseconds since Jan 1, 1970 TotalMicroSeconds()57 uint64_t TotalMicroSeconds() const { 58 PTHREAD_MUTEX_LOCKER(locker, m_mutexAP.get()); 59 return (uint64_t)(m_timeval.tv_sec) * 1000000ull + 60 (uint64_t)m_timeval.tv_usec; 61 } 62 GetTime(uint64_t & sec,uint32_t & usec)63 void GetTime(uint64_t &sec, uint32_t &usec) const { 64 PTHREAD_MUTEX_LOCKER(locker, m_mutexAP.get()); 65 sec = m_timeval.tv_sec; 66 usec = m_timeval.tv_usec; 67 } 68 // Return the number of microseconds elapsed between now and the 69 // m_timeval ElapsedMicroSeconds(bool update)70 uint64_t ElapsedMicroSeconds(bool update) { 71 PTHREAD_MUTEX_LOCKER(locker, m_mutexAP.get()); 72 struct timeval now; 73 gettimeofday(&now, NULL); 74 uint64_t now_usec = 75 (uint64_t)(now.tv_sec) * 1000000ull + (uint64_t)now.tv_usec; 76 uint64_t this_usec = 77 (uint64_t)(m_timeval.tv_sec) * 1000000ull + (uint64_t)m_timeval.tv_usec; 78 uint64_t elapsed = now_usec - this_usec; 79 // Update the timer time value if requeseted 80 if (update) 81 m_timeval = now; 82 return elapsed; 83 } 84 GetTimeOfDay()85 static uint64_t GetTimeOfDay() { 86 struct timeval now; 87 gettimeofday(&now, NULL); 88 uint64_t now_usec = 89 (uint64_t)(now.tv_sec) * 1000000ull + (uint64_t)now.tv_usec; 90 return now_usec; 91 } 92 93 static void OffsetTimeOfDay(struct timespec *ts, 94 __darwin_time_t sec_offset = 0, 95 long nsec_offset = 0) { 96 if (ts == NULL) 97 return; 98 // Get the current time in a timeval structure 99 struct timeval now; 100 gettimeofday(&now, NULL); 101 // Morph it into a timespec 102 TIMEVAL_TO_TIMESPEC(&now, ts); 103 // Offset the timespec if requested 104 if (sec_offset != 0 || nsec_offset != 0) { 105 // Offset the nano seconds 106 ts->tv_nsec += nsec_offset; 107 // Offset the seconds taking into account a nano-second overflow 108 ts->tv_sec = ts->tv_sec + ts->tv_nsec / 1000000000 + sec_offset; 109 // Trim the nanoseconds back there was an overflow 110 ts->tv_nsec = ts->tv_nsec % 1000000000; 111 } 112 } TimeOfDayLaterThan(struct timespec & ts)113 static bool TimeOfDayLaterThan(struct timespec &ts) { 114 struct timespec now; 115 OffsetTimeOfDay(&now); 116 if (now.tv_sec > ts.tv_sec) 117 return true; 118 else if (now.tv_sec < ts.tv_sec) 119 return false; 120 else { 121 if (now.tv_nsec > ts.tv_nsec) 122 return true; 123 else 124 return false; 125 } 126 } 127 128 protected: 129 // Classes that inherit from DNBTimer can see and modify these 130 std::unique_ptr<PThreadMutex> m_mutexAP; 131 struct timeval m_timeval; 132 }; 133 134 #endif // LLDB_TOOLS_DEBUGSERVER_SOURCE_DNBTIMER_H 135