1061da546Spatrick //===-- DNBTimer.h ----------------------------------------------*- C++ -*-===// 2061da546Spatrick // 3061da546Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4061da546Spatrick // See https://llvm.org/LICENSE.txt for license information. 5061da546Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6061da546Spatrick // 7061da546Spatrick //===----------------------------------------------------------------------===// 8061da546Spatrick // 9061da546Spatrick // Created by Greg Clayton on 12/13/07. 10061da546Spatrick // 11061da546Spatrick //===----------------------------------------------------------------------===// 12061da546Spatrick 13dda28197Spatrick #ifndef LLDB_TOOLS_DEBUGSERVER_SOURCE_DNBTIMER_H 14dda28197Spatrick #define LLDB_TOOLS_DEBUGSERVER_SOURCE_DNBTIMER_H 15061da546Spatrick 16061da546Spatrick #include "DNBDefs.h" 17061da546Spatrick #include "PThreadMutex.h" 18be691f3bSpatrick #include <cstdint> 19061da546Spatrick #include <memory> 20061da546Spatrick #include <sys/time.h> 21061da546Spatrick 22061da546Spatrick class DNBTimer { 23061da546Spatrick public: 24061da546Spatrick // Constructors and Destructors DNBTimer(bool threadSafe)25061da546Spatrick DNBTimer(bool threadSafe) : m_mutexAP() { 26061da546Spatrick if (threadSafe) 27061da546Spatrick m_mutexAP.reset(new PThreadMutex(PTHREAD_MUTEX_RECURSIVE)); 28061da546Spatrick Reset(); 29061da546Spatrick } 30061da546Spatrick DNBTimer(const DNBTimer & rhs)31061da546Spatrick DNBTimer(const DNBTimer &rhs) : m_mutexAP() { 32061da546Spatrick // Create a new mutex to make this timer thread safe as well if 33061da546Spatrick // the timer we are copying is thread safe 34061da546Spatrick if (rhs.IsThreadSafe()) 35061da546Spatrick m_mutexAP.reset(new PThreadMutex(PTHREAD_MUTEX_RECURSIVE)); 36061da546Spatrick m_timeval = rhs.m_timeval; 37061da546Spatrick } 38061da546Spatrick 39061da546Spatrick DNBTimer &operator=(const DNBTimer &rhs) { 40061da546Spatrick // Create a new mutex to make this timer thread safe as well if 41061da546Spatrick // the timer we are copying is thread safe 42061da546Spatrick if (rhs.IsThreadSafe()) 43061da546Spatrick m_mutexAP.reset(new PThreadMutex(PTHREAD_MUTEX_RECURSIVE)); 44061da546Spatrick m_timeval = rhs.m_timeval; 45061da546Spatrick return *this; 46061da546Spatrick } 47061da546Spatrick ~DNBTimer()48061da546Spatrick ~DNBTimer() {} 49061da546Spatrick IsThreadSafe()50061da546Spatrick bool IsThreadSafe() const { return m_mutexAP.get() != NULL; } 51061da546Spatrick // Reset the time value to now Reset()52061da546Spatrick void Reset() { 53061da546Spatrick PTHREAD_MUTEX_LOCKER(locker, m_mutexAP.get()); 54061da546Spatrick gettimeofday(&m_timeval, NULL); 55061da546Spatrick } 56*f6aab3d8Srobert // Get the total microseconds since Jan 1, 1970 TotalMicroSeconds()57061da546Spatrick uint64_t TotalMicroSeconds() const { 58061da546Spatrick PTHREAD_MUTEX_LOCKER(locker, m_mutexAP.get()); 59061da546Spatrick return (uint64_t)(m_timeval.tv_sec) * 1000000ull + 60061da546Spatrick (uint64_t)m_timeval.tv_usec; 61061da546Spatrick } 62061da546Spatrick GetTime(uint64_t & sec,uint32_t & usec)63061da546Spatrick void GetTime(uint64_t &sec, uint32_t &usec) const { 64061da546Spatrick PTHREAD_MUTEX_LOCKER(locker, m_mutexAP.get()); 65061da546Spatrick sec = m_timeval.tv_sec; 66061da546Spatrick usec = m_timeval.tv_usec; 67061da546Spatrick } 68061da546Spatrick // Return the number of microseconds elapsed between now and the 69061da546Spatrick // m_timeval ElapsedMicroSeconds(bool update)70061da546Spatrick uint64_t ElapsedMicroSeconds(bool update) { 71061da546Spatrick PTHREAD_MUTEX_LOCKER(locker, m_mutexAP.get()); 72061da546Spatrick struct timeval now; 73061da546Spatrick gettimeofday(&now, NULL); 74061da546Spatrick uint64_t now_usec = 75061da546Spatrick (uint64_t)(now.tv_sec) * 1000000ull + (uint64_t)now.tv_usec; 76061da546Spatrick uint64_t this_usec = 77061da546Spatrick (uint64_t)(m_timeval.tv_sec) * 1000000ull + (uint64_t)m_timeval.tv_usec; 78061da546Spatrick uint64_t elapsed = now_usec - this_usec; 79061da546Spatrick // Update the timer time value if requeseted 80061da546Spatrick if (update) 81061da546Spatrick m_timeval = now; 82061da546Spatrick return elapsed; 83061da546Spatrick } 84061da546Spatrick GetTimeOfDay()85061da546Spatrick static uint64_t GetTimeOfDay() { 86061da546Spatrick struct timeval now; 87061da546Spatrick gettimeofday(&now, NULL); 88061da546Spatrick uint64_t now_usec = 89061da546Spatrick (uint64_t)(now.tv_sec) * 1000000ull + (uint64_t)now.tv_usec; 90061da546Spatrick return now_usec; 91061da546Spatrick } 92061da546Spatrick 93061da546Spatrick static void OffsetTimeOfDay(struct timespec *ts, 94061da546Spatrick __darwin_time_t sec_offset = 0, 95061da546Spatrick long nsec_offset = 0) { 96061da546Spatrick if (ts == NULL) 97061da546Spatrick return; 98061da546Spatrick // Get the current time in a timeval structure 99061da546Spatrick struct timeval now; 100061da546Spatrick gettimeofday(&now, NULL); 101061da546Spatrick // Morph it into a timespec 102061da546Spatrick TIMEVAL_TO_TIMESPEC(&now, ts); 103061da546Spatrick // Offset the timespec if requested 104061da546Spatrick if (sec_offset != 0 || nsec_offset != 0) { 105061da546Spatrick // Offset the nano seconds 106061da546Spatrick ts->tv_nsec += nsec_offset; 107061da546Spatrick // Offset the seconds taking into account a nano-second overflow 108061da546Spatrick ts->tv_sec = ts->tv_sec + ts->tv_nsec / 1000000000 + sec_offset; 109061da546Spatrick // Trim the nanoseconds back there was an overflow 110061da546Spatrick ts->tv_nsec = ts->tv_nsec % 1000000000; 111061da546Spatrick } 112061da546Spatrick } TimeOfDayLaterThan(struct timespec & ts)113061da546Spatrick static bool TimeOfDayLaterThan(struct timespec &ts) { 114061da546Spatrick struct timespec now; 115061da546Spatrick OffsetTimeOfDay(&now); 116061da546Spatrick if (now.tv_sec > ts.tv_sec) 117061da546Spatrick return true; 118061da546Spatrick else if (now.tv_sec < ts.tv_sec) 119061da546Spatrick return false; 120061da546Spatrick else { 121061da546Spatrick if (now.tv_nsec > ts.tv_nsec) 122061da546Spatrick return true; 123061da546Spatrick else 124061da546Spatrick return false; 125061da546Spatrick } 126061da546Spatrick } 127061da546Spatrick 128061da546Spatrick protected: 129061da546Spatrick // Classes that inherit from DNBTimer can see and modify these 130061da546Spatrick std::unique_ptr<PThreadMutex> m_mutexAP; 131061da546Spatrick struct timeval m_timeval; 132061da546Spatrick }; 133061da546Spatrick 134dda28197Spatrick #endif // LLDB_TOOLS_DEBUGSERVER_SOURCE_DNBTIMER_H 135