The new API cannot be used from userspace because it is not merely a wrapper around existing userspace-capable objects (threads and queues), but instead requires much more complex and lower-level access to memory that can't be touched from userspace. The vast majority of work queue users are operating from privileged mode, so there's little motivation to go through the pain and complexity of converting all functions to system calls. Copy the necessary pieces of the existing userspace work queue API out and expose them with new names and types: * k_work_handler_t becomes k_work_user_handler_t * k_work becomes k_work_user * k_work_q becomes k_work_user_q etc. Because the replacement API cannot use the same types new API names are also introduced to make it more clear that the userspace work queue API is a separate functionality. Signed-off-by: Peter Bigot <peter.bigot@nordicsemi.no>
60 lines
1.4 KiB
C
60 lines
1.4 KiB
C
/*
|
|
* Copyright (c) 2018 Intel Corporation
|
|
* Copyright (c) 2016 Wind River Systems, Inc.
|
|
*
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
|
|
#include <kernel.h>
|
|
|
|
static void z_work_user_q_main(void *work_q_ptr, void *p2, void *p3)
|
|
{
|
|
struct k_work_user_q *work_q = work_q_ptr;
|
|
|
|
ARG_UNUSED(p2);
|
|
ARG_UNUSED(p3);
|
|
|
|
while (true) {
|
|
struct k_work_user *work;
|
|
k_work_user_handler_t handler;
|
|
|
|
work = k_queue_get(&work_q->queue, K_FOREVER);
|
|
if (work == NULL) {
|
|
continue;
|
|
}
|
|
|
|
handler = work->handler;
|
|
__ASSERT(handler != NULL, "handler must be provided");
|
|
|
|
/* Reset pending state so it can be resubmitted by handler */
|
|
if (atomic_test_and_clear_bit(&work->flags,
|
|
K_WORK_USER_STATE_PENDING)) {
|
|
handler(work);
|
|
}
|
|
|
|
/* Make sure we don't hog up the CPU if the FIFO never (or
|
|
* very rarely) gets empty.
|
|
*/
|
|
k_yield();
|
|
}
|
|
}
|
|
|
|
void k_work_user_queue_start(struct k_work_user_q *work_q, k_thread_stack_t *stack,
|
|
size_t stack_size, int prio, const char *name)
|
|
{
|
|
k_queue_init(&work_q->queue);
|
|
|
|
/* Created worker thread will inherit object permissions and memory
|
|
* domain configuration of the caller
|
|
*/
|
|
k_thread_create(&work_q->thread, stack, stack_size, z_work_user_q_main,
|
|
work_q, NULL, NULL, prio, K_USER | K_INHERIT_PERMS,
|
|
K_FOREVER);
|
|
k_object_access_grant(&work_q->queue, &work_q->thread);
|
|
if (name != NULL) {
|
|
k_thread_name_set(&work_q->thread, name);
|
|
}
|
|
|
|
k_thread_start(&work_q->thread);
|
|
}
|