Implement POSIX.1-2004 Monotonic Clock.

* hires.h: Change hires_us to hires_ns, with nanosecond resolution.
(hires_ns::primed_ft): Remove.
(hires_ns::nsecs): New prototype.
(hires_ns::usecs): Rewrite in terms of nsecs.
(hires_ns::resolution): New prototype.
* times.cc: Change hires_us to hires_ns.
(ntod): Declare.
(systime): Remove.
(hires_ns::prime): Increase resolution to nanoseconds.
(hires_ns::nsecs): Rename usecs to nsecs to reflect increased resolution.
Remove justdelta argument.
(hires_ns::resolution): New function.
(clock_gettime): Accept CLOCK_MONOTONIC.
Use EINVAL instead of ENOSYS per POSIX.1-2004.
(clock_getres): Ditto.
(clock_setres): Use EINVAL instead of ENOSYS to conform with other
implementations.
* strace.cc (strace::microseconds): Adjust for hires_ns.
* sysconf.cc (sca): Set _SC_MONOTONIC_CLOCK to _POSIX_MONOTONIC_CLOCK.
* include/cygwin/version.h (CYGWIN_VERSION_API_MINOR): Bump.
This commit is contained in:
Yaakov Selkowitz 2010-08-09 16:47:48 +00:00
parent f717289618
commit b150f5236b
6 changed files with 99 additions and 37 deletions

View File

@ -1,3 +1,27 @@
2010-08-09 Yaakov Selkowitz <yselkowitz@users.sourceforge.net>
Implement POSIX.1-2004 Monotonic Clock.
* hires.h: Change hires_us to hires_ns, with nanosecond resolution.
(hires_ns::primed_ft): Remove.
(hires_ns::nsecs): New prototype.
(hires_ns::usecs): Rewrite in terms of nsecs.
(hires_ns::resolution): New prototype.
* times.cc: Change hires_us to hires_ns.
(ntod): Declare.
(systime): Remove.
(hires_ns::prime): Increase resolution to nanoseconds.
(hires_ns::nsecs): Rename usecs to nsecs to reflect increased resolution.
Remove justdelta argument.
(hires_ns::resolution): New function.
(clock_gettime): Accept CLOCK_MONOTONIC.
Use EINVAL instead of ENOSYS per POSIX.1-2004.
(clock_getres): Ditto.
(clock_setres): Use EINVAL instead of ENOSYS to conform with other
implementations.
* strace.cc (strace::microseconds): Adjust for hires_ns.
* sysconf.cc (sca): Set _SC_MONOTONIC_CLOCK to _POSIX_MONOTONIC_CLOCK.
* include/cygwin/version.h (CYGWIN_VERSION_API_MINOR): Bump.
2010-08-09 Yaakov Selkowitz <yselkowitz@users.sourceforge.net> 2010-08-09 Yaakov Selkowitz <yselkowitz@users.sourceforge.net>
* fhandler_proc.cc: Add /proc/filesystems virtual file. * fhandler_proc.cc: Add /proc/filesystems virtual file.

View File

@ -29,14 +29,15 @@ class hires_base
void reset() {inited = false;} void reset() {inited = false;}
}; };
class hires_us : public hires_base class hires_ns : public hires_base
{ {
LARGE_INTEGER primed_ft;
LARGE_INTEGER primed_pc; LARGE_INTEGER primed_pc;
double freq; double freq;
void prime (); void prime ();
public: public:
LONGLONG usecs (bool justdelta); LONGLONG nsecs ();
LONGLONG usecs () {return nsecs () / 1000LL;}
LONGLONG resolution();
}; };
class hires_ms : public hires_base class hires_ms : public hires_base

View File

