46 #include <sys/timerfd.h>
50 static size_t io_timer_impl_dev_cancel(
io_dev_t *dev,
struct ev_task *task);
51 static size_t io_timer_impl_dev_abort(
io_dev_t *dev,
struct ev_task *task);
54 static const struct io_dev_vtbl io_timer_impl_dev_vtbl = {
55 &io_timer_impl_dev_get_ctx,
56 &io_timer_impl_dev_get_exec,
57 &io_timer_impl_dev_cancel,
58 &io_timer_impl_dev_abort
64 static int io_timer_impl_getoverrun(
const io_timer_t *timer);
65 static int io_timer_impl_gettime(
66 const io_timer_t *timer,
struct itimerspec *value);
67 static int io_timer_impl_settime(
io_timer_t *timer,
int flags,
68 const struct itimerspec *value,
struct itimerspec *ovalue);
69 static void io_timer_impl_submit_wait(
74 &io_timer_impl_get_dev,
75 &io_timer_impl_get_clock,
76 &io_timer_impl_getoverrun,
77 &io_timer_impl_gettime,
78 &io_timer_impl_settime,
79 &io_timer_impl_submit_wait
83 static int io_timer_impl_svc_notify_fork(
85 static void io_timer_impl_svc_shutdown(
struct io_svc *svc);
88 static const struct io_svc_vtbl io_timer_impl_svc_vtbl = {
89 &io_timer_impl_svc_notify_fork,
90 &io_timer_impl_svc_shutdown
108 unsigned shutdown : 1;
109 unsigned wait_posted : 1;
114 static void io_timer_impl_watch_func(
struct io_poll_watch *watch,
int events);
115 static void io_timer_impl_wait_task_func(
struct ev_task *task);
118 static inline struct io_timer_impl *io_timer_impl_from_timer(
121 const struct io_svc *svc);
134 return impl ? &impl->timer_vptr : NULL;
138 io_timer_free(
void *ptr)
141 free(io_timer_impl_from_timer(ptr));
148 struct io_timer_impl *impl = io_timer_impl_from_timer(timer);
156 impl->dev_vptr = &io_timer_impl_dev_vtbl;
157 impl->timer_vptr = &io_timer_impl_vtbl;
166 impl->clockid = clockid;
169 &io_timer_impl_watch_func);
173 impl->
exec, &io_timer_impl_wait_task_func);
176 if ((errsv = pthread_mutex_init(&impl->mtx, NULL)))
181 impl->wait_posted = 0;
187 if (io_timer_impl_open(impl) == -1) {
199 pthread_mutex_destroy(&impl->mtx);
209 struct io_timer_impl *impl = io_timer_impl_from_timer(timer);
213 io_timer_impl_svc_shutdown(&impl->svc);
216 pthread_mutex_lock(&impl->mtx);
219 while (impl->wait_posted) {
223 pthread_mutex_unlock(&impl->mtx);
225 pthread_mutex_lock(&impl->mtx);
227 pthread_mutex_unlock(&impl->mtx);
231 io_timer_impl_close(impl);
234 pthread_mutex_destroy(&impl->mtx);
249 io_timer_t *tmp = io_timer_init(timer, poll, exec, clockid);
259 io_timer_free((
void *)timer);
269 io_timer_fini(timer);
270 io_timer_free((
void *)timer);
275 io_timer_impl_dev_get_ctx(
const io_dev_t *dev)
277 const struct io_timer_impl *impl = io_timer_impl_from_dev(dev);
283 io_timer_impl_dev_get_exec(
const io_dev_t *dev)
285 const struct io_timer_impl *impl = io_timer_impl_from_dev(dev);
298 io_timer_impl_pop(impl, &queue, task);
300 return io_timer_wait_queue_post(&queue, -1, ECANCELED);
311 io_timer_impl_pop(impl, &queue, task);
317 io_timer_impl_get_dev(
const io_timer_t *timer)
319 const struct io_timer_impl *impl = io_timer_impl_from_timer(timer);
321 return &impl->dev_vptr;
325 io_timer_impl_get_clock(
const io_timer_t *timer)
327 const struct io_timer_impl *impl = io_timer_impl_from_timer(timer);
328 assert(impl->clockid == CLOCK_REALTIME
329 || impl->clockid == CLOCK_MONOTONIC);
331 switch (impl->clockid) {
334 default:
return NULL;
339 io_timer_impl_getoverrun(
const io_timer_t *timer)
341 const struct io_timer_impl *impl = io_timer_impl_from_timer(timer);
344 pthread_mutex_lock((pthread_mutex_t *)&impl->mtx);
346 int overrun = impl->overrun;
348 pthread_mutex_unlock((pthread_mutex_t *)&impl->mtx);
355 io_timer_impl_gettime(
const io_timer_t *timer,
struct itimerspec *value)
357 const struct io_timer_impl *impl = io_timer_impl_from_timer(timer);
359 return timerfd_gettime(impl->tfd, value);
363 io_timer_impl_settime(
io_timer_t *timer,
int flags,
364 const struct itimerspec *value,
struct itimerspec *ovalue)
366 struct io_timer_impl *impl = io_timer_impl_from_timer(timer);
369 if (flags & TIMER_ABSTIME)
370 flags_ |= TFD_TIMER_ABSTIME;
372 return timerfd_settime(impl->tfd, flags_, value, ovalue);
378 struct io_timer_impl *impl = io_timer_impl_from_timer(timer);
383 task->
exec = impl->exec;
387 pthread_mutex_lock(&impl->mtx);
389 if (impl->shutdown) {
391 pthread_mutex_unlock(&impl->mtx);
393 io_timer_wait_post(wait, -1, ECANCELED);
397 pthread_mutex_unlock(&impl->mtx);
413 struct itimerspec value = { { 0, 0 }, { 0, 0 } };
414 if (timerfd_gettime(impl->tfd, &value) == -1 && !result) {
419 if (io_timer_impl_close(impl) == -1 && !result) {
424 if (io_timer_impl_open(impl) == -1 && !result) {
429 if (timerfd_settime(impl->tfd, 0, &value, NULL) == -1 && !result) {
439 io_timer_impl_svc_shutdown(
struct io_svc *svc)
445 pthread_mutex_lock(&impl->mtx);
447 int shutdown = !impl->shutdown;
457 impl->wait_posted = 0;
460 pthread_mutex_unlock(&impl->mtx);
465 io_timer_impl_dev_cancel(dev, NULL);
469 io_timer_impl_watch_func(
struct io_poll_watch *watch,
int events)
477 pthread_mutex_lock(&impl->mtx);
479 int post_wait = !impl->wait_posted && !impl->shutdown;
481 impl->wait_posted = 1;
483 pthread_mutex_unlock(&impl->mtx);
490 io_timer_impl_wait_task_func(
struct ev_task *task)
505 result = read(impl->tfd, &value,
sizeof(value));
506 }
while (result == -1 && errno == EINTR);
507 if (result !=
sizeof(value))
510 if (value > (uintmax_t)INT_MAX + 1)
511 value = (uintmax_t)INT_MAX + 1;
512 if (overrun > (
int)(INT_MAX - value))
517 if (result == -1 && (errno == EAGAIN || errno == EWOULDBLOCK)) {
526 pthread_mutex_lock(&impl->mtx);
529 impl->overrun = overrun;
530 if (overrun >= 0 || errno)
533 if (events && !impl->shutdown)
535 impl->wait_posted = 0;
537 pthread_mutex_unlock(&impl->mtx);
540 io_timer_wait_queue_post(&queue, overrun, errno);
545 io_timer_impl_from_dev(
const io_dev_t *dev)
553 io_timer_impl_from_timer(
const io_timer_t *timer)
561 io_timer_impl_from_svc(
const struct io_svc *svc)
576 pthread_mutex_lock(&impl->mtx);
583 pthread_mutex_unlock(&impl->mtx);
594 if (io_timer_impl_close(impl) == -1) {
599 impl->tfd = timerfd_create(impl->clockid, TFD_NONBLOCK | TFD_CLOEXEC);
600 if (impl->tfd == -1) {
602 goto error_timerfd_create;
608 goto error_poll_watch;
616 error_timerfd_create:
642 if (close(tfd) == -1 && !result) {