kernel: fix mailbox usage of SYS_DLIST_FOR_EACH_NODE()

SYS_DLIST_FOR_EACH_NODE() is marked as non-safe when an item is removed
from the list while looping over it. This is not true per-se, since the
item, when removed, keeps its next and prev pointers intact; however, it
is true if the item is then put into a list, be it a different one or
the same one. To prevent this, SYS_DLIST_FOR_EACH_NODE_SAFE() must be
used.

_mbox_message_put() can remove items from the rx queue and then put them
in the ready queue: this would cause the loop to start processing other
ready threads as item in the rx queue.

k_mbox_get() also removes items, from the tx queue, but does not seem to
add them to another list; however, it now uses the safe version as well,
since that is the proper usage.

Change-Id: Ieccbff238fc8a036c0d53d873eaaf55f4f5a14af
Signed-off-by: Benjamin Walsh <benjamin.walsh@windriver.com>
Signed-off-by: Anas Nashif <anas.nashif@intel.com>
This commit is contained in:
Benjamin Walsh 2016-11-12 11:53:21 -05:00 committed by Anas Nashif
commit ade6dc937f

View file

@ -250,7 +250,7 @@ static int _mbox_message_put(struct k_mbox *mbox, struct k_mbox_msg *tx_msg,
struct k_thread *sending_thread;
struct k_thread *receiving_thread;
struct k_mbox_msg *rx_msg;
sys_dnode_t *wait_q_item;
sys_dnode_t *wait_q_item, *next_wait_q_item;
unsigned int key;
/* save sender id so it can be used during message matching */
@ -263,7 +263,9 @@ static int _mbox_message_put(struct k_mbox *mbox, struct k_mbox_msg *tx_msg,
/* search mailbox's rx queue for a compatible receiver */
key = irq_lock();
SYS_DLIST_FOR_EACH_NODE(&mbox->rx_msg_queue, wait_q_item) {
SYS_DLIST_FOR_EACH_NODE_SAFE(&mbox->rx_msg_queue, wait_q_item,
next_wait_q_item) {
receiving_thread = (struct k_thread *)wait_q_item;
rx_msg = (struct k_mbox_msg *)receiving_thread->base.swap_data;
@ -436,7 +438,7 @@ int k_mbox_get(struct k_mbox *mbox, struct k_mbox_msg *rx_msg, void *buffer,
{
struct k_thread *sending_thread;
struct k_mbox_msg *tx_msg;
sys_dnode_t *wait_q_item;
sys_dnode_t *wait_q_item, *next_wait_q_item;
unsigned int key;
int result;
@ -446,7 +448,9 @@ int k_mbox_get(struct k_mbox *mbox, struct k_mbox_msg *rx_msg, void *buffer,
/* search mailbox's tx queue for a compatible sender */
key = irq_lock();
SYS_DLIST_FOR_EACH_NODE(&mbox->tx_msg_queue, wait_q_item) {
SYS_DLIST_FOR_EACH_NODE_SAFE(&mbox->tx_msg_queue, wait_q_item,
next_wait_q_item) {
sending_thread = (struct k_thread *)wait_q_item;
tx_msg = (struct k_mbox_msg *)sending_thread->base.swap_data;