26 #if !LELY_NO_STDIO && defined(__linux__)
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);
136 impl->timer_vptr = NULL;
138 return &impl->timer_vptr;
142 io_timer_free(
void *ptr)
145 free(io_timer_impl_from_timer(ptr));
152 struct io_timer_impl *impl = io_timer_impl_from_timer(timer);
160 impl->dev_vptr = &io_timer_impl_dev_vtbl;
161 impl->timer_vptr = &io_timer_impl_vtbl;
170 impl->clockid = clockid;
173 &io_timer_impl_watch_func);
177 impl->
exec, &io_timer_impl_wait_task_func);
180 if ((errsv = pthread_mutex_init(&impl->mtx, NULL)))
185 impl->wait_posted = 0;
191 if (io_timer_impl_open(impl) == -1) {
203 pthread_mutex_destroy(&impl->mtx);
213 struct io_timer_impl *impl = io_timer_impl_from_timer(timer);
217 io_timer_impl_svc_shutdown(&impl->svc);
220 pthread_mutex_lock(&impl->mtx);
223 while (impl->wait_posted) {
227 pthread_mutex_unlock(&impl->mtx);
229 pthread_mutex_lock(&impl->mtx);
231 pthread_mutex_unlock(&impl->mtx);
235 io_timer_impl_close(impl);
238 pthread_mutex_destroy(&impl->mtx);
253 io_timer_t *tmp = io_timer_init(timer, poll, exec, clockid);
263 io_timer_free((
void *)timer);
273 io_timer_fini(timer);
274 io_timer_free((
void *)timer);
279 io_timer_impl_dev_get_ctx(
const io_dev_t *dev)
281 const struct io_timer_impl *impl = io_timer_impl_from_dev(dev);
287 io_timer_impl_dev_get_exec(
const io_dev_t *dev)
289 const struct io_timer_impl *impl = io_timer_impl_from_dev(dev);
302 io_timer_impl_pop(impl, &queue, task);
304 return io_timer_wait_queue_post(&queue, -1, ECANCELED);
315 io_timer_impl_pop(impl, &queue, task);
321 io_timer_impl_get_dev(
const io_timer_t *timer)
323 const struct io_timer_impl *impl = io_timer_impl_from_timer(timer);
325 return &impl->dev_vptr;
329 io_timer_impl_get_clock(
const io_timer_t *timer)
331 const struct io_timer_impl *impl = io_timer_impl_from_timer(timer);
332 assert(impl->clockid == CLOCK_REALTIME
333 || impl->clockid == CLOCK_MONOTONIC);
335 switch (impl->clockid) {
338 default:
return NULL;
343 io_timer_impl_getoverrun(
const io_timer_t *timer)
345 const struct io_timer_impl *impl = io_timer_impl_from_timer(timer);
348 pthread_mutex_lock((pthread_mutex_t *)&impl->mtx);
350 int overrun = impl->overrun;
352 pthread_mutex_unlock((pthread_mutex_t *)&impl->mtx);
359 io_timer_impl_gettime(
const io_timer_t *timer,
struct itimerspec *value)
361 const struct io_timer_impl *impl = io_timer_impl_from_timer(timer);
363 return timerfd_gettime(impl->tfd, value);
367 io_timer_impl_settime(
io_timer_t *timer,
int flags,
368 const struct itimerspec *value,
struct itimerspec *ovalue)
370 struct io_timer_impl *impl = io_timer_impl_from_timer(timer);
373 if (flags & TIMER_ABSTIME)
374 flags_ |= TFD_TIMER_ABSTIME;
376 return timerfd_settime(impl->tfd, flags_, value, ovalue);
382 struct io_timer_impl *impl = io_timer_impl_from_timer(timer);
387 task->
exec = impl->exec;
391 pthread_mutex_lock(&impl->mtx);
393 if (impl->shutdown) {
395 pthread_mutex_unlock(&impl->mtx);
397 io_timer_wait_post(wait, -1, ECANCELED);
401 pthread_mutex_unlock(&impl->mtx);
417 struct itimerspec value = { { 0, 0 }, { 0, 0 } };
418 if (timerfd_gettime(impl->tfd, &value) == -1) {
423 if (io_timer_impl_close(impl) == -1 && !result) {
428 if (io_timer_impl_open(impl) == -1 && !result) {
433 if (timerfd_settime(impl->tfd, 0, &value, NULL) == -1 && !result) {
443 io_timer_impl_svc_shutdown(
struct io_svc *svc)
449 pthread_mutex_lock(&impl->mtx);
451 int shutdown = !impl->shutdown;
461 impl->wait_posted = 0;
464 pthread_mutex_unlock(&impl->mtx);
469 io_timer_impl_dev_cancel(dev, NULL);
473 io_timer_impl_watch_func(
struct io_poll_watch *watch,
int events)
481 pthread_mutex_lock(&impl->mtx);
483 int post_wait = !impl->wait_posted && !impl->shutdown;
485 impl->wait_posted = 1;
487 pthread_mutex_unlock(&impl->mtx);
495 io_timer_impl_wait_task_func(
struct ev_task *task)
510 result = read(impl->tfd, &value,
sizeof(value));
511 }
while (result == -1 && errno == EINTR);
512 if (result !=
sizeof(value))
515 if (value > (uintmax_t)INT_MAX + 1)
516 value = (uintmax_t)INT_MAX + 1;
517 if (overrun > (
int)(INT_MAX - value))
522 if (result == -1 && (errno == EAGAIN || errno == EWOULDBLOCK)) {
531 pthread_mutex_lock(&impl->mtx);
534 impl->overrun = overrun;
535 if (overrun >= 0 || errno)
538 if (events && !impl->shutdown)
540 impl->wait_posted = 0;
542 pthread_mutex_unlock(&impl->mtx);
545 io_timer_wait_queue_post(&queue, overrun, errno);
550 io_timer_impl_from_dev(
const io_dev_t *dev)
558 io_timer_impl_from_timer(
const io_timer_t *timer)
566 io_timer_impl_from_svc(
const struct io_svc *svc)
581 pthread_mutex_lock(&impl->mtx);
588 pthread_mutex_unlock(&impl->mtx);
599 if (io_timer_impl_close(impl) == -1) {
604 impl->tfd = timerfd_create(impl->clockid, TFD_NONBLOCK | TFD_CLOEXEC);
605 if (impl->tfd == -1) {
607 goto error_timerfd_create;
613 goto error_poll_watch;
621 error_timerfd_create:
647 if (close(tfd) == -1 && !result) {
656 #endif // !LELY_NO_STDIO && __linux__