Skip to content

Commit

Permalink
kernel: workq: Add internal function z_work_submit_to_queue()
Browse files Browse the repository at this point in the history
This adds the internal function z_work_submit_to_queue(), which
submits the work item to the queue but doesn't force the thread to yield,
compared to the public function k_work_submit_to_queue().

When called from poll.c in the context of k_work_poll events, it ensures
that the thread does not yield in the context of the spinlock of object
that became available.

Fixes zephyrproject-rtos#45267

Signed-off-by: Lucas Dietrich <ld.adecy@gmail.com>
  • Loading branch information
lucasdietrich authored and carlescufi committed May 10, 2022
1 parent d778d5c commit 9a848b3
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 5 deletions.
5 changes: 4 additions & 1 deletion kernel/poll.c
Original file line number Diff line number Diff line change
Expand Up @@ -576,6 +576,9 @@ static void triggered_work_expiration_handler(struct _timeout *timeout)
k_work_submit_to_queue(twork->workq, &twork->work);
}

extern int z_work_submit_to_queue(struct k_work_q *queue,
struct k_work *work);

static int signal_triggered_work(struct k_poll_event *event, uint32_t status)
{
struct z_poller *poller = event->poller;
Expand All @@ -587,7 +590,7 @@ static int signal_triggered_work(struct k_poll_event *event, uint32_t status)

z_abort_timeout(&twork->timeout);
twork->poll_result = 0;
k_work_submit_to_queue(work_q, &twork->work);
z_work_submit_to_queue(work_q, &twork->work);
}

return 0;
Expand Down
27 changes: 23 additions & 4 deletions kernel/work.c
Original file line number Diff line number Diff line change
Expand Up @@ -355,19 +355,38 @@ static int submit_to_queue_locked(struct k_work *work,
return ret;
}

int k_work_submit_to_queue(struct k_work_q *queue,
struct k_work *work)
/* Submit work to a queue but do not yield the current thread.
*
* Intended for internal use.
*
* See also submit_to_queue_locked().
*
* @param queuep pointer to a queue reference.
* @param work the work structure to be submitted
*
* @retval see submit_to_queue_locked()
*/
int z_work_submit_to_queue(struct k_work_q *queue,
struct k_work *work)
{
__ASSERT_NO_MSG(work != NULL);

k_spinlock_key_t key = k_spin_lock(&lock);

SYS_PORT_TRACING_OBJ_FUNC_ENTER(k_work, submit_to_queue, queue, work);

int ret = submit_to_queue_locked(work, &queue);

k_spin_unlock(&lock, key);

return ret;
}

int k_work_submit_to_queue(struct k_work_q *queue,
struct k_work *work)
{
SYS_PORT_TRACING_OBJ_FUNC_ENTER(k_work, submit_to_queue, queue, work);

int ret = z_work_submit_to_queue(queue, work);

/* submit_to_queue_locked() won't reschedule on its own
* (really it should, otherwise this process will result in
* spurious calls to z_swap() due to the race), so do it here
Expand Down

0 comments on commit 9a848b3

Please sign in to comment.