-
Notifications
You must be signed in to change notification settings - Fork 2k
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
core/thread: add thread states for FreeRTOS queue implementation #18454
base: master
Are you sure you want to change the base?
core/thread: add thread states for FreeRTOS queue implementation #18454
Conversation
Adds the special `STATUS_QUEUE_FULL_BLOCKED` and `STATUS_QUEUE_EMPTY_BLOCKED` thread states for the queue blocking mechanism in the FreeRTOS compatibility layer implementation. These additional thread states are necessary because the previously used thread states `STATUS_RECEIVE_BLOCKED` and `STATUS_SEND_BLOCKED` can no longer be used because they are not compatible with the thread flag blocking mechanism used by `gnrc_netif` since PR 16748, which can cause crashes.
New blobecause the previously used thread states `STATUS_RECEIVE_BLOCKED` and `STATUS_SEND_BLOCKED` can no longer be used because they are not compatible with the thread flag blocking mechanism used by `gnrc_netif` since PR 16748king states have to be used.
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.
ACK. Code looks good and test result is provided.
Since this is affecting core, we need a 2nd ACK, though.
#if IS_USED(MODULE_ESP_FREERTOS_COMMON) | ||
STATUS_QUEUE_FULL_BLOCKED, /**< FreeRTOS compatibility layer queue full */ | ||
STATUS_QUEUE_EMPTY_BLOCKED, /**< FreeRTOS compatibility layer queue empty */ | ||
#endif |
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.
If you add those at the end it will not mess up the thread state mapping in OpenOCD.
The use of this enum in OpenOCD also would speak for adding this unconditionally.
We already have STATUS_ZOMBIE
which is only used by mynewt-core
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.
If you add those at the end it will not mess up the thread state mapping in OpenOCD.
The use of this enum in OpenOCD also would speak for adding this unconditionally. We already have
STATUS_ZOMBIE
which is only used bymynewt-core
Hm, I got an assert here
Line 156 in 25a5269
assert(thread->status < STATUS_ON_RUNQUEUE); |
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.
We already have
STATUS_ZOMBIE
which is only used bymynewt-core
I couldn't find that.
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's set by thread_zombify()
which is only called by that package.
I guess the assert could be replaced by
assert(thread->status == STATUS_RUNNING || thread->status == STATUS_PENDING);
but I'm not sure if this assumption is backed in elsewhere too 😕
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.
According to the documentation, thread_add_to_list
may only be called for threads that are not in a runqueue. This is ensured by the assert
.
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's set by
thread_zombify()
which is only called by that package.
Ah ok, it is a permanent state.
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 guess the assert could be replaced by
assert(thread->status == STATUS_RUNNING || thread->status == STATUS_PENDING);but I'm not sure if this assumption is backed in elsewhere too confused
Hm, >= STATUS_ON_RUNQUEUE
is also used several times:
263: if (!(process->status >= STATUS_ON_RUNQUEUE)) {
268: if (process->status >= STATUS_ON_RUNQUEUE) {
280: int on_runqueue = (active_thread->status >= STATUS_ON_RUNQUEUE);
./core/sched.c
146: if (me->status >= STATUS_ON_RUNQUEUE) {
./core/thread.c
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.
If you add those at the end it will not mess up the thread state mapping in OpenOCD.
The use of this enum in OpenOCD also would speak for adding this unconditionally.
I see, it seems not to be a short-term solution. Maybe, we should continue with PR #18439 with state STATUS_MUTEX_BLOCKED
for now which also solves the problem.
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.
Defining them unconditionally would cost 18 additional bytes in ROM.
Is this still needed? |
I would say yes. In the FreeRTOS customization layer, |
Contribution description
This PR adds the thread states
STATE_QUEUE_FULL_BLOCKED
andSTATE_QUEUE_EMPTY_BLOCKED
which are compiled in depending on whether the FreeRTOS compatibility layer for ESP SoCs is used.This change fixes a problem that was figured out when investigating a crash in
tests/nimble_rpble_gnrc
in PR #18439.The FreeRTOS queue and semaphore implementation of the FreeRTOS compatibility layer previously used
STATUS_RECEIVE_BLOCKED
andSTATE_SEND_BLOCKED
to block a thread when the corresponding queue was empty and full, respectively. This was compatible to the blocking mechanism used formsg
bygnrc_netif
. However, since PR #16748,gnrc_netif
no longer uses themsg
blocking mechanism, but uses thread flags.As a consequence, RIOT may crash when using FreeRTOS queues and semaphores together with
gnrc_netif
for the ESP network interfaces ifSTATUS_RECEIVE_BLOCKED
in same thread andSTATUS_RECEIVE_BLOCKED
is used by FreeRTOS compatibility layer. If thegnrc_netif
thread is blocked because of a FreeRTOS semaphore and is therefore inSTATUS_RECEIVE_BLOCKED
state, the_msg_send
function will cause a crash because it then assumes thattarget->wait_data
contains a pointer to a message of typemsg_t
, but by using thread flags it contains just the flag mask. This situation can easily occur when the ESP hardware is used by thegnrc_netif
thread while another thread is sending something timer controlled to thegnrc_netif
thread. See also #18439 (comment).To solve this problem
STATE_QUEUE_FULL_BLOCKED
andSTATE_QUEUE_EMPTY_BLOCKED
are introduced.Testing procedure
Use command
and check that the WiFi network interface still works.
Use command
ps
, the output should look likeThe
sys_evt
thread should be in statebl qemt
.Issues/PRs references
Prerequisite for PR #18439