Skip to content

Commit 912e7ff

Browse files
teburdcarlescufi
authored andcommitted
rtio: Add callback op
Adds a callback op to RTIO enabling C logic to be interspersed with I/O operations. This is not safe from userspace but allowable in kernel space. Signed-off-by: Tom Burdick <[email protected]>
1 parent bb72809 commit 912e7ff

File tree

5 files changed

+109
-26
lines changed

5 files changed

+109
-26
lines changed

include/zephyr/rtio/rtio.h

Lines changed: 52 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -52,9 +52,6 @@ extern "C" {
5252
* @}
5353
*/
5454

55-
56-
struct rtio_iodev;
57-
5855
/**
5956
* @brief RTIO API
6057
* @defgroup rtio_api RTIO API
@@ -121,6 +118,23 @@ struct rtio_iodev;
121118
* @}
122119
*/
123120

121+
/** @cond ignore */
122+
struct rtio;
123+
struct rtio_cqe;
124+
struct rtio_sqe;
125+
struct rtio_iodev;
126+
struct rtio_iodev_sqe;
127+
/** @endcond */
128+
129+
/**
130+
* @typedef rtio_callback_t
131+
* @brief Callback signature for RTIO_OP_CALLBACK
132+
* @param r RTIO context being used with the callback
133+
* @param sqe Submission for the callback op
134+
* @param arg0 Argument option as part of the sqe
135+
*/
136+
typedef void (*rtio_callback_t)(struct rtio *r, const struct rtio_sqe *sqe, void *arg0);
137+
124138
/**
125139
* @brief A submission queue event
126140
*/
@@ -147,7 +161,6 @@ struct rtio_sqe {
147161
/** OP_TX, OP_RX */
148162
struct {
149163
uint32_t buf_len; /**< Length of buffer */
150-
151164
uint8_t *buf; /**< Buffer to use*/
152165
};
153166

@@ -159,12 +172,19 @@ struct rtio_sqe {
159172

160173
/** OP_CALLBACK */
161174
struct {
162-
void (*callback)(struct rtio *r, struct rtio_sqe *sqe, void *arg0);
163-
void *arg0;
175+
rtio_callback_t callback;
176+
void *arg0; /**< Last argument given to callback */
164177
};
165178
};
166179
};
167180

181+
182+
/** @cond ignore */
183+
/* Ensure the rtio_sqe never grows beyond a common cacheline size of 64 bytes */
184+
BUILD_ASSERT(sizeof(struct rtio_sqe) <= 64);
185+
/** @endcond */
186+
187+
168188
/**
169189
* @brief Submission queue
170190
*
@@ -195,8 +215,6 @@ struct rtio_cq {
195215
struct rtio_cqe buffer[];
196216
};
197217

198-
struct rtio;
199-
struct rtio_iodev_sqe;
200218

201219
struct rtio_executor_api {
202220
/**
@@ -341,11 +359,12 @@ struct rtio_iodev {
341359
/** An operation that transmits (writes) */
342360
#define RTIO_OP_TX (RTIO_OP_RX+1)
343361

344-
/** An operation that transmits tiny writes */
362+
/** An operation that transmits tiny writes by copying the data to write */
345363
#define RTIO_OP_TINY_TX (RTIO_OP_TX+1)
346364

347-
/** An operation that does some small functional work */
348-
#define RTIO_OP_FUNC (RTIO_OP_TINY_TX+1)
365+
/** An operation that calls a given function (callback) */
366+
#define RTIO_OP_CALLBACK (RTIO_OP_TINY_TX+1)
367+
349368

350369

351370
/**
@@ -427,6 +446,28 @@ static inline void rtio_sqe_prep_tiny_write(struct rtio_sqe *sqe,
427446
sqe->userdata = userdata;
428447
}
429448

449+
/**
450+
* @brief Prepare a callback op submission
451+
*
452+
* A somewhat special operation in that it may only be done in kernel mode.
453+
*
454+
* Used where general purpose logic is required in a queue of io operations to do
455+
* transforms or logic.
456+
*/
457+
static inline void rtio_sqe_prep_callback(struct rtio_sqe *sqe,
458+
rtio_callback_t callback,
459+
void *arg0,
460+
void *userdata)
461+
{
462+
sqe->op = RTIO_OP_CALLBACK;
463+
sqe->prio = 0;
464+
sqe->flags = 0;
465+
sqe->iodev = NULL;
466+
sqe->callback = callback;
467+
sqe->arg0 = arg0;
468+
sqe->userdata = userdata;
469+
}
470+
430471
/**
431472
* @brief Statically define and initialize a fixed length submission queue.
432473
*

subsys/rtio/rtio_executor_common.h

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
/*
2+
* Copyright (c) 2023 Intel Corporation.
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
#include <zephyr/rtio/rtio.h>
8+
9+
/**
10+
* @brief Executor handled submissions
11+
*/
12+
static void rtio_executor_submit_self(struct rtio_iodev_sqe *iodev_sqe)
13+
{
14+
const struct rtio_sqe *sqe = iodev_sqe->sqe;
15+
16+
switch (sqe->op) {
17+
case RTIO_OP_CALLBACK:
18+
sqe->callback(iodev_sqe->r, sqe, sqe->arg0);
19+
rtio_iodev_sqe_ok(iodev_sqe, 0);
20+
break;
21+
default:
22+
rtio_iodev_sqe_err(iodev_sqe, -EINVAL);
23+
}
24+
}
25+
26+
/**
27+
* @brief Common executor handling of submit
28+
*
29+
* Some submissions may have NULL for the iodev pointer which implies
30+
* an executor related operation such as a callback or flush. This
31+
* common codepath avoids duplicating efforts for dealing with this.
32+
*/
33+
static void rtio_executor_submit(struct rtio_iodev_sqe *iodev_sqe)
34+
{
35+
if (iodev_sqe->sqe->iodev == NULL) {
36+
rtio_executor_submit_self(iodev_sqe);
37+
} else {
38+
rtio_iodev_submit(iodev_sqe);
39+
}
40+
}

