Welcome to mirror list, hosted at ThFree Co, Russian Federation.

cygwin.com/git/newlib-cygwin.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--winsup/cygwin/ChangeLog28
-rw-r--r--winsup/cygwin/cygwin.din2
-rw-r--r--winsup/cygwin/hires.h8
-rw-r--r--winsup/cygwin/include/cygwin/version.h4
-rw-r--r--winsup/cygwin/include/pthread.h1
-rw-r--r--winsup/cygwin/ntdll.h1
-rw-r--r--winsup/cygwin/posix.sgml15
-rw-r--r--winsup/cygwin/sysconf.cc4
-rw-r--r--winsup/cygwin/thread.cc9
-rw-r--r--winsup/cygwin/timer.cc7
-rw-r--r--winsup/cygwin/times.cc88
11 files changed, 156 insertions, 11 deletions
diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog
index 7f5cae4cb..61060a8cc 100644
--- a/winsup/cygwin/ChangeLog
+++ b/winsup/cygwin/ChangeLog
@@ -1,3 +1,31 @@
+2011-05-17 Yaakov Selkowitz <yselkowitz@users.sourceforge.net>
+
+ * 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.
+
2011-05-17 Corinna Vinschen <corinna@vinschen.de>
* miscfuncs.cc (thread_wrapper): Remove unused _cygtls record.
diff --git a/winsup/cygwin/cygwin.din b/winsup/cygwin/cygwin.din
index 12c3f3d57..8d1e7032e 100644
--- a/winsup/cygwin/cygwin.din
+++ b/winsup/cygwin/cygwin.din
@@ -217,6 +217,7 @@ clearerr SIGFE
_clearerr = clearerr SIGFE
clock SIGFE
_clock = clock SIGFE
+clock_getcpuclockid SIGFE
clock_getres SIGFE
clock_gettime SIGFE
clock_setres SIGFE
@@ -1212,6 +1213,7 @@ pthread_equal SIGFE
pthread_exit SIGFE
pthread_getattr_np SIGFE
pthread_getconcurrency SIGFE
+pthread_getcpuclockid SIGFE
pthread_getschedparam SIGFE
pthread_getsequence_np SIGFE
pthread_getspecific SIGFE
diff --git a/winsup/cygwin/hires.h b/winsup/cygwin/hires.h
index 0acfafdbd..15c8d209d 100644
--- a/winsup/cygwin/hires.h
+++ b/winsup/cygwin/hires.h
@@ -13,6 +13,14 @@ details. */
#include <mmsystem.h>
+/* Conversions for per-process and per-thread clocks */
+#define PID_TO_CLOCKID(pid) (pid * 8 + CLOCK_PROCESS_CPUTIME_ID)
+#define CLOCKID_TO_PID(cid) ((cid - CLOCK_PROCESS_CPUTIME_ID) / 8)
+#define CLOCKID_IS_PROCESS(cid) ((cid % 8) == CLOCK_PROCESS_CPUTIME_ID)
+#define THREADID_TO_CLOCKID(tid) (tid * 8 + CLOCK_THREAD_CPUTIME_ID)
+#define CLOCKID_TO_THREADID(cid) ((cid - CLOCK_THREAD_CPUTIME_ID) / 8)
+#define CLOCKID_IS_THREAD(cid) ((cid % 8) == CLOCK_THREAD_CPUTIME_ID)
+
/* Largest delay in ms for sleep and alarm calls.
Allow actual delay to exceed requested delay by 10 s.
Express as multiple of 1000 (i.e. seconds) + max resolution
diff --git a/winsup/cygwin/include/cygwin/version.h b/winsup/cygwin/include/cygwin/version.h
index ea66d4097..fed1c0ccc 100644
--- a/winsup/cygwin/include/cygwin/version.h
+++ b/winsup/cygwin/include/cygwin/version.h
@@ -412,12 +412,14 @@ details. */
244: Export clock_settime.
245: Export pthread_attr_getguardsize, pthread_attr_setguardsize,
pthread_attr_setstack, pthread_attr_setstackaddr.
+ 246: Add CLOCK_PROCESS_CPUTIME_ID, CLOCK_THREAD_CPUTIME_ID.
+ Export clock_getcpuclockid, pthread_getcpuclockid.
*/
/* Note that we forgot to bump the api for ualarm, strtoll, strtoull */
#define CYGWIN_VERSION_API_MAJOR 0
-#define CYGWIN_VERSION_API_MINOR 245
+#define CYGWIN_VERSION_API_MINOR 246
/* There is also a compatibity version number associated with the
shared memory regions. It is incremented when incompatible
diff --git a/winsup/cygwin/include/pthread.h b/winsup/cygwin/include/pthread.h
index e963eba54..4ed53ab08 100644
--- a/winsup/cygwin/include/pthread.h
+++ b/winsup/cygwin/include/pthread.h
@@ -141,6 +141,7 @@ int pthread_create (pthread_t *, const pthread_attr_t *,
int pthread_detach (pthread_t);
int pthread_equal (pthread_t, pthread_t);
void pthread_exit (void *);
+int pthread_getcpuclockid (pthread_t, clockid_t *);
int pthread_getschedparam (pthread_t, int *, struct sched_param *);
void *pthread_getspecific (pthread_key_t);
int pthread_join (pthread_t, void **);
diff --git a/winsup/cygwin/ntdll.h b/winsup/cygwin/ntdll.h
index 9c5597ec1..77aeeece0 100644
--- a/winsup/cygwin/ntdll.h
+++ b/winsup/cygwin/ntdll.h
@@ -938,6 +938,7 @@ typedef enum _EVENT_INFORMATION_CLASS
typedef enum _THREAD_INFORMATION_CLASS
{
ThreadBasicInformation = 0,
+ ThreadTimes = 1,
ThreadImpersonationToken = 5
} THREAD_INFORMATION_CLASS, *PTHREAD_INFORMATION_CLASS;
diff --git a/winsup/cygwin/posix.sgml b/winsup/cygwin/posix.sgml
index a576b353f..f6ec0b0e2 100644
--- a/winsup/cygwin/posix.sgml
+++ b/winsup/cygwin/posix.sgml
@@ -90,8 +90,9 @@ also IEEE Std 1003.1-2008 (POSIX.1-2008).</para>
cimagf
clearerr
clock
- clock_getres (see chapter "Implementation Notes")
- clock_gettime (see chapter "Implementation Notes")
+ clock_getcpuclockid
+ clock_getres
+ clock_gettime
clock_settime (see chapter "Implementation Notes")
clog
clogf
@@ -564,6 +565,7 @@ also IEEE Std 1003.1-2008 (POSIX.1-2008).</para>
pthread_equal
pthread_exit
pthread_getconcurrency
+ pthread_getcpuclockid
pthread_getschedparam
pthread_getspecific
pthread_join
@@ -836,7 +838,7 @@ also IEEE Std 1003.1-2008 (POSIX.1-2008).</para>
tgamma
tgammaf
time
- timer_create
+ timer_create (see chapter "Implementation Notes")
timer_delete
timer_gettime
timer_settime
@@ -1292,7 +1294,6 @@ also IEEE Std 1003.1-2008 (POSIX.1-2008).</para>
ceill
cexpl
cimagl
- clock_getcpuclockid
clogl
conjl
copysignl
@@ -1386,7 +1387,6 @@ also IEEE Std 1003.1-2008 (POSIX.1-2008).</para>
pthread_barrier[...]
pthread_condattr_getclock
pthread_condattr_setclock
- pthread_getcpuclockid
pthread_mutexattr_getrobust
pthread_mutexattr_setrobust
pthread_mutex_consistent
@@ -1441,9 +1441,8 @@ by keeping track of the current root and accomodating this in the file
related function calls. A real chroot functionality is not supported by
Windows however.</para>
-<para><function>clock_getres</function> and <function>clock_gettime</function>
-only support CLOCK_REALTIME and CLOCK_MONOTONIC for now. <function>clock_setres</function>
-and <function>clock_settime</function> only support CLOCK_REALTIME.</para>
+<function>clock_setres</function>, <function>clock_settime</function>, and
+<function>timer_create</function> only support CLOCK_REALTIME.</para>
<para>BSD file locks created via <function>flock</function> are not
propagated to the parent process and sibling processes. The locks are
diff --git a/winsup/cygwin/sysconf.cc b/winsup/cygwin/sysconf.cc
index 73c44fe36..0dbb17610 100644
--- a/winsup/cygwin/sysconf.cc
+++ b/winsup/cygwin/sysconf.cc
@@ -160,7 +160,7 @@ static struct
{cons, {c:BC_STRING_MAX}}, /* 60, _SC_BC_STRING_MAX */
{cons, {c:-1L}}, /* 61, _SC_CLOCK_SELECTION */
{nsup, {c:0}}, /* 62, _SC_COLL_WEIGHTS_MAX */
- {cons, {c:-1L}}, /* 63, _SC_CPUTIME */
+ {cons, {c:_POSIX_CPUTIME}}, /* 63, _SC_CPUTIME */
{cons, {c:EXPR_NEST_MAX}}, /* 64, _SC_EXPR_NEST_MAX */
{cons, {c:HOST_NAME_MAX}}, /* 65, _SC_HOST_NAME_MAX */
{cons, {c:IOV_MAX}}, /* 66, _SC_IOV_MAX */
@@ -177,7 +177,7 @@ static struct
{cons, {c:-1L}}, /* 77, _SC_SPORADIC_SERVER */
{nsup, {c:0}}, /* 78, _SC_SS_REPL_MAX */
{cons, {c:SYMLOOP_MAX}}, /* 79, _SC_SYMLOOP_MAX */
- {cons, {c:-1L}}, /* 80, _SC_THREAD_CPUTIME */
+ {cons, {c:_POSIX_THREAD_CPUTIME}}, /* 80, _SC_THREAD_CPUTIME */
{cons, {c:-1L}}, /* 81, _SC_THREAD_SPORADIC_SERVER */
{cons, {c:-1L}}, /* 82, _SC_TIMEOUTS */
{cons, {c:-1L}}, /* 83, _SC_TRACE */
diff --git a/winsup/cygwin/thread.cc b/winsup/cygwin/thread.cc
index b53fc7f70..c70709bff 100644
--- a/winsup/cygwin/thread.cc
+++ b/winsup/cygwin/thread.cc
@@ -2510,6 +2510,15 @@ pthread_getconcurrency ()
return MT_INTERFACE->concurrency;
}
+extern "C" int
+pthread_getcpuclockid (pthread_t thread, clockid_t *clk_id)
+{
+ if (!pthread::is_good_object (&thread))
+ return (ESRCH);
+ *clk_id = (clockid_t) THREADID_TO_CLOCKID (thread->getsequence_np ());
+ return 0;
+}
+
/* keep this in sync with sched.cc */
extern "C" int
pthread_getschedparam (pthread_t thread, int *policy,
diff --git a/winsup/cygwin/timer.cc b/winsup/cygwin/timer.cc
index 91e71146c..be740e07a 100644
--- a/winsup/cygwin/timer.cc
+++ b/winsup/cygwin/timer.cc
@@ -300,6 +300,13 @@ timer_create (clockid_t clock_id, struct sigevent *evp, timer_t *timerid)
myfault efault;
if (efault.faulted (EFAULT))
return -1;
+
+ if (CLOCKID_IS_PROCESS (clock_id) || CLOCKID_IS_THREAD (clock_id))
+ {
+ set_errno (ENOTSUP);
+ return -1;
+ }
+
if (clock_id != CLOCK_REALTIME)
{
set_errno (EINVAL);
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;
+}