uloop-kqueue.c 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209
  1. /*
  2. * uloop - event loop implementation
  3. *
  4. * Copyright (C) 2010-2016 Felix Fietkau <nbd@openwrt.org>
  5. *
  6. * Permission to use, copy, modify, and/or distribute this software for any
  7. * purpose with or without fee is hereby granted, provided that the above
  8. * copyright notice and this permission notice appear in all copies.
  9. *
  10. * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
  11. * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  12. * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
  13. * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  14. * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  15. * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  16. * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  17. */
  18. static int uloop_init_pollfd(void)
  19. {
  20. struct timespec timeout = { 0, 0 };
  21. struct kevent ev = {};
  22. if (poll_fd >= 0)
  23. return 0;
  24. poll_fd = kqueue();
  25. if (poll_fd < 0)
  26. return -1;
  27. EV_SET(&ev, SIGCHLD, EVFILT_SIGNAL, EV_ADD, 0, 0, 0);
  28. kevent(poll_fd, &ev, 1, NULL, 0, &timeout);
  29. return 0;
  30. }
  31. static uint16_t get_flags(unsigned int flags, unsigned int mask)
  32. {
  33. uint16_t kflags = 0;
  34. if (!(flags & mask))
  35. return EV_DELETE;
  36. kflags = EV_ADD;
  37. if (flags & ULOOP_EDGE_TRIGGER)
  38. kflags |= EV_CLEAR;
  39. return kflags;
  40. }
  41. static struct kevent events[ULOOP_MAX_EVENTS];
  42. static int register_kevent(struct uloop_fd *fd, unsigned int flags)
  43. {
  44. struct timespec timeout = { 0, 0 };
  45. struct kevent ev[2];
  46. int nev = 0;
  47. unsigned int fl = 0;
  48. unsigned int changed;
  49. uint16_t kflags;
  50. if (flags & ULOOP_EDGE_DEFER)
  51. flags &= ~ULOOP_EDGE_TRIGGER;
  52. changed = flags ^ fd->flags;
  53. if (changed & ULOOP_EDGE_TRIGGER)
  54. changed |= flags;
  55. if (!changed)
  56. return 0;
  57. if (changed & ULOOP_READ) {
  58. kflags = get_flags(flags, ULOOP_READ);
  59. EV_SET(&ev[nev++], fd->fd, EVFILT_READ, kflags, 0, 0, fd);
  60. }
  61. if (changed & ULOOP_WRITE) {
  62. kflags = get_flags(flags, ULOOP_WRITE);
  63. EV_SET(&ev[nev++], fd->fd, EVFILT_WRITE, kflags, 0, 0, fd);
  64. }
  65. if (!flags)
  66. fl |= EV_DELETE;
  67. if (kevent(poll_fd, ev, nev, NULL, fl, &timeout) == -1)
  68. return -1;
  69. return 0;
  70. }
  71. static int register_poll(struct uloop_fd *fd, unsigned int flags)
  72. {
  73. if (flags & ULOOP_EDGE_TRIGGER)
  74. flags |= ULOOP_EDGE_DEFER;
  75. else
  76. flags &= ~ULOOP_EDGE_DEFER;
  77. return register_kevent(fd, flags);
  78. }
  79. static int __uloop_fd_delete(struct uloop_fd *fd)
  80. {
  81. return register_poll(fd, 0);
  82. }
  83. static int64_t get_timestamp_us(void)
  84. {
  85. #ifdef CLOCK_MONOTONIC
  86. struct timespec ts = { 0, 0 };
  87. clock_gettime(CLOCK_MONOTONIC, &ts);
  88. return ts.tv_sec * 1000000 + ts.tv_nsec / 1000;
  89. #else
  90. struct timeval tv = { 0, 0 };
  91. gettimeofday(&tv, NULL);
  92. return tv.tv_sec * 1000000 + tv.tv_usec;
  93. #endif
  94. }
  95. static int uloop_fetch_events(int timeout)
  96. {
  97. struct timespec ts;
  98. int nfds, n;
  99. if (timeout >= 0) {
  100. ts.tv_sec = timeout / 1000;
  101. ts.tv_nsec = (timeout % 1000) * 1000000;
  102. }
  103. nfds = kevent(poll_fd, NULL, 0, events, ARRAY_SIZE(events), timeout >= 0 ? &ts : NULL);
  104. for (n = 0; n < nfds; n++) {
  105. if (events[n].filter == EVFILT_TIMER) {
  106. struct uloop_interval *tm = events[n].udata;
  107. tm->priv.time.fired = get_timestamp_us();
  108. tm->expirations += events[n].data;
  109. tm->cb(tm);
  110. continue;
  111. }
  112. struct uloop_fd_event *cur = &cur_fds[n];
  113. struct uloop_fd *u = events[n].udata;
  114. unsigned int ev = 0;
  115. cur->fd = u;
  116. if (!u)
  117. continue;
  118. if (events[n].flags & EV_ERROR) {
  119. u->error = true;
  120. if (!(u->flags & ULOOP_ERROR_CB))
  121. uloop_fd_delete(u);
  122. }
  123. if(events[n].filter == EVFILT_READ)
  124. ev |= ULOOP_READ;
  125. else if (events[n].filter == EVFILT_WRITE)
  126. ev |= ULOOP_WRITE;
  127. if (events[n].flags & EV_EOF)
  128. u->eof = true;
  129. else if (!ev)
  130. cur->fd = NULL;
  131. cur->events = ev;
  132. if (u->flags & ULOOP_EDGE_DEFER) {
  133. u->flags &= ~ULOOP_EDGE_DEFER;
  134. u->flags |= ULOOP_EDGE_TRIGGER;
  135. register_kevent(u, u->flags);
  136. }
  137. }
  138. return nfds;
  139. }
  140. static int timer_register(struct uloop_interval *tm, unsigned int msecs)
  141. {
  142. struct kevent ev;
  143. tm->priv.time.msecs = msecs;
  144. tm->priv.time.fired = get_timestamp_us();
  145. EV_SET(&ev, (uintptr_t)tm, EVFILT_TIMER, EV_ADD, NOTE_USECONDS, msecs * 1000, tm);
  146. return kevent(poll_fd, &ev, 1, NULL, 0, NULL);
  147. }
  148. static int timer_remove(struct uloop_interval *tm)
  149. {
  150. struct kevent ev;
  151. EV_SET(&ev, (uintptr_t)tm, EVFILT_TIMER, EV_DELETE, 0, 0, NULL);
  152. return kevent(poll_fd, &ev, 1, NULL, 0, NULL);
  153. }
  154. static int64_t timer_next(struct uloop_interval *tm)
  155. {
  156. int64_t t1 = tm->priv.time.fired;
  157. int64_t t2 = get_timestamp_us();
  158. while (t1 < t2)
  159. t1 += tm->priv.time.msecs * 1000;
  160. return (t1 - t2) / 1000;
  161. }