Streamline time/times functionality. Remove last remains of former

Windows 9x compatibility.
	* fhandler_disk_file.cc (fhandler_base::fstat_helper): Drop now unneeded
	casts in calls to_timestruc_t.
	(fhandler_base::utimens_fs): Ditto for timespec_to_filetime.
	* fhandler_proc.cc (format_proc_stat): Ditto for to_time_t.
	* hires.h (class hires_ms): Remove unused member initime_ns.
	Remove declarations for timeGetTime_ns and prime.
	(hires_ms::uptime): Remove.
	* posix_ipc.cc (ipc_cond_timedwait): Ditto for timespec_to_filetime.
	* fhandler_registry.cc (fhandler_registry::fstat): Add cast.
	* resource.cc (fill_rusage): Call NtQueryInformationProcess rather than
	GetProcessTimes to deal with LARGE_INTEGER rather than FILETIME.
	* times.cc: Simplify time handling.  Throughout, use LARGE_INTEGER
	rather than FILETIME to simplify computations.  Throughout use
	{u}int64_t rather than {unsigned} long long.  Drop unneeded casts since
	NSPERSEC is 64 bit anyway.
	(systime_ns): Remove.
	(times): Call NtQuerySystemInformation to fetch boot time.  Call
	NtQueryInformationProcess rather than GetProcessTimes to deal with
	LARGE_INTEGER rather than FILETIME.  Call GetSystemTimeAsFileTime.
	(totimeval): Use constant 1000000 as in other functions.
	(time_t_to_filetime): Remove.
	(to_time_t): Change return type to time_t.
	(time_as_timestruc_t): Rename filetime to systime.
	(time): Ditto. Add cast.
	(hires_ns::nsecs): Fix return type cast.
	(hires_ms::timeGetTime_ns): Remove.
	(hires_ns::prime): Remove.
	(hires_ms::nsecs): Drop call to prime.  Call GetSystemTimeAsFileTime
	directly.  Subtract FACTOR here since it's the only function needing
	to do so.
	(minperiod): Cosmetically change to ULONG.
	(hires_ns::resolution): Fix return type cast.
	(hires_ms::resolution): Simplify, rely on NtQueryTimerResolution.
	* winsup.h: Align time related prototypes to above changes.
This commit is contained in:
Corinna Vinschen 2013-06-14 09:09:41 +00:00
parent ba763af559
commit 0ff057d5a5
9 changed files with 141 additions and 214 deletions

View File

@ -1,3 +1,42 @@
2013-06-13 Corinna Vinschen <corinna@vinschen.de>
Streamline time/times functionality. Remove last remains of former
Windows 9x compatibility.
* fhandler_disk_file.cc (fhandler_base::fstat_helper): Drop now unneeded
casts in calls to_timestruc_t.
(fhandler_base::utimens_fs): Ditto for timespec_to_filetime.
* fhandler_proc.cc (format_proc_stat): Ditto for to_time_t.
* hires.h (class hires_ms): Remove unused member initime_ns.
Remove declarations for timeGetTime_ns and prime.
(hires_ms::uptime): Remove.
* posix_ipc.cc (ipc_cond_timedwait): Ditto for timespec_to_filetime.
* fhandler_registry.cc (fhandler_registry::fstat): Add cast.
* resource.cc (fill_rusage): Call NtQueryInformationProcess rather than
GetProcessTimes to deal with LARGE_INTEGER rather than FILETIME.
* times.cc: Simplify time handling. Throughout, use LARGE_INTEGER
rather than FILETIME to simplify computations. Throughout use
{u}int64_t rather than {unsigned} long long. Drop unneeded casts since
NSPERSEC is 64 bit anyway.
(systime_ns): Remove.
(times): Call NtQuerySystemInformation to fetch boot time. Call
NtQueryInformationProcess rather than GetProcessTimes to deal with
LARGE_INTEGER rather than FILETIME. Call GetSystemTimeAsFileTime.
(totimeval): Use constant 1000000 as in other functions.
(time_t_to_filetime): Remove.
(to_time_t): Change return type to time_t.
(time_as_timestruc_t): Rename filetime to systime.
(time): Ditto. Add cast.
(hires_ns::nsecs): Fix return type cast.
(hires_ms::timeGetTime_ns): Remove.
(hires_ns::prime): Remove.
(hires_ms::nsecs): Drop call to prime. Call GetSystemTimeAsFileTime
directly. Subtract FACTOR here since it's the only function needing
to do so.
(minperiod): Cosmetically change to ULONG.
(hires_ns::resolution): Fix return type cast.
(hires_ms::resolution): Simplify, rely on NtQueryTimerResolution.
* winsup.h: Align time related prototypes to above changes.
2013-06-13 Corinna Vinschen <corinna@vinschen.de> 2013-06-13 Corinna Vinschen <corinna@vinschen.de>
* net.cc (gen_old_if_name): New function to generate short interface * net.cc (gen_old_if_name): New function to generate short interface

