Anonymous | Login | 2024-12-02 07:16 UTC |
Main | My View | View Issues | Change Log | Docs |
Viewing Issue Simple Details [ Jump to Notes ] | [ Issue History ] [ Print ] | ||||||
ID | Category | Severity | Type | Date Submitted | Last Update | ||
0001216 | [1003.1(2016/18)/Issue7+TC2] System Interfaces | Comment | Enhancement Request | 2018-11-26 18:53 | 2024-06-11 09:08 | ||
Reporter | mikecrowe | View Status | public | ||||
Assigned To | ajosey | ||||||
Priority | normal | Resolution | Accepted As Marked | ||||
Status | Closed | ||||||
Name | Mike Crowe | ||||||
Organization | |||||||
User Reference | |||||||
Section | pthread | ||||||
Page Number | 0 | ||||||
Line Number | 0 | ||||||
Interp Status | --- | ||||||
Final Accepted Text | Note: 0005339 | ||||||
Summary | 0001216: Adding clockid parameter to functions that accept absolute struct timespec timeouts | ||||||
Description |
POSIX contains several functions that support waiting with an absolute timeout passed as a struct timespec. This time must almost always be measured against CLOCK_REALTIME. (pthread_cond_timedwait also supports a single alternative clock specified at construction time via pthread_condattr_setclock.) Embedded systems and desktop computers may not have a good source of accurate time, particularly at boot. This can result in CLOCK_REALTIME warping by a large amount when the real time is known. In such situations, CLOCK_REALTIME is not a good choice for expressing timeouts. A member of the Android libc team has reported[1] that this has been the cause of real world bugs in Android applications. I've worked on software at different companies where we had to work around this problem. The C++ standard provides std::condition_variable::wait_until and std::timed_mutex::try_lock_until methods which support arbitrary clocks. Current implementations that build upon POSIX convert these clocks to CLOCK_REALTIME, which can cause race conditions when CLOCK_REALTIME is warped. The C++ standard requires the clock to be specified at the time of the wait, which means that pthread_condattr_setclock isn't useful. The above problems can be solved by adding variants of the affected functions that take an extra clockid_t parameter to indicate the clock that should be used. Initially, implementations would be required to only support passing CLOCK_REALTIME which would make adding support straightforward. Support for CLOCK_MONOTONIC would be suggested, and implementations would be free to support other clocks if they wished. This proposal is the result of a thread[2] on the mailing list and my original defect report[3] only covering pthread_cond_timedwait. Various naming options for the new functions were discussed[4] and the following names are based on one of the more popular options. In all cases the clock immediately precedes the timespec timeout. int pthread_mutex_clocklock( pthread_mutex_t *restrict mutex, clockid_t clock, const struct timespec *restrict abstime) int pthread_rwlock_clockrdlock( pthread_rwlock_t *restrict rwlock, clockid_t clock, const struct timespec *restrict abstime) int pthread_rwlock_clockwrlock( pthread_rwlock_t *restrict rwlock, clockid_t clock, const struct timespec *restrict abstime) int pthread_cond_clockwait( pthread_cond_t *restrict cond, pthread_mutex_t *restrict mutex, clockid_t clock, const struct timespec *restrict abstime) int sem_clockwait( sem_t *restrict sem, clockid_t clock, const struct timespec *restrict abstime) ssize_t mq_clockreceive( mqd_t mqdes, char *restrict msg_ptr, size_t msg_len, unsigned int *restrict msg_prio, clockid_t clock, const struct timespec *restrict abs_timeout) int mq_clocksend( mqd_t mqdes, const char *restrict msg_ptr, size_t msg_len, unsigned int msg_prio, clockid_t clock, const struct timespec *restrict abs_timeout) These functions all behave the same as their "timed" equivalents, but measure the timeout against the specified clock rather than CLOCK_REALTIME. If passed an unsupported clock, these functions indicate failure in the same way as their "timed" equivalents and return/set errno to ENOTSUP as required. Support for a clock by one function does not require that the clock be supported by any of the others. [1] https://www.mail-archive.com/austin-group-l@opengroup.org/msg02902.html [^] [2] https://www.mail-archive.com/austin-group-l@opengroup.org/msg02813.html [^] [3] http://austingroupbugs.net/view.php?id=1164 [^] [4] https://www.mail-archive.com/austin-group-l@opengroup.org/msg03034.html [^] |
||||||
Desired Action | The addition of the above functions, or ones that provide equivalent functionality. | ||||||
Tags | issue8 | ||||||
Attached Files | |||||||
|
Relationships | |||||||||||
|
Notes | |
(0004171) nick (manager) 2018-11-27 16:02 |
As a reminder, the Austin Group procedures (see https://opengroup.org/austin/docs/austin_sd6.txt) [^] state:
|
(0004196) mikecrowe (reporter) 2019-01-07 21:26 |
This issue was discussed in the 2018-11-29 teleconference[1] and I received advice on how to proceed. In particular, during the call we discussed making the new functions distinguish between valid-but-unsupported clocks (such as CLOCK_PROCESS_CPUTIME_ID) and an entirely invalid clock. After further thought, I've realised that there are actually three separate error cases: 1. Valid, but nonsensical clock (such as CLOCK_PROCESS_CPUTIME_ID.) 2. Valid, but (currently) unsupported clock (such as CLOCK_MONOTONIC in an implementation that doesn't support it yet.) 3. Invalid clock ID. Whilst implementing the new functions within glibc I realised that returning different errors for these situations is error-prone because a complete list of valid clocks is required for the target platform. There is a high risk that a new clock is added, but not all the functions are updated to return an appropriate error. Therefore, I propose that all three cases return/set errno to EINVAL. [1] https://www.mail-archive.com/austin-group-l@opengroup.org/msg03074.html [^] |
(0004215) mikecrowe (reporter) 2019-01-19 04:08 |
Here's my suggested wording for pthread_cond_clockwait (with a single hint to the other new functions too.) It would be great to receive feedback on whether the changes are broadly appropriate, and whether there is a better way to describe the changes. Once I know whether I'm on the right track, I can add the remaining functions (which will hopefully require fewer changes.) (I have glibc implementations of sem_clockwait, pthread_mutex_clockwait, pthread_cond_clockwait, pthread_rwlock_clockrdlock and pthread_rwlock_clockwrlock working. I just need to get the commit messages into shape before posting them to the glibc list.) Thanks. Mike. *** Add to lists at lines 3070, 10833, 18119, 52281, 52599, 52710, 55292, 124395, 130171: pthread_cond_clockwait() *** After line 10727 insert: int pthread_cond_clockwait(pthread_cond_t *restrict, pthread_mutex_t *restrict, clockid_t, const struct timespec *restrict); *** After line 10767 insert: It calls pthread_cond_clockwait() with m as the mutex argument and the call returns zero or certain error numbers (see pthread_cond_clockwait()). *** After line 17972 insert: It blocks in a call to pthread_cond_clockwait() with m as the mutex argument. *** Line 30449 Change "and pthread_cond_timedwait" to ", pthread_cond_timedwait and pthread_cond_clockwait". *** Lines 52513, 52515, 52519, 52582, 124488 Change "or pthread_cond_timedwait" to ", pthread_cond_timedwait or pthread_cond_clockwait". *** After line 52743 insert: int pthread_cond_clockwait(pthread_cond_t *restrict cond, pthread_mutex_t *restrict mutex, clockid_t clock_id, const struct timespec *restrict abstime); *** Lines 52747, 52762, 52763, 52766, 52781, 52783, 52786, 52848, 52882 Add ", pthread_cond_clockwait()" after "pthread_cond_timedwait()" *** After line 52797 insert: The pthread_cond_clockwait() function shall be equivalent to pthread_cond_timedwait(), except that the absolute time specified by abstime is measured against the clock indicated by clock_id rather than the clock specified in the condition variable's clock attribute. All implementations shall support passing CLOCK_REALTIME to pthread_cond_clockwait() as the clock_id parameter. If the Monotonic Clock option is supported, all implementations shall support a clock_id of CLOCK_MONOTONIC. *** Line 52822: Change to "The pthread_cond_timedwait() and pthread_cond_clockwait() functions shall fail if:" *** Line 52823, 52850: Change "pthread_cond_timedwait()" to "pthread_cond_timedwait() or pthread_cond_clockwait()" *** Line 52825: Add "or the clock_id parameter passed to pthread_cond_clockwait is invalid or not supported." *** Insert after line 52879: Choice of clock Care should be taken to decide which clock is most appropriate when waiting with a timeout. The system clock, CLOCK_REALTIME, as used by default with pthread_cond_timedwait() may be subject to jumps forwards and backwards in order to correct it against actual time. CLOCK_MONOTONIC is guaranteed not to jump backwards and must also advance in real time, so using it via pthread_cond_clockwait() or pthread_condattr_setclock() may be more appropriate. *** Line 52943: Replace CLOCK_REALTIME with CLOCK_MONOTONIC *** Line 52947: Replace line with: rc = pthread_cond_clockwait(&t.cond, &t.mn, CLOCK_MONOTONIC, &ts); *** After line line 52956 insert: Using CLOCK_MONOTONIC rather than CLOCK_REALTIME means that the timeout is not influenced by the system clock being changed. *** After line 53084 insert: Note that the /clock/ attribute shall have no effect on the pthread_cond_clockwait() function. *** Lines 54147, 54186, 54321, 55282: After "pthread_cond_timedwait()" insert ", pthread_cond_clockwait()". *** Line 123502: Delete remainder of paragraph starting with "This capability has not been added to other functions...". Insert in its place: For condition variables, this capability is also available by passing CLOCK_MONOTONIC to the pthread_cond_clockwait() function. Similarly, CLOCK_MONOTONIC can be specified when calling sem_clockwait, pthread_mutex_clocklock, pthread_rwlock_clockrdlock and pthread_rwlock_clockwrlock. *** After line 123535: Subsequently, it was discovered that using a particular clock for the timeout was desired by some users. In particular, the ISO C++11 standard requires the clock to be a property of the wait for its std::condition_variable and std::timed_mutex. This led to the addition of sem_clockwait(), pthread_mutex_clockwait(), pthread_cond_clockwait(), pthread_rwlock_clockrdlock() and pthread_rwlock_clockwrlock() functions that accepted a clock parameter to measure their absolute timeout against. The addition of the corresponding mq_clockreceive and mq_clocksend may be considered in the future. |
(0004276) mikecrowe (reporter) 2019-03-06 13:17 |
I've posted patches for pthread_cond_clockwait, sem_clockwait, pthread_rwlock_clockrdlock and pthread_rwlock_clockwrlock to the glibc mailing list. I received only one reply for a straightforward-to-fix problem. https://sourceware.org/ml/libc-alpha/2019-02/msg00637.html [^] pthread_mutex_clocklock requires more work. |
(0004387) mikecrowe (reporter) 2019-05-07 12:09 |
Suggested wording updates for all new functions: ** General *** Insert after p3622:123506 It was later found necessary to add variants of almost all interfaces that accept absolute timeouts that allow the clock to be specified. This is because, despite the claim in the previous paragraph, it is not possible to safely use a CLOCK_REALTIME absolute timeout even to prevent errors when the system clock is warped by a potentially large amount. A "safety timeout" of a minute on a call pthread_mutex_timedlock() could actually mean no timeout at all if the system clock is warped forwards immediately prior to the call. This functionality is provided by the new "clockwait" variants of the existing "timedwait" functions that accept an extra clockid_t parameter to indicate the clock to be used for the wait. The clock parameter is passed rather than using attributes as previously for pthread_cond_timedwait in order to allow ISOXXX C++11 and later to be implemented correctly. C++ requires that the clock to use for the wait is not known until the time of the wait call, so it cannot be supplied during creation. The new functions are sem_clockwait(), pthread_cond_clockwait(), pthread_mutex_clocklock(), pthread_mutex_clockrdlock() and pthread_mutex_clockwrlock(). It is expected that mq_clockreceive() and mq_clocksend() functions will be added in a future version of this standard too. ** pthread_cond_clockwait *** Add to lists at lines - p111:3070 - p318:10833 - p518:18119 - p1604:52281 - p1612:52599 - p1615:52710 - p1695:55292 - p3641:124395 - p3793:130171 pthread_cond_clockwait() *** After line p316:10727 insert: int pthread_cond_clockwait(pthread_cond_t *restrict, pthread_mutex_t *restrict, clockid_t, const struct timespec *restrict); *** After line p514:17967 insert: It calls pthread_cond_clockwait() with m as the mutex argument and the call returns zero or certain error numbers (see pthread_cond_clockwait()). *** After line p514:17972 insert: It blocks in a call to pthread_cond_clockwait() with m as the mutex argument. *** Line p900:30449 Change "and pthread_cond_timedwait" to ", pthread_cond_timedwait and pthread_cond_clockwait". *** Lines p1610:52513,52515,52519, p1611:52582, p3643:124488 Change "or pthread_cond_timedwait" to ", pthread_cond_timedwait or pthread_cond_clockwait". *** After line p1617:52743 insert: int pthread_cond_clockwait(pthread_cond_t *restrict cond, pthread_mutex_t *restrict mutex, clockid_t clock_id, const struct timespec *restrict abstime); *** Lines p1617:52747,52762,52763,52766,52781,52783, p1618:52786, p1619:52848, p1620:52882 Add ", pthread_cond_clockwait()" after "pthread_cond_timedwait()" *** After line p1618:52797 insert: The pthread_cond_clockwait() function shall be equivalent to pthread_cond_timedwait(), except that the absolute time specified by abstime is measured against the clock indicated by clock_id rather than the clock specified in the condition variable's clock attribute. All implementations shall support passing CLOCK_REALTIME to pthread_cond_clockwait() as the clock_id parameter. If the Monotonic Clock option is supported, all implementations shall support a clock_id of CLOCK_MONOTONIC. *** Line p1618:52822: Change to "The pthread_cond_timedwait() and pthread_cond_clockwait() functions shall fail if:" *** Line p1618:52823, p1619:52850: Change "pthread_cond_timedwait()" to "pthread_cond_timedwait() or pthread_cond_clockwait()" *** Line p1618:52825: Add "or the clock_id parameter passed to pthread_cond_clockwait is invalid or not supported." *** Insert after line p1620:52879: Choice of clock Care should be taken to decide which clock is most appropriate when waiting with a timeout. The system clock, CLOCK_REALTIME, as used by default with pthread_cond_timedwait() may be subject to jumps forwards and backwards in order to correct it against actual time. CLOCK_MONOTONIC is guaranteed not to jump backwards and must also advance in real time, so using it via pthread_cond_clockwait() or pthread_condattr_setclock() may be more appropriate. *** Line p1621:52943: Replace CLOCK_REALTIME with CLOCK_MONOTONIC *** Line p1621:52947: Replace line with: rc = pthread_cond_clockwait(&t.cond, &t.mn, CLOCK_MONOTONIC, &ts); *** After line line p1622:52956 insert: Using CLOCK_MONOTONIC rather than CLOCK_REALTIME means that the timeout is not influenced by the system clock being changed. *** After line p1626:53084 insert: Note that the /clock/ attribute shall have no effect on the pthread_cond_clockwait() function. *** Lines p1661:54147, p1662:54186, p1665:54321, p1694:55282: After "pthread_cond_timedwait()" insert ", pthread_cond_clockwait()". *** Line p3621:123502: Delete remainder of paragraph starting with "This capability has not been added to other functions...". Insert in its place: For condition variables, this capability is also available by passing CLOCK_MONOTONIC to the pthread_cond_clockwait() function. Similarly, CLOCK_MONOTONIC can be specified when calling sem_clockwait, pthread_mutex_clocklock, pthread_rwlock_clockrdlock and pthread_rwlock_clockwrlock. *** After line p3622:123535: Subsequently, it was discovered that using a particular clock for the timeout was desired by some users. In particular, the ISO C++11 standard requires the clock to be a property of the wait for its std::condtion_variable and std::timed_mutex. This led to the addition of sem_clockwait(), pthread_mutex_clockwait(), pthread_cond_clockwait(), pthread_rwlock_clockrdlock() and pthread_rwlock_clockwrlock() functions that accepted a clock parameter to measure their absolute timeout against. The addition of the corresponding mq_clockreceive and mq_clocksend may be considered in the future. ** sem_clockwait *** Add to list at p111:3069 sem_clockwait *** After line p329:11164 insert int sem_clockwait(sem_t *restrict, clockid_t clock_id, const struct timespec *restrict) *** Add to list at p427:14548 sem_clockwait *** Add to list at p517:18120 sem_clockwait *** Add to lists at p681:23337,23362 sem_clockwait *** Add to lists at p1849:59892: sem_clockwait *** Add to lists at p1851:59918,59922,59924,59946 sem_clockwait *** Add to list at p1853:59972 sem_clockwait *** Add to list at p1855:60057 sem_clockwait *** Add to lists at p1856:60113,60121 sem_clockwait *** p1858:60140 Add sem_clockwait to NAME *** After p1858:60145 insert int sem_clockwait(sem_t *restrict, clockid_t clock_id, const struct timespec *restrict abstime) *** After p1858:60147 "sem_timedwait", insert and sem_clockwait *** Before p1858:60155 insert: For sem_timedwait, *** On p1858:60156 insert new sentence after sentence end: For sem_clockwait, the timeout shall be measured against the clock represented by the clock_id parameter. *** p1858:60162, p1858:60167 replace "function" with and sem_clockwait() functions *** Append to p1858:p60170 Alternatively the sem_clockwait() function was passed an invalid or unsupported clock_id. *** p1860:60230 Replace "CLOCK_REALTIME" with "CLOCK_MONOTONIC". *** p1860:60235 Replace "sem_timedwait" with "sem_clockwait". *** p1860:60236 Replace "sem_timedwait(&sem, &ts)" with "sem_clockwait(&sem, CLOCK_MONOTONIC, &ts)" *** p1860:60241,60243,60245: Replace "sem_timedwait" with "sem_clockwait". *** Add to list p1862:60307 sem_clockwait *** Add to list p3563:120877 sem_clockwait *** Add to list p3770:129389,129400 sem_clockwait *** Add to list p3792:130143 sem_clockwait ** pthread_mutex_clocklock *** Add to list p111:3075 pthread_mutex_clocklock *** Insert after p317:10761 int pthread_mutex_clocklock(pthread_mutex_t *restrict, clockid_t clock_id, const struct timespec *restrict); *** Add to list p318:10838 pthread_mutex_clocklock *** Add to list p427:14547: pthread_mutex_clocklock *** Insert after p514:17962: It calls pthread_mutex_clocklock( ) with m as the mutex argument and the call returns zero or [EOWNERDEAD]. *** Add to list p681:23337: pthread_mutex_clocklock *** Add to list p1665:54333: pthread_mutex_clocklock *** Add to list p1668:54417: pthread_mutex_clocklock *** Add to list p1673:54574: pthread_mutex_clocklock *** In line p1676:54616, insert pthread_mutex_clocklock *** After line p1676:54621, insert int pthread_mutex_clocklock(pthread_mutex_t *restrict mutex, clockid_t clock_id, const struct timespec *restrict abstime); *** Begin line p1676:54623 with The pthread_mutex_timedlock() and pthread_mutex_clocklock() functions shall lock... *** Begin line p1676:54631 with For pthread_mutex_timedlock, the timeout shall... *** On line p1676:54632, insert new sentence after sentence end: For pthread_mutex_clocklock, the timeout shall be measured against the clock represented by the clock_id parameter. *** On line p1676:54642 and p1676:54644 replace "pthread_mutex_timedlock()" with pthread_mutex_timedlock() or pthread_mutex_clocklock() *** On line p1676:54653 and p1676:54656 replace "function" with and pthread_mutex_clocklock() functions *** Insert after p1677:54666 Alternatively the pthread_mutex_clocklock() function was passed an invalid or unsupported clock_id. *** On line p1677:54675 replace "function" with and pthread_mutex_clocklock() functions *** Add to list at p3563:120888 pthread_mutex_clocklock *** Add to list at p3770:129399 pthread_mutex_clocklock *** Add to list at p3793:130175 pthread_mutex_clocklock ** pthread_rwlock_clockrdlock & pthread_rwlock_clockwrlock *** Add to list at p111:3072 pthread_rwlock_clockwrlock, pthread_rwlock_clockrdlock *** Insert after line p317:10787 int pthread_rwlock_clockrdlock(pthread_rwlock_t *restrict, clockid_t clock_id, const struct timespec *restrict); *** Insert after line p317:10789 int pthread_rwlock_clockwrlock(pthread_rwlock_t *restrict, clockid_t clock_id, const struct timespec *restrict); *** Add to list at p318:10841 pthread_rwlock_clockwrlock(), pthread_rwlock_clockrdlock() *** Add to list at p319:10842 pthread_rwlock_clockwrlock(), pthread_rwlock_clockrdlock() *** Add to list at p427:14548 pthread_rwlock_clockwrlock(), pthread_rwlock_clockrdlock() *** Add to list at p519:18175 pthread_rwlock_clockwrlock(), pthread_rwlock_clockrdlock() *** Add to list at p1705:55499 pthread_rwlock_clockwrlock(), pthread_rwlock_clockrdlock() *** Add to list at p1708:55600 pthread_rwlock_clockwrlock(), pthread_rwlock_clockrdlock() *** Add to line p1710:55625 pthread_rwlock_clockrdlock *** Insert after line p1710:55630 int pthread_rwlock_clockrdlock(pthread_rwlock_t *restrict, clockid_t clock_id, const struct timespec *restrict); *** Replace p1710:55632 "function" with and pthread_rwlock_clockrdlock() functions *** Insert at beginning of p1710:55639 For pthread_rwlock_timedrdlock(), *** On line p1710:55640, insert new sentence after sentence end For pthread_rwlock_clockrdclock(), the timeout shall be measured against the clock represented by the clock_id parameter. *** On line p1710:55645, after "pthread_rwlock_timedrdlock" insert or pthread_rwlock_clockrdlock *** On line p1710:55650, replace "function" with and pthread_rwlock_clockrdlock functions *** On line p1710:55654, replace "function" with and pthread_rwlock_clockrdlock functions *** On line p1710:55656, replace "function" with and pthread_rwlock_clockrdlock functions *** On line p1710:55661 add Alternatively, the pthread_rwlock_clockrdlock() function was passed an invalid or unsupported clock_id. *** On line p1711:55671, after "pthread_rwlock_timedrdlock()" add or pthread_rwlock_clockrdlock() *** Add to list at p1711:55676: pthread_rwlock_clockwrlock() *** Add to line p1712:55688 pthread_rwlock_clockwrlock *** Insert after line p1712:55693 int pthread_rwlock_clockwrlock(pthread_rwlock_t *restrict rwlock, clockid_t clock_id, const struct timespec *restrict abstime); *** Replace p1712:55695 "function" with and pthread_rwlock_clockwrlock() functions *** Insert at beginning of p1712:55702 For pthread_rwlock_timedrdlock, *** On line p1712:55703, insert new sentence after sentence end For pthread_rwlock_clockwrclock(), the timeout shall be measured against the clock represented by the clock_id parameter. *** On line p1712:55708, after "pthread_rwlock_timedwrlock" insert or pthread_rwlock_clockwrlock *** On line p1712:55713 replace function with and pthread_rwlock_clockwrlock functions *** On line p1712:55717 replace function with and pthread_rwlock_clockwrlock functions *** On line p1712:55719 replace function with and pthread_rwlock_clockwrlock functions *** On line p1712:55723 add Alternatively, the pthread_rwlock_clockwrlock() function was passed an invalid or unsupported clock_id. *** On line p1713:55732, after "pthread_rwlock_timedwrlock()" add or pthread_rwlock_clockwrlock() *** Add to line p1713:55737 pthread_rwlock_clockrdlock *** Add to list on p1716:55801 pthread_rwlock_clockwrlock(), pthread_rwlock_clockrdlock() *** Add to list on p1718:55863 pthread_rwlock_clockwrlock(), pthread_rwlock_clockrdlock() *** Add to list on p3563:120899 pthread_rwlock_clockwrlock(), pthread_rwlock_clockrdlock() *** Add to list on p3770:129399 pthread_rwlock_clockwrlock(), pthread_rwlock_clockrdlock() *** Add to list on p3792:130137 pthread_rwlock_clockwrlock(), pthread_rwlock_clockrdlock() |
(0004391) enh (reporter) 2019-05-09 18:03 |
tomcherry from Android's C/C++ team has implemented this for Android too (https://android-review.googlesource.com/c/platform/bionic/+/958058) [^] and we're happy to submit that as soon this gets accepted into POSIX. He had two quick comments about the wording (but can't log in for some reason): The first is on the phrasing of 'A "safety timeout" of a minute on a call pthread_mutex_timedlock() could actually mean no timeout at all if the system clock is warped forwards immediately prior to the call.' I'm used to the term 'no timeout' meaning that the call will block indefinitely, but in this case, pthread_mutex_timedlock() will immediately return, right? Would it be more clear if 'could actually mean no timeout at all' were replaced with 'would return immediately regardless of if the lock was acquired' ? The second is that it may be worth commenting on the other situation, where time is warped backwards immediately prior to the call and the time out happens much later than originally expected. It's actually that issue that has caused more issues for Android than the former. |
(0004478) mikecrowe (reporter) 2019-07-09 17:31 |
Updated wording hopefully addressing Tom Cherry's comments and improving the description of EINVAL returns. ** General *** Insert after p3622:123506 It was later found necessary to add variants of almost all interfaces that accept absolute timeouts that allow the clock to be specified. This is because, despite the claim in the previous paragraph, it is not possible to safely use a CLOCK_REALTIME absolute timeout even to prevent errors when the system clock is warped by a potentially large amount. A "safety timeout" of a minute on a call pthread_mutex_timedlock() could actually mean that the call would return ETIMEDOUT early without acquiring the lock if the system clock is warped forwards immediately prior to or during the call. On the other hand, a short timeout could end up being arbitrarily long if the system clock is warped backwards immediately prior to or during the call. These problems are solved by the new "clockwait" variants of the existing "timedwait" functions. These variants accept an extra clockid_t parameter to indicate the clock to be used for the wait. The clock parameter is passed rather than using attributes as previously for pthread_cond_timedwait in order to allow ISO/IEC 14882:2011 (C++11) and later to be implemented correctly. C++ requires that the clock to use for the wait is not known until the time of the wait call, so it cannot be supplied during creation. The new functions are sem_clockwait(), pthread_cond_clockwait(), pthread_mutex_clocklock(), pthread_mutex_clockrdlock() and pthread_mutex_clockwrlock(). It is expected that mq_clockreceive() and mq_clocksend() functions will be added in a future version of this standard too. ** pthread_cond_clockwait *** Add to lists at lines - p111:3070 - p318:10833 - p518:18119 - p1604:52281 - p1612:52599 - p1615:52710 - p1695:55292 - p3641:124395 - p3793:130171 pthread_cond_clockwait() *** After line p316:10727 insert: int pthread_cond_clockwait(pthread_cond_t *restrict, pthread_mutex_t *restrict, clockid_t, const struct timespec *restrict); *** After line p514:17967 insert: It calls pthread_cond_clockwait() with m as the mutex argument and the call returns zero or certain error numbers (see pthread_cond_clockwait()). *** After line p514:17972 insert: It blocks in a call to pthread_cond_clockwait() with m as the mutex argument. *** Line p900:30449 Change "and pthread_cond_timedwait" to ", pthread_cond_timedwait and pthread_cond_clockwait". *** Lines p1610:52513,52515,52519, p1611:52582, p3643:124488 Change "or pthread_cond_timedwait" to ", pthread_cond_timedwait or pthread_cond_clockwait". *** After line p1617:52743 insert: int pthread_cond_clockwait(pthread_cond_t *restrict cond, pthread_mutex_t *restrict mutex, clockid_t clock_id, const struct timespec *restrict abstime); *** Lines p1617:52747,52762,52763,52766,52781,52783, p1618:52786, p1619:52848, p1620:52882 Add ", pthread_cond_clockwait()" after "pthread_cond_timedwait()" *** After line p1618:52797 insert: The pthread_cond_clockwait() function shall be equivalent to pthread_cond_timedwait(), except that the absolute time specified by abstime is measured against the clock indicated by clock_id rather than the clock specified in the condition variable's clock attribute. All implementations shall support passing CLOCK_REALTIME to pthread_cond_clockwait() as the clock_id parameter. If the Monotonic Clock option is supported, all implementations shall support a clock_id of CLOCK_MONOTONIC. *** Line p1618:52822: Change to "The pthread_cond_timedwait() and pthread_cond_clockwait() functions shall fail if:" *** Line p1618:52823, p1619:52850: Change "pthread_cond_timedwait()" to "pthread_cond_timedwait() or pthread_cond_clockwait()" *** Line p1618:52825: Add "or the clock_id parameter passed to pthread_cond_clockwait is invalid or not supported." *** Insert after line p1620:52879: Choice of clock Care should be taken to decide which clock is most appropriate when waiting with a timeout. The system clock, CLOCK_REALTIME, as used by default with pthread_cond_timedwait() may be subject to jumps forwards and backwards in order to correct it against actual time. CLOCK_MONOTONIC is guaranteed not to jump backwards and must also advance in real time, so using it via pthread_cond_clockwait() or pthread_condattr_setclock() may be more appropriate. *** Line p1621:52943: Replace CLOCK_REALTIME with CLOCK_MONOTONIC *** Line p1621:52947: Replace line with: rc = pthread_cond_clockwait(&t.cond, &t.mn, CLOCK_MONOTONIC, &ts); *** After line line p1622:52956 insert: Using CLOCK_MONOTONIC rather than CLOCK_REALTIME means that the timeout is not influenced by the system clock being changed. *** After line p1626:53084 insert: Note that the /clock/ attribute shall have no effect on the pthread_cond_clockwait() function. *** Lines p1661:54147, p1662:54186, p1665:54321, p1694:55282: After "pthread_cond_timedwait()" insert ", pthread_cond_clockwait()". *** Line p3621:123502: Delete remainder of paragraph starting with "This capability has not been added to other functions...". Insert in its place: For condition variables, this capability is also available by passing CLOCK_MONOTONIC to the pthread_cond_clockwait() function. Similarly, CLOCK_MONOTONIC can be specified when calling sem_clockwait, pthread_mutex_clocklock, pthread_rwlock_clockrdlock and pthread_rwlock_clockwrlock. *** After line p3622:123535: Subsequently, it was discovered that using a particular clock for the timeout was desired by some users. In particular, the ISO C++11 standard requires the clock to be a property of the wait for its std::condtion_variable and std::timed_mutex. This led to the addition of sem_clockwait(), pthread_mutex_clockwait(), pthread_cond_clockwait(), pthread_rwlock_clockrdlock() and pthread_rwlock_clockwrlock() functions that accepted a clock parameter to measure their absolute timeout against. The addition of the corresponding mq_clockreceive and mq_clocksend may be considered in the future. ** sem_clockwait *** Add to list at p111:3069 sem_clockwait *** After line p329:11164 insert int sem_clockwait(sem_t *restrict, clockid_t clock_id, const struct timespec *restrict) *** Add to list at p427:14548 sem_clockwait *** Add to list at p517:18120 sem_clockwait *** Add to lists at p681:23337,23362 sem_clockwait *** Add to lists at p1849:59892: sem_clockwait *** Add to lists at p1851:59918,59922,59924,59946 sem_clockwait *** Add to list at p1853:59972 sem_clockwait *** Add to list at p1855:60057 sem_clockwait *** Add to lists at p1856:60113,60121 sem_clockwait *** p1858:60140 Add sem_clockwait to NAME *** After p1858:60145 insert int sem_clockwait(sem_t *restrict, clockid_t clock_id, const struct timespec *restrict abstime) *** After p1858:60147 "sem_timedwait", insert and sem_clockwait *** Before p1858:60155 insert: For sem_timedwait, *** On p1858:60156 insert new sentence after sentence end: For sem_clockwait, the timeout shall be measured against the clock represented by the clock_id parameter. *** p1858:60162, p1858:60167 replace "function" with and sem_clockwait() functions *** Append to p1858:p60170 Alternatively the sem_clockwait() function was passed an invalid or unsupported clock_id. *** p1860:60230 Replace "CLOCK_REALTIME" with "CLOCK_MONOTONIC". *** p1860:60235 Replace "sem_timedwait" with "sem_clockwait". *** p1860:60236 Replace "sem_timedwait(&sem, &ts)" with "sem_clockwait(&sem, CLOCK_MONOTONIC, &ts)" *** p1860:60241,60243,60245: Replace "sem_timedwait" with "sem_clockwait". *** Add to list p1862:60307 sem_clockwait *** Add to list p3563:120877 sem_clockwait *** Add to list p3770:129389,129400 sem_clockwait *** Add to list p3792:130143 sem_clockwait ** pthread_mutex_clocklock *** Add to list p111:3075 pthread_mutex_clocklock *** Insert after p317:10761 int pthread_mutex_clocklock(pthread_mutex_t *restrict, clockid_t clock_id, const struct timespec *restrict); *** Add to list p318:10838 pthread_mutex_clocklock *** Add to list p427:14547: pthread_mutex_clocklock *** Insert after p514:17962: It calls pthread_mutex_clocklock( ) with m as the mutex argument and the call returns zero or [EOWNERDEAD]. *** Add to list p681:23337: pthread_mutex_clocklock *** Add to list p1665:54333: pthread_mutex_clocklock *** Add to list p1668:54417: pthread_mutex_clocklock *** Add to list p1673:54574: pthread_mutex_clocklock *** In line p1676:54616, insert pthread_mutex_clocklock *** After line p1676:54621, insert int pthread_mutex_clocklock(pthread_mutex_t *restrict mutex, clockid_t clock_id, const struct timespec *restrict abstime); *** Begin line p1676:54623 with The pthread_mutex_timedlock() and pthread_mutex_clocklock() functions shall lock... *** Begin line p1676:54631 with For pthread_mutex_timedlock, the timeout shall... *** On line p1676:54632, insert new sentence after sentence end: For pthread_mutex_clocklock, the timeout shall be measured against the clock represented by the clock_id parameter. *** On line p1676:54642 and p1676:54644 replace "pthread_mutex_timedlock()" with pthread_mutex_timedlock() or pthread_mutex_clocklock() *** On line p1676:54653 and p1676:54656 replace "function" with and pthread_mutex_clocklock() functions *** Insert after p1677:54666 Alternatively the pthread_mutex_clocklock() function was passed an invalid or unsupported clock_id. *** On line p1677:54675 replace "function" with and pthread_mutex_clocklock() functions *** Add to list at p3563:120888 pthread_mutex_clocklock *** Add to list at p3770:129399 pthread_mutex_clocklock *** Add to list at p3793:130175 pthread_mutex_clocklock ** pthread_rwlock_clockrdlock & pthread_rwlock_clockwrlock *** Add to list at p111:3072 pthread_rwlock_clockwrlock, pthread_rwlock_clockrdlock *** Insert after line p317:10787 int pthread_rwlock_clockrdlock(pthread_rwlock_t *restrict, clockid_t clock_id, const struct timespec *restrict); *** Insert after line p317:10789 int pthread_rwlock_clockwrlock(pthread_rwlock_t *restrict, clockid_t clock_id, const struct timespec *restrict); *** Add to list at p318:10841 pthread_rwlock_clockwrlock(), pthread_rwlock_clockrdlock() *** Add to list at p319:10842 pthread_rwlock_clockwrlock(), pthread_rwlock_clockrdlock() *** Add to list at p427:14548 pthread_rwlock_clockwrlock(), pthread_rwlock_clockrdlock() *** Add to list at p519:18175 pthread_rwlock_clockwrlock(), pthread_rwlock_clockrdlock() *** Add to list at p1705:55499 pthread_rwlock_clockwrlock(), pthread_rwlock_clockrdlock() *** Add to list at p1708:55600 pthread_rwlock_clockwrlock(), pthread_rwlock_clockrdlock() *** Add to line p1710:55625 pthread_rwlock_clockrdlock *** Insert after line p1710:55630 int pthread_rwlock_clockrdlock(pthread_rwlock_t *restrict, clockid_t clock_id, const struct timespec *restrict); *** Replace p1710:55632 "function" with and pthread_rwlock_clockrdlock() functions *** Insert at beginning of p1710:55639 For pthread_rwlock_timedrdlock(), *** On line p1710:55640, insert new sentence after sentence end For pthread_rwlock_clockrdclock(), the timeout shall be measured against the clock represented by the clock_id parameter. *** On line p1710:55645, after "pthread_rwlock_timedrdlock" insert or pthread_rwlock_clockrdlock *** On line p1710:55650, replace "function" with and pthread_rwlock_clockrdlock functions *** On line p1710:55654, replace "function" with and pthread_rwlock_clockrdlock functions *** On line p1710:55656, replace "function" with and pthread_rwlock_clockrdlock functions *** On line p1710:55661 add Alternatively, the pthread_rwlock_clockrdlock() function was passed an invalid or unsupported clock_id. *** On line p1711:55671, after "pthread_rwlock_timedrdlock()" add or pthread_rwlock_clockrdlock() *** Add to list at p1711:55676: pthread_rwlock_clockwrlock() *** Add to line p1712:55688 pthread_rwlock_clockwrlock *** Insert after line p1712:55693 int pthread_rwlock_clockwrlock(pthread_rwlock_t *restrict rwlock, clockid_t clock_id, const struct timespec *restrict abstime); *** Replace p1712:55695 "function" with and pthread_rwlock_clockwrlock() functions *** Insert at beginning of p1712:55702 For pthread_rwlock_timedrdlock, *** On line p1712:55703, insert new sentence after sentence end For pthread_rwlock_clockwrclock(), the timeout shall be measured against the clock represented by the clock_id parameter. *** On line p1712:55708, after "pthread_rwlock_timedwrlock" insert or pthread_rwlock_clockwrlock *** On line p1712:55713 replace function with and pthread_rwlock_clockwrlock functions *** On line p1712:55717 replace function with and pthread_rwlock_clockwrlock functions *** On line p1712:55719 replace function with and pthread_rwlock_clockwrlock functions *** On line p1712:55723 add Alternatively, the pthread_rwlock_clockwrlock() function was passed an invalid or unsupported clock_id. *** On line p1713:55732, after "pthread_rwlock_timedwrlock()" add or pthread_rwlock_clockwrlock() *** Add to line p1713:55737 pthread_rwlock_clockrdlock *** Add to list on p1716:55801 pthread_rwlock_clockwrlock(), pthread_rwlock_clockrdlock() *** Add to list on p1718:55863 pthread_rwlock_clockwrlock(), pthread_rwlock_clockrdlock() *** Add to list on p3563:120899 pthread_rwlock_clockwrlock(), pthread_rwlock_clockrdlock() *** Add to list on p3770:129399 pthread_rwlock_clockwrlock(), pthread_rwlock_clockrdlock() *** Add to list on p3792:130137 pthread_rwlock_clockwrlock(), pthread_rwlock_clockrdlock() |
(0004481) mikecrowe (reporter) 2019-07-14 18:08 |
Implementations of these functions have landed for glibc 2.30. See https://sourceware.org/git/?p=glibc.git;a=log;h=65dd7e9ce36ca8485a68ed41ac731188b6473dd2 [^] |
(0004485) enh (reporter) 2019-07-16 02:46 |
great to hear! we'd just been talking about whether to merge the bionic change first, but now we can just be followers :-) this will be in Android R. see https://android-review.googlesource.com/c/platform/bionic/+/958058. [^] |
(0005057) geoffclare (manager) 2020-10-21 15:13 |
The *_clockwait() and *_clocklock() additions have been made in the Issue8NewAPIs branch in gitlab, based on Note: 0004478. Some of the suggested changes were to SEE ALSO sections and other cross-references, which were not needed as those are references to pages, not individual functions. There were also some that would have updated old change history. Finally, some pointer pages are needed but I have deferred adding them as I think it would be better to rename the *_timed*() pages to *_clock*() and add pointer pages for the *_timed*() functions. This could be handled by making the eventual resolution of this bug something like, "Make the changes from The Open Group document Cxxx and also rename the affected *_timed*() pages to *_clock*() and add pointer pages for the *_timed*() functions." |
(0005122) geoffclare (manager) 2020-11-26 10:57 |
The changes to add new functions in XBD 4.12 Memory Synchronization overlap with bug 0001426. This should be resolved by applying 1426 first and then, instead of just adding the new functions to the table, treat each *_clock*() function the same as the corresponding *_timed*() function in the updated XBD 4.12. |
(0005339) geoffclare (manager) 2021-04-29 15:40 |
Make the changes from "Additional APIs for Issue 8, Part 1" (Austin/1110). Resolve the overlap with bug 1426 by applying 1426 first and then, instead of just adding the new functions to the table, treat each *_clock*() function the same as the corresponding *_timed*() function in the updated XBD 4.12. In addition, rename the *_timed*() pages to *_clock*() and add pointer pages for the *_timed*() functions. |
Issue History | |||
Date Modified | Username | Field | Change |
2018-11-26 18:53 | mikecrowe | New Issue | |
2018-11-26 18:53 | mikecrowe | Status | New => Under Review |
2018-11-26 18:53 | mikecrowe | Assigned To | => ajosey |
2018-11-26 18:53 | mikecrowe | Name | => Mike Crowe |
2018-11-26 18:53 | mikecrowe | Section | => pthread |
2018-11-26 18:53 | mikecrowe | Page Number | => 0 |
2018-11-26 18:53 | mikecrowe | Line Number | => 0 |
2018-11-27 09:23 | geoffclare | Project | 1003.1(2008)/Issue 7 => 1003.1(2016/18)/Issue7+TC2 |
2018-11-27 09:23 | geoffclare | Relationship added | related to 0001164 |
2018-11-27 16:02 | nick | Note Added: 0004171 | |
2019-01-07 21:26 | mikecrowe | Note Added: 0004196 | |
2019-01-19 04:08 | mikecrowe | Note Added: 0004215 | |
2019-03-06 13:17 | mikecrowe | Note Added: 0004276 | |
2019-05-07 12:09 | mikecrowe | Note Added: 0004387 | |
2019-05-09 18:03 | enh | Note Added: 0004391 | |
2019-07-09 17:31 | mikecrowe | Note Added: 0004478 | |
2019-07-14 18:08 | mikecrowe | Note Added: 0004481 | |
2019-07-16 02:46 | enh | Note Added: 0004485 | |
2020-10-21 15:13 | geoffclare | Note Added: 0005057 | |
2020-11-26 10:52 | geoffclare | Relationship added | related to 0001426 |
2020-11-26 10:57 | geoffclare | Note Added: 0005122 | |
2021-04-29 15:40 | geoffclare | Note Added: 0005339 | |
2021-04-29 15:41 | geoffclare | Interp Status | => --- |
2021-04-29 15:41 | geoffclare | Final Accepted Text | => Note: 0005339 |
2021-04-29 15:41 | geoffclare | Status | Under Review => Resolved |
2021-04-29 15:41 | geoffclare | Resolution | Open => Accepted As Marked |
2021-04-29 15:41 | geoffclare | Tag Attached: issue8 | |
2021-05-10 13:26 | geoffclare | Status | Resolved => Applied |
2024-06-11 09:08 | agadmin | Status | Applied => Closed |
Mantis 1.1.6[^] Copyright © 2000 - 2008 Mantis Group |