You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
IDF version (run git describe --tags to find it): 4.0
Build System: CMake
Compiler version (run xtensa-esp32-elf-gcc --version to find it): xtensa-esp32-elf-gcc (crosstool-NG esp-2019r2) 8.2.0
Operating System: Linux
(Windows only) environment type: n/a
Using an IDE?: yes, Qt Creator
Power Supply: external 3.3V
Problem Description
In looking to add CLOCK_MONOTONIC support to pthread condition variables, I noticed that pthread_cond_timedwait is returning an ETIMEDOUT error before the time actually expires. If the current time is retrieved after the function returns an ETIMEDOUT error, the time will likely be before the timeout passed to the function.
Should the conversion of the time difference from the passed time to the current gettimeofday round up in pthread_cond_var.c? I.e. should the conversions from diff_time to timeout_msec and them timeout_msec to timeout_ticks round to the next time if there is a remainder?
Additionally, there looks to need to be one extra timeout_ticks added to get the xSemaphoreTake call to return after the time has expired.
Expected Behavior
pthread_cond_timedwait returns ETIMEDOUT only if the timeout has actually passed.
Actual Behavior
pthread_cond_timeout returns the error code too early.
Steps to reproduce
Running the code below produces output similar to the following. The extra time should be positive when the timeout occurs.
Extra time: -1786000, status: timeout
Extra time: -618000, status: timeout
Extra time: -123000, status: timeout
Extra time: -79000, status: timeout
Extra time: -160000, status: timeout
Extra time: -83000, status: timeout
Extra time: -82000, status: timeout
Code to reproduce this issue
using ClockT = std::chrono::system_clock;
std::mutex mutex;
std::condition_variable cond;
std::unique_lock lock(mutex);
for (int i = 0; i < 20; ++i) {
auto timeout = ClockT::now() + std::chrono::seconds(1);
auto secs = std::chrono::time_point_cast<std::chrono::seconds>(timeout);
auto nsecs = std::chrono::duration_cast<std::chrono::nanoseconds>
(timeout - secs);
structtimespec ts = {
.tv_sec = static_cast<time_t>(secs.time_since_epoch().count()),
.tv_nsec = static_cast<long>(nsecs.count())};
int rc = ::pthread_cond_timedwait(cond.native_handle(),
lock.mutex()->native_handle(), &ts);
auto status = (rc == ETIMEDOUT) ? std::cv_status::timeout :
std::cv_status::no_timeout;
auto end = ClockT::now();
auto extra = end - timeout;
printf("Extra time: %lld, status: %s\n", extra.count(),
(status == std::cv_status::timeout) ? "timeout" : "no timeout");
}
Potential Fix
This patch seems to resolve the issue with a consistent return of ETIMEDOUT and a positive extra time after the timeout.
github-actionsbot
changed the title
pthread_cond_timedwait returns timeout too early
pthread_cond_timedwait returns timeout too early (IDFGH-5119)
Apr 19, 2021
The code change and a test (both based very closely on your submissions) have been submitted for merging internally. Thanks again for the clear report.
Additionally, there looks to need to be one extra timeout_ticks added to get the xSemaphoreTake call to return after the time has expired.
The reason for this is that FreeRTOS delays are only accurate to the tick period. Specifically, vTaskDelay(1) delays for an amount of time greater than zero and less than the tick period - because (in an idle system) the task will resume immediately after the next tick interrupt (start of time quantum), but it could have gone to sleep at any point during the previous time quantum. So in order to ensure we wait for at least 1 tick period, it's necessary to vTaskDelay(2).
Environment
git describe --tags
to find it): 4.0xtensa-esp32-elf-gcc --version
to find it): xtensa-esp32-elf-gcc (crosstool-NG esp-2019r2) 8.2.0Problem Description
In looking to add CLOCK_MONOTONIC support to pthread condition variables, I noticed that pthread_cond_timedwait is returning an ETIMEDOUT error before the time actually expires. If the current time is retrieved after the function returns an ETIMEDOUT error, the time will likely be before the timeout passed to the function.
Should the conversion of the time difference from the passed time to the current gettimeofday round up in pthread_cond_var.c? I.e. should the conversions from diff_time to timeout_msec and them timeout_msec to timeout_ticks round to the next time if there is a remainder?
Additionally, there looks to need to be one extra timeout_ticks added to get the xSemaphoreTake call to return after the time has expired.
Expected Behavior
pthread_cond_timedwait returns ETIMEDOUT only if the timeout has actually passed.
Actual Behavior
pthread_cond_timeout returns the error code too early.
Steps to reproduce
Running the code below produces output similar to the following. The extra time should be positive when the timeout occurs.
Extra time: -1786000, status: timeout
Extra time: -618000, status: timeout
Extra time: -123000, status: timeout
Extra time: -79000, status: timeout
Extra time: -160000, status: timeout
Extra time: -83000, status: timeout
Extra time: -82000, status: timeout
Code to reproduce this issue
Potential Fix
This patch seems to resolve the issue with a consistent return of ETIMEDOUT and a positive extra time after the timeout.
The text was updated successfully, but these errors were encountered: