blob: b063ead71a4205c2d1d355d622b59474977ce57c [file] [log] [blame]
/*
* Copyright (c) 2024 Croxel Inc.
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <zephyr/rtio/work.h>
#include <zephyr/kernel.h>
#define RTIO_WORKQ_PRIO_MED CONFIG_RTIO_WORKQ_PRIO_MED
#define RTIO_WORKQ_PRIO_HIGH RTIO_WORKQ_PRIO_MED - 1
#define RTIO_WORKQ_PRIO_LOW RTIO_WORKQ_PRIO_MED + 1
K_P4WQ_DEFINE(rtio_workq,
CONFIG_RTIO_WORKQ_THREADS_POOL,
CONFIG_RTIO_WORKQ_STACK_SIZE);
K_MEM_SLAB_DEFINE_STATIC(rtio_work_items_slab,
sizeof(struct rtio_work_req),
CONFIG_RTIO_WORKQ_POOL_ITEMS,
4);
static void rtio_work_handler(struct k_p4wq_work *work)
{
struct rtio_work_req *req = CONTAINER_OF(work,
struct rtio_work_req,
work);
struct rtio_iodev_sqe *iodev_sqe = req->iodev_sqe;
req->handler(iodev_sqe);
k_mem_slab_free(&rtio_work_items_slab, req);
}
struct rtio_work_req *rtio_work_req_alloc(void)
{
struct rtio_work_req *req;
int err;
err = k_mem_slab_alloc(&rtio_work_items_slab, (void **)&req, K_NO_WAIT);
if (err) {
return NULL;
}
/** Initialize work item before using it as it comes
* from a Memory slab (no-init region).
*/
req->work.thread = NULL;
(void)k_sem_init(&req->work.done_sem, 1, 1);
return req;
}
void rtio_work_req_submit(struct rtio_work_req *req,
struct rtio_iodev_sqe *iodev_sqe,
rtio_work_submit_t handler)
{
if (!req) {
return;
}
if (!iodev_sqe || !handler) {
k_mem_slab_free(&rtio_work_items_slab, req);
return;
}
struct k_p4wq_work *work = &req->work;
struct rtio_sqe *sqe = &iodev_sqe->sqe;
/** Link the relevant info so that we can get it on the k_p4wq_work work item.
*/
req->iodev_sqe = iodev_sqe;
req->handler = handler;
/** Set the required information to handle the action */
work->handler = rtio_work_handler;
work->deadline = 0;
if (sqe->prio == RTIO_PRIO_LOW) {
work->priority = RTIO_WORKQ_PRIO_LOW;
} else if (sqe->prio == RTIO_PRIO_HIGH) {
work->priority = RTIO_WORKQ_PRIO_HIGH;
} else {
work->priority = RTIO_WORKQ_PRIO_MED;
}
/** Decoupling action: Let the P4WQ execute the action. */
k_p4wq_submit(&rtio_workq, work);
}
uint32_t rtio_work_req_used_count_get(void)
{
return k_mem_slab_num_used_get(&rtio_work_items_slab);
}