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;
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;