44 static const struct io_dev_vtbl io_can_rt_dev_vtbl = {
45 &io_can_rt_dev_get_ctx,
46 &io_can_rt_dev_get_exec,
47 &io_can_rt_dev_cancel,
52 static void io_can_rt_svc_shutdown(
struct io_svc *svc);
55 static const struct io_svc_vtbl io_can_rt_svc_vtbl = {
57 &io_can_rt_svc_shutdown
74 unsigned shutdown : 1;
75 unsigned submitted : 1;
80 static void io_can_rt_read_func(
struct ev_task *task);
81 static void io_can_rt_task_func(
struct ev_task *task);
94 const struct can_msg *msg,
int errc);
95 static size_t io_can_rt_read_msg_queue_post(
99 const struct can_err *err,
int errc);
100 static size_t io_can_rt_read_err_queue_post(
103 static int io_can_rt_read_msg_cmp(
const void *p1,
const void *p2);
111 static void io_can_rt_async_read_msg_func(
struct ev_task *task);
119 static void io_can_rt_async_read_err_func(
struct ev_task *task);
126 static void io_can_rt_async_shutdown_func(
struct ev_task *task);
129 io_can_rt_alloc(
void)
138 io_can_rt_free(
void *ptr)
158 rt->dev_vptr = &io_can_rt_dev_vtbl;
160 rt->svc = (
struct io_svc)IO_SVC_INIT(&io_can_rt_svc_vtbl);
168 goto error_create_strand;
171 rt->msg = (
struct can_msg)CAN_MSG_INIT;
172 rt->err = (
struct can_err)CAN_ERR_INIT;
174 &rt->err, NULL, rt->exec, &io_can_rt_read_func);
176 rt->task = (
struct ev_task)EV_TASK_INIT(rt->exec, &io_can_rt_task_func);
188 rbtree_init(&rt->msg_queue, &io_can_rt_read_msg_cmp);
260 return &rt->dev_vptr;
278 task->
exec = rt->exec;
288 io_can_rt_read_msg_post(
291 task->_data = &rt->msg_queue;
302 int submit = !rt->submitted;
326 if (task->_data == &rt->msg_queue)
327 io_can_rt_do_pop_read_msg(rt, &queue, read_msg);
332 return io_can_rt_read_msg_queue_post(
349 if (task->_data == &rt->msg_queue)
350 io_can_rt_do_pop_read_msg(rt, &queue, read_msg);
369 async_read_msg->promise = promise;
370 async_read_msg->read_msg =
372 flags, &io_can_rt_async_read_msg_func);
373 async_read_msg->msg = (
struct can_msg)CAN_MSG_INIT;
378 *pread_msg = &async_read_msg->read_msg;
390 task->
exec = rt->exec;
400 io_can_rt_read_err_post(
403 task->_data = &rt->err_queue;
405 int submit = !rt->submitted;
429 if (task->_data == &rt->err_queue)
430 io_can_rt_do_pop_read_err(rt, &queue, read_err);
435 return io_can_rt_read_err_queue_post(
452 if (task->_data == &rt->err_queue)
453 io_can_rt_do_pop_read_err(rt, &queue, read_err);
471 async_read_err->promise = promise;
472 async_read_err->read_err =
474 &io_can_rt_async_read_err_func);
475 async_read_err->err = (
struct can_err)CAN_ERR_INIT;
480 *pread_err = &async_read_err->read_err;
495 async_shutdown->promise = promise;
496 async_shutdown->task = (
struct ev_task)EV_TASK_INIT(
497 rt->exec, &io_can_rt_async_shutdown_func);
499 io_can_rt_svc_shutdown(&rt->svc);
518 io_can_rt_dev_get_ctx(
const io_dev_t *dev)
526 io_can_rt_dev_get_exec(
const io_dev_t *dev)
538 struct sllist msg_queue, err_queue;
545 io_can_rt_do_pop(rt, &msg_queue, &err_queue, task);
549 size_t nmsg = io_can_rt_read_msg_queue_post(
551 size_t nerr = io_can_rt_read_err_queue_post(
553 return nerr < SIZE_MAX - nmsg ? nmsg + nerr : SIZE_MAX;
567 io_can_rt_do_pop(rt, &queue, &queue, task);
575 io_can_rt_svc_shutdown(
struct io_svc *svc)
583 int shutdown = !rt->shutdown;
586 if (shutdown && rt->submitted
595 io_can_rt_dev_cancel(dev, NULL);
599 io_can_rt_read_func(
struct ev_task *task)
625 io_can_rt_read_msg_queue_post(&queue, rt->read.
msg, 0);
626 }
else if (!rt->read.
r.
result) {
636 io_can_rt_read_err_queue_post(&queue, rt->read.
err, 0);
637 }
else if (rt->read.
r.
errc) {
638 struct sllist msg_queue, err_queue;
644 io_can_rt_do_pop(rt, &msg_queue, &err_queue, NULL);
648 io_can_rt_read_msg_queue_post(
649 &msg_queue, NULL, rt->read.
r.
errc);
650 io_can_rt_read_err_queue_post(
651 &err_queue, NULL, rt->read.
r.
errc);
658 io_can_rt_task_func(
struct ev_task *task)
666 assert(rt->submitted);
667 int submit = rt->submitted =
680 io_can_rt_from_dev(
const io_dev_t *dev)
688 io_can_rt_from_svc(
const struct io_svc *svc)
714 }
else if (task->_data == &rt->msg_queue) {
715 io_can_rt_do_pop_read_msg(rt, msg_queue,
717 }
else if (task->_data == &rt->err_queue) {
718 io_can_rt_do_pop_read_err(rt, err_queue,
731 assert(task->_data == &rt->msg_queue);
734 if (node == &read_msg->_node) {
737 struct sllist queue = read_msg->_queue;
745 }
else if (rt->submitted &&
rbtree_empty(&rt->msg_queue)
768 assert(task->_data == &rt->err_queue);
781 const struct can_msg *msg,
int errc)
783 read_msg->
r.
msg = msg;
784 read_msg->
r.
errc = errc;
792 io_can_rt_read_msg_queue_post(
802 io_can_rt_read_msg_post(read_msg, msg, errc);
811 const struct can_err *err,
int errc)
813 read_err->
r.
err = err;
814 read_err->
r.
errc = errc;
822 io_can_rt_read_err_queue_post(
832 io_can_rt_read_err_post(read_err, err, errc);
840 io_can_rt_read_msg_cmp(
const void *p1,
const void *p2)
847 int cmp = (r2->
id < r1->
id) - (r1->
id < r2->
id);
854 io_can_rt_async_read_msg_func(
struct ev_task *task)
863 if (read_msg->
r.
msg) {
864 async_read_msg->msg = *read_msg->
r.
msg;
865 read_msg->
r.
msg = &async_read_msg->msg;
873 io_can_rt_async_read_err_func(
struct ev_task *task)
882 if (read_err->
r.
err) {
883 async_read_err->err = *read_err->
r.
err;
884 read_err->
r.
err = &async_read_err->err;
892 io_can_rt_async_shutdown_func(
struct ev_task *task)
void ev_exec_post(ev_exec_t *exec, struct ev_task *task)
Submits *task to *exec for execution.
A CAN or CAN FD format frame.
struct can_err * err
The address at which to store the CAN error frame.
const struct ev_exec_vtbl *const ev_exec_t
An abstract task executor.
void * ev_promise_data(const ev_promise_t *promise)
Returns a pointer to the shared state of a promise.
void rbnode_init(struct rbnode *node, const void *key)
Initializes a node in a red-black tree.
void ev_promise_release(ev_promise_t *promise)
Releases a reference to a promise.
uint_least32_t id
The identifier (11 or 29 bits, depending on the CAN_FLAG_IDE flag).
A CAN channel read operation.
This header file is part of the I/O library; it contains the I/O context and service declarations...
size_t ev_task_queue_abort(struct sllist *queue)
Aborts the tasks in queue by invoking ev_exec_on_task_fini() for each of them.
void mtx_destroy(mtx_t *mtx)
Releases any resources used by the mutex at mtx.
int errnum2c(errnum_t errnum)
Transforms a platform-independent error number to a native error code.
ev_future_t * io_can_rt_async_read_err(io_can_rt_t *rt, struct io_can_rt_read_err **pread_err)
Submits an asynchronous CAN error frame read operation to a CAN frame router and creates a future whi...
size_t io_can_rt_abort_read_err(io_can_rt_t *rt, struct io_can_rt_read_err *read_err)
Aborts the specified CAN error frame read operation if it is pending.
ev_exec_t * io_dev_get_exec(const io_dev_t *dev)
Returns a pointer to the executor used by the I/O device to execute asynchronous tasks.
Indicates that the requested operation succeeded.
io_can_chan_t * io_can_rt_get_chan(const io_can_rt_t *rt)
Returns a pointer to the CAN channel used by the CAN frame router.
void ev_exec_on_task_fini(ev_exec_t *exec)
Undoes the effect of a previous call to ev_exec_on_task_init().
void io_ctx_insert(io_ctx_t *ctx, struct io_svc *svc)
Registers an I/O service with an I/O context.
A node in a singly-linked list.
ev_promise_t * ev_promise_create(size_t size, ev_promise_dtor_t *dtor)
Constructs a new promise with an optional empty shared state.
struct slnode * sllist_pop_front(struct sllist *list)
Pops a node from the front of a singly-linked list.
struct sllist * sllist_append(struct sllist *dst, struct sllist *src)
Appends the singly-linked list at src to the one at dst.
This header file is part of the event library; it contains the strand executor declarations.
void io_can_rt_submit_read_err(io_can_rt_t *rt, struct io_can_rt_read_err *read_err)
Submits a CAN error frame read operation to a CAN frame router.
struct io_can_rt_read_msg_result r
The result of the read operation.
void ev_strand_destroy(ev_exec_t *exec)
Destroys a strand executor.
struct slnode * sllist_remove(struct sllist *list, struct slnode *node)
Removes a node from a singly-linked list.
A mutex type that supports neither timeout nor test and return.
int mtx_unlock(mtx_t *mtx)
Unlocks the mutex at mtx.
void set_errc(int errc)
Sets the current (thread-specific) native error code to errc.
struct io_can_rt_read_msg * io_can_rt_read_msg_from_task(struct ev_task *task)
Obtains a pointer to a CAN frame read operation from a pointer to its completion task.
void sllist_push_back(struct sllist *list, struct slnode *node)
Pushes a node to the back of a singly-linked list.
This header file is part of the C11 and POSIX compatibility library; it includes <threads.h>, if it exists, and defines any missing functionality.
int mtx_lock(mtx_t *mtx)
Blocks until it locks the mutex at mtx.
const struct io_can_chan_vtbl *const io_can_chan_t
An abstract CAN channel.
void io_can_chan_submit_read(io_can_chan_t *chan, struct io_can_chan_read *read)
Submits a read operation to a CAN channel.
pthread_mutex_t mtx_t
A complete object type that holds an identifier for a mutex.
This header file is part of the utilities library; it contains the native and platform-independent er...
#define rbtree_foreach(tree, node)
Iterates over each node in a red-black tree in ascending order.
ev_exec_t * exec
A pointer to the executor to which the task is (to be) submitted.
const struct can_err * err
A pointer to the received CAN error frame, or NULL on error (or if the operation is canceled)...
static size_t io_can_chan_cancel_read(io_can_chan_t *chan, struct io_can_chan_read *read)
Cancels the specified CAN channel read operation if it is pending.
void io_can_rt_destroy(io_can_rt_t *rt)
Destroys a CAN frame router.
size_t io_can_rt_cancel_read_err(io_can_rt_t *rt, struct io_can_rt_read_err *read_err)
Cancels the specified CAN error frame read operation if it is pending.
size_t io_can_rt_abort_read_msg(io_can_rt_t *rt, struct io_can_rt_read_msg *read_msg)
Aborts the specified CAN frame read operation if it is pending.
static size_t io_can_chan_abort_read(io_can_chan_t *chan, struct io_can_chan_read *read)
Aborts the specified CAN channel read operation if it is pending.
void ev_exec_on_task_init(ev_exec_t *exec)
Indicates to the specified executor that a task will be submitted for execution in the future...
uint_least32_t id
The identifier of the CAN frame to be received.
This header file is part of the I/O library; it contains the CAN frame router declarations.
struct io_can_chan_read * io_can_chan_read_from_task(struct ev_task *task)
Obtains a pointer to a CAN channel read operation from a pointer to its completion task...
int get_errc(void)
Returns the last (thread-specific) native error code set by a system call or library function...
void ev_promise_set_release(ev_promise_t *promise, void *value)
Satisfies a promise prepared by ev_promise_set_acquire(), and stores the specified value for retrieva...
ev_future_t * ev_promise_get_future(ev_promise_t *promise)
Returns (a reference to) a future associated with the specified promise.
io_dev_t * io_can_rt_get_dev(const io_can_rt_t *rt)
Returns a pointer to the abstract I/O device representing the CAN frame router.
struct io_can_rt_read_err * io_can_rt_read_err_from_task(struct ev_task *task)
Obtains a pointer to a CAN error frame read operation from a pointer to its completion task...
io_can_rt_t * io_can_rt_create(io_can_chan_t *chan, ev_exec_t *exec)
Creates a new CAN frame router.
int result
The result of the read operation: 1 if a CAN frame is received, 0 if an error frame is received...
struct rbnode * rbtree_find(const struct rbtree *tree, const void *key)
Finds a node in a red-black tree.
io_dev_t * io_can_chan_get_dev(const io_can_chan_t *chan)
Returns a pointer to the abstract I/O device representing the CAN channel.
void rbtree_remove(struct rbtree *tree, struct rbnode *node)
Removes a node from a red-black tree.
struct ev_task task
The task (to be) submitted upon completion (or cancellation) of the read operation.
int errc
The error number, obtained as if by get_errc(), if result is -1.
size_t io_can_rt_cancel_read_msg(io_can_rt_t *rt, struct io_can_rt_read_msg *read_msg)
Cancels the specified CAN frame read operation if it is pending.
int errno2c(int errnum)
Transforms a standard C error number to a native error code.
const struct can_msg * msg
A pointer to the received CAN frame, or NULL on error (or if the operation is canceled).
void io_ctx_remove(io_ctx_t *ctx, struct io_svc *svc)
Unregisters an I/O service with an I/O context.
struct io_can_chan_read_result r
The result of the read operation.
io_ctx_t * io_dev_get_ctx(const io_dev_t *dev)
Returns a pointer to the I/O context with which the I/O device is registered.
uint_least8_t flags
The flags (any combination of CAN_FLAG_IDE, CAN_FLAG_RTR, CAN_FLAG_FDF, CAN_FLAG_BRS and CAN_FLAG_ESI...
ev_future_t * io_can_rt_async_shutdown(io_can_rt_t *rt)
Shuts down a CAN frame router, cancels all pending operations and creates a (void) future which becom...
struct io_can_rt_read_err_result r
The result of the read operation.
int sllist_empty(const struct sllist *list)
Returns 1 if the singly-linked list is empty, and 0 if not.
#define structof(ptr, type, member)
Obtains the address of a structure from the address of one of its members.
This header file is part of the event library; it contains the abstract task executor interface...
int ev_promise_set(ev_promise_t *promise, void *value)
Satiesfies a promise, if it was not aready satisfied, and stores the specified value for retrieval by...
struct can_msg * msg
The address at which to store the CAN frame.
The virtual table of an I/O service.
ev_exec_t * ev_strand_create(ev_exec_t *inner_exec)
Creates a strand executor.
A CAN frame read operation suitable for use with a CAN frame router.
struct ev_task * ev_task_from_node(struct slnode *node)
Converts a pointer to a node in a queue to the address of the task containing the node...
int ev_promise_set_acquire(ev_promise_t *promise)
Checks if the specified promise can be satisfied by the caller and, if so, prevents others from satis...
void rbtree_init(struct rbtree *tree, rbtree_cmp_t *cmp)
Initializes a red-black tree.
int errc
The error number, obtained as if by get_errc(), if msg is NULL.
void rbtree_insert(struct rbtree *tree, struct rbnode *node)
Inserts a node into a red-black tree.
A CAN error frame read operation suitable for use with a CAN frame router.
int errc
The error number, obtained as if by get_errc(), if err is NULL.
This header file is part of the C11 and POSIX compatibility library; it includes <stdlib.h> and defines any missing functionality.
void sllist_init(struct sllist *list)
Initializes a singly-linked list.
struct ev_task task
The task (to be) submitted upon completion (or cancellation) of the read operation.
struct ev_task task
The task (to be) submitted upon completion (or cancellation) of the write operation.
uint_least8_t flags
The flags of the CAN frame to be received (any combination of CAN_FLAG_IDE, CAN_FLAG_RTR, CAN_FLAG_FDF, CAN_FLAG_BRS and CAN_FLAG_ESI).
const struct io_dev_vtbl *const io_dev_t
An abstract I/O device.
void io_can_rt_submit_read_msg(io_can_rt_t *rt, struct io_can_rt_read_msg *read_msg)
Submits a CAN frame read operation to a CAN frame router.
This is the internal header file of the I/O library.
This is the public header file of the utilities library.
ev_future_t * io_can_rt_async_read_msg(io_can_rt_t *rt, uint_least32_t id, uint_least8_t flags, struct io_can_rt_read_msg **pread_msg)
Submits an asynchronous CAN frame read operation to a CAN frame router and creates a future which bec...
A node in a red-black tree.
int mtx_init(mtx_t *mtx, int type)
Creates a mutex object with properties indicated by type, which must have one of the four values: ...
int rbtree_empty(const struct rbtree *tree)
Returns 1 if the red-black tree is empty, and 0 if not.