On Tue, Mar 14, 2023 at 12:10 PM Nathan Bossart <nathandboss...@gmail.com> wrote: > > * NOTE: although the delay is specified in microseconds, the effective > > - * resolution is only 1/HZ, or 10 milliseconds, on most Unixen. Expect > > - * the requested delay to be rounded up to the next resolution boundary. > > + * resolution is only 1/HZ on systems that use periodic kernel ticks to > > wake > > + * up. This may cause sleeps to be rounded up by 1-20 milliseconds on > > older > > + * Unixen and Windows. > > nitpick: Could the 1/HZ versus 20 milliseconds discrepancy cause confusion? > Otherwise, I think this is the right idea.
Better words welcome; 1-20ms summarises the range I actually measured, and if reports are correct about Windows' HZ=64 (1/HZ = 15.625ms) then it neatly covers that too, so I don't feel too bad about not chasing down the reason for that 10ms/20ms discrepancy; maybe I looked at the wrong HZ number (which you can change, anyway), I'm not too used to NetBSD... BTW they have a project plan to fix that https://wiki.netbsd.org/projects/project/tickless/ > > + * CAUTION: if interrupted by a signal, this function will return, but its > > + * interface doesn't report that. It's not a good idea to use this > > + * for long sleeps in the backend, because backends are expected to > > respond to > > + * interrupts promptly. Better practice for long sleeps is to use > > WaitLatch() > > + * with a timeout. > > I'm not sure this argument follows. If pg_usleep() returns if interrupted, > then why are we concerned about delayed responses to interrupts? Because you can't rely on it: 1. Maybe the signal is delivered just before pg_usleep() begins, and a handler sets some flag we would like to react to. Now pg_usleep() will not be interrupted. That problem is solved by using latches instead. 2. Maybe the signal is one that is no longer handled by a handler at all; these days, latches use SIGURG, which pops out when you read a signalfd or kqueue, so pg_usleep() will not wake up. That problem is solved by using latches instead. (The word "interrupt" is a bit overloaded, which doesn't help with this discussion.) > > - delay.tv_usec = microsec % 1000000L; > > - (void) select(0, NULL, NULL, NULL, &delay); > > + delay.tv_nsec = (microsec % 1000000L) * 1000; > > + (void) nanosleep(&delay, NULL); > > Using nanosleep() seems reasonable to me. Thanks for looking!