42 static size_t io_user_timer_dev_cancel(
io_dev_t *dev,
struct ev_task *task);
43 static size_t io_user_timer_dev_abort(
io_dev_t *dev,
struct ev_task *task);
46 static 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
56 static int io_user_timer_getoverrun(
const io_timer_t *timer);
57 static int io_user_timer_gettime(
58 const io_timer_t *timer,
struct itimerspec *value);
59 static int io_user_timer_settime(
io_timer_t *timer,
int flags,
60 const struct itimerspec *value,
struct itimerspec *ovalue);
61 static 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
75 static int io_user_timer_clock_getres(
76 const io_clock_t *clock,
struct timespec *res);
77 static int io_user_timer_clock_gettime(
79 static int io_user_timer_clock_settime(
83 static const struct io_clock_vtbl io_user_timer_clock_vtbl = {
84 &io_user_timer_clock_getres,
85 &io_user_timer_clock_gettime,
86 &io_user_timer_clock_settime
90 static void io_user_timer_svc_shutdown(
struct io_svc *svc);
93 static 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;
121 static inline struct io_user_timer *io_user_timer_from_timer(
123 static inline struct io_user_timer *io_user_timer_from_clock(
126 const struct io_svc *svc);
131 static void io_user_timer_do_settime(
struct io_user_timer *user);
133 static inline int timespec_valid(
const struct timespec *tp);
136 io_user_timer_alloc(
void)
146 user->timer_vptr = NULL;
148 return &user->timer_vptr;
152 io_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);
250 io_user_timer_dev_get_ctx(
const io_dev_t *dev)
252 const struct io_user_timer *user = io_user_timer_from_dev(dev);
258 io_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);
292 io_user_timer_get_dev(
const io_timer_t *timer)
294 const struct io_user_timer *user = io_user_timer_from_timer(timer);
296 return &user->dev_vptr;
300 io_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;
308 io_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;
323 io_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)
342 io_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);
401 io_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);
419 io_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);
436 io_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);
454 io_user_timer_svc_shutdown(
struct io_svc *svc)
462 int shutdown = !user->shutdown;
470 io_user_timer_dev_cancel(dev, NULL);
474 io_user_timer_from_dev(
const io_dev_t *dev)
482 io_user_timer_from_timer(
const io_timer_t *timer)
490 io_user_timer_from_clock(
const io_clock_t *clock)
498 io_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);
576 timespec_valid(
const struct timespec *tp)
578 return tp->tv_sec >= 0 && tp->tv_nsec >= 0 && tp->tv_nsec < 1000000000l;
581 #endif // !LELY_NO_MALLOC