Cygwin: implement extensible clock interface
- Drop hires_[nm]s clocks, rename hires.h to clock.h. - Implement clk_t class as an extensible clock class in new file clock.cc. - Introduce get_clock(clock_id) returning a pointer to the clk_t instance for clock_id. Provide the following methods along the lines of the former hires classes: void clk_t::nsecs (struct timespec *); ULONGLONG clk_t::nsecs (); LONGLONG clk_t::usecs (); LONGLONG clk_t::msecs (); void clk_t::resolution (struct timespec *); - Add CLOCK_REALTIME_COARSE, CLOCK_MONOTONIC_RAW, CLOCK_MONOTONIC_COARSE and CLOCK_BOOTTIME clocks. - Allow clock_nanosleep, pthread_condattr_setclock and timer_create to use all new clocks (both clocks should be usable with a small tweak, though). - Bump DLL major version to 2.12. Signed-off-by: Corinna Vinschen <corinna@vinschen.de>
This commit is contained in:
149
winsup/cygwin/clock.h
Normal file
149
winsup/cygwin/clock.h
Normal file
@@ -0,0 +1,149 @@
|
||||
/* 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 (8)
|
||||
|
||||
/* 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:
|
||||
LONG inited;
|
||||
LONGLONG ticks_per_sec;
|
||||
virtual void init ();
|
||||
virtual int now (clockid_t, struct timespec *) = 0;
|
||||
|
||||
public:
|
||||
int nsecs (clockid_t _id, struct timespec *ts)
|
||||
{
|
||||
return now (_id, ts);
|
||||
}
|
||||
void resolution (struct timespec *);
|
||||
|
||||
/* shortcuts for non-process/thread clocks */
|
||||
void nsecs (struct timespec *ts) { nsecs (0, ts); }
|
||||
ULONGLONG nsecs ()
|
||||
{
|
||||
struct timespec ts;
|
||||
nsecs (&ts);
|
||||
return (ULONGLONG) ts.tv_sec * NSPERSEC + ts.tv_nsec;
|
||||
}
|
||||
LONGLONG n100secs ()
|
||||
{
|
||||
struct timespec ts;
|
||||
nsecs (&ts);
|
||||
return ts.tv_sec * NS100PERSEC + ts.tv_nsec / (NSPERSEC/NS100PERSEC);
|
||||
}
|
||||
LONGLONG usecs ()
|
||||
{
|
||||
struct timespec ts;
|
||||
nsecs (&ts);
|
||||
return ts.tv_sec * USPERSEC + ts.tv_nsec / (NSPERSEC/USPERSEC);
|
||||
}
|
||||
LONGLONG msecs ()
|
||||
{
|
||||
struct timespec ts;
|
||||
nsecs (&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
|
||||
{
|
||||
virtual void init ();
|
||||
virtual int now (clockid_t, 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:
|
||||
virtual void init ();
|
||||
private:
|
||||
virtual int now (clockid_t, struct timespec *);
|
||||
};
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
#endif /*__CLOCK_H__*/
|
Reference in New Issue
Block a user