xref: /openbsd-src/gnu/llvm/lldb/tools/debugserver/source/DNBTimer.h (revision f6aab3d83b51b91c24247ad2c2573574de475a82)
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