subsys/rtio/rtio_executor_concurrent.c

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,10 @@
1212
#include <zephyr/logging/log.h>
1313
LOG_MODULE_REGISTER(rtio_executor_concurrent, CONFIG_RTIO_LOG_LEVEL);
1414

15-
#define CONEX_TASK_COMPLETE BIT(0)
16-
#define CONEX_TASK_SUSPENDED BIT(1)
15+
#include "rtio_executor_common.h"
1716

17+
#define CONEX_TASK_COMPLETE BIT(0)
18+
#define CONEX_TASK_SUSPENDED BIT(1)
1819

1920
/**
2021
* @file
@@ -53,10 +54,10 @@ static uint16_t conex_task_next(struct rtio_concurrent_executor *exc)
5354
}
5455

5556
static inline uint16_t conex_task_id(struct rtio_concurrent_executor *exc,
56-
const struct rtio_iodev_sqe *iodev_sqe)
57+
const struct rtio_iodev_sqe *iodev_sqe)
5758
{
5859
__ASSERT_NO_MSG(iodev_sqe <= &exc->task_cur[exc->task_mask] &&
59-
iodev_sqe >= &exc->task_cur[0]);
60+
iodev_sqe >= &exc->task_cur[0]);
6061
return iodev_sqe - &exc->task_cur[0];
6162
}
6263

@@ -147,7 +148,6 @@ static void conex_prepare(struct rtio *r, struct rtio_concurrent_executor *exc)
147148
exc->last_sqe = last_sqe;
148149
}
149150

150-
151151
/**
152152
* @brief Resume tasks that are suspended
153153
*
@@ -161,7 +161,7 @@ static void conex_resume(struct rtio *r, struct rtio_concurrent_executor *exc)
161161
if (exc->task_status[task_id & exc->task_mask] & CONEX_TASK_SUSPENDED) {
162162
LOG_DBG("resuming suspended task %d", task_id);
163163
exc->task_status[task_id & exc->task_mask] &= ~CONEX_TASK_SUSPENDED;
164-
rtio_iodev_submit(&exc->task_cur[task_id & exc->task_mask]);
164+
rtio_executor_submit(&exc->task_cur[task_id & exc->task_mask]);
165165
}
166166
}
167167
}
@@ -176,8 +176,7 @@ static void conex_resume(struct rtio *r, struct rtio_concurrent_executor *exc)
176176
int rtio_concurrent_submit(struct rtio *r)
177177
{
178178

179-
struct rtio_concurrent_executor *exc =
180-
(struct rtio_concurrent_executor *)r->executor;
179+
struct rtio_concurrent_executor *exc = (struct rtio_concurrent_executor *)r->executor;
181180
k_spinlock_key_t key;
182181

183182
key = k_spin_lock(&exc->lock);
@@ -219,9 +218,9 @@ void rtio_concurrent_ok(struct rtio_iodev_sqe *iodev_sqe, int result)
219218
next_sqe = rtio_spsc_next(r->sq, sqe);
220219

221220
exc->task_cur[task_id].sqe = next_sqe;
222-
rtio_iodev_submit(&exc->task_cur[task_id]);
221+
rtio_executor_submit(&exc->task_cur[task_id]);
223222
} else {
224-
exc->task_status[task_id] |= CONEX_TASK_COMPLETE;
223+
exc->task_status[task_id] |= CONEX_TASK_COMPLETE;
225224
}
226225

227226
bool transaction = sqe->flags & RTIO_SQE_TRANSACTION;

subsys/rtio/rtio_executor_simple.c

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
* SPDX-License-Identifier: Apache-2.0
55
*/
66

7+
#include "rtio_executor_common.h"
78
#include <zephyr/rtio/rtio_executor_simple.h>
89
#include <zephyr/rtio/rtio.h>
910
#include <zephyr/kernel.h>
@@ -61,9 +62,7 @@ int rtio_simple_submit(struct rtio *r)
6162
exc->task.sqe = sqe;
6263
exc->task.r = r;
6364

64-
if (sqe != NULL) {
65-
rtio_iodev_submit(&exc->task);
66-
}
65+
rtio_executor_submit(&exc->task);
6766

6867
return 0;
6968
}
@@ -144,6 +143,6 @@ void rtio_simple_err(struct rtio_iodev_sqe *iodev_sqe, int result)
144143

145144
iodev_sqe->sqe = rtio_spsc_consume(r->sq);
146145
if (iodev_sqe->sqe != NULL) {
147-
rtio_iodev_submit(iodev_sqe);
146+
rtio_executor_submit(iodev_sqe);
148147
}
149148
}

subsys/rtio/rtio_handlers.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@
1313
* the iodev is a valid accessible k_object (if given) and
1414
* the buffer pointers are valid accessible memory by the calling
1515
* thread.
16+
*
17+
* Each op code that is acceptable from user mode must also be validated.
1618
*/
1719
static inline bool rtio_vrfy_sqe(struct rtio_sqe *sqe)
1820
{
@@ -34,7 +36,9 @@ static inline bool rtio_vrfy_sqe(struct rtio_sqe *sqe)
3436
case RTIO_OP_TINY_TX:
3537
break;
3638
default:
37-
/* RTIO OP must be known */
39+
/* RTIO OP must be known and allowable from user mode
40+
* otherwise it is invalid
41+
*/
3842
valid_sqe = false;
3943
}
4044

0 commit comments

Comments
 (0)