[PATCH] clock_nanosleep(2), pthread_condattr_[gs]etclock(3)
Corinna Vinschen
corinna-cygwin@cygwin.com
Thu Jul 21 09:36:00 GMT 2011
On Jul 21 11:21, Corinna Vinschen wrote:
> On Jul 20 21:22, Yaakov (Cygwin/X) wrote:
> > Looking at the other uses of cancelable_wait(), would the following make
> > sense:
> >
> > * change the timeout argument to struct timespec *;
> > * cancelable_wait (object, INFINITE) calls change to (object, NULL);
> > * cancelable_wait (object, DWORD) calls change to (object, ×pec);
> > * then in cancelable_wait:
> >
> > HANDLE hTimer;
> > HANDLE wait_objects[4];
> > ....
> > wait_objects[num++] = object;
> >
> > if (timeout)
> > {
> > LARGE_INTEGER li;
> > li.QuadPart = (timeout->tv_sec * NSPERSEC) + (timeout->tv_nsec /
> > 100); /* rounding? */
> > hTimer = CreateWaitableTimer (NULL, FALSE, NULL);
> > SetWaitableTimer (hTimer, &li, 0, NULL, NULL, FALSE); /* handle
> > possible error? what would cause one? */
> > wait_objects[num++] = hTimer;
> > }
> > ...
> > while (1)
> > {
> > res = WaitForMultipleObjects (num, wait_objects, FALSE, INFINITE);
> > ....
> >
> > Or am I completely off-base here?
>
> No, you're not at all off-base. Personally I'd prefer to use the native
> NT timer functions, but that's not important. What I'm missing is a way
> to specify relative vs. absolute timeouts in your above sketch. I guess
> we need a flag argument as well.
>
> Other than that, I think we should make sure to create the waitable
> timer only once on a per-thread base. Object creation and deletion is
> usually a time consuming process. So what we could do is to add a
> HANDLE "cw_timer" to struct _local_storage in cygtls.h, which gets
> inited to NULL in _cygtls::init_thread as well as in
> _cygtls::fixup_after_fork.
>
> Then cancelable_wait with a non-NULL timespec would check for the handle
> being NULL and create a non-inheritable timer, if so. All subsequent
> calls only set (and cancel) the timer.
>
> Does that sound reasonable?
Btw., if you call NtQueryTimer right before NtCancelTimer, then you get
the remaining time for free to return to clock_nanosleep. It would
be nice if NtQueryTimer would return the remaining time after calling
NtCancelTimer, but my experiments show that some weird value gets
returned. See my attached testcase. Build with -lntdll.
Corinna
--
Corinna Vinschen Please, send mails regarding Cygwin to
Cygwin Project Co-Leader cygwin AT cygwin DOT com
Red Hat
-------------- next part --------------
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include <ddk/ntddk.h>
int
main (int argc, char* argv[])
{
NTSTATUS status;
HANDLE timer;
LARGE_INTEGER duetime;
PTIMER_BASIC_INFORMATION tbi;
int cnt = 10, i;
long long lastTimer = 0;
duetime.QuadPart = -10000000000LL;
tbi = (PTIMER_BASIC_INFORMATION)
calloc (cnt + 1, sizeof (TIMER_BASIC_INFORMATION));
if (!tbi)
{
printf ("malloc failed\n:");
return 1;
}
status = NtCreateTimer (&timer, TIMER_ALL_ACCESS, NULL, NotificationTimer);
if (!NT_SUCCESS (status))
{
printf ("NtCreateTimer: %p\n", status);
return 1;
}
status = NtSetTimer (timer, &duetime, NULL, NULL, FALSE, 1000000L, NULL);
if (!NT_SUCCESS (status))
{
printf ("NtSetTimer: %p\n", status);
return 1;
}
for (i = 0; i < cnt; ++i)
{
do
{
NtQueryTimer (timer, TimerBasicInformation, tbi + i, sizeof *tbi,
NULL);
//Sleep(1);
}
while (tbi[i].TimeRemaining.QuadPart
== tbi[i - 1].TimeRemaining.QuadPart);
}
NtCancelTimer (timer, NULL);
status = NtQueryTimer (timer, TimerBasicInformation, tbi + i, sizeof *tbi,
NULL);
if (!NT_SUCCESS (status))
printf ("NtQueryTimer: %p\n", status);
NtClose (timer);
for (i = 1; i < cnt + 1; ++i)
printf("Timer: %lld (%llx), dTimer: %lld usec\n",
tbi[i].TimeRemaining.QuadPart,
tbi[i].TimeRemaining.QuadPart,
(tbi[i - 1].TimeRemaining.QuadPart
- tbi[i].TimeRemaining.QuadPart) / 10);
return 0;
}
More information about the Cygwin-patches
mailing list