Skip to content

Commit

Permalink
WIP kernel: work: refactor to use scheduler API
Browse files Browse the repository at this point in the history
This uses the cherry-picked scheduler API from zephyrproject-rtos#29668 to avoid certain
race conditions in SMP between unpending and readying threads.

Signed-off-by: Peter Bigot <[email protected]>
  • Loading branch information
pabigot committed Dec 20, 2020
1 parent fed7fdd commit b8c3c7a
Showing 1 changed file with 7 additions and 19 deletions.
26 changes: 7 additions & 19 deletions kernel/work.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
#include <wait_q.h>
#include <spinlock.h>
#include <errno.h>
#include <ksched.h>
#include <sys/scheduler.h>
#include <sys/printk.h>

/* Lock to protect the internal state of all work items, and
Expand Down Expand Up @@ -182,15 +182,9 @@ static inline void queue_remove(struct k_work_q *queue,
static inline bool _notify_queue(struct k_work_q *queue)
{
bool rv = false;
struct k_thread *waiter;

if (queue != NULL) {
waiter = z_unpend_first_thread(&queue->notifyq);
if (waiter) {
rv = true;
arch_thread_return_value_set(waiter, 0);
z_ready_thread(waiter);
}
rv = k_sched_wake(&queue->notifyq, 0, NULL);
}

return rv;
Expand Down Expand Up @@ -599,8 +593,6 @@ static void work_queue_main(void *workq_ptr, void *p2, void *p3)
work = CONTAINER_OF(node, struct k_work, node);
} else if (atomic_test_and_clear_bit(&queue->flags,
K_WORK_QUEUE_DRAIN_BIT)) {
struct k_thread *waiter;

/* Not busy and draining: move threads waiting for
* drain to ready state. The held spinlock inhibits
* reschedule; released threads get their chance when
Expand All @@ -611,13 +603,7 @@ static void work_queue_main(void *workq_ptr, void *p2, void *p3)
* here doesn't mean that the queue will allow new
* submissions.
*/
do {
waiter = z_unpend_first_thread(&queue->drainq);
if (waiter) {
arch_thread_return_value_set(waiter, 1);
z_ready_thread(waiter);
}
} while (waiter != NULL);
(void)k_sched_wake_all(&queue->drainq, 1, NULL);
}

if (work == NULL) {
Expand All @@ -628,7 +614,8 @@ static void work_queue_main(void *workq_ptr, void *p2, void *p3)
* check again.
*/

(void)z_pend_curr(&queue->lock, key, &queue->notifyq, K_FOREVER);
(void)k_sched_wait(&queue->lock, key, &queue->notifyq,
K_FOREVER, NULL);
continue;
}

Expand Down Expand Up @@ -706,7 +693,8 @@ int k_work_queue_drain(struct k_work_q *queue,
}

_notify_queue(queue);
ret = z_pend_curr(&queue->lock, key, &queue->drainq, K_FOREVER);
ret = k_sched_wait(&queue->lock, key, &queue->drainq,
K_FOREVER, NULL);
} else {
k_spin_unlock(&queue->lock, key);
}
Expand Down

0 comments on commit b8c3c7a

Please sign in to comment.