View File

@ -518,14 +518,14 @@ fhandler_base::fstat_helper (struct stat *buf,
PFILE_NETWORK_OPEN_INFORMATION pfnoi = pc.fnoi (); PFILE_NETWORK_OPEN_INFORMATION pfnoi = pc.fnoi ();
ULONG attributes = pc.file_attributes (); ULONG attributes = pc.file_attributes ();
to_timestruc_t ((PFILETIME) &pfnoi->LastAccessTime, &buf->st_atim); to_timestruc_t (&pfnoi->LastAccessTime, &buf->st_atim);
to_timestruc_t ((PFILETIME) &pfnoi->LastWriteTime, &buf->st_mtim); to_timestruc_t (&pfnoi->LastWriteTime, &buf->st_mtim);
/* If the ChangeTime is 0, the underlying FS doesn't support this timestamp /* If the ChangeTime is 0, the underlying FS doesn't support this timestamp
(FAT for instance). If so, it's faked using LastWriteTime. */ (FAT for instance). If so, it's faked using LastWriteTime. */
to_timestruc_t (pfnoi->ChangeTime.QuadPart ? (PFILETIME) &pfnoi->ChangeTime to_timestruc_t (pfnoi->ChangeTime.QuadPart ? &pfnoi->ChangeTime
: (PFILETIME) &pfnoi->LastWriteTime, : &pfnoi->LastWriteTime,
&buf->st_ctim); &buf->st_ctim);
to_timestruc_t ((PFILETIME) &pfnoi->CreationTime, &buf->st_birthtim); to_timestruc_t (&pfnoi->CreationTime, &buf->st_birthtim);
buf->st_dev = get_dev (); buf->st_dev = get_dev ();
/* CV 2011-01-13: Observations on the Cygwin mailing list point to an /* CV 2011-01-13: Observations on the Cygwin mailing list point to an
interesting behaviour in some Windows versions. Apparently the size of interesting behaviour in some Windows versions. Apparently the size of
@ -1343,8 +1343,8 @@ fhandler_base::utimens_fs (const struct timespec *tvp)
fbi.CreationTime.QuadPart = 0LL; fbi.CreationTime.QuadPart = 0LL;
/* UTIME_OMIT is handled in timespec_to_filetime by setting FILETIME to 0. */ /* UTIME_OMIT is handled in timespec_to_filetime by setting FILETIME to 0. */
timespec_to_filetime (&tmp[0], (LPFILETIME) &fbi.LastAccessTime); timespec_to_filetime (&tmp[0], &fbi.LastAccessTime);
timespec_to_filetime (&tmp[1], (LPFILETIME) &fbi.LastWriteTime); timespec_to_filetime (&tmp[1], &fbi.LastWriteTime);
fbi.ChangeTime.QuadPart = 0LL; fbi.ChangeTime.QuadPart = 0LL;
fbi.FileAttributes = 0; fbi.FileAttributes = 0;
NTSTATUS status = NtSetInformationFile (get_handle (), &io, &fbi, sizeof fbi, NTSTATUS status = NtSetInformationFile (get_handle (), &io, &fbi, sizeof fbi,

View File

@ -570,7 +570,7 @@ format_proc_stat (void *, char *&destbuf)
swap_in = spi->PagesRead; swap_in = spi->PagesRead;
swap_out = spi->PagefilePagesWritten; swap_out = spi->PagefilePagesWritten;
context_switches = spi->ContextSwitches; context_switches = spi->ContextSwitches;
boot_time = to_time_t ((FILETIME *) &stodi.BootTime.QuadPart); boot_time = to_time_t (&stodi.BootTime);
eobuf += __small_sprintf (eobuf, "page %u %u\n" eobuf += __small_sprintf (eobuf, "page %u %u\n"
"swap %u %u\n" "swap %u %u\n"

View File

@ -508,7 +508,7 @@ fhandler_registry::fstat (struct stat *buf)
RegQueryInfoKeyW (hKey, NULL, NULL, NULL, &subkey_count, NULL, RegQueryInfoKeyW (hKey, NULL, NULL, NULL, &subkey_count, NULL,
NULL, NULL, NULL, NULL, NULL, &ftLastWriteTime)) NULL, NULL, NULL, NULL, NULL, &ftLastWriteTime))
{ {
to_timestruc_t (&ftLastWriteTime, &buf->st_mtim); to_timestruc_t ((PLARGE_INTEGER) &ftLastWriteTime, &buf->st_mtim);
buf->st_ctim = buf->st_birthtim = buf->st_mtim; buf->st_ctim = buf->st_birthtim = buf->st_mtim;
time_as_timestruc_t (&buf->st_atim); time_as_timestruc_t (&buf->st_atim);
if (file_type > virt_none) if (file_type > virt_none)

View File

@ -1,6 +1,6 @@
/* hires.h: Definitions for hires clock calculations /* hires.h: Definitions for hires clock calculations
Copyright 2002, 2003, 2004, 2005, 2009, 2010, 2011, 2012 Red Hat, Inc. Copyright 2002, 2003, 2004, 2005, 2009, 2010, 2011, 2012, 2013 Red Hat, Inc.
This file is part of Cygwin. This file is part of Cygwin.
@ -55,15 +55,11 @@ class hires_ns : public hires_base
class hires_ms : public hires_base class hires_ms : public hires_base
{ {
LONGLONG initime_ns;
LONGLONG timeGetTime_ns ();
void prime ();
public: public:
LONGLONG nsecs (); LONGLONG nsecs ();
LONGLONG usecs () {return nsecs () / 10LL;} LONGLONG usecs () {return nsecs () / 10LL;}
LONGLONG msecs () {return nsecs () / 10000LL;} LONGLONG msecs () {return nsecs () / 10000LL;}
UINT resolution (); UINT resolution ();
LONGLONG uptime () {return (nsecs () - initime_ns) / 10000LL;}
}; };
extern hires_ms gtod; extern hires_ms gtod;

View File

@ -199,7 +199,7 @@ ipc_cond_timedwait (HANDLE evt, HANDLE mtx, const struct timespec *abstime)
NotificationTimer); NotificationTimer);
if (!NT_SUCCESS (status)) if (!NT_SUCCESS (status))
return geterrno_from_nt_status (status); return geterrno_from_nt_status (status);
timespec_to_filetime (abstime, (FILETIME *) &duetime); timespec_to_filetime (abstime, &duetime);
status = NtSetTimer (w4[timer_idx], &duetime, NULL, NULL, FALSE, 0, NULL); status = NtSetTimer (w4[timer_idx], &duetime, NULL, NULL, FALSE, 0, NULL);
if (!NT_SUCCESS (status)) if (!NT_SUCCESS (status))
{ {

View File

@ -65,18 +65,16 @@ add_rusage (struct rusage *r1, struct rusage *r2)
void __stdcall void __stdcall
fill_rusage (struct rusage *r, HANDLE h) fill_rusage (struct rusage *r, HANDLE h)
{ {
FILETIME creation_time = {0,0}; KERNEL_USER_TIMES kut;
FILETIME exit_time = {0,0};
FILETIME kernel_time = {0,0};
FILETIME user_time = {0,0};
struct timeval tv; struct timeval tv;
memset (r, 0, sizeof (*r)); memset (&kut, 0, sizeof kut);
GetProcessTimes (h, &creation_time, &exit_time, &kernel_time, &user_time); memset (r, 0, sizeof *r);
totimeval (&tv, &kernel_time, 0, 0); NtQueryInformationProcess (h, ProcessTimes, &kut, sizeof kut, NULL);
totimeval (&tv, &kut.KernelTime, 0, 0);
add_timeval (&r->ru_stime, &tv); add_timeval (&r->ru_stime, &tv);
totimeval (&tv, &user_time, 0, 0); totimeval (&tv, &kut.UserTime, 0, 0);
add_timeval (&r->ru_utime, &tv); add_timeval (&r->ru_utime, &tv);
VM_COUNTERS vmc; VM_COUNTERS vmc;

View File

@ -1,7 +1,7 @@
/* times.cc /* times.cc
Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
2007, 2008, 2009, 2010, 2011, 2012 Red Hat, Inc. 2007, 2008, 2009, 2010, 2011, 2012, 2013 Red Hat, Inc.
This file is part of Cygwin. This file is part of Cygwin.
@ -31,28 +31,17 @@ hires_ms NO_COPY gtod;
hires_ns NO_COPY ntod; hires_ns NO_COPY ntod;
static inline LONGLONG
systime_ns ()
{
LARGE_INTEGER x;
GetSystemTimeAsFileTime ((LPFILETIME) &x);
x.QuadPart -= FACTOR; /* Add conversion factor for UNIX vs. Windows base time */
return x.QuadPart;
}
/* Cygwin internal */ /* Cygwin internal */
static unsigned long long __stdcall static uint64_t __stdcall
__to_clock_t (FILETIME *src, int flag) __to_clock_t (PLARGE_INTEGER src, int flag)
{ {
unsigned long long total = ((unsigned long long) src->dwHighDateTime << 32) + ((unsigned)src->dwLowDateTime); uint64_t total = src->QuadPart;
syscall_printf ("dwHighDateTime %u, dwLowDateTime %u", src->dwHighDateTime, src->dwLowDateTime);
/* Convert into clock ticks - the total is in 10ths of a usec. */ /* Convert into clock ticks - the total is in 10ths of a usec. */
if (flag) if (flag)
total -= FACTOR; total -= FACTOR;
total /= (unsigned long long) (NSPERSEC / CLOCKS_PER_SEC); total /= NSPERSEC / CLOCKS_PER_SEC;
syscall_printf ("total %08x %08x", (unsigned) (total>>32), (unsigned) (total)); debug_printf ("total %016X", total);
return total; return total;
} }
@ -60,31 +49,37 @@ __to_clock_t (FILETIME *src, int flag)
extern "C" clock_t extern "C" clock_t
times (struct tms *buf) times (struct tms *buf)
{ {
FILETIME creation_time, exit_time, kernel_time, user_time;
myfault efault; myfault efault;
if (efault.faulted (EFAULT)) if (efault.faulted (EFAULT))
return ((clock_t) -1); return ((clock_t) -1);
LONGLONG ticks = gtod.uptime (); static SYSTEM_TIMEOFDAY_INFORMATION stodi;
/* Ticks is in milliseconds, convert to our ticks. Use long long to prevent KERNEL_USER_TIMES kut;
overflow. */ LARGE_INTEGER ticks;
clock_t tc = (clock_t) (ticks * CLOCKS_PER_SEC / 1000);
GetProcessTimes (GetCurrentProcess (), &creation_time, &exit_time, /* Fetch boot time if we haven't already. */
&kernel_time, &user_time); if (!stodi.BootTime.QuadPart)
NtQuerySystemInformation (SystemTimeOfDayInformation,
&stodi, sizeof stodi, NULL);
NtQueryInformationProcess (NtCurrentProcess (), ProcessTimes,
&kut, sizeof kut, NULL);
GetSystemTimeAsFileTime ((LPFILETIME) &ticks);
/* uptime */
ticks.QuadPart -= stodi.BootTime.QuadPart;
/* ticks is in in 100ns, convert to clock ticks. */
clock_t tc = (clock_t) (ticks.QuadPart * CLOCKS_PER_SEC / NSPERSEC);
syscall_printf ("ticks %D, CLOCKS_PER_SEC %d", ticks, CLOCKS_PER_SEC); syscall_printf ("ticks %D, CLOCKS_PER_SEC %d", ticks, CLOCKS_PER_SEC);
syscall_printf ("user_time %D, kernel_time %D, " syscall_printf ("UserTime %D, KernelTime %D, CreationTime %D, ExitTime %D",
"creation_time %D, exit_time %D", kut.UserTime, kut.KernelTime, kut.CreateTime, kut.ExitTime);
user_time, kernel_time, buf->tms_stime = __to_clock_t (&kut.KernelTime, 0);
creation_time, exit_time); buf->tms_utime = __to_clock_t (&kut.UserTime, 0);
buf->tms_stime = __to_clock_t (&kernel_time, 0); timeval_to_filetime (&myself->rusage_children.ru_stime, &kut.KernelTime);
buf->tms_utime = __to_clock_t (&user_time, 0); buf->tms_cstime = __to_clock_t (&kut.KernelTime, 1);
timeval_to_filetime (&myself->rusage_children.ru_stime, &kernel_time); timeval_to_filetime (&myself->rusage_children.ru_utime, &kut.UserTime);
buf->tms_cstime = __to_clock_t (&kernel_time, 1); buf->tms_cutime = __to_clock_t (&kut.UserTime, 1);
timeval_to_filetime (&myself->rusage_children.ru_utime, &user_time);
buf->tms_cutime = __to_clock_t (&user_time, 1);
return tc; return tc;
} }
@ -142,15 +137,15 @@ timezone (void)
/* Cygwin internal */ /* Cygwin internal */
void __stdcall void __stdcall
totimeval (struct timeval *dst, FILETIME *src, int sub, int flag) totimeval (struct timeval *dst, PLARGE_INTEGER src, int sub, int flag)
{ {
long long x = __to_clock_t (src, flag); int64_t x = __to_clock_t (src, flag);
x *= (int) (1e6) / CLOCKS_PER_SEC; /* Turn x into usecs */ x *= (int64_t) 1000000 / CLOCKS_PER_SEC; /* Turn x into usecs */
x -= (long long) sub * (int) (1e6); x -= (int64_t) sub * 1000000;
dst->tv_usec = x % (long long) (1e6); /* And split */ dst->tv_usec = x % 1000000; /* And split */
dst->tv_sec = x / (long long) (1e6); dst->tv_sec = x / 1000000;
} }
/* FIXME: Make thread safe */ /* FIXME: Make thread safe */
@ -183,38 +178,23 @@ gettimeofday (struct timeval *tv, void *tzvp)
EXPORT_ALIAS (gettimeofday, _gettimeofday) EXPORT_ALIAS (gettimeofday, _gettimeofday)
/* Cygwin internal */
void
time_t_to_filetime (time_t time_in, FILETIME *out)
{
long long x = time_in * NSPERSEC + FACTOR;
out->dwHighDateTime = x >> 32;
out->dwLowDateTime = x;
}
/* Cygwin internal */ /* Cygwin internal */
void __stdcall void __stdcall
timespec_to_filetime (const struct timespec *time_in, FILETIME *out) timespec_to_filetime (const struct timespec *time_in, PLARGE_INTEGER out)
{ {
if (time_in->tv_nsec == UTIME_OMIT) if (time_in->tv_nsec == UTIME_OMIT)
out->dwHighDateTime = out->dwLowDateTime = 0; out->QuadPart = 0;
else else
{ out->QuadPart = time_in->tv_sec * NSPERSEC
long long x = time_in->tv_sec * NSPERSEC + + time_in->tv_nsec / (1000000000/NSPERSEC) + FACTOR;
time_in->tv_nsec / (1000000000/NSPERSEC) + FACTOR;
out->dwHighDateTime = x >> 32;
out->dwLowDateTime = x;
}
} }
/* Cygwin internal */ /* Cygwin internal */
void __stdcall void __stdcall
timeval_to_filetime (const struct timeval *time_in, FILETIME *out) timeval_to_filetime (const struct timeval *time_in, PLARGE_INTEGER out)
{ {
long long x = time_in->tv_sec * NSPERSEC + out->QuadPart = time_in->tv_sec * NSPERSEC
time_in->tv_usec * (NSPERSEC/1000000) + FACTOR; + time_in->tv_usec * (NSPERSEC/1000000) + FACTOR;
out->dwHighDateTime = x >> 32;
out->dwLowDateTime = x;
} }
/* Cygwin internal */ /* Cygwin internal */
@ -253,36 +233,36 @@ timeval_to_timespec (const struct timeval *tvp, struct timespec *tmp)
/* Cygwin internal */ /* Cygwin internal */
/* Convert a Win32 time to "UNIX" format. */ /* Convert a Win32 time to "UNIX" format. */
long __stdcall time_t __stdcall
to_time_t (FILETIME *ptr) to_time_t (PLARGE_INTEGER ptr)
{ {
/* A file time is the number of 100ns since jan 1 1601 /* A file time is the number of 100ns since jan 1 1601
stuffed into two long words. stuffed into two long words.
A time_t is the number of seconds since jan 1 1970. */ A time_t is the number of seconds since jan 1 1970. */
long long x = ((long long) ptr->dwHighDateTime << 32) + ((unsigned)ptr->dwLowDateTime); int64_t x = ptr->QuadPart;
/* pass "no time" as epoch */ /* pass "no time" as epoch */
if (x == 0) if (x == 0)
return 0; return 0;
x -= FACTOR; /* number of 100ns between 1601 and 1970 */ x -= FACTOR; /* number of 100ns between 1601 and 1970 */
x /= (long long) NSPERSEC; /* number of 100ns in a second */ x /= NSPERSEC; /* number of 100ns in a second */
return x; return x;
} }
/* Cygwin internal */ /* Cygwin internal */
/* Convert a Win32 time to "UNIX" timestruc_t format. */ /* Convert a Win32 time to "UNIX" timestruc_t format. */
void __stdcall void __stdcall
to_timestruc_t (FILETIME *ptr, timestruc_t *out) to_timestruc_t (PLARGE_INTEGER ptr, timestruc_t *out)
{ {
/* A file time is the number of 100ns since jan 1 1601 /* A file time is the number of 100ns since jan 1 1601
stuffed into two long words. stuffed into two long words.
A timestruc_t is the number of seconds and microseconds since jan 1 1970 A timestruc_t is the number of seconds and microseconds since jan 1 1970
stuffed into a time_t and a long. */ stuffed into a time_t and a long. */
long rem; int64_t rem;
long long x = ((long long) ptr->dwHighDateTime << 32) + ((unsigned)ptr->dwLowDateTime); int64_t x = ptr->QuadPart;
/* pass "no time" as epoch */ /* pass "no time" as epoch */
if (x == 0) if (x == 0)
@ -293,8 +273,8 @@ to_timestruc_t (FILETIME *ptr, timestruc_t *out)
} }
x -= FACTOR; /* number of 100ns between 1601 and 1970 */ x -= FACTOR; /* number of 100ns between 1601 and 1970 */
rem = x % ((long long)NSPERSEC); rem = x % NSPERSEC;
x /= (long long) NSPERSEC; /* number of 100ns in a second */ x /= NSPERSEC; /* number of 100ns in a second */
out->tv_nsec = rem * 100; /* as tv_nsec is in nanoseconds */ out->tv_nsec = rem * 100; /* as tv_nsec is in nanoseconds */
out->tv_sec = x; out->tv_sec = x;
} }
@ -304,10 +284,10 @@ to_timestruc_t (FILETIME *ptr, timestruc_t *out)
void __stdcall void __stdcall
time_as_timestruc_t (timestruc_t * out) time_as_timestruc_t (timestruc_t * out)
{ {
FILETIME filetime; LARGE_INTEGER systime;
GetSystemTimeAsFileTime (&filetime); GetSystemTimeAsFileTime ((LPFILETIME) &systime);
to_timestruc_t (&filetime, out); to_timestruc_t (&systime, out);
} }
/* time: POSIX 4.5.1.1, C 4.12.2.4 */ /* time: POSIX 4.5.1.1, C 4.12.2.4 */
@ -316,10 +296,10 @@ extern "C" time_t
time (time_t * ptr) time (time_t * ptr)
{ {
time_t res; time_t res;
FILETIME filetime; LARGE_INTEGER systime;
GetSystemTimeAsFileTime (&filetime); GetSystemTimeAsFileTime ((LPFILETIME) &systime);
res = to_time_t (&filetime); res = to_time_t (&systime);
if (ptr) if (ptr)
*ptr = res; *ptr = res;
@ -486,7 +466,7 @@ hires_ns::nsecs (bool monotonic)
if (inited < 0) if (inited < 0)
{ {
set_errno (ENOSYS); set_errno (ENOSYS);
return (long long) -1; return (LONGLONG) -1;
} }
LARGE_INTEGER now; LARGE_INTEGER now;
@ -502,73 +482,13 @@ hires_ns::nsecs (bool monotonic)
return now.QuadPart; return now.QuadPart;
} }
LONGLONG
hires_ms::timeGetTime_ns ()
{
LARGE_INTEGER t;
/* This is how timeGetTime is implemented in winmm.dll.
The real timeGetTime subtracts and adds some values which are constant
over the lifetime of the process. Since we don't need absolute accuracy
of the value returned by timeGetTime, only relative accuracy, we can skip
this step. However, if we ever find out that we need absolute accuracy,
here's how it works in it's full beauty:
- At process startup, winmm initializes two calibration values:
DWORD tick_count_start;
LARGE_INTEGER int_time_start;
do
{
tick_count_start = GetTickCount ();
do
{
int_time_start.HighPart = SharedUserData.InterruptTime.High1Time;
int_time_start.LowPart = SharedUserData.InterruptTime.LowPart;
}
while (int_time_start.HighPart
!= SharedUserData.InterruptTime.High2Time);
}
while (tick_count_start != GetTickCount ();
- timeGetTime computes its return value in the loop as below, and then:
t.QuadPart -= int_time_start.QuadPart;
t.QuadPart /= 10000;
t.LowPart += tick_count_start;
return t.LowPart;
*/
do
{
t.HighPart = SharedUserData.InterruptTime.High1Time;
t.LowPart = SharedUserData.InterruptTime.LowPart;
}
while (t.HighPart != SharedUserData.InterruptTime.High2Time);
/* We use the value in full 100ns resolution in the calling functions
anyway, so we can skip dividing by 10000 here. */
return t.QuadPart;
}
void
hires_ms::prime ()
{
if (!inited)
{
int priority = GetThreadPriority (GetCurrentThread ());
SetThreadPriority (GetCurrentThread (), THREAD_PRIORITY_TIME_CRITICAL);
initime_ns = systime_ns () - timeGetTime_ns ();
inited = true;
SetThreadPriority (GetCurrentThread (), priority);
}
return;
}
LONGLONG LONGLONG
hires_ms::nsecs () hires_ms::nsecs ()
{ {
if (!inited) LARGE_INTEGER systime;
prime (); GetSystemTimeAsFileTime ((LPFILETIME) &systime);
return systime_ns (); /* Add conversion factor for UNIX vs. Windows base time */
return systime.QuadPart - FACTOR;
} }
extern "C" int extern "C" int
@ -579,8 +499,7 @@ clock_gettime (clockid_t clk_id, struct timespec *tp)
pid_t pid = CLOCKID_TO_PID (clk_id); pid_t pid = CLOCKID_TO_PID (clk_id);
HANDLE hProcess; HANDLE hProcess;
KERNEL_USER_TIMES kut; KERNEL_USER_TIMES kut;
ULONG sizeof_kut = sizeof (KERNEL_USER_TIMES); int64_t x;
long long x;
if (pid == 0) if (pid == 0)
pid = getpid (); pid = getpid ();
@ -593,11 +512,12 @@ clock_gettime (clockid_t clk_id, struct timespec *tp)
} }
hProcess = OpenProcess (PROCESS_QUERY_INFORMATION, 0, p->dwProcessId); hProcess = OpenProcess (PROCESS_QUERY_INFORMATION, 0, p->dwProcessId);
NtQueryInformationProcess (hProcess, ProcessTimes, &kut, sizeof_kut, &sizeof_kut); NtQueryInformationProcess (hProcess, ProcessTimes,
&kut, sizeof kut, NULL);
x = kut.KernelTime.QuadPart + kut.UserTime.QuadPart; x = kut.KernelTime.QuadPart + kut.UserTime.QuadPart;
tp->tv_sec = x / (long long) NSPERSEC; tp->tv_sec = x / NSPERSEC;
tp->tv_nsec = (x % (long long) NSPERSEC) * 100LL; tp->tv_nsec = (x % NSPERSEC) * 100LL;
CloseHandle (hProcess); CloseHandle (hProcess);
return 0; return 0;
@ -608,8 +528,7 @@ clock_gettime (clockid_t clk_id, struct timespec *tp)
long thr_id = CLOCKID_TO_THREADID (clk_id); long thr_id = CLOCKID_TO_THREADID (clk_id);
HANDLE hThread; HANDLE hThread;
KERNEL_USER_TIMES kut; KERNEL_USER_TIMES kut;
ULONG sizeof_kut = sizeof (KERNEL_USER_TIMES); int64_t x;
long long x;
if (thr_id == 0) if (thr_id == 0)
thr_id = pthread::self ()->getsequence_np (); thr_id = pthread::self ()->getsequence_np ();
@ -621,11 +540,12 @@ clock_gettime (clockid_t clk_id, struct timespec *tp)
return -1; return -1;
} }
NtQueryInformationThread (hThread, ThreadTimes, &kut, sizeof_kut, &sizeof_kut); NtQueryInformationThread (hThread, ThreadTimes,
&kut, sizeof kut, NULL);
x = kut.KernelTime.QuadPart + kut.UserTime.QuadPart; x = kut.KernelTime.QuadPart + kut.UserTime.QuadPart;
tp->tv_sec = x / (long long) NSPERSEC; tp->tv_sec = x / NSPERSEC;
tp->tv_nsec = (x % (long long) NSPERSEC) * 100LL; tp->tv_nsec = (x % NSPERSEC) * 100LL;
CloseHandle (hThread); CloseHandle (hThread);
return 0; return 0;
@ -689,7 +609,7 @@ clock_settime (clockid_t clk_id, const struct timespec *tp)
return settimeofday (&tv, NULL); return settimeofday (&tv, NULL);
} }
static DWORD minperiod; // FIXME: Maintain period after a fork. static ULONG minperiod; // FIXME: Maintain period after a fork.
LONGLONG LONGLONG
hires_ns::resolution () hires_ns::resolution ()
@ -699,7 +619,7 @@ hires_ns::resolution ()
if (inited < 0) if (inited < 0)
{ {
set_errno (ENOSYS); set_errno (ENOSYS);
return (long long) -1; return (LONGLONG) -1;
} }
return (freq <= 1.0) ? 1LL : (LONGLONG) freq; return (freq <= 1.0) ? 1LL : (LONGLONG) freq;
@ -710,39 +630,13 @@ hires_ms::resolution ()
{ {
if (!minperiod) if (!minperiod)
{ {
NTSTATUS status;
ULONG coarsest, finest, actual; ULONG coarsest, finest, actual;
status = NtQueryTimerResolution (&coarsest, &finest, &actual); NtQueryTimerResolution (&coarsest, &finest, &actual);
if (NT_SUCCESS (status)) /* The actual resolution of the OS timer is a system-wide setting which
/* The actual resolution of the OS timer is a system-wide setting which can be changed any time, by any process. The only fixed value we
can be changed any time, by any process. The only fixed value we can rely on is the coarsest value. */
can rely on is the coarsest value. */ minperiod = coarsest;
minperiod = coarsest;
else
{
/* There's no good reason that NtQueryTimerResolution should fail
at all, but let's play it safe. Try to empirically determine
current timer resolution */
int priority = GetThreadPriority (GetCurrentThread ());
SetThreadPriority (GetCurrentThread (),
THREAD_PRIORITY_TIME_CRITICAL);
LONGLONG period = 0;
for (int i = 0; i < 4; i++)
{
LONGLONG now;
LONGLONG then = timeGetTime_ns ();
while ((now = timeGetTime_ns ()) == then)
continue;
then = now;
while ((now = timeGetTime_ns ()) == then)
continue;
period += now - then;
}
SetThreadPriority (GetCurrentThread (), priority);
period /= 4L;
minperiod = (DWORD) period;
}
} }
return minperiod; return minperiod;
} }

