40 static size_t io_can_rt_dev_cancel(
io_dev_t *dev,
struct ev_task *task);
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;
168 goto error_create_strand;
174 &rt->err, NULL, rt->exec, &io_can_rt_read_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);
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);
480 *pread_err = &async_read_err->read_err;
495 async_shutdown->promise = promise;
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)
#define CAN_MSG_INIT
The static initializer for can_msg.
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.
io_can_rt_t * io_can_rt_create(io_can_chan_t *chan, ev_exec_t *exec)
Creates a new CAN frame router.
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.
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.
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_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_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.
void io_can_rt_destroy(io_can_rt_t *rt)
Destroys a 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.
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...
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.
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.
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.
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.
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...
This header file is part of the I/O library; it contains the CAN frame router declarations.
#define IO_CAN_RT_READ_MSG_INIT(id, flags, func)
The static initializer for io_can_rt_read_msg.
#define IO_CAN_RT_READ_ERR_INIT(func)
The static initializer for io_can_rt_read_err.
This header file is part of the I/O library; it contains the I/O context and service declarations.
void io_ctx_insert(io_ctx_t *ctx, struct io_svc *svc)
Registers an I/O service with an I/O context.
#define IO_SVC_INIT(vptr)
The static initializer for io_svc.
void io_ctx_remove(io_ctx_t *ctx, struct io_svc *svc)
Unregisters an I/O service with an I/O context.
This header file is part of the utilities library; it contains the native and platform-independent er...
int errnum2c(errnum_t errnum)
Transforms a platform-independent error number to a native error code.
@ ERRNUM_CANCELED
Operation canceled.
int get_errc(void)
Returns the last (thread-specific) native error code set by a system call or library function.
void set_errc(int errc)
Sets the current (thread-specific) native error code to errc.
int errno2c(int errnum)
Transforms a standard C error number to a native error code.
This header file is part of the event library; it contains the abstract task executor interface.
void ev_exec_post(ev_exec_t *exec, struct ev_task *task)
Submits *task to *exec for execution.
void ev_exec_on_task_fini(ev_exec_t *exec)
Undoes the effect of a previous call to ev_exec_on_task_init().
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.
void ev_promise_release(ev_promise_t *promise)
Releases a reference to a promise.
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...
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.
ev_promise_t * ev_promise_create(size_t size, ev_promise_dtor_t *dtor)
Constructs a new promise with an optional empty shared state.
void * ev_promise_data(const ev_promise_t *promise)
Returns a pointer to the shared state of a promise.
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...
const struct ev_exec_vtbl *const ev_exec_t
An abstract task executor.
const struct io_can_chan_vtbl *const io_can_chan_t
An abstract CAN channel.
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.
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.
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.
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 io_can_chan_submit_read(io_can_chan_t *chan, struct io_can_chan_read *read)
Submits a read operation to a CAN channel.
#define IO_CAN_CHAN_READ_INIT(msg, err, tp, exec, func)
The static initializer for io_can_chan_read.
This is the public header file of the utilities library.
#define structof(ptr, type, member)
Obtains the address of a structure from the address of one of its members.
#define CAN_ERR_INIT
The static initializer for a can_err struct.
const struct io_dev_vtbl *const io_dev_t
An abstract I/O device.
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.
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.
void rbnode_init(struct rbnode *node, const void *key)
Initializes a node in a red-black tree.
void rbtree_insert(struct rbtree *tree, struct rbnode *node)
Inserts a node into a red-black tree.
void rbtree_init(struct rbtree *tree, rbtree_cmp_t *cmp)
Initializes a red-black tree.
void rbtree_remove(struct rbtree *tree, struct rbnode *node)
Removes a node from a red-black tree.
int rbtree_empty(const struct rbtree *tree)
Returns 1 if the red-black tree is empty, and 0 if not.
#define rbtree_foreach(tree, node)
Iterates over each node in a red-black tree in ascending order.
struct rbnode * rbtree_find(const struct rbtree *tree, const void *key)
Finds a node in a red-black tree.
void sllist_init(struct sllist *list)
Initializes 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.
struct slnode * sllist_remove(struct sllist *list, struct slnode *node)
Removes a node from a singly-linked list.
void sllist_push_back(struct sllist *list, struct slnode *node)
Pushes a node to the back of a singly-linked list.
int sllist_empty(const struct sllist *list)
Returns 1 if the singly-linked list is empty, and 0 if not.
struct slnode * sllist_pop_front(struct sllist *list)
Pops a node from the front of a singly-linked list.
This is the internal header file of the I/O library.
This header file is part of the C11 and POSIX compatibility library; it includes <stdlib....
This header file is part of the event library; it contains the strand executor declarations.
void ev_strand_destroy(ev_exec_t *exec)
Destroys a strand executor.
ev_exec_t * ev_strand_create(ev_exec_t *inner_exec)
Creates a strand executor.
A CAN or CAN FD format frame.
uint_least32_t id
The identifier (11 or 29 bits, depending on the CAN_FLAG_IDE flag).
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_exec_t * exec
A pointer to the executor to which the task is (to be) submitted.
int result
The result of the read operation: 1 if a CAN frame is received, 0 if an error frame is received,...
int errc
The error number, obtained as if by get_errc(), if result is -1.
A CAN channel read operation.
struct ev_task task
The task (to be) submitted upon completion (or cancellation) of the read operation.
struct io_can_chan_read_result r
The result of the read operation.
struct can_msg * msg
The address at which to store the CAN frame.
struct can_err * err
The address at which to store the CAN error frame.
const struct can_err * err
A pointer to the received CAN error frame, or NULL on error (or if the operation is canceled).
int errc
The error number, obtained as if by get_errc(), if err is NULL.
A CAN error frame read operation suitable for use with a CAN frame router.
struct io_can_rt_read_err_result r
The result of the read operation.
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 msg is NULL.
const struct can_msg * msg
A pointer to the received CAN frame, or NULL on error (or if the operation is canceled).
A CAN frame read operation suitable for use with a CAN frame router.
uint_least32_t id
The identifier of the CAN frame to be received.
struct io_can_rt_read_msg_result r
The result of the read operation.
struct ev_task task
The task (to be) submitted upon completion (or cancellation) of the read operation.
uint_least8_t flags
The flags of the CAN frame to be received (any combination of CAN_FLAG_IDE, CAN_FLAG_RTR,...
The virtual table of an I/O service.
A node in a red-black tree.
const void * key
A pointer to the key for this node.
A node in a singly-linked list.
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.
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.
#define EV_TASK_INIT(exec, func)
The static initializer for ev_task.
This header file is part of the C11 and POSIX compatibility library; it includes <threads....
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 mtx_lock(mtx_t *mtx)
Blocks until it locks the mutex at mtx.
@ thrd_success
Indicates that the requested operation succeeded.
int mtx_unlock(mtx_t *mtx)
Unlocks the mutex at mtx.
pthread_mutex_t mtx_t
A complete object type that holds an identifier for a mutex.
void mtx_destroy(mtx_t *mtx)
Releases any resources used by the mutex at mtx.
@ mtx_plain
A mutex type that supports neither timeout nor test and return.