@ -389,12 +389,13 @@ details. */
227: Add pseudo_reloc_start, pseudo_reloc_end, image_base to per_process. 227: Add pseudo_reloc_start, pseudo_reloc_end, image_base to per_process.
228: CW_STRERROR added. 228: CW_STRERROR added.
229: Add mkostemp, mkostemps. 229: Add mkostemp, mkostemps.
230: Add CLOCK_MONOTONIC.
*/ */
/* Note that we forgot to bump the api for ualarm, strtoll, strtoull */ /* Note that we forgot to bump the api for ualarm, strtoll, strtoull */
#define CYGWIN_VERSION_API_MAJOR 0 #define CYGWIN_VERSION_API_MAJOR 0
#define CYGWIN_VERSION_API_MINOR 229 #define CYGWIN_VERSION_API_MINOR 230
/* There is also a compatibity version number associated with the /* There is also a compatibity version number associated with the
shared memory regions. It is incremented when incompatible shared memory regions. It is incremented when incompatible

View File

@ -74,8 +74,8 @@ strace::hello ()
int int
strace::microseconds () strace::microseconds ()
{ {
static hires_us now; static hires_ns now;
return (int) now.usecs (true); return (int) now.usecs ();
} }
static int __stdcall static int __stdcall

View File

@ -165,7 +165,7 @@ static struct
{cons, {c:IOV_MAX}}, /* 66, _SC_IOV_MAX */ {cons, {c:IOV_MAX}}, /* 66, _SC_IOV_MAX */
{cons, {c:_POSIX_IPV6}}, /* 67, _SC_IPV6 */ {cons, {c:_POSIX_IPV6}}, /* 67, _SC_IPV6 */
{cons, {c:LINE_MAX}}, /* 68, _SC_LINE_MAX */ {cons, {c:LINE_MAX}}, /* 68, _SC_LINE_MAX */
{cons, {c:-1L}}, /* 69, _SC_MONOTONIC_CLOCK */ {cons, {c:_POSIX_MONOTONIC_CLOCK}}, /* 69, _SC_MONOTONIC_CLOCK */
{cons, {c:_POSIX_RAW_SOCKETS}}, /* 70, _SC_RAW_SOCKETS */ {cons, {c:_POSIX_RAW_SOCKETS}}, /* 70, _SC_RAW_SOCKETS */
{cons, {c:_POSIX_READER_WRITER_LOCKS}}, /* 71, _SC_READER_WRITER_LOCKS */ {cons, {c:_POSIX_READER_WRITER_LOCKS}}, /* 71, _SC_READER_WRITER_LOCKS */
{cons, {c:_POSIX_REGEXP}}, /* 72, _SC_REGEXP */ {cons, {c:_POSIX_REGEXP}}, /* 72, _SC_REGEXP */

View File

