178 lines
		
	
	
		
			4.4 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			178 lines
		
	
	
		
			4.4 KiB
		
	
	
	
		
			C++
		
	
	
	
| /* clock.h: Definitions for clock calculations
 | |
| 
 | |
| This file is part of Cygwin.
 | |
| 
 | |
| This software is a copyrighted work licensed under the terms of the
 | |
| Cygwin license.  Please consult the file "CYGWIN_LICENSE" for
 | |
| details. */
 | |
| 
 | |
| #ifndef __CLOCK_H__
 | |
| #define __CLOCK_H__
 | |
| 
 | |
| #include <mmsystem.h>
 | |
| 
 | |
| /* Must be a power of 2. */
 | |
| #define MAX_CLOCKS		 (16)
 | |
| 
 | |
| /* Conversions for per-process and per-thread clocks */
 | |
| #define CLOCKID(cid) \
 | |
| 		((cid) % MAX_CLOCKS)
 | |
| #define PID_TO_CLOCKID(pid) \
 | |
| 		((pid) * MAX_CLOCKS + CLOCK_PROCESS_CPUTIME_ID)
 | |
| #define CLOCKID_TO_PID(cid) \
 | |
| 		(((cid) - CLOCK_PROCESS_CPUTIME_ID) / MAX_CLOCKS)
 | |
| #define CLOCKID_IS_PROCESS(cid) \
 | |
| 		(CLOCKID(cid) == CLOCK_PROCESS_CPUTIME_ID)
 | |
| #define THREADID_TO_CLOCKID(tid) \
 | |
| 		((tid) * MAX_CLOCKS + CLOCK_THREAD_CPUTIME_ID)
 | |
| #define CLOCKID_TO_THREADID(cid) \
 | |
| 		(((cid) - CLOCK_THREAD_CPUTIME_ID) / MAX_CLOCKS)
 | |
| #define CLOCKID_IS_THREAD(cid) \
 | |
| 		(CLOCKID(cid) == CLOCK_THREAD_CPUTIME_ID)
 | |
| 
 | |
| /* Largest delay in ms for sleep and alarm calls.
 | |
|    Allow actual delay to exceed requested delay by 10 s.
 | |
|    Express as multiple of 1000 (i.e. seconds) + max resolution
 | |
|    The tv_sec argument in timeval structures cannot exceed
 | |
|    CLOCK_DELAY_MAX / 1000 - 1, so that adding fractional part
 | |
|    and rounding won't exceed CLOCK_DELAY_MAX */
 | |
| #define CLOCK_DELAY_MAX ((((UINT_MAX - 10000) / 1000) * 1000) + 10)
 | |
| 
 | |
| /* 100ns difference between Windows and UNIX timebase. */
 | |
| #define FACTOR (0x19db1ded53e8000LL)
 | |
| /* # of nanosecs per second. */
 | |
| #define NSPERSEC (1000000000LL)
 | |
| /* # of 100ns intervals per second. */
 | |
| #define NS100PERSEC (10000000LL)
 | |
| /* # of microsecs per second. */
 | |
| #define USPERSEC (1000000LL)
 | |
| /* # of millisecs per second. */
 | |
| #define MSPERSEC (1000L)
 | |
| 
 | |
| class clk_t
 | |
