From c8ce54290ddec2e84ac94bef53c518c43140c183 Mon Sep 17 00:00:00 2001 From: Yaakov Selkowitz Date: Tue, 17 May 2011 17:08:10 +0000 Subject: * cygwin.din (clock_getcpuclockid): Export. (pthread_getcpuclockid): Export. * hires.h (PID_TO_CLOCKID): New macro. (CLOCKID_TO_PID): New macro. (CLOCKID_IS_PROCESS): New macro. (THREADID_TO_CLOCKID): New macro. (CLOCKID_TO_THREADID): New macro. (CLOCKID_IS_THREAD): New macro. * ntdll.h (enum _THREAD_INFORMATION_CLASS): Add ThreadTimes. * posix.sgml (std-notimpl): Add clock_getcpuclockid and pthread_getcpuclockid from here... (std-susv4): ... to here. (std-notes): Remove limitations of clock_getres and clock_gettime. Note limitation of timer_create to CLOCK_REALTIME. * sysconf.cc (sca): Set _SC_CPUTIME to _POSIX_CPUTIME, and _SC_THREAD_CPUTIME to _POSIX_THREAD_CPUTIME. * thread.cc (pthread_getcpuclockid): New function. * timer.cc (timer_create): Set errno to ENOTSUP for CPU-time clocks. * times.cc (clock_gettime): Handle CLOCK_PROCESS_CPUTIME_ID and CLOCK_THREAD_CPUTIME_ID. (clock_getres): Ditto. (clock_settime): Set errno to EPERM for CPU-time clocks. (clock_getcpuclockid): New function. * include/pthread.h (pthread_getcpuclockid): Declare. * include/cygwin/version.h (CYGWIN_VERSION_API_MINOR): Bump. --- winsup/cygwin/times.cc | 88 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 88 insertions(+) (limited to 'winsup/cygwin/times.cc') diff --git a/winsup/cygwin/times.cc b/winsup/cygwin/times.cc index 4e6697e76..6bb68ecd1 100644 --- a/winsup/cygwin/times.cc +++ b/winsup/cygwin/times.cc @@ -15,6 +15,7 @@ details. */ #include #include #include +#include #include "cygerrno.h" #include "security.h" #include "path.h" @@ -22,6 +23,7 @@ details. */ #include "dtable.h" #include "cygheap.h" #include "pinfo.h" +#include "thread.h" #include "cygtls.h" #include "ntdll.h" @@ -594,6 +596,63 @@ hires_ms::nsecs () extern "C" int clock_gettime (clockid_t clk_id, struct timespec *tp) { + if (CLOCKID_IS_PROCESS (clk_id)) + { + pid_t pid = CLOCKID_TO_PID (clk_id); + HANDLE hProcess; + KERNEL_USER_TIMES kut; + ULONG sizeof_kut = sizeof (KERNEL_USER_TIMES); + long long x; + + if (pid == 0) + pid = getpid (); + + pinfo p (pid); + if (!p->exists ()) + { + set_errno (EINVAL); + return -1; + } + + hProcess = OpenProcess (PROCESS_QUERY_INFORMATION, 0, p->dwProcessId); + NtQueryInformationProcess (hProcess, ProcessTimes, &kut, sizeof_kut, &sizeof_kut); + + x = kut.KernelTime.QuadPart + kut.UserTime.QuadPart; + tp->tv_sec = x / (long long) NSPERSEC; + tp->tv_nsec = (x % (long long) NSPERSEC) * 100LL; + + CloseHandle (hProcess); + return 0; + } + + if (CLOCKID_IS_THREAD (clk_id)) + { + long thr_id = CLOCKID_TO_THREADID (clk_id); + HANDLE hThread; + KERNEL_USER_TIMES kut; + ULONG sizeof_kut = sizeof (KERNEL_USER_TIMES); + long long x; + + if (thr_id == 0) + thr_id = pthread::self ()->getsequence_np (); + + hThread = OpenThread (THREAD_QUERY_INFORMATION, 0, thr_id); + if (!hThread) + { + set_errno (EINVAL); + return -1; + } + + NtQueryInformationThread (hThread, ThreadTimes, &kut, sizeof_kut, &sizeof_kut); + + x = kut.KernelTime.QuadPart + kut.UserTime.QuadPart; + tp->tv_sec = x / (long long) NSPERSEC; + tp->tv_nsec = (x % (long long) NSPERSEC) * 100LL; + + CloseHandle (hThread); + return 0; + } + switch (clk_id) { case CLOCK_REALTIME: @@ -630,6 +689,16 @@ clock_settime (clockid_t clk_id, const struct timespec *tp) { struct timeval tv; + if (CLOCKID_IS_PROCESS (clk_id) || CLOCKID_IS_THREAD (clk_id)) + /* According to POSIX, the privileges to set a particular clock + * are implementation-defined. On Linux, CPU-time clocks are not + * settable; do the same here. + */ + { + set_errno (EPERM); + return -1; + } + if (clk_id != CLOCK_REALTIME) { set_errno (EINVAL); @@ -702,6 +771,16 @@ hires_ms::resolution () extern "C" int clock_getres (clockid_t clk_id, struct timespec *tp) { + if (CLOCKID_IS_PROCESS (clk_id) || CLOCKID_IS_THREAD (clk_id)) + { + ULONG coarsest, finest, actual; + + NtQueryTimerResolution (&coarsest, &finest, &actual); + tp->tv_sec = coarsest / NSPERSEC; + tp->tv_nsec = (coarsest % NSPERSEC) * 100; + return 0; + } + switch (clk_id) { case CLOCK_REALTIME: @@ -776,3 +855,12 @@ clock_setres (clockid_t clk_id, struct timespec *tp) period_set = true; return 0; } + +extern "C" int +clock_getcpuclockid (pid_t pid, clockid_t *clk_id) +{ + if (pid != 0 && !pinfo (pid)->exists ()) + return (ESRCH); + *clk_id = (clockid_t) PID_TO_CLOCKID (pid); + return 0; +} -- cgit v1.2.3