-
Notifications
You must be signed in to change notification settings - Fork 3k
events: Fix zero wait condition in non-rtos semaphore #3991
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
@geky Good catch, I'll test if it solves the issue but there is others in the ticker code. |
events/equeue/equeue_mbed.cpp
Outdated
@@ -131,7 +131,7 @@ static void equeue_sema_timeout(equeue_sema_t *s) { | |||
bool equeue_sema_wait(equeue_sema_t *s, int ms) { | |||
int signal = 0; | |||
Timeout timeout; | |||
if (ms > 0) { | |||
if (ms >= 0) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm worried of what can happen with a delay of 0
us.
The timestamp is computed from the current time (here) and there is good chances that it will be in the past (or a far future!) when it will be actually set.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm, that's a good point. Do you think we should clamp it to 1 millisecond to be safe?
It does look like timer events in the past are handled correctly (in common code):
- during insertion: https://github.com/ARMmbed/mbed-os/blob/master/hal/mbed_ticker_api.c#L70
- during the irq handler: https://github.com/ARMmbed/mbed-os/blob/master/hal/mbed_ticker_api.c#L37-L46
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It would be reasonable to apply the same behaviour as the one used by RTX semaphore:
when millisec is 0, the function returns instantly.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It would be reasonable to apply the same behaviour as the one used by RTX semaphore:
What do you think @geky ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That is the current behaviour of this pr. When ms is 0
, the ticker attach should interrupt immediately and set the flag to 1
, causing the following while loop (here) to exit immediately.
Do you think the zero case behaviour should be explicit?
- if (ms > 0) {
+ if (ms == 0) {
+ return false;
+ } else if (ms > 0) {
timeout.attach_us(callback(equeue_sema_timeout, s), ms*1000);
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@geky Yes I think that if ms is 0 then the function should returns instantly. The current version is more like osThreadYield
followed by a return when the task is rescheduled.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@pan-, should be updated. At the very least this makes the less travelled code path clearer.
d836520
to
3f32163
Compare
@pan-, should be updated, let me know if you still have concerns. At the very least this makes the less travelled code path clearer. |
events/equeue/equeue_mbed.cpp
Outdated
if (ms > 0) { | ||
if (ms == 0) { | ||
return false; | ||
} else if (ms >= 0) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not a blocker for the PR, but it strictly greater than 0 might be clearer.
i also wonder what should happen when ms is less than 0 ?
Is it expected that the semaphore will put the system to sleep without timeout ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sounds reasonable.
Throughout the equeue library a timeout of -1
is used to represent an infinite wait, so here any negative value would indicate that the semaphore waits forever.
I added a bit of clarification to the function declaration since it's easy to miss that corner case at this level: https://github.com/ARMmbed/mbed-os/pull/3991/files#diff-224d7ae23d9d5591b6a59537012c82d9
Before, if the semaphore recieved a wait of zero, the semaphore would erronously drop the ticker event to wake up the device, causing the device to go to sleep without any mechanism to wake itself up. During a dispatch operation, the event queue dispatches all events that have expired, so the call to equeue_sema_wait very rarely has a wait of zero. But this can happen when an event is posted just after a dispatch has occured.
3f32163
to
2bcb095
Compare
/morph test |
/morph test |
Result: SUCCESSYour command has finished executing! Here's what you wrote!
OutputAll builds and test passed! |
Before, if the semaphore recieved a wait of zero, the semaphore would erronously drop the ticker event to wake up the device, causing the device to go to sleep without any mechanism to wake itself up.
During a dispatch operation, the event queue dispatches all events that have expired, so the call to equeue_sema_wait very rarely has a wait of zero. But this can happen when an event is posted just after a dispatch has occured.
The rtos version handles this correctly:
https://github.com/ARMmbed/mbed-os/blob/master/events/equeue/equeue_mbed.cpp#L105
related issue #3857
cc @pan-, @tbondar, @nvlsianpu