View File

@ -214,12 +214,12 @@ void __reg2 nofinalslash (const char *src, char *dst);
void __reg3 *hook_or_detect_cygwin (const char *, const void *, WORD&, HANDLE h = NULL); void __reg3 *hook_or_detect_cygwin (const char *, const void *, WORD&, HANDLE h = NULL);
/* Time related */ /* Time related */
void __stdcall totimeval (struct timeval *, FILETIME *, int, int); void __stdcall totimeval (struct timeval *, PLARGE_INTEGER, int, int);
long __stdcall to_time_t (FILETIME *); time_t __stdcall to_time_t (PLARGE_INTEGER);
void __stdcall to_timestruc_t (FILETIME *, timestruc_t *); void __stdcall to_timestruc_t (PLARGE_INTEGER, timestruc_t *);
void __stdcall time_as_timestruc_t (timestruc_t *); void __stdcall time_as_timestruc_t (timestruc_t *);
void __stdcall timespec_to_filetime (const struct timespec *, FILETIME *); void __stdcall timeval_to_filetime (const struct timeval *, PLARGE_INTEGER);
void __stdcall timeval_to_filetime (const struct timeval *, FILETIME *); void __stdcall timespec_to_filetime (const struct timespec *, PLARGE_INTEGER);
/* Console related */ /* Console related */
void __stdcall set_console_title (char *); void __stdcall set_console_title (char *);