newlib/winsup/cygwin/clock.h
Corinna Vinschen 1daece5861 Cygwin: clocks: Add CLOCK_REALTIME_ALARM/CLOCK_BOOTTIME_ALARM clocks
Signed-off-by: Corinna Vinschen <corinna@vinschen.de>
2019-01-22 15:42:07 +01:00

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__*/