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:
parent
ba763af559
commit
0ff057d5a5
|
@ -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>
|
||||
|
||||
* net.cc (gen_old_if_name): New function to generate short interface
|
||||
|
|
|
@ -518,14 +518,14 @@ fhandler_base::fstat_helper (struct stat *buf,
|
|||
PFILE_NETWORK_OPEN_INFORMATION pfnoi = pc.fnoi ();
|
||||
ULONG attributes = pc.file_attributes ();
|
||||
|
||||
to_timestruc_t ((PFILETIME) &pfnoi->LastAccessTime, &buf->st_atim);
|
||||
to_timestruc_t ((PFILETIME) &pfnoi->LastWriteTime, &buf->st_mtim);
|
||||
to_timestruc_t (&pfnoi->LastAccessTime, &buf->st_atim);
|
||||
to_timestruc_t (&pfnoi->LastWriteTime, &buf->st_mtim);
|
||||
/* If the ChangeTime is 0, the underlying FS doesn't support this timestamp
|
||||
(FAT for instance). If so, it's faked using LastWriteTime. */
|
||||
to_timestruc_t (pfnoi->ChangeTime.QuadPart ? (PFILETIME) &pfnoi->ChangeTime
|
||||
: (PFILETIME) &pfnoi->LastWriteTime,
|
||||
to_timestruc_t (pfnoi->ChangeTime.QuadPart ? &pfnoi->ChangeTime
|
||||
: &pfnoi->LastWriteTime,
|
||||
&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 ();
|
||||
/* CV 2011-01-13: Observations on the Cygwin mailing list point to an
|
||||
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;
|
||||
/* 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[1], (LPFILETIME) &fbi.LastWriteTime);
|
||||
timespec_to_filetime (&tmp[0], &fbi.LastAccessTime);
|
||||
timespec_to_filetime (&tmp[1], &fbi.LastWriteTime);
|
||||
fbi.ChangeTime.QuadPart = 0LL;
|
||||
fbi.FileAttributes = 0;
|
||||
NTSTATUS status = NtSetInformationFile (get_handle (), &io, &fbi, sizeof fbi,
|
||||
|
|
|
@ -570,7 +570,7 @@ format_proc_stat (void *, char *&destbuf)
|
|||
swap_in = spi->PagesRead;
|
||||
swap_out = spi->PagefilePagesWritten;
|
||||
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"
|
||||
"swap %u %u\n"
|
||||
|
|
|
@ -508,7 +508,7 @@ fhandler_registry::fstat (struct stat *buf)
|
|||
RegQueryInfoKeyW (hKey, NULL, NULL, NULL, &subkey_count, NULL,
|
||||
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;
|
||||
time_as_timestruc_t (&buf->st_atim);
|
||||
if (file_type > virt_none)
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* 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.
|
||||
|
||||
|
@ -55,15 +55,11 @@ class hires_ns : public hires_base
|
|||
|
||||
class hires_ms : public hires_base
|
||||
{
|
||||
LONGLONG initime_ns;
|
||||
LONGLONG timeGetTime_ns ();
|
||||
void prime ();
|
||||
public:
|
||||
LONGLONG nsecs ();
|
||||
LONGLONG usecs () {return nsecs () / 10LL;}
|
||||
LONGLONG msecs () {return nsecs () / 10000LL;}
|
||||
UINT resolution ();
|
||||
LONGLONG uptime () {return (nsecs () - initime_ns) / 10000LL;}
|
||||
};
|
||||
|
||||
extern hires_ms gtod;
|
||||
|
|
|
@ -199,7 +199,7 @@ ipc_cond_timedwait (HANDLE evt, HANDLE mtx, const struct timespec *abstime)
|
|||
NotificationTimer);
|
||||
if (!NT_SUCCESS (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);
|
||||
if (!NT_SUCCESS (status))
|
||||
{
|
||||
|
|
|
@ -65,18 +65,16 @@ add_rusage (struct rusage *r1, struct rusage *r2)
|
|||
void __stdcall
|
||||
fill_rusage (struct rusage *r, HANDLE h)
|
||||
{
|
||||
FILETIME creation_time = {0,0};
|
||||
FILETIME exit_time = {0,0};
|
||||
FILETIME kernel_time = {0,0};
|
||||
FILETIME user_time = {0,0};
|
||||
KERNEL_USER_TIMES kut;
|
||||
|
||||
struct timeval tv;
|
||||
|
||||
memset (r, 0, sizeof (*r));
|
||||
GetProcessTimes (h, &creation_time, &exit_time, &kernel_time, &user_time);
|
||||
totimeval (&tv, &kernel_time, 0, 0);
|
||||
memset (&kut, 0, sizeof kut);
|
||||
memset (r, 0, sizeof *r);
|
||||
NtQueryInformationProcess (h, ProcessTimes, &kut, sizeof kut, NULL);
|
||||
totimeval (&tv, &kut.KernelTime, 0, 0);
|
||||
add_timeval (&r->ru_stime, &tv);
|
||||
totimeval (&tv, &user_time, 0, 0);
|
||||
totimeval (&tv, &kut.UserTime, 0, 0);
|
||||
add_timeval (&r->ru_utime, &tv);
|
||||
|
||||
VM_COUNTERS vmc;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/* times.cc
|
||||
|
||||
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.
|
||||
|
||||
|
@ -31,28 +31,17 @@ hires_ms NO_COPY gtod;
|
|||
|
||||
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 */
|
||||
static unsigned long long __stdcall
|
||||
__to_clock_t (FILETIME *src, int flag)
|
||||
static uint64_t __stdcall
|
||||
__to_clock_t (PLARGE_INTEGER src, int flag)
|
||||
{
|
||||
unsigned long long total = ((unsigned long long) src->dwHighDateTime << 32) + ((unsigned)src->dwLowDateTime);
|
||||
syscall_printf ("dwHighDateTime %u, dwLowDateTime %u", src->dwHighDateTime, src->dwLowDateTime);
|
||||
|
||||
uint64_t total = src->QuadPart;
|
||||
/* Convert into clock ticks - the total is in 10ths of a usec. */
|
||||
if (flag)
|
||||
total -= FACTOR;
|
||||
|
||||
total /= (unsigned long long) (NSPERSEC / CLOCKS_PER_SEC);
|
||||
syscall_printf ("total %08x %08x", (unsigned) (total>>32), (unsigned) (total));
|
||||
total /= NSPERSEC / CLOCKS_PER_SEC;
|
||||
debug_printf ("total %016X", total);
|
||||
return total;
|
||||
}
|
||||
|
||||
|
@ -60,31 +49,37 @@ __to_clock_t (FILETIME *src, int flag)
|
|||
extern "C" clock_t
|
||||
times (struct tms *buf)
|
||||
{
|
||||
FILETIME creation_time, exit_time, kernel_time, user_time;
|
||||
|
||||
myfault efault;
|
||||
if (efault.faulted (EFAULT))
|
||||
return ((clock_t) -1);
|
||||
|
||||
LONGLONG ticks = gtod.uptime ();
|
||||
/* Ticks is in milliseconds, convert to our ticks. Use long long to prevent
|
||||
overflow. */
|
||||
clock_t tc = (clock_t) (ticks * CLOCKS_PER_SEC / 1000);
|
||||
static SYSTEM_TIMEOFDAY_INFORMATION stodi;
|
||||
KERNEL_USER_TIMES kut;
|
||||
LARGE_INTEGER ticks;
|
||||
|
||||
GetProcessTimes (GetCurrentProcess (), &creation_time, &exit_time,
|
||||
&kernel_time, &user_time);
|
||||
/* Fetch boot time if we haven't already. */
|
||||
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 ("user_time %D, kernel_time %D, "
|
||||
"creation_time %D, exit_time %D",
|
||||
user_time, kernel_time,
|
||||
creation_time, exit_time);
|
||||
buf->tms_stime = __to_clock_t (&kernel_time, 0);
|
||||
buf->tms_utime = __to_clock_t (&user_time, 0);
|
||||
timeval_to_filetime (&myself->rusage_children.ru_stime, &kernel_time);
|
||||
buf->tms_cstime = __to_clock_t (&kernel_time, 1);
|
||||
timeval_to_filetime (&myself->rusage_children.ru_utime, &user_time);
|
||||
buf->tms_cutime = __to_clock_t (&user_time, 1);
|
||||
syscall_printf ("UserTime %D, KernelTime %D, CreationTime %D, ExitTime %D",
|
||||
kut.UserTime, kut.KernelTime, kut.CreateTime, kut.ExitTime);
|
||||
buf->tms_stime = __to_clock_t (&kut.KernelTime, 0);
|
||||
buf->tms_utime = __to_clock_t (&kut.UserTime, 0);
|
||||
timeval_to_filetime (&myself->rusage_children.ru_stime, &kut.KernelTime);
|
||||
buf->tms_cstime = __to_clock_t (&kut.KernelTime, 1);
|
||||
timeval_to_filetime (&myself->rusage_children.ru_utime, &kut.UserTime);
|
||||
buf->tms_cutime = __to_clock_t (&kut.UserTime, 1);
|
||||
|
||||
return tc;
|
||||
}
|
||||
|
@ -142,15 +137,15 @@ timezone (void)
|
|||
|
||||
/* Cygwin internal */
|
||||
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 -= (long long) sub * (int) (1e6);
|
||||
x *= (int64_t) 1000000 / CLOCKS_PER_SEC; /* Turn x into usecs */
|
||||
x -= (int64_t) sub * 1000000;
|
||||
|
||||
dst->tv_usec = x % (long long) (1e6); /* And split */
|
||||
dst->tv_sec = x / (long long) (1e6);
|
||||
dst->tv_usec = x % 1000000; /* And split */
|
||||
dst->tv_sec = x / 1000000;
|
||||
}
|
||||
|
||||
/* FIXME: Make thread safe */
|
||||
|
@ -183,38 +178,23 @@ gettimeofday (struct timeval *tv, void *tzvp)
|
|||
|
||||
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 */
|
||||
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)
|
||||
out->dwHighDateTime = out->dwLowDateTime = 0;
|
||||
out->QuadPart = 0;
|
||||
else
|
||||
{
|
||||
long long x = time_in->tv_sec * NSPERSEC +
|
||||
time_in->tv_nsec / (1000000000/NSPERSEC) + FACTOR;
|
||||
out->dwHighDateTime = x >> 32;
|
||||
out->dwLowDateTime = x;
|
||||
}
|
||||
out->QuadPart = time_in->tv_sec * NSPERSEC
|
||||
+ time_in->tv_nsec / (1000000000/NSPERSEC) + FACTOR;
|
||||
}
|
||||
|
||||
/* Cygwin internal */
|
||||
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 +
|
||||
time_in->tv_usec * (NSPERSEC/1000000) + FACTOR;
|
||||
out->dwHighDateTime = x >> 32;
|
||||
out->dwLowDateTime = x;
|
||||
out->QuadPart = time_in->tv_sec * NSPERSEC
|
||||
+ time_in->tv_usec * (NSPERSEC/1000000) + FACTOR;
|
||||
}
|
||||
|
||||
/* Cygwin internal */
|
||||
|
@ -253,36 +233,36 @@ timeval_to_timespec (const struct timeval *tvp, struct timespec *tmp)
|
|||
|
||||
/* Cygwin internal */
|
||||
/* Convert a Win32 time to "UNIX" format. */
|
||||
long __stdcall
|
||||
to_time_t (FILETIME *ptr)
|
||||
time_t __stdcall
|
||||
to_time_t (PLARGE_INTEGER ptr)
|
||||
{
|
||||
/* A file time is the number of 100ns since jan 1 1601
|
||||
stuffed into two long words.
|
||||
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 */
|
||||
if (x == 0)
|
||||
return 0;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/* Cygwin internal */
|
||||
/* Convert a Win32 time to "UNIX" timestruc_t format. */
|
||||
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
|
||||
stuffed into two long words.
|
||||
A timestruc_t is the number of seconds and microseconds since jan 1 1970
|
||||
stuffed into a time_t and a long. */
|
||||
|
||||
long rem;
|
||||
long long x = ((long long) ptr->dwHighDateTime << 32) + ((unsigned)ptr->dwLowDateTime);
|
||||
int64_t rem;
|
||||
int64_t x = ptr->QuadPart;
|
||||
|
||||
/* pass "no time" as epoch */
|
||||
if (x == 0)
|
||||
|
@ -293,8 +273,8 @@ to_timestruc_t (FILETIME *ptr, timestruc_t *out)
|
|||
}
|
||||
|
||||
x -= FACTOR; /* number of 100ns between 1601 and 1970 */
|
||||
rem = x % ((long long)NSPERSEC);
|
||||
x /= (long long) NSPERSEC; /* number of 100ns in a second */
|
||||
rem = x % NSPERSEC;
|
||||
x /= NSPERSEC; /* number of 100ns in a second */
|
||||
out->tv_nsec = rem * 100; /* as tv_nsec is in nanoseconds */
|
||||
out->tv_sec = x;
|
||||
}
|
||||
|
@ -304,10 +284,10 @@ to_timestruc_t (FILETIME *ptr, timestruc_t *out)
|
|||
void __stdcall
|
||||
time_as_timestruc_t (timestruc_t * out)
|
||||
{
|
||||
FILETIME filetime;
|
||||
LARGE_INTEGER systime;
|
||||
|
||||
GetSystemTimeAsFileTime (&filetime);
|
||||
to_timestruc_t (&filetime, out);
|
||||
GetSystemTimeAsFileTime ((LPFILETIME) &systime);
|
||||
to_timestruc_t (&systime, out);
|
||||
}
|
||||
|
||||
/* time: POSIX 4.5.1.1, C 4.12.2.4 */
|
||||
|
@ -316,10 +296,10 @@ extern "C" time_t
|
|||
time (time_t * ptr)
|
||||
{
|
||||
time_t res;
|
||||
FILETIME filetime;
|
||||
LARGE_INTEGER systime;
|
||||
|
||||
GetSystemTimeAsFileTime (&filetime);
|
||||
res = to_time_t (&filetime);
|
||||
GetSystemTimeAsFileTime ((LPFILETIME) &systime);
|
||||
res = to_time_t (&systime);
|
||||
if (ptr)
|
||||
*ptr = res;
|
||||
|
||||
|
@ -486,7 +466,7 @@ hires_ns::nsecs (bool monotonic)
|
|||
if (inited < 0)
|
||||
{
|
||||
set_errno (ENOSYS);
|
||||
return (long long) -1;
|
||||
return (LONGLONG) -1;
|
||||
}
|
||||
|
||||
LARGE_INTEGER now;
|
||||
|
@ -502,73 +482,13 @@ hires_ns::nsecs (bool monotonic)
|
|||
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
|
||||
hires_ms::nsecs ()
|
||||
{
|
||||
if (!inited)
|
||||
prime ();
|
||||
return systime_ns ();
|
||||
LARGE_INTEGER systime;
|
||||
GetSystemTimeAsFileTime ((LPFILETIME) &systime);
|
||||
/* Add conversion factor for UNIX vs. Windows base time */
|
||||
return systime.QuadPart - FACTOR;
|
||||
}
|
||||
|
||||
extern "C" int
|
||||
|
@ -579,8 +499,7 @@ clock_gettime (clockid_t clk_id, struct timespec *tp)
|
|||
pid_t pid = CLOCKID_TO_PID (clk_id);
|
||||
HANDLE hProcess;
|
||||
KERNEL_USER_TIMES kut;
|
||||
ULONG sizeof_kut = sizeof (KERNEL_USER_TIMES);
|
||||
long long x;
|
||||
int64_t x;
|
||||
|
||||
if (pid == 0)
|
||||
pid = getpid ();
|
||||
|
@ -593,11 +512,12 @@ clock_gettime (clockid_t clk_id, struct timespec *tp)
|
|||
}
|
||||
|
||||
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;
|
||||
tp->tv_sec = x / (long long) NSPERSEC;
|
||||
tp->tv_nsec = (x % (long long) NSPERSEC) * 100LL;
|
||||
tp->tv_sec = x / NSPERSEC;
|
||||
tp->tv_nsec = (x % NSPERSEC) * 100LL;
|
||||
|
||||
CloseHandle (hProcess);
|
||||
return 0;
|
||||
|
@ -608,8 +528,7 @@ clock_gettime (clockid_t clk_id, struct timespec *tp)
|
|||
long thr_id = CLOCKID_TO_THREADID (clk_id);
|
||||
HANDLE hThread;
|
||||
KERNEL_USER_TIMES kut;
|
||||
ULONG sizeof_kut = sizeof (KERNEL_USER_TIMES);
|
||||
long long x;
|
||||
int64_t x;
|
||||
|
||||
if (thr_id == 0)
|
||||
thr_id = pthread::self ()->getsequence_np ();
|
||||
|
@ -621,11 +540,12 @@ clock_gettime (clockid_t clk_id, struct timespec *tp)
|
|||
return -1;
|
||||
}
|
||||
|
||||
NtQueryInformationThread (hThread, ThreadTimes, &kut, sizeof_kut, &sizeof_kut);
|
||||
NtQueryInformationThread (hThread, ThreadTimes,
|
||||
&kut, sizeof kut, NULL);
|
||||
|
||||
x = kut.KernelTime.QuadPart + kut.UserTime.QuadPart;
|
||||
tp->tv_sec = x / (long long) NSPERSEC;
|
||||
tp->tv_nsec = (x % (long long) NSPERSEC) * 100LL;
|
||||
tp->tv_sec = x / NSPERSEC;
|
||||
tp->tv_nsec = (x % NSPERSEC) * 100LL;
|
||||
|
||||
CloseHandle (hThread);
|
||||
return 0;
|
||||
|
@ -689,7 +609,7 @@ clock_settime (clockid_t clk_id, const struct timespec *tp)
|
|||
return settimeofday (&tv, NULL);
|
||||
}
|
||||
|
||||
static DWORD minperiod; // FIXME: Maintain period after a fork.
|
||||
static ULONG minperiod; // FIXME: Maintain period after a fork.
|
||||
|
||||
LONGLONG
|
||||
hires_ns::resolution ()
|
||||
|
@ -699,7 +619,7 @@ hires_ns::resolution ()
|
|||
if (inited < 0)
|
||||
{
|
||||
set_errno (ENOSYS);
|
||||
return (long long) -1;
|
||||
return (LONGLONG) -1;
|
||||
}
|
||||
|
||||
return (freq <= 1.0) ? 1LL : (LONGLONG) freq;
|
||||
|
@ -710,39 +630,13 @@ hires_ms::resolution ()
|
|||
{
|
||||
if (!minperiod)
|
||||
{
|
||||
NTSTATUS status;
|
||||
ULONG coarsest, finest, actual;
|
||||
|
||||
status = NtQueryTimerResolution (&coarsest, &finest, &actual);
|
||||
if (NT_SUCCESS (status))
|
||||
/* 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 rely on is the coarsest value. */
|
||||
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;
|
||||
}
|
||||
NtQueryTimerResolution (&coarsest, &finest, &actual);
|
||||
/* 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 rely on is the coarsest value. */
|
||||
minperiod = coarsest;
|
||||
}
|
||||
return minperiod;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
||||
/* Time related */
|
||||
void __stdcall totimeval (struct timeval *, FILETIME *, int, int);
|
||||
long __stdcall to_time_t (FILETIME *);
|
||||
void __stdcall to_timestruc_t (FILETIME *, timestruc_t *);
|
||||
void __stdcall totimeval (struct timeval *, PLARGE_INTEGER, int, int);
|
||||
time_t __stdcall to_time_t (PLARGE_INTEGER);
|
||||
void __stdcall to_timestruc_t (PLARGE_INTEGER, 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 *, FILETIME *);
|
||||
void __stdcall timeval_to_filetime (const struct timeval *, PLARGE_INTEGER);
|
||||
void __stdcall timespec_to_filetime (const struct timespec *, PLARGE_INTEGER);
|
||||
|
||||
/* Console related */
|
||||
void __stdcall set_console_title (char *);
|
||||
|
|
Loading…
Reference in New Issue