39 static size_t io_user_timer_dev_cancel(
io_dev_t *dev,
struct ev_task *task);
40 static size_t io_user_timer_dev_abort(
io_dev_t *dev,
struct ev_task *task);
43 static const struct io_dev_vtbl io_user_timer_dev_vtbl = {
44 &io_user_timer_dev_get_ctx,
45 &io_user_timer_dev_get_exec,
46 &io_user_timer_dev_cancel,
47 &io_user_timer_dev_abort
53 static int io_user_timer_getoverrun(
const io_timer_t *timer);
54 static int io_user_timer_gettime(
55 const io_timer_t *timer,
struct itimerspec *value);
56 static int io_user_timer_settime(
io_timer_t *timer,
int flags,
57 const struct itimerspec *value,
struct itimerspec *ovalue);
58 static void io_user_timer_submit_wait(
63 &io_user_timer_get_dev,
64 &io_user_timer_get_clock,
65 &io_user_timer_getoverrun,
66 &io_user_timer_gettime,
67 &io_user_timer_settime,
68 &io_user_timer_submit_wait
72 static int io_user_timer_clock_getres(
73 const io_clock_t *clock,
struct timespec *res);
74 static int io_user_timer_clock_gettime(
76 static int io_user_timer_clock_settime(
80 static const struct io_clock_vtbl io_user_timer_clock_vtbl = {
81 &io_user_timer_clock_getres,
82 &io_user_timer_clock_gettime,
83 &io_user_timer_clock_settime
87 static void io_user_timer_svc_shutdown(
struct io_svc *svc);
90 static const struct io_svc_vtbl io_user_timer_svc_vtbl = {
92 &io_user_timer_svc_shutdown
111 struct timespec prev;
112 struct timespec next;
113 struct itimerspec value;
118 static inline struct io_user_timer *io_user_timer_from_timer(
120 static inline struct io_user_timer *io_user_timer_from_clock(
123 const struct io_svc *svc);
128 static void io_user_timer_do_settime(
struct io_user_timer *user);
130 static inline int timespec_valid(
const struct timespec *tp);
133 io_user_timer_alloc(
void)
139 return user ? &user->timer_vptr : NULL;
143 io_user_timer_free(
void *ptr)
146 free(io_user_timer_from_timer(ptr));
153 struct io_user_timer *user = io_user_timer_from_timer(timer);
157 user->dev_vptr = &io_user_timer_dev_vtbl;
158 user->timer_vptr = &io_user_timer_vtbl;
159 user->clock_vptr = &io_user_timer_clock_vtbl;
161 user->svc = (
struct io_svc)IO_SVC_INIT(&io_user_timer_svc_vtbl);
178 user->now = (
struct timespec){ 0, 0 };
179 user->prev = (
struct timespec){ 0, 0 };
180 user->next = (
struct timespec){ 0, 0 };
181 user->value = (
struct itimerspec){ { 0, 0 }, { 0, 0 } };
192 struct io_user_timer *user = io_user_timer_from_timer(timer);
196 io_user_timer_svc_shutdown(&user->svc);
215 io_timer_t *tmp = io_user_timer_init(timer, ctx, exec, func, arg);
225 io_user_timer_free((
void *)timer);
235 io_user_timer_fini(timer);
236 io_user_timer_free((
void *)timer);
241 io_user_timer_dev_get_ctx(
const io_dev_t *dev)
243 const struct io_user_timer *user = io_user_timer_from_dev(dev);
249 io_user_timer_dev_get_exec(
const io_dev_t *dev)
251 const struct io_user_timer *user = io_user_timer_from_dev(dev);
264 io_user_timer_pop(user, &queue, task);
277 io_user_timer_pop(user, &queue, task);
283 io_user_timer_get_dev(
const io_timer_t *timer)
285 const struct io_user_timer *user = io_user_timer_from_timer(timer);
287 return &user->dev_vptr;
291 io_user_timer_get_clock(
const io_timer_t *timer)
293 const struct io_user_timer *user = io_user_timer_from_timer(timer);
295 return &user->clock_vptr;
299 io_user_timer_getoverrun(
const io_timer_t *timer)
301 const struct io_user_timer *user = io_user_timer_from_timer(timer);
306 int overrun = user->overrun;
314 io_user_timer_gettime(
const io_timer_t *timer,
struct itimerspec *value)
316 const struct io_user_timer *user = io_user_timer_from_timer(timer);
322 *value = user->value;
323 if (value->it_value.tv_sec || value->it_value.tv_nsec)
333 io_user_timer_settime(
io_timer_t *timer,
int flags,
334 const struct itimerspec *value,
struct itimerspec *ovalue)
336 struct io_user_timer *user = io_user_timer_from_timer(timer);
339 struct timespec expiry = value->it_value;
340 if (!timespec_valid(&value->it_interval) || !timespec_valid(&expiry)) {
350 if ((expiry.tv_sec || expiry.tv_nsec) && !(flags & TIMER_ABSTIME))
354 *ovalue = user->value;
355 if (ovalue->it_value.tv_sec || ovalue->it_value.tv_nsec)
358 user->value = (
struct itimerspec){ value->it_interval, expiry };
361 io_user_timer_do_settime(user);
368 struct io_user_timer *user = io_user_timer_from_timer(timer);
373 task->
exec = user->exec;
379 if (user->shutdown) {
387 io_user_timer_do_settime(user);
392 io_user_timer_clock_getres(
const io_clock_t *clock,
struct timespec *res)
394 const struct io_user_timer *user = io_user_timer_from_clock(clock);
410 io_user_timer_clock_gettime(
const io_clock_t *clock,
struct timespec *tp)
412 const struct io_user_timer *user = io_user_timer_from_clock(clock);
427 io_user_timer_clock_settime(
io_clock_t *clock,
const struct timespec *tp)
429 struct io_user_timer *user = io_user_timer_from_clock(clock);
437 user->prev = user->now;
440 io_user_timer_do_settime(user);
445 io_user_timer_svc_shutdown(
struct io_svc *svc)
453 int shutdown = !user->shutdown;
461 io_user_timer_dev_cancel(dev, NULL);
465 io_user_timer_from_dev(
const io_dev_t *dev)
473 io_user_timer_from_timer(
const io_timer_t *timer)
481 io_user_timer_from_clock(
const io_clock_t *clock)
489 io_user_timer_from_svc(
const struct io_svc *svc)
523 struct timespec *expiry = &user->value.it_value;
524 assert(timespec_valid(expiry));
526 if ((expiry->tv_sec || expiry->tv_nsec)
528 const struct timespec *period = &user->value.it_interval;
529 assert(timespec_valid(period));
531 if (period->tv_sec || period->tv_nsec) {
538 *expiry = (
struct timespec){ 0, 0 };
545 struct timespec next = { 0, 0 };
549 next = user->next = *expiry;
554 int overrun = user->overrun;
563 io_timer_wait_queue_post(&queue, overrun, 0);
567 timespec_valid(
const struct timespec *tp)
569 return tp->tv_sec >= 0 && tp->tv_nsec >= 0 && tp->tv_nsec < 1000000000l;
const struct ev_exec_vtbl *const ev_exec_t
An abstract task executor.
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.
void set_errnum(errnum_t errnum)
Sets the current (thread-specific) platform-independent error number to errnum.
Indicates that the requested operation succeeded.
void io_ctx_insert(io_ctx_t *ctx, struct io_svc *svc)
Registers an I/O service with an I/O context.
struct sllist * sllist_append(struct sllist *dst, struct sllist *src)
Appends the singly-linked list at src to the one at dst.
const struct io_clock_vtbl *const io_clock_t
An abstract clock.
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.
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.
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...
This header file is part of the I/O library; it contains the user-defined timer declarations.
ev_exec_t * exec
A pointer to the executor to which the task is (to be) submitted.
This header file is part of the utilities library; it contains the time function declarations.
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...
int get_errc(void)
Returns the last (thread-specific) native error code set by a system call or library function...
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 timespec_add(struct timespec *tp, const struct timespec *inc)
Adds the time interval *inc to the time at tp.
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...
void io_user_timer_destroy(io_timer_t *timer)
Destroys a user-defined timer.
int errno2c(int errnum)
Transforms a standard C error number to a native error code.
int timespec_cmp(const void *p1, const void *p2)
Compares two times.
void io_ctx_remove(io_ctx_t *ctx, struct io_svc *svc)
Unregisters an I/O service with an I/O context.
struct ev_task task
The task (to be) submitted upon completion (or cancellation) of the wait operation.
#define structof(ptr, type, member)
Obtains the address of a structure from the address of one of its members.
The virtual table of an I/O service.
A wait operation suitable for use with an I/O timer.
const struct io_timer_vtbl *const io_timer_t
An abstract timer.
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.
const struct io_dev_vtbl *const io_dev_t
An abstract I/O device.
This is the public header file of the utilities library.
void timespec_sub(struct timespec *tp, const struct timespec *dec)
Subtracts the time interval *dec from the time at tp.
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: ...