Skip to content

Commit 7f0df4a

Browse files
committed
rtio: Add a context pool
Adds a context pool that can be used when a number of threads may be dynamically created to use with RTIO. While the pool has a small cost to it, the cost of verifying a statically declared kobject likely makes it worth avoiding dynamically allocating these with the typical kobject_alloc method. Instead this arena style pool of objects can be used where the kobject validation uses the gperf hash created at build time. Signed-off-by: Tom Burdick <thomas.burdick@intel.com>
1 parent 1c0608d commit 7f0df4a

File tree

6 files changed

+212
-2
lines changed

6 files changed

+212
-2
lines changed

include/zephyr/rtio/pool.h

Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
/*
2+
* Copyright (c) 2025 Intel Corporation
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
/**
8+
* @file
9+
* @brief Real-Time IO pool API for maintaining a pool for RTIO contexts
10+
*/
11+
12+
#ifndef ZEPHYR_INCLUDE_RTIO_POOL_H_
13+
#define ZEPHYR_INCLUDE_RTIO_POOL_H_
14+
15+
#include "zephyr/kernel.h"
16+
#include <zephyr/sys/atomic.h>
17+
#include <zephyr/rtio/rtio.h>
18+
19+
#ifdef __cplusplus
20+
extern "C" {
21+
#endif
22+
23+
/**
24+
* @brief RTIO Pool
25+
* @defgroup rtio_pool RTIO Pool API
26+
* @ingroup rtio
27+
* @{
28+
*/
29+
30+
/**
31+
* @brief Pool of RTIO contexts to use with dynamically created threads
32+
*/
33+
struct rtio_pool {
34+
/** Size of the pool */
35+
size_t pool_size;
36+
37+
/** Array containing contexts of the pool */
38+
struct rtio **contexts;
39+
40+
/** Atomic bitmap to signal a member is used/unused */
41+
atomic_t *used;
42+
};
43+
44+
/**
45+
* @brief Obtain an RTIO context from a pool
46+
*/
47+
__syscall struct rtio *rtio_pool_acquire(struct rtio_pool *pool);
48+
49+
static inline struct rtio *z_impl_rtio_pool_acquire(struct rtio_pool *pool)
50+
{
51+
struct rtio *r = NULL;
52+
53+
for (size_t i = 0; i < pool->pool_size; i++) {
54+
if (atomic_test_and_set_bit(pool->used, i) == 0) {
55+
r = pool->contexts[i];
56+
break;
57+
}
58+
}
59+
60+
k_object_access_grant(r, k_current_get());
61+
62+
return r;
63+
}
64+
65+
/**
66+
* @brief Return an RTIO context to a pool
67+
*/
68+
__syscall void rtio_pool_release(struct rtio_pool *pool, struct rtio *r);
69+
70+
static inline void z_impl_rtio_pool_release(struct rtio_pool *pool, struct rtio *r)
71+
{
72+
k_object_access_revoke(r, k_current_get());
73+
74+
for (size_t i = 0; i < pool->pool_size; i++) {
75+
if (pool->contexts[i] == r) {
76+
atomic_clear_bit(pool->used, i);
77+
break;
78+
}
79+
}
80+
}
81+
82+
/* clang-format off */
83+
84+
/** @cond ignore */
85+
86+
#define Z_RTIO_POOL_NAME_N(n, name) \
87+
name##_##n
88+
89+
#define Z_RTIO_POOL_DEFINE_N(n, name, sq_sz, cq_sz) \
90+
RTIO_DEFINE(Z_RTIO_POOL_NAME_N(n, name), sq_sz, cq_sz)
91+
92+
#define Z_RTIO_POOL_REF_N(n, name) \
93+
&Z_RTIO_POOL_NAME_N(n, name)
94+
95+
/** @endcond */
96+
97+
/**
98+
* @brief Statically define and initialize a pool of RTIO contexts
99+
*
100+
* @param name Name of the RTIO pool
101+
* @param pool_sz Number of RTIO contexts to allocate in the pool
102+
* @param sq_sz Size of the submission queue entry pool per context
103+
* @param cq_sz Size of the completion queue entry pool per context
104+
*/
105+
#define RTIO_POOL_DEFINE(name, pool_sz, sq_sz, cq_sz) \
106+
LISTIFY(pool_sz, Z_RTIO_POOL_DEFINE_N, (;), name, sq_sz, cq_sz); \
107+
static struct rtio * name##_contexts[] = { \
108+
LISTIFY(pool_sz, Z_RTIO_POOL_REF_N, (,), name) \
109+
}; \
110+
ATOMIC_DEFINE(name##_used, pool_sz); \
111+
STRUCT_SECTION_ITERABLE(rtio_pool, name) = { \
112+
.pool_size = pool_sz, \
113+
.contexts = name##_contexts, \
114+
.used = name##_used, \
115+
}
116+
117+
/* clang-format on */
118+
119+
/**
120+
* @}
121+
*/
122+
123+
#ifdef __cplusplus
124+
}
125+
#endif
126+
127+
#include <zephyr/syscalls/pool.h>
128+
129+
#endif /* ZEPHYR_INCLUDE_RTIO_POOL_H_ */

scripts/build/gen_kobject_list.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,7 @@
114114
("ztest_test_rule", ("CONFIG_ZTEST", True, False)),
115115
("rtio", ("CONFIG_RTIO", False, False)),
116116
("rtio_iodev", ("CONFIG_RTIO", False, False)),
117+
("rtio_pool", ("CONFIG_RTIO", False, False)),
117118
("sensor_decoder_api", ("CONFIG_SENSOR_ASYNC_API", True, False))
118119
])
119120

subsys/rtio/CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ if(CONFIG_RTIO)
1111
zephyr_library_sources(rtio_executor.c)
1212
zephyr_library_sources(rtio_init.c)
1313
zephyr_library_sources(rtio_sched.c)
14-
zephyr_library_sources_ifdef(CONFIG_USERSPACE rtio_handlers.c)
14+
zephyr_library_sources_ifdef(CONFIG_USERSPACE rtio_syscalls.c)
1515
endif()
1616

1717
zephyr_library_sources_ifdef(CONFIG_RTIO_WORKQ rtio_workq.c)

subsys/rtio/rtio_handlers.c renamed to subsys/rtio/rtio_syscalls.c

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,3 +133,22 @@ static inline int z_vrfy_rtio_submit(struct rtio *r, uint32_t wait_count)
133133
return z_impl_rtio_submit(r, wait_count);
134134
}
135135
#include <zephyr/syscalls/rtio_submit_mrsh.c>
136+
137+
138+
static inline struct rtio * z_vrfy_rtio_pool_acquire(struct rtio_pool *rpool)
139+
{
140+
K_OOPS(K_SYSCALL_OBJ(rpool, K_OBJ_RTIO_POOL));
141+
142+
return z_impl_rtio_pool_acquire(rpool);
143+
}
144+
#include <zephyr/sysaclls/rtio_pool_acquire_mrsh.c>
145+
146+
147+
static inline void z_vrfy_rtio_pool_release(struct rtio_pool *rpool, struct rtio *r)
148+
{
149+
K_OOPS(K_SYSCALL_OBJ(rpool, K_OBJ_RTIO_POOL));
150+
K_OOPS(K_SYSCALL_OBJ(r, K_OBJ_RTIO));
151+
152+
z_impl_rtio_pool_release(rpool, r);
153+
}
154+
#include <zephyr/sysaclls/rtio_pool_acquire_mrsh.c>

tests/subsys/rtio/rtio_api/CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ cmake_minimum_required(VERSION 3.20.0)
55
find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
66
project(rtio_api_test)
77

8-
target_sources(app PRIVATE src/test_rtio_api.c)
8+
target_sources(app PRIVATE src/test_rtio_api.c src/test_rtio_pool.c)
99

1010
target_include_directories(app PRIVATE
1111
${ZEPHYR_BASE}/include
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
/*
2+
* Copyright (c) 2025 Intel Corporation.
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
#include <errno.h>
8+
#include <zephyr/ztest.h>
9+
#include <zephyr/kernel.h>
10+
#include <zephyr/sys/atomic.h>
11+
#include <zephyr/sys/kobject.h>
12+
#include <zephyr/sys/libc-hooks.h>
13+
#include <zephyr/app_memory/mem_domain.h>
14+
#include <zephyr/sys/util_loops.h>
15+
#include <zephyr/sys/time_units.h>
16+
#include <zephyr/timing/timing.h>
17+
#include <zephyr/rtio/rtio.h>
18+
#include <zephyr/rtio/pool.h>
19+
20+
RTIO_POOL_DEFINE(rpool, 2, 8, 8);
21+
22+
ZTEST_USER(rtio_pool, test_rtio_pool_acquire_release)
23+
{
24+
struct rtio *r = rtio_pool_acquire(&rpool);
25+
26+
zassert_not_null(r, "expected valid rtio context");
27+
28+
struct rtio_sqe nop_sqe;
29+
struct rtio_cqe nop_cqe;
30+
31+
rtio_sqe_prep_nop(&nop_sqe, NULL, NULL);
32+
rtio_sqe_copy_in(r, &nop_sqe, 1);
33+
rtio_submit(r, 1);
34+
rtio_cqe_copy_out(r, &nop_cqe, 1, K_FOREVER);
35+
36+
rtio_pool_release(&rpool, r);
37+
}
38+
39+
static void *rtio_pool_setup(void)
40+
{
41+
#ifdef CONFIG_USERSPACE
42+
k_mem_domain_init(&rtio_domain, 0, NULL);
43+
k_mem_domain_add_partition(&rtio_domain, &rtio_partition);
44+
#if Z_LIBC_PARTITION_EXISTS
45+
k_mem_domain_add_partition(&rtio_domain, &z_libc_partition);
46+
#endif /* Z_LIBC_PARTITION_EXISTS */
47+
#endif /* CONFIG_USERSPACE */
48+
49+
return NULL;
50+
}
51+
52+
static void rtio_pool_before(void *a)
53+
{
54+
ARG_UNUSED(a);
55+
56+
#ifdef CONFIG_USERSPACE
57+
k_object_access_grant(&rpool, k_current_get());
58+
#endif /* CONFIG_USERSPACE */
59+
}
60+
61+
ZTEST_SUITE(rtio_pool, NULL, rtio_pool_setup, rtio_pool_before, NULL, NULL);

0 commit comments

Comments
 (0)