This is the mail archive of the
cygwin-patches
mailing list for the Cygwin project.
Re: [PATCH] POSIX monotonic clock
On Mon, 2010-08-02 at 20:37 -0400, Christopher Faylor wrote:
> But that changes the sense of the errno. EINVAL would indicate an unsupported
> argument. At least some of the cases fail because of an unimplemented NT
> function call, e.g., ENOSYS. Regardless of what POSIX says, I think that ENOSYS
> is ok, in at least some cases, for Cygwin since I believe QueryPerformanceCounter
> doesn't work on NT3.5 and NT4.
Thanks for the review. This patch uses ENOSYS for QueryPerformance*
failures and EINVAL for unsupported/illegal CLOCK_* arguments. If this
is OK, then I'll proceed with the newlib patch, which needs to be
applied first.
Yaakov
2010-08-02 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.
Index: hires.h
===================================================================
RCS file: /cvs/src/src/winsup/cygwin/hires.h,v
retrieving revision 1.15
diff -u -r1.15 hires.h
--- hires.h 26 May 2010 14:48:17 -0000 1.15
+++ hires.h 3 Aug 2010 05:40:41 -0000
@@ -29,14 +29,15 @@
void reset() {inited = false;}
};
-class hires_us : public hires_base
+class hires_ns : public hires_base
{
- LARGE_INTEGER primed_ft;
LARGE_INTEGER primed_pc;
double freq;
void prime ();
public:
- LONGLONG usecs (bool justdelta);
+ LONGLONG nsecs ();
+ LONGLONG usecs () {return nsecs () / 1000LL;}
+ LONGLONG resolution();
};
class hires_ms : public hires_base
Index: strace.cc
===================================================================
RCS file: /cvs/src/src/winsup/cygwin/strace.cc,v
retrieving revision 1.68
diff -u -r1.68 strace.cc
--- strace.cc 18 May 2010 14:30:51 -0000 1.68
+++ strace.cc 3 Aug 2010 05:40:41 -0000
@@ -74,8 +74,8 @@
int
strace::microseconds ()
{
- static hires_us now;
- return (int) now.usecs (true);
+ static hires_ns now;
+ return (int) now.usecs ();
}
static int __stdcall
Index: sysconf.cc
===================================================================
RCS file: /cvs/src/src/winsup/cygwin/sysconf.cc,v
retrieving revision 1.53
diff -u -r1.53 sysconf.cc
--- sysconf.cc 12 Nov 2009 14:40:47 -0000 1.53
+++ sysconf.cc 3 Aug 2010 05:40:41 -0000
@@ -165,7 +165,7 @@
{cons, {c:IOV_MAX}}, /* 66, _SC_IOV_MAX */
{cons, {c:_POSIX_IPV6}}, /* 67, _SC_IPV6 */
{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_READER_WRITER_LOCKS}}, /* 71, _SC_READER_WRITER_LOCKS */
{cons, {c:_POSIX_REGEXP}}, /* 72, _SC_REGEXP */
Index: times.cc
===================================================================
RCS file: /cvs/src/src/winsup/cygwin/times.cc,v
retrieving revision 1.102
diff -u -r1.102 times.cc
--- times.cc 12 Jun 2010 16:34:26 -0000 1.102
+++ times.cc 3 Aug 2010 05:40:41 -0000
@@ -36,6 +36,8 @@
to handle that case. */
hires_ms gtod __attribute__((section (".cygwin_dll_common"), shared));
+hires_ns NO_COPY ntod;
+
static inline LONGLONG
systime_ns ()
{
@@ -48,12 +50,6 @@
return x.QuadPart;
}
-static inline LONGLONG
-systime ()
-{
- return systime_ns () / 10;
-}
-
/* Cygwin internal */
static unsigned long long __stdcall
__to_clock_t (FILETIME *src, int flag)
@@ -623,7 +619,7 @@
#define stupid_printf if (cygwin_finished_initializing) debug_printf
void
-hires_us::prime ()
+hires_ns::prime ()
{
LARGE_INTEGER ifreq;
if (!QueryPerformanceFrequency (&ifreq))
@@ -642,14 +638,13 @@
return;
}
- primed_ft.QuadPart = systime ();
- freq = (double) ((double) 1000000. / (double) ifreq.QuadPart);
+ freq = (double) ((double) 1000000000. / (double) ifreq.QuadPart);
inited = true;
SetThreadPriority (GetCurrentThread (), priority);
}
LONGLONG
-hires_us::usecs (bool justdelta)
+hires_ns::nsecs ()
{
if (!inited)
prime ();
@@ -668,8 +663,7 @@
// FIXME: Use round() here?
now.QuadPart = (LONGLONG) (freq * (double) (now.QuadPart - primed_pc.QuadPart));
- LONGLONG res = justdelta ? now.QuadPart : primed_ft.QuadPart + now.QuadPart;
- return res;
+ return now.QuadPart;
}
void
@@ -706,23 +700,53 @@
extern "C" int
clock_gettime (clockid_t clk_id, struct timespec *tp)
{
- if (clk_id != CLOCK_REALTIME)
+ switch (clk_id)
{
- set_errno (ENOSYS);
- return -1;
+ case CLOCK_REALTIME:
+ {
+ 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;
}
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
hires_ms::resolution ()
{
@@ -753,17 +777,29 @@
extern "C" int
clock_getres (clockid_t clk_id, struct timespec *tp)
{
- if (clk_id != CLOCK_REALTIME)
+ switch (clk_id)
{
- set_errno (ENOSYS);
- return -1;
+ case CLOCK_REALTIME:
+ {
+ 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;
}
@@ -773,7 +809,7 @@
static NO_COPY bool period_set;
if (clk_id != CLOCK_REALTIME)
{
- set_errno (ENOSYS);
+ set_errno (EINVAL);
return -1;
}
Index: include/cygwin/version.h
===================================================================
RCS file: /cvs/src/src/winsup/cygwin/include/cygwin/version.h,v
retrieving revision 1.319
diff -u -r1.319 version.h
--- include/cygwin/version.h 19 Jul 2010 18:22:40 -0000 1.319
+++ include/cygwin/version.h 3 Aug 2010 05:40:41 -0000
@@ -389,12 +389,13 @@
227: Add pseudo_reloc_start, pseudo_reloc_end, image_base to per_process.
228: CW_STRERROR added.
229: Add mkostemp, mkostemps.
+ 230: Add CLOCK_MONOTONIC.
*/
/* Note that we forgot to bump the api for ualarm, strtoll, strtoull */
#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
shared memory regions. It is incremented when incompatible