42static size_t io_user_timer_dev_cancel(
io_dev_t *dev,
struct ev_task *task);
43static size_t io_user_timer_dev_abort(
io_dev_t *dev,
struct ev_task *task);
46static const struct io_dev_vtbl io_user_timer_dev_vtbl = {
47 &io_user_timer_dev_get_ctx,
48 &io_user_timer_dev_get_exec,
49 &io_user_timer_dev_cancel,
50 &io_user_timer_dev_abort
56static int io_user_timer_getoverrun(
const io_timer_t *timer);
57static int io_user_timer_gettime(
58 const io_timer_t *timer,
struct itimerspec *value);
59static int io_user_timer_settime(
io_timer_t *timer,
int flags,
60 const struct itimerspec *value,
struct itimerspec *ovalue);
61static void io_user_timer_submit_wait(
66 &io_user_timer_get_dev,
67 &io_user_timer_get_clock,
68 &io_user_timer_getoverrun,
69 &io_user_timer_gettime,
70 &io_user_timer_settime,
71 &io_user_timer_submit_wait
75static int io_user_timer_clock_getres(
76 const io_clock_t *clock,
struct timespec *res);
77static int io_user_timer_clock_gettime(
79static int io_user_timer_clock_settime(
84 &io_user_timer_clock_getres,
85 &io_user_timer_clock_gettime,
86 &io_user_timer_clock_settime
90static void io_user_timer_svc_shutdown(
struct io_svc *svc);
93static const struct io_svc_vtbl io_user_timer_svc_vtbl = {
95 &io_user_timer_svc_shutdown
114 struct timespec prev;
115 struct timespec next;
116 struct itimerspec value;
126 const struct io_svc *svc);
131static void io_user_timer_do_settime(
struct io_user_timer *user);
133static inline int timespec_valid(
const struct timespec *tp);
136io_user_timer_alloc(
void)
146 user->timer_vptr = NULL;
148 return &user->timer_vptr;
152io_user_timer_free(
void *ptr)
155 free(io_user_timer_from_timer(ptr));
162 struct io_user_timer *user = io_user_timer_from_timer(timer);
166 user->dev_vptr = &io_user_timer_dev_vtbl;
167 user->timer_vptr = &io_user_timer_vtbl;
168 user->clock_vptr = &io_user_timer_clock_vtbl;
187 user->now = (
struct timespec){ 0, 0 };
188 user->prev = (
struct timespec){ 0, 0 };
189 user->next = (
struct timespec){ 0, 0 };
190 user->value = (
struct itimerspec){ { 0, 0 }, { 0, 0 } };
201 struct io_user_timer *user = io_user_timer_from_timer(timer);
205 io_user_timer_svc_shutdown(&user->svc);
224 io_timer_t *tmp = io_user_timer_init(timer, ctx, exec, func, arg);
234 io_user_timer_free((
void *)timer);
244 io_user_timer_fini(timer);
245 io_user_timer_free((
void *)timer);
250io_user_timer_dev_get_ctx(
const io_dev_t *dev)
252 const struct io_user_timer *user = io_user_timer_from_dev(dev);
258io_user_timer_dev_get_exec(
const io_dev_t *dev)
260 const struct io_user_timer *user = io_user_timer_from_dev(dev);
273 io_user_timer_pop(user, &queue, task);
286 io_user_timer_pop(user, &queue, task);
294 const struct io_user_timer *user = io_user_timer_from_timer(timer);
296 return &user->dev_vptr;
300io_user_timer_get_clock(
const io_timer_t *timer)
302 const struct io_user_timer *user = io_user_timer_from_timer(timer);
304 return &user->clock_vptr;
308io_user_timer_getoverrun(
const io_timer_t *timer)
310 const struct io_user_timer *user = io_user_timer_from_timer(timer);
315 int overrun = user->overrun;
323io_user_timer_gettime(
const io_timer_t *timer,
struct itimerspec *value)
325 const struct io_user_timer *user = io_user_timer_from_timer(timer);
331 *value = user->value;
332 if (value->it_value.tv_sec || value->it_value.tv_nsec)
342io_user_timer_settime(
io_timer_t *timer,
int flags,
343 const struct itimerspec *value,
struct itimerspec *ovalue)
345 struct io_user_timer *user = io_user_timer_from_timer(timer);
348 struct timespec expiry = value->it_value;
349 if (!timespec_valid(&value->it_interval) || !timespec_valid(&expiry)) {
359 if ((expiry.tv_sec || expiry.tv_nsec) && !(flags & TIMER_ABSTIME))
363 *ovalue = user->value;
364 if (ovalue->it_value.tv_sec || ovalue->it_value.tv_nsec)
367 user->value = (
struct itimerspec){ value->it_interval, expiry };
370 io_user_timer_do_settime(user);
377 struct io_user_timer *user = io_user_timer_from_timer(timer);
382 task->
exec = user->exec;
388 if (user->shutdown) {
396 io_user_timer_do_settime(user);
401io_user_timer_clock_getres(
const io_clock_t *clock,
struct timespec *res)
403 const struct io_user_timer *user = io_user_timer_from_clock(clock);
419io_user_timer_clock_gettime(
const io_clock_t *clock,
struct timespec *tp)
421 const struct io_user_timer *user = io_user_timer_from_clock(clock);
436io_user_timer_clock_settime(
io_clock_t *clock,
const struct timespec *tp)
438 struct io_user_timer *user = io_user_timer_from_clock(clock);
446 user->prev = user->now;
449 io_user_timer_do_settime(user);
454io_user_timer_svc_shutdown(
struct io_svc *svc)
462 int shutdown = !user->shutdown;
470 io_user_timer_dev_cancel(dev, NULL);
474io_user_timer_from_dev(
const io_dev_t *dev)
482io_user_timer_from_timer(
const io_timer_t *timer)
490io_user_timer_from_clock(
const io_clock_t *clock)
498io_user_timer_from_svc(
const struct io_svc *svc)
532 struct timespec *expiry = &user->value.it_value;
533 assert(timespec_valid(expiry));
535 if ((expiry->tv_sec || expiry->tv_nsec)
537 const struct timespec *period = &user->value.it_interval;
538 assert(timespec_valid(period));
540 if (period->tv_sec || period->tv_nsec) {
547 *expiry = (
struct timespec){ 0, 0 };
554 struct timespec next = { 0, 0 };
558 next = user->next = *expiry;
563 int overrun = user->overrun;
572 io_timer_wait_queue_post(&queue, overrun, 0);
576timespec_valid(
const struct timespec *tp)
578 return tp->tv_sec >= 0 && tp->tv_nsec >= 0 && tp->tv_nsec < 1000000000l;
const struct io_clock_vtbl *const io_clock_t
An abstract clock.
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_INVAL
Invalid argument.
@ 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.
void set_errnum(errnum_t errnum)
Sets the current (thread-specific) platform-independent error number to errnum.
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.
const struct ev_exec_vtbl *const ev_exec_t
An abstract task executor.
const struct io_timer_vtbl *const io_timer_t
An abstract timer.
This header file is part of the I/O library; it contains the user-defined timer declarations.
void io_user_timer_setnext_t(const struct timespec *tp, void *arg)
The type of function invoked by a user-defined timer when the expiration time is updated with io_time...
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.
const struct io_dev_vtbl *const io_dev_t
An abstract I/O device.
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.
This header file is part of the C11 and POSIX compatibility library; it includes <stdlib....
ev_exec_t * exec
A pointer to the executor to which the task is (to be) submitted.
The virtual table of an I/O service.
A wait operation suitable for use with an I/O timer.
struct ev_task task
The task (to be) submitted upon completion (or cancellation) of the wait operation.
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.
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.
io_timer_t * io_user_timer_create(io_ctx_t *ctx, ev_exec_t *exec, io_user_timer_setnext_t *func, void *arg)
Creates a new user-defined timer.
void io_user_timer_destroy(io_timer_t *timer)
Destroys a user-defined timer.
This header file is part of the utilities library; it contains the time function declarations.
int timespec_cmp(const void *p1, const void *p2)
Compares two times.
void timespec_add(struct timespec *tp, const struct timespec *inc)
Adds the time interval *inc to the time at tp.
void timespec_sub(struct timespec *tp, const struct timespec *dec)
Subtracts the time interval *dec from the time at tp.