| {
 | |
|  protected:
 | |
|   /* Some values are returned as ticks/s, some as 100ns period of a
 | |
|      single tick.  Store the original value and use a computation method
 | |
|      making the most sense for the value given, to avoid rounding issues. */
 | |
|   union
 | |
|     {
 | |
|       LONGLONG ticks_per_sec;
 | |
|       LONGLONG period;
 | |
|     };
 | |
|   void init ();
 | |
|   virtual int now (clockid_t, struct timespec *) = 0;
 | |
| 
 | |
|  public:
 | |
|   int nsecs (clockid_t _id, struct timespec *ts)
 | |
|   {
 | |
|     return now (_id, ts);
 | |
|   }
 | |
|   virtual void resolution (struct timespec *);
 | |
| 
 | |
|   /* shortcuts for non-process/thread clocks */
 | |
|   void nsecs (struct timespec *ts)
 | |
|   {
 | |
|     now (0, ts);
 | |
|   }
 | |
|   ULONGLONG nsecs ()
 | |
|   {
 | |
|     struct timespec ts;
 | |
|     now (0, &ts);
 | |
|     return (ULONGLONG) ts.tv_sec * NSPERSEC + ts.tv_nsec;
 | |
|   }
 | |
|   LONGLONG n100secs ()
 | |
|   {
 | |
|     struct timespec ts;
 | |
|     now (0, &ts);
 | |
|     return ts.tv_sec * NS100PERSEC + ts.tv_nsec / (NSPERSEC/NS100PERSEC);
 | |
|   }
 | |
|   LONGLONG usecs ()
 | |
|   {
 | |
|     struct timespec ts;
 | |
|     now (0, &ts);
 | |
|     return ts.tv_sec * USPERSEC + ts.tv_nsec / (NSPERSEC/USPERSEC);
 | |
|   }
 | |
|   LONGLONG msecs ()
 | |
|   {
 | |
|     struct timespec ts;
 | |
|     now (0, &ts);
 | |
|     return ts.tv_sec * MSPERSEC + ts.tv_nsec / (NSPERSEC/MSPERSEC);
 | |
|   }
 | |
| };
 | |
| 
 | |
| class clk_realtime_coarse_t : public clk_t
 | |
| {
 | |
|   virtual int now (clockid_t, struct timespec *);
 | |
| };
 | |
| 
 | |
| class clk_realtime_t : public clk_t
 | |
| {
 | |
|   void init ();
 | |
|   virtual int now (clockid_t, struct timespec *);
 | |
|  public:
 | |
|   virtual void resolution (struct timespec *);
 | |
| };
 | |
| 
 | |
| class clk_process_t : public clk_t
 | |
| {
 | |
|   virtual int now (clockid_t, struct timespec *);
 | |
| };
 | |
| 
 | |
| class clk_thread_t : public clk_t
 | |
| {
 | |
|   virtual int now (clockid_t, struct timespec *);
 | |
| };
 | |
| 
 | |
| class clk_monotonic_t : public clk_t
 | |
| {
 | |
|  protected:
 | |
|   void init ();
 | |
|  private:
 | |
|   virtual int now (clockid_t, struct timespec *);
 | |
|  public:
 | |
|   virtual void resolution (struct timespec *);
 | |
|   /* Under strace 1st call is so early that vtable is NULL. */
 | |
|   LONGLONG strace_usecs ()
 | |
|   {
 | |
|     struct timespec ts;
 | |
|     clk_monotonic_t::now (0, &ts);
 | |
|     return ts.tv_sec * USPERSEC + ts.tv_nsec / (NSPERSEC/USPERSEC);
 | |
|   }
 | |
| };
 | |
| 
 | |
| class clk_monotonic_coarse_t : public clk_t
 | |
| {
 | |
|   virtual int now (clockid_t, struct timespec *);
 | |
| };
 | |
| 
 | |
| class clk_boottime_t : public clk_monotonic_t
 | |
| {
 | |
|   virtual int now (clockid_t, struct timespec *);
 | |
| };
 | |
| 
 | |
| clk_t *get_clock (clockid_t clk_id);
 | |
| 
 | |
| /* Compute interval between two timespec timestamps: ts1  = ts1 - ts0. */
 | |
| static inline void
 | |
| ts_diff (const struct timespec &ts0, struct timespec &ts1)
 | |
| {
 | |
|   ts1.tv_nsec -= ts0.tv_nsec;
 | |
|   if (ts1.tv_nsec < 0)
 | |
|     {
 | |
|       ts1.tv_nsec += NSPERSEC;
 | |
|       --ts1.tv_sec;
 | |
|     }
 | |
|   ts1.tv_sec -= ts0.tv_sec;
 | |
| }
 | |
| 
 | |
| static inline bool
 | |
| valid_timespec (const timespec& ts)
 | |
| {
 | |
|   if (ts.tv_nsec < 0 || ts.tv_nsec >= NSPERSEC || ts.tv_sec < 0)
 | |
|     return false;
 | |
|   return true;
 | |
| }
 | |
| 
 | |
| #endif /*__CLOCK_H__*/
 |