Austin Group Defect Tracker

Aardvark Mark III


Viewing Issue Simple Details Jump to Notes ] Issue History ] Print ]
ID Category Severity Type Date Submitted Last Update
0001271 [1003.1(2008)/Issue 7] System Interfaces Editorial Enhancement Request 2019-07-20 16:50 2019-08-15 15:51
Reporter scottcheloha View Status public  
Assigned To ajosey
Priority normal Resolution Open  
Status Under Review  
Name Scott Cheloha
Organization
User Reference
Section clock_nanosleep()
Page Number (where is the page number in the HTML version?)
Line Number (where is the line number in the HTML version?)
Interp Status ---
Final Accepted Text
Summary 0001271: clock_nanosleep() TIMER_ABSTIME: if rmtp is non-NULL, set it to clock_id's time value when returning.
Description Assuming clock_id is a valid and supported clock, if TIMER_ABSTIME is set and rmtp is non-NULL the time value of clock_id's clock at wakeup should be written to rmtp upon return from clock_nanosleep().

Why?

First, this behavior is intuitive. When TIMER_ABSTIME is unset the remaining time for the sleep is written out to rmtp upon return. If TIMER_ABSTIME is set the analogous behavior would be to write the absolute time for the given clock to rmtp, no?

Second, this behavior is useful. Consider an event loop: in an event-driven application where work is performed at particular times the application must *always* read the clock when it wakes up. Even if there is an error, assuming the process isn't terminated the application is eventually going to read the clock. With the current time in hand the application can then decide what to do: either run the events that are ready or go back to sleep.

Portable applications cannot assume the current time in the TIMER_ABSTIME case if clock_nanosleep() returns 0 because the wakeup latency is not defined by the specification. Portable applications will always need to get the current time when they wake up. This is particularly true in the CLOCK_REALTIME case: discontinuous time jumps are permitted by the standard and clock_nanosleep() has defined behavior in that case.

Given that you *always* want to know the current time on clock_id's clock when you wake up, why not just write it out to the spare timespec we have available in the argument list currently serving no purpose?

For implementations using a kernel you save a system call. This means avoiding a potentially costly trip back to the kernel, a useful property for realtime applications.

As for implementations on systems without a kernel, or implementations in library code, in order to compute the remaining time in in the non-TIMER_ABSTIME case that code already needs to have a way to retrieve the current time. So in the TIMER_ABSTIME case those implementations can simply write that value to rmtp.

Kernel or no kernel, little additional code is required of any currently conforming implementation to provide this feature.

The sole potential dealbreaker is that the current specification mandates that rmtp not be modified in the TIMER_ABSTIME case. If there are applications mixing relative and absolute sleeps they may break if this new behavior is enabled. But I think the likelihood of practical code depending upon that behavior is extremely small. Practical event loops are not written with a mix of relative and absolute sleeps.

Of course, if the potential for breaking existing applications is unacceptable a new flag could be introduced that, if set, enabled this new behavior. Possible names for the flag's symbol include "TIMER_NOW", "TIMER_UPDATE", or "TIMER_GET". When set in flags along with TIMER_ABSTIME, if the the rmtp argument is non-NULL, the implementation should write the current time value of clock_id's clock to the timespec represented by rmtp on wakeup. Behavior would be undefined if the new flag were set without TIMER_ABSTIME.

To enable the new behavior, code would then look something like this:

struct timespec deadline, now;
int status;

for (;;) {
    get_next_deadline(&deadline);
    status = clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME|TIMER_GET, &deadline, &now);
    if (status == -1) {
        /* handle error */
    }
    if (deadline.tv_sec > now.tv_sec ||
        (deadline.tv_sec == now.tv_sec && deadline.tv_nsec >= now.tv_nsec)) {
        /* handle deadline */
    }
}
Desired Action Without a new flag, the change is relatively simple.

Update the clock_nanosleep() page. In particular, the RETURN VALUE section's second paragraph should be updated.

> If the clock_nanosleep() function returns because it has been interrupted by a signal,
> it shall return the corresponding error value.
> For the relative clock_nanosleep() function,
> if the rmtp argument is non-NULL,
> the timespec structure referenced by it shall be updated to contain the amount of time
> remaining in the interval (the requested time minus the time actually slept).
> If the rmtp argument is NULL,
> the remaining time is not returned.
> The rqtp and rmtp arguments can point to the same object.
> The absolute clock_nanosleep() function has no effect on the structure referenced by rmtp.

