[PATCH v4 1/2] POSIX Asynchronous I/O support: aio files

Mark Geisert mark@maxrnd.com
Tue Jul 24 05:03:00 GMT 2018


Corinna Vinschen wrote:
> Hi Mark,
>
> there's just one problem left:
[...]
>> +
>> +  QueryUnbiasedInterruptTime (&time0);
>
> Nice idea to use QueryUnbiasedInterruptTime.  The problem here is just
> that QueryUnbiasedInterruptTime has been introduced with Windows 7, but
> we still support Windows Vista :}
>
> We could just drop Vista support (is anybody actually using it?) but
> there's an alternative: Include hires.h and use ntod, a global ns
> counter object using Windows performance counters under the hood:
>
>   #include "hires.h"
>
>   time0 = ntod.nsecs ();  /* ns, *not* 100ns */
>   ...
>
> With that single change I think your patch series can go in.

I don't want to be the one to say "drop Vista" because I tend to stay on the 
trailing edge of Windows versions myself.  Your idea of using ntod.nsecs() is a 
nice fix, and dealing with nanoseconds all the way simplifies the code a bit:

static int
aiosuspend (const struct aiocb *const aiolist[],
          int nent, const struct timespec *timeout)
{
   /* Returns lowest list index of completed aios, else 'nent' if all completed.
    * If none completed on entry, wait for interval specified by 'timeout'.
    */
   int       res;
   sigset_t  sigmask;
   siginfo_t si;
   ULONGLONG nsecs = 0;
   ULONGLONG time0, time1;
   struct timespec to = {0};

   if (timeout)
     {
       to = *timeout;
       if (to.tv_sec < 0 || to.tv_nsec < 0 || to.tv_nsec > NSPERSEC)
         {
           set_errno (EINVAL);
           return -1;
         }
       nsecs = (NSPERSEC * to.tv_sec) + to.tv_nsec;
     }

retry:
   sigemptyset (&sigmask);
   int aiocount = 0;
   for (int i = 0; i < nent; ++i)
     if (aiolist[i] && aiolist[i]->aio_liocb)
       {
         if (aiolist[i]->aio_errno == EINPROGRESS ||
             aiolist[i]->aio_errno == ENOBUFS ||
             aiolist[i]->aio_errno == EBUSY)
           {
             ++aiocount;
             if (aiolist[i]->aio_sigevent.sigev_notify == SIGEV_SIGNAL ||
                 aiolist[i]->aio_sigevent.sigev_notify == SIGEV_THREAD)
               sigaddset (&sigmask, aiolist[i]->aio_sigevent.sigev_signo);
           }
         else
           return i;
       }

   if (aiocount == 0)
     return nent;

   if (timeout && nsecs == 0)
     {
       set_errno (EAGAIN);
       return -1;
     }

   time0 = ntod.nsecs ();
   /* Note wait below is abortable even w/ empty sigmask and infinite timeout */
   res = sigtimedwait (&sigmask, &si, timeout ? &to : NULL);
   if (res == -1)
     return -1; /* Return with errno set by failed sigtimedwait() */
   time1 = ntod.nsecs ();

   /* Adjust timeout to account for time just waited */
   time1 -= time0;
   if (time1 > nsecs)
     nsecs = 0; // just in case we didn't get rescheduled very quickly
   else
     nsecs -= time1;
   to.tv_sec = nsecs / NSPERSEC;
   to.tv_nsec = nsecs % NSPERSEC;

   goto retry;
}

The final patch set for the POSIX AIO feature will be appearing shortly.
Thanks & Regards,

..mark



More information about the Cygwin-patches mailing list