[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, &timespec);
> > * 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