diff options
Diffstat (limited to 'winsup/cygwin/local_includes/clock.h')
-rw-r--r-- | winsup/cygwin/local_includes/clock.h | 177 |
1 files changed, 177 insertions, 0 deletions
diff --git a/winsup/cygwin/local_includes/clock.h b/winsup/cygwin/local_includes/clock.h new file mode 100644 index 000000000..7323299df --- /dev/null +++ b/winsup/cygwin/local_includes/clock.h @@ -0,0 +1,177 @@ +/* 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__*/ |