43 static size_t io_can_rt_dev_cancel(
io_dev_t *dev,
struct ev_task *task);
47 static const struct io_dev_vtbl io_can_rt_dev_vtbl = {
48 &io_can_rt_dev_get_ctx,
49 &io_can_rt_dev_get_exec,
50 &io_can_rt_dev_cancel,
55 static void io_can_rt_svc_shutdown(
struct io_svc *svc);
58 static const struct io_svc_vtbl io_can_rt_svc_vtbl = {
60 &io_can_rt_svc_shutdown
77 unsigned shutdown : 1;
78 unsigned submitted : 1;
83 static void io_can_rt_read_func(
struct ev_task *task);
84 static void io_can_rt_task_func(
struct ev_task *task);
97 const struct can_msg *msg,
int errc);
98 static size_t io_can_rt_read_msg_queue_post(
102 const struct can_err *err,
int errc);
103 static size_t io_can_rt_read_err_queue_post(
106 static int io_can_rt_read_msg_cmp(
const void *p1,
const void *p2);
114 static void io_can_rt_async_read_msg_func(
struct ev_task *task);
122 static void io_can_rt_async_read_err_func(
struct ev_task *task);
129 static void io_can_rt_async_shutdown_func(
struct ev_task *task);
132 io_can_rt_alloc(
void)
143 io_can_rt_free(
void *ptr)
163 rt->dev_vptr = &io_can_rt_dev_vtbl;
173 goto error_create_strand;
179 &rt->err, NULL, rt->exec, &io_can_rt_read_func);
193 rbtree_init(&rt->msg_queue, &io_can_rt_read_msg_cmp);
265 return &rt->dev_vptr;
283 task->
exec = rt->exec;
293 io_can_rt_read_msg_post(
296 task->_data = &rt->msg_queue;
307 int submit = !rt->submitted;
332 if (task->_data == &rt->msg_queue)
333 io_can_rt_do_pop_read_msg(rt, &queue, read_msg);
338 return io_can_rt_read_msg_queue_post(
355 if (task->_data == &rt->msg_queue)
356 io_can_rt_do_pop_read_msg(rt, &queue, read_msg);
376 async_read_msg->promise = promise;
377 async_read_msg->read_msg =
379 flags, &io_can_rt_async_read_msg_func);
385 *pread_msg = &async_read_msg->read_msg;
397 task->
exec = rt->exec;
407 io_can_rt_read_err_post(
410 task->_data = &rt->err_queue;
412 int submit = !rt->submitted;
437 if (task->_data == &rt->err_queue)
438 io_can_rt_do_pop_read_err(rt, &queue, read_err);
443 return io_can_rt_read_err_queue_post(
460 if (task->_data == &rt->err_queue)
461 io_can_rt_do_pop_read_err(rt, &queue, read_err);
480 async_read_err->promise = promise;
481 async_read_err->read_err =
483 &io_can_rt_async_read_err_func);
489 *pread_err = &async_read_err->read_err;
505 async_shutdown->promise = promise;
507 rt->
exec, &io_can_rt_async_shutdown_func);
509 io_can_rt_svc_shutdown(&rt->svc);
528 io_can_rt_dev_get_ctx(
const io_dev_t *dev)
536 io_can_rt_dev_get_exec(
const io_dev_t *dev)
548 struct sllist msg_queue, err_queue;
555 io_can_rt_do_pop(rt, &msg_queue, &err_queue, task);
559 size_t nmsg = io_can_rt_read_msg_queue_post(
561 size_t nerr = io_can_rt_read_err_queue_post(
563 return nerr < SIZE_MAX - nmsg ? nmsg + nerr : SIZE_MAX;
577 io_can_rt_do_pop(rt, &queue, &queue, task);
585 io_can_rt_svc_shutdown(
struct io_svc *svc)
593 int shutdown = !rt->shutdown;
596 if (shutdown && rt->submitted
605 io_can_rt_dev_cancel(dev, NULL);
609 io_can_rt_read_func(
struct ev_task *task)
635 io_can_rt_read_msg_queue_post(&queue, rt->read.
msg, 0);
636 }
else if (!rt->read.
r.
result) {
646 io_can_rt_read_err_queue_post(&queue, rt->read.
err, 0);
647 }
else if (rt->read.
r.
errc) {
648 struct sllist msg_queue, err_queue;
654 io_can_rt_do_pop(rt, &msg_queue, &err_queue, NULL);
658 io_can_rt_read_msg_queue_post(
659 &msg_queue, NULL, rt->read.
r.
errc);
660 io_can_rt_read_err_queue_post(
661 &err_queue, NULL, rt->read.
r.
errc);
668 io_can_rt_task_func(
struct ev_task *task)
676 assert(rt->submitted);
677 int submit = rt->submitted =
690 io_can_rt_from_dev(
const io_dev_t *dev)
698 io_can_rt_from_svc(
const struct io_svc *svc)
724 }
else if (
task->_data == &rt->msg_queue) {
725 io_can_rt_do_pop_read_msg(rt, msg_queue,
727 }
else if (
task->_data == &rt->err_queue) {
728 io_can_rt_do_pop_read_err(rt, err_queue,
741 assert(task->_data == &rt->msg_queue);
744 if (node == &read_msg->_node) {
747 struct sllist queue = read_msg->_queue;
755 }
else if (rt->submitted &&
rbtree_empty(&rt->msg_queue)
778 assert(task->_data == &rt->err_queue);
791 const struct can_msg *msg,
int errc)
793 read_msg->
r.
msg = msg;
794 read_msg->
r.
errc = errc;
802 io_can_rt_read_msg_queue_post(
812 io_can_rt_read_msg_post(read_msg, msg, errc);
821 const struct can_err *err,
int errc)
823 read_err->
r.
err = err;
824 read_err->
r.
errc = errc;
832 io_can_rt_read_err_queue_post(
842 io_can_rt_read_err_post(read_err, err, errc);
850 io_can_rt_read_msg_cmp(
const void *p1,
const void *p2)
857 int cmp = (r2->
id < r1->
id) - (r1->
id < r2->
id);
864 io_can_rt_async_read_msg_func(
struct ev_task *
task)
873 if (read_msg->
r.
msg) {
874 async_read_msg->msg = *read_msg->
r.
msg;
875 read_msg->
r.
msg = &async_read_msg->msg;
883 io_can_rt_async_read_err_func(
struct ev_task *task)
892 if (read_err->
r.
err) {
893 async_read_err->err = *read_err->
r.
err;
894 read_err->
r.
err = &async_read_err->err;
902 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.