/* * Copyright (c) 2024 Croxel Inc. * Copyright (c) 2025 Croxel Inc. * * SPDX-License-Identifier: Apache-2.0 */ #include #include K_MEM_SLAB_DEFINE_STATIC(rtio_work_items_slab, sizeof(struct rtio_work_req), CONFIG_RTIO_WORKQ_POOL_ITEMS, 4); static K_THREAD_STACK_ARRAY_DEFINE(rtio_workq_threads_stack, CONFIG_RTIO_WORKQ_THREADS_POOL, CONFIG_RTIO_WORKQ_THREADS_POOL_STACK_SIZE); static struct k_thread rtio_work_threads[CONFIG_RTIO_WORKQ_THREADS_POOL]; static K_QUEUE_DEFINE(rtio_workq); 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; } 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; } req->iodev_sqe = iodev_sqe; req->handler = handler; /** For now we're simply treating this as a FIFO queue. It may be * desirable to expand this to handle queue ordering based on RTIO * SQE priority. */ k_queue_append(&rtio_workq, req); } uint32_t rtio_work_req_used_count_get(void) { return k_mem_slab_num_used_get(&rtio_work_items_slab); } static void rtio_workq_thread_fn(void *arg1, void *arg2, void *arg3) { ARG_UNUSED(arg1); ARG_UNUSED(arg2); ARG_UNUSED(arg3); while (true) { struct rtio_work_req *req = k_queue_get(&rtio_workq, K_FOREVER); if (req != NULL) { req->handler(req->iodev_sqe); k_mem_slab_free(&rtio_work_items_slab, req); } } } static int static_init(void) { for (size_t i = 0 ; i < ARRAY_SIZE(rtio_work_threads) ; i++) { k_thread_create(&rtio_work_threads[i], rtio_workq_threads_stack[i], CONFIG_RTIO_WORKQ_THREADS_POOL_STACK_SIZE, rtio_workq_thread_fn, NULL, NULL, NULL, CONFIG_RTIO_WORKQ_THREADS_POOL_PRIO, 0, K_NO_WAIT); } return 0; } SYS_INIT(static_init, POST_KERNEL, 1);