@ -36,6 +36,8 @@ details. */
to handle that case. */ to handle that case. */
hires_ms gtod __attribute__((section (".cygwin_dll_common"), shared)); hires_ms gtod __attribute__((section (".cygwin_dll_common"), shared));
hires_ns NO_COPY ntod;
static inline LONGLONG static inline LONGLONG
systime_ns () systime_ns ()
{ {
@ -48,12 +50,6 @@ systime_ns ()
return x.QuadPart; return x.QuadPart;
} }
static inline LONGLONG
systime ()
{
return systime_ns () / 10;
}
/* Cygwin internal */ /* Cygwin internal */
static unsigned long long __stdcall static unsigned long long __stdcall
__to_clock_t (FILETIME *src, int flag) __to_clock_t (FILETIME *src, int flag)
@ -623,7 +619,7 @@ cygwin_tzset ()
#define stupid_printf if (cygwin_finished_initializing) debug_printf #define stupid_printf if (cygwin_finished_initializing) debug_printf
void void
hires_us::prime () hires_ns::prime ()
{ {
LARGE_INTEGER ifreq; LARGE_INTEGER ifreq;
if (!QueryPerformanceFrequency (&ifreq)) if (!QueryPerformanceFrequency (&ifreq))
@ -642,14 +638,13 @@ hires_us::prime ()
return; return;
} }
primed_ft.QuadPart = systime (); freq = (double) ((double) 1000000000. / (double) ifreq.QuadPart);
freq = (double) ((double) 1000000. / (double) ifreq.QuadPart);
inited = true; inited = true;
SetThreadPriority (GetCurrentThread (), priority); SetThreadPriority (GetCurrentThread (), priority);
} }
LONGLONG LONGLONG
hires_us::usecs (bool justdelta) hires_ns::nsecs ()
{ {
if (!inited) if (!inited)
prime (); prime ();
@ -668,8 +663,7 @@ hires_us::usecs (bool justdelta)
// FIXME: Use round() here? // FIXME: Use round() here?
now.QuadPart = (LONGLONG) (freq * (double) (now.QuadPart - primed_pc.QuadPart)); now.QuadPart = (LONGLONG) (freq * (double) (now.QuadPart - primed_pc.QuadPart));
LONGLONG res = justdelta ? now.QuadPart : primed_ft.QuadPart + now.QuadPart; return now.QuadPart;
return res;
} }
void void
@ -706,23 +700,53 @@ hires_ms::nsecs ()
extern "C" int extern "C" int
clock_gettime (clockid_t clk_id, struct timespec *tp) clock_gettime (clockid_t clk_id, struct timespec *tp)
{ {
if (clk_id != CLOCK_REALTIME) switch (clk_id)
{ {
set_errno (ENOSYS); case CLOCK_REALTIME:
return -1; {
LONGLONG now = gtod.nsecs ();
if (now == (LONGLONG) -1)
return -1;
tp->tv_sec = now / NSPERSEC;
tp->tv_nsec = (now % NSPERSEC) * (1000000000 / NSPERSEC);
break;
}
case CLOCK_MONOTONIC:
{
LONGLONG now = ntod.nsecs ();
if (now == (LONGLONG) -1)
return -1;
tp->tv_sec = now / 1000000000;
tp->tv_nsec = (now % 1000000000);
break;
}
default:
set_errno (EINVAL);
return -1;
} }
LONGLONG now = gtod.nsecs ();
if (now == (LONGLONG) -1)
return -1;
tp->tv_sec = now / NSPERSEC;
tp->tv_nsec = (now % NSPERSEC) * (1000000000 / NSPERSEC);
return 0; return 0;
} }
static DWORD minperiod; // FIXME: Maintain period after a fork. static DWORD minperiod; // FIXME: Maintain period after a fork.
LONGLONG
hires_ns::resolution()
{
if (!inited)
prime ();
if (inited < 0)
{
set_errno (ENOSYS);
return (long long) -1;
}
return (LONGLONG) freq;
}
UINT UINT
hires_ms::resolution () hires_ms::resolution ()
{ {
@ -753,17 +777,29 @@ hires_ms::resolution ()
extern "C" int extern "C" int
clock_getres (clockid_t clk_id, struct timespec *tp) clock_getres (clockid_t clk_id, struct timespec *tp)
{ {
if (clk_id != CLOCK_REALTIME) switch (clk_id)
{ {
set_errno (ENOSYS); case CLOCK_REALTIME:
return -1; {
DWORD period = gtod.resolution ();
tp->tv_sec = period / 1000;
tp->tv_nsec = (period % 1000) * 1000000;
break;
}
case CLOCK_MONOTONIC:
{
LONGLONG period = ntod.resolution ();
tp->tv_sec = period / 1000000000;
tp->tv_nsec = period % 1000000000;
break;
}
default:
set_errno (EINVAL);
return -1;
} }
DWORD period = gtod.resolution ();
tp->tv_sec = period / 1000;
tp->tv_nsec = (period % 1000) * 1000000;
return 0; return 0;
} }
@ -773,7 +809,7 @@ clock_setres (clockid_t clk_id, struct timespec *tp)
static NO_COPY bool period_set; static NO_COPY bool period_set;
if (clk_id != CLOCK_REALTIME) if (clk_id != CLOCK_REALTIME)
{ {
set_errno (ENOSYS); set_errno (EINVAL);
return -1; return -1;
} }