becomes

> If the clock_nanosleep() function returns because it has been interrupted by a signal,
> it shall return the corresponding error value.
> For the relative clock_nanosleep() function,
> if the rmtp argument is non-NULL,
> the timespec structure referenced by it shall be updated to contain the amount of time
> remaining in the interval (the requested time minus the time actually slept).
> For the absolute clock_nanosleep() function,
> if the rmtp argument is non-NULL,
> the timespec structure referenced by it shall be updated to contain the time value of the
> clock specified by clock_id.
> For both the relative and absolute clock_nanosleep() functions,
> if the rmtp argument is NULL,
> it is ignored.
> The rqtp and rmtp arguments can point to the same object.

--

If people find the flag preferable the change would be more involved.

Update the RETURN VALUES section on the clock_nanosleep() page. The second paragraph would need to be modified:

> If the clock_nanosleep() function returns because it has been interrupted by a signal,
> it shall return the corresponding error value.
> For the relative clock_nanosleep() function,
> if the rmtp argument is non-NULL,
> the timespec structure referenced by it shall be updated to contain the amount of time
> remaining in the interval (the requested time minus the time actually slept).
> The rqtp and rmtp arguments can point to the same object.
> The absolute clock_nanosleep() function has no effect on the structure referenced by rmtp.

should changed to something akin to the following:

> If the clock_nanosleep() function returns because it has been interrupted by a signal,
> it shall return the corresponding error value.
>
> For the relative clock_nanosleep() function,
> if the rmtp argument is non-NULL,
> the timespec structure referenced by it shall be updated to contain the amount of time
> remaining in the interval (the requested time minus the time actually slept).
> If the rmtp argument is NULL,
> the remaining time is not returned.
>
> For the absolute clock_nanosleep() function,
> if the TIMER_GET flag is set and the rmtp argument is non-NULL,
> the timespec structure referenced by rmtp shall be updated to contain the time value of the
> clock specified by clock_id.
> If TIMER_GET flag is unset,
> or the rmtp argument is NULL,
> the time value of the clock specified by clock_id is not returned.
>
> Regardless of the value of flags, the rqtp and rmtp arguments can point to the same object.
Tags No tags attached.
Attached Files

- Relationships

-  Notes
(0004522)
eblake (manager)
2019-08-15 15:51
edited on: 2019-08-15 15:53

The idea was discussed in the 2019-08-15 meeting; consensus was that a new flag may have merit, but we would need a reference implementation. Is there a link pointing to a library where this has been implemented already, or to a mailing list discussion where an existing implementation has expressed interest in taking this up first, before standardizing anything?

A new flag has further benefits - the new behavior becomes introspectible (if the flag exists, you can opt in to using it), so that is better than changing the default behavior.

I fired off a question to glibc to see if they want to become a reference implementation: https://sourceware.org/ml/libc-alpha/2019-08/msg00394.html [^]


- Issue History
Date Modified Username Field Change
2019-07-20 16:50 scottcheloha New Issue
2019-07-20 16:50 scottcheloha Status New => Under Review
2019-07-20 16:50 scottcheloha Assigned To => ajosey
2019-07-20 16:50 scottcheloha Name => Scott Cheloha
2019-07-20 16:50 scottcheloha Section => clock_nanosleep()
2019-07-20 16:50 scottcheloha Page Number => (where is the page number in the HTML version?)
2019-07-20 16:50 scottcheloha Line Number => (where is the line number in the HTML version?)
2019-07-20 17:08 Don Cragun Page Number (where is the page number in the HTML version?) => 671
2019-07-20 17:08 Don Cragun Line Number (where is the line number in the HTML version?) => 22756-22761
2019-07-20 17:08 Don Cragun Interp Status => ---
2019-07-20 17:12 scottcheloha Page Number 671 => (where is the page number in the HTML version?)
2019-07-20 17:12 scottcheloha Line Number 22756-22761 => (where is the line number in the HTML version?)
2019-07-20 17:12 scottcheloha Description Updated
2019-07-20 17:12 scottcheloha Desired Action Updated
2019-07-20 17:24 scottcheloha Desired Action Updated
2019-08-15 15:51 eblake Note Added: 0004522
2019-08-15 15:53 eblake Note Edited: 0004522


Mantis 1.1.6[^]
Copyright © 2000 - 2008 Mantis Group
Powered by Mantis Bugtracker