diff options
author | Yaakov Selkowitz <yselkowi@redhat.com> | 2011-05-17 17:08:10 +0000 |
---|---|---|
committer | Yaakov Selkowitz <yselkowi@redhat.com> | 2011-05-17 17:08:10 +0000 |
commit | c8ce54290ddec2e84ac94bef53c518c43140c183 (patch) | |
tree | 3aedcb9955b2a790c5a39a722dd1145cd8b8a550 /winsup/cygwin/times.cc | |
parent | 5e3af166d7f81d96adb225f6511d08e70bb2610d (diff) | |
download | cygnal-c8ce54290ddec2e84ac94bef53c518c43140c183.tar.gz cygnal-c8ce54290ddec2e84ac94bef53c518c43140c183.tar.bz2 cygnal-c8ce54290ddec2e84ac94bef53c518c43140c183.zip |
* 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.
Diffstat (limited to 'winsup/cygwin/times.cc')
-rw-r--r-- | winsup/cygwin/times.cc | 88 |
1 files changed, 88 insertions, 0 deletions
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 <sys/timeb.h> #include <utime.h> #include <stdlib.h> +#include <unistd.h> #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; +} |