Hi, The nanosleep.2 page could use some cleanup. Here's a bunch of fixes, rewrites, etc.
I've included my notes on the changes below. I have some (mostly stylistic) questions in there, too. -- DESCRIPTION - We suspend the calling thread, not the calling process. - Note that we block for "at least" the given timeout. After all, we might block for longer. - Be more explicit about signal delivery. Should we reference sigaction(2) here alongside SA_RESTART? e.g.: ... even if SA_RESTART is set for the interrupting signal (see sigaction(2) for further details). RETURN VALUES - Make it clear there are three cases here: success, signal, and other errors. Separate them into three paragraphs. - Note that we update remainder in the success case *and* the signal case, but not the other case. I'm unsure about the correct voice here. Should nanosleep actively return values? Or should values "be returned"? EXAMPLES - Add some examples. The first example is trivial. Just warmup. Show them how to pack a timespec and make the call. The second example demonstrates how to set up a sub-second timeout. Sometimes people screw this up, I think it's worth highlighting. The last example is more complex. Show them how to differentiate between a signal and programmer error. Show how the remainder argument works. Show that timeout and remainder can point to the same struct. I'm unclear on whether I need the indent here in the .Bd block. I think it looks better than unindented code, but maybe I'm flouting some practice we have. ERRORS - Simplify the opening sentence. Yeesh, what a mouthful. - "1000 million" is better written "one billion". We've done this change already in other pages. - Note that remainder must be non-NULL for an EFAULT to occur. - Use the past tense consistently. Unsure if a second EFAULT case for remainder is a good thing here. Strictly speaking, NULL is not a valid part of the process address space. Maybe that's too pedantic? Also, do we have a more standard "boilerplate" sentence for EFAULT? SEE ALSO - Cross reference sigaction(2). We mention SA_RESTART in the description. HISTORY - Clarify what happened to the historical sleep system call a bit. - I'm pretty sure nanosleep() is a POSIX invention, so note that it really first appeared in POSIX.1b (realtime extensions), and then talk about the implementation we got from NetBSD. If someone can find nanosleep() in the wild before 1993 we can fix the attribution. - No need to mention that FreeBSD also got their implementation from NetBSD. -- Index: nanosleep.2 =================================================================== RCS file: /cvs/src/lib/libc/sys/nanosleep.2,v retrieving revision 1.16 diff -u -p -r1.16 nanosleep.2 --- nanosleep.2 31 Dec 2018 18:54:00 -0000 1.16 +++ nanosleep.2 20 Jul 2021 22:14:50 -0000 @@ -41,53 +41,114 @@ .Ft int .Fn nanosleep "const struct timespec *timeout" "struct timespec *remainder" .Sh DESCRIPTION +The .Fn nanosleep -suspends execution of the calling process for the duration specified by +function suspends execution of the calling thread for at least the +duration specified by .Fa timeout . -An unmasked signal will cause it to terminate the sleep early, -regardless of the +Delivery of an unmasked signal to the calling thread will terminate the +sleep early, +even if .Dv SA_RESTART -value on the interrupting signal. +is set for the interrupting signal. .Sh RETURN VALUES -If the +If .Fn nanosleep -function returns because the requested duration has elapsed, the value -returned will be zero. +sleeps the full +.Fa timeout +without interruption it returns 0. +If +.Fa remainder +is +.Pf non- Dv NULL +it is set to zero. .Pp -If the +If .Fn nanosleep -function returns due to the delivery of a signal, the value returned -will be \-1, and the global variable +is interrupted by a signal it returns -1 and the global variable .Va errno -will be set to indicate the interruption. +is set to +.Dv EINTR . If .Fa remainder -is non-null, the timespec structure it references is updated to contain the -unslept amount (the requested duration minus the duration actually slept). -.Sh ERRORS -If any of the following conditions occur, the +is +.Pf non- Dv NULL +it is set to the unslept portion of the +.Fa timeout . +.Pp +Otherwise, .Fn nanosleep -function shall return \-1 and set +returns -1 and the global variable .Va errno -to the corresponding value. +is set to indicate the error. +.Sh EXAMPLES +Count down from ten: +.Bd -literal + struct timespec one_second; + int i; + + one_second.tv_sec = 1; + one_second.tv_nsec = 0; + + for (i = 10; i >= 0; i--) { + if (nanosleep(&one_second, NULL) == -1) + err(1, "nanosleep"); + printf("%4d\\n", i); + } +.Ed +.Pp +Check a condition once every one hundred milliseconds: +.Bd -literal + struct timespec hundred_ms; + extern int done; + + hundred_ms.tv_sec = 0; + hundred_ms.tv_nsec = 100 * 1000 * 1000; + + while (!done) { + if (nanosleep(&hundred_ms, NULL) == -1) + err(1, "nanosleep"); + } +.Ed +.Pp +Sleep for at least sixty seconds and print the time remaining whenever +a signal interrupts the sleep: +.Bd -literal + struct timespec timeout; + + timeout.tv_sec = 60; + timeout.tv_nsec = 0; + + while (nanosleep(&timeout, &timeout) == -1) { + if (errno != EINTR) + err(1, "nanosleep"); + printf("time left: %lld.%09ld seconds\\n", + (long long)timeout.tv_sec, timeout.tv_nsec); + } +.Ed +.Sh ERRORS +.Fn nanosleep +will fail if: .Bl -tag -width Er .It Bq Er EINTR -.Fn nanosleep -was interrupted by the delivery of a signal. +The call was interrupted by the delivery of a signal. .It Bq Er EINVAL .Fa timeout specified a nanosecond value less than zero or greater than or equal to -1000 million, +one billion, or a second value less than zero. .It Bq Er EFAULT -Either .Fa timeout -or +pointed to memory that is not a valid part of the process address space. +.It Bq Er EFAULT .Fa remainder -points to memory that is not a valid part of the process address space. +was +.Pf non- Dv NULL +and pointed to memory that is not a valid part of the process address space. .El .Sh SEE ALSO .Xr sleep 1 , +.Xr sigaction 2 , .Xr sleep 3 .Sh STANDARDS The @@ -97,17 +158,23 @@ function conforms to .Sh HISTORY The predecessor of this system call, .Fn sleep , -appeared in -.At v3 , -but was removed when +first appeared in +.At v3 . +It was removed in +.At v7 +and replaced with a C library implementation based on .Xr alarm 3 -was introduced into -.At v7 . +and +.Xr signal 3 . +.Pp The .Fn nanosleep -system call has been available since +function first appeared in +.St -p1003.1b-93 . +.Pp +This implementation of +.Fn nanosleep +first appeared in .Nx 1.3 and was ported to -.Ox 2.1 -and -.Fx 3.0 . +.Ox 2.1 .