Commit 9c27d729 authored by Tom Burdick's avatar Tom Burdick Committed by Benjamin Cabé
Browse files

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: default avatarTom Burdick <thomas.burdick@intel.com>
parent 80ab4b81
Loading
Loading
Loading
Loading
+1 −0
Changes for include/zephyr/linker/common-ram.ld: 1 added line, 0 removed lines.
Original line number Diff line number Diff line
@@ -126,6 +126,7 @@ ITERABLE_SECTION_RAM(scmi_protocol, Z_LINK_ITERABLE_SUBALIGN)

#if defined(CONFIG_RTIO)
	ITERABLE_SECTION_RAM(rtio, Z_LINK_ITERABLE_SUBALIGN)
	ITERABLE_SECTION_RAM(rtio_pool, Z_LINK_ITERABLE_SUBALIGN)
	ITERABLE_SECTION_RAM(rtio_iodev, Z_LINK_ITERABLE_SUBALIGN)
	ITERABLE_SECTION_RAM(rtio_sqe_pool, Z_LINK_ITERABLE_SUBALIGN)
	ITERABLE_SECTION_RAM(rtio_cqe_pool, Z_LINK_ITERABLE_SUBALIGN)
+125 −0
Changes for include/zephyr/rtio/rtio.h: 125 added lines, 0 removed lines.
Original line number Diff line number Diff line
@@ -1421,6 +1421,9 @@ static inline void z_impl_rtio_release_buffer(struct rtio *r, void *buff, uint32

/**
 * Grant access to an RTIO context to a user thread
 *
 * @param r RTIO context
 * @param t Thread to grant permissions to
 */
static inline void rtio_access_grant(struct rtio *r, struct k_thread *t)
{
@@ -1435,6 +1438,26 @@ static inline void rtio_access_grant(struct rtio *r, struct k_thread *t)
#endif
}


/**
 * Revoke access to an RTIO context from a user thread
 *
 * @param r RTIO context
 * @param t Thread to revoke permissions from
 */
static inline void rtio_access_revoke(struct rtio *r, struct k_thread *t)
{
	k_object_access_revoke(r, t);

#ifdef CONFIG_RTIO_SUBMIT_SEM
	k_object_access_revoke(r->submit_sem, t);
#endif

#ifdef CONFIG_RTIO_CONSUME_SEM
	k_object_access_revoke(r->consume_sem, t);
#endif
}

/**
 * @brief Attempt to cancel an SQE
 *
@@ -1674,6 +1697,108 @@ static inline int z_impl_rtio_submit(struct rtio *r, uint32_t wait_count)
}
#endif /* CONFIG_RTIO_SUBMIT_SEM */

/**
 * @brief Pool of RTIO contexts to use with dynamically created threads
 */
struct rtio_pool {
	/** Size of the pool */
	size_t pool_size;

	/** Array containing contexts of the pool */
	struct rtio **contexts;

	/** Atomic bitmap to signal a member is used/unused */
	atomic_t *used;
};

/**
 * @brief Obtain an RTIO context from a pool
 *
 * @param pool RTIO pool to acquire a context from
 *
 * @retval NULL no available contexts
 * @retval r Valid context with permissions granted to the calling thread
 */
__syscall struct rtio *rtio_pool_acquire(struct rtio_pool *pool);

static inline struct rtio *z_impl_rtio_pool_acquire(struct rtio_pool *pool)
{
	struct rtio *r = NULL;

	for (size_t i = 0; i < pool->pool_size; i++) {
		if (atomic_test_and_set_bit(pool->used, i) == 0) {
			r = pool->contexts[i];
			break;
		}
	}

	if (r != NULL) {
		rtio_access_grant(r, k_current_get());
	}

	return r;
}

/**
 * @brief Return an RTIO context to a pool
 *
 * @param pool RTIO pool to return a context to
 * @param r RTIO context to return to the pool
 */
__syscall void rtio_pool_release(struct rtio_pool *pool, struct rtio *r);

static inline void z_impl_rtio_pool_release(struct rtio_pool *pool, struct rtio *r)
{

	if (k_is_user_context()) {
		rtio_access_revoke(r, k_current_get());
	}

	for (size_t i = 0; i < pool->pool_size; i++) {
		if (pool->contexts[i] == r) {
			atomic_clear_bit(pool->used, i);
			break;
		}
	}
}

/* clang-format off */

/** @cond ignore */

#define Z_RTIO_POOL_NAME_N(n, name)                                             \
	name##_##n

#define Z_RTIO_POOL_DEFINE_N(n, name, sq_sz, cq_sz)				\
	RTIO_DEFINE(Z_RTIO_POOL_NAME_N(n, name), sq_sz, cq_sz)

#define Z_RTIO_POOL_REF_N(n, name)                                              \
	&Z_RTIO_POOL_NAME_N(n, name)

/** @endcond */

/**
 * @brief Statically define and initialize a pool of RTIO contexts
 *
 * @param name Name of the RTIO pool
 * @param pool_sz Number of RTIO contexts to allocate in the pool
 * @param sq_sz Size of the submission queue entry pool per context
 * @param cq_sz Size of the completion queue entry pool per context
 */
#define RTIO_POOL_DEFINE(name, pool_sz, sq_sz, cq_sz)				\
	LISTIFY(pool_sz, Z_RTIO_POOL_DEFINE_N, (;), name, sq_sz, cq_sz);        \
	static struct rtio *name##_contexts[] = {                               \
		LISTIFY(pool_sz, Z_RTIO_POOL_REF_N, (,), name)                  \
	};                                                                      \
	ATOMIC_DEFINE(name##_used, pool_sz);                                    \
	STRUCT_SECTION_ITERABLE(rtio_pool, name) = {                            \
		.pool_size = pool_sz,                                           \
		.contexts = name##_contexts,                                    \
		.used = name##_used,                                            \
	}

/* clang-format on */

/**
 * @}
 */
+1 −0
Changes for scripts/build/gen_kobject_list.py: 1 added line, 0 removed lines.
Original line number Diff line number Diff line
@@ -114,6 +114,7 @@ kobjects = OrderedDict([
    ("ztest_test_rule", ("CONFIG_ZTEST", True, False)),
    ("rtio", ("CONFIG_RTIO", False, False)),
    ("rtio_iodev", ("CONFIG_RTIO", False, False)),
    ("rtio_pool", ("CONFIG_RTIO", False, False)),
    ("sensor_decoder_api", ("CONFIG_SENSOR_ASYNC_API", True, False))
])

+1 −1
Changes for subsys/rtio/CMakeLists.txt: 1 added line, 1 removed line.
Original line number Diff line number Diff line
@@ -11,7 +11,7 @@ if(CONFIG_RTIO)
	zephyr_library_sources(rtio_executor.c)
	zephyr_library_sources(rtio_init.c)
	zephyr_library_sources(rtio_sched.c)
	zephyr_library_sources_ifdef(CONFIG_USERSPACE rtio_handlers.c)
	zephyr_library_sources_ifdef(CONFIG_USERSPACE rtio_syscalls.c)
endif()

zephyr_library_sources_ifdef(CONFIG_RTIO_WORKQ rtio_workq.c)
+19 −0
Changes for subsys/rtio/rtio_syscalls.c: 19 added lines, 0 removed lines.
Original line number Diff line number Diff line
@@ -135,3 +135,22 @@ static inline int z_vrfy_rtio_submit(struct rtio *r, uint32_t wait_count)
	return z_impl_rtio_submit(r, wait_count);
}
#include <zephyr/syscalls/rtio_submit_mrsh.c>


static inline struct rtio *z_vrfy_rtio_pool_acquire(struct rtio_pool *rpool)
{
	K_OOPS(K_SYSCALL_OBJ(rpool, K_OBJ_RTIO_POOL));

	return z_impl_rtio_pool_acquire(rpool);
}
#include <zephyr/syscalls/rtio_pool_acquire_mrsh.c>


static inline void z_vrfy_rtio_pool_release(struct rtio_pool *rpool, struct rtio *r)
{
	K_OOPS(K_SYSCALL_OBJ(rpool, K_OBJ_RTIO_POOL));
	K_OOPS(K_SYSCALL_OBJ(r, K_OBJ_RTIO));

	z_impl_rtio_pool_release(rpool, r);
}
#include <zephyr/syscalls/rtio_pool_release_mrsh.c>
Loading