epoll.c 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. #include "iowatcher.h"
  2. #ifdef EVENT_EPOLL
  3. #include "hplatform.h"
  4. #include "hdef.h"
  5. #include "hevent.h"
  6. #include <sys/epoll.h>
  7. #include "array.h"
  8. #define EVENTS_INIT_SIZE 64
  9. ARRAY_DECL(struct epoll_event, events);
  10. typedef struct epoll_ctx_s {
  11. int epfd;
  12. struct events events;
  13. } epoll_ctx_t;
  14. int iowatcher_init(hloop_t* loop) {
  15. if (loop->iowatcher) return 0;
  16. epoll_ctx_t* epoll_ctx;
  17. HV_ALLOC_SIZEOF(epoll_ctx);
  18. epoll_ctx->epfd = epoll_create(EVENTS_INIT_SIZE);
  19. events_init(&epoll_ctx->events, EVENTS_INIT_SIZE);
  20. loop->iowatcher = epoll_ctx;
  21. return 0;
  22. }
  23. int iowatcher_cleanup(hloop_t* loop) {
  24. if (loop->iowatcher == NULL) return 0;
  25. epoll_ctx_t* epoll_ctx = (epoll_ctx_t*)loop->iowatcher;
  26. close(epoll_ctx->epfd);
  27. events_cleanup(&epoll_ctx->events);
  28. HV_FREE(loop->iowatcher);
  29. return 0;
  30. }
  31. int iowatcher_add_event(hloop_t* loop, int fd, int events) {
  32. if (loop->iowatcher == NULL) {
  33. iowatcher_init(loop);
  34. }
  35. epoll_ctx_t* epoll_ctx = (epoll_ctx_t*)loop->iowatcher;
  36. hio_t* io = loop->ios.ptr[fd];
  37. struct epoll_event ee;
  38. memset(&ee, 0, sizeof(ee));
  39. ee.data.fd = fd;
  40. // pre events
  41. if (io->events & HV_READ) {
  42. ee.events |= EPOLLIN;
  43. }
  44. if (io->events & HV_WRITE) {
  45. ee.events |= EPOLLOUT;
  46. }
  47. // now events
  48. if (events & HV_READ) {
  49. ee.events |= EPOLLIN;
  50. }
  51. if (events & HV_WRITE) {
  52. ee.events |= EPOLLOUT;
  53. }
  54. int op = io->events == 0 ? EPOLL_CTL_ADD : EPOLL_CTL_MOD;
  55. epoll_ctl(epoll_ctx->epfd, op, fd, &ee);
  56. if (op == EPOLL_CTL_ADD) {
  57. if (epoll_ctx->events.size == epoll_ctx->events.maxsize) {
  58. events_double_resize(&epoll_ctx->events);
  59. }
  60. epoll_ctx->events.size++;
  61. }
  62. return 0;
  63. }
  64. int iowatcher_del_event(hloop_t* loop, int fd, int events) {
  65. epoll_ctx_t* epoll_ctx = (epoll_ctx_t*)loop->iowatcher;
  66. if (epoll_ctx == NULL) return 0;
  67. hio_t* io = loop->ios.ptr[fd];
  68. struct epoll_event ee;
  69. memset(&ee, 0, sizeof(ee));
  70. ee.data.fd = fd;
  71. // pre events
  72. if (io->events & HV_READ) {
  73. ee.events |= EPOLLIN;
  74. }
  75. if (io->events & HV_WRITE) {
  76. ee.events |= EPOLLOUT;
  77. }
  78. // now events
  79. if (events & HV_READ) {
  80. ee.events &= ~EPOLLIN;
  81. }
  82. if (events & HV_WRITE) {
  83. ee.events &= ~EPOLLOUT;
  84. }
  85. int op = ee.events == 0 ? EPOLL_CTL_DEL : EPOLL_CTL_MOD;
  86. epoll_ctl(epoll_ctx->epfd, op, fd, &ee);
  87. if (op == EPOLL_CTL_DEL) {
  88. epoll_ctx->events.size--;
  89. }
  90. return 0;
  91. }
  92. int iowatcher_poll_events(hloop_t* loop, int timeout) {
  93. epoll_ctx_t* epoll_ctx = (epoll_ctx_t*)loop->iowatcher;
  94. if (epoll_ctx == NULL) return 0;
  95. if (epoll_ctx->events.size == 0) return 0;
  96. int nepoll = epoll_wait(epoll_ctx->epfd, epoll_ctx->events.ptr, epoll_ctx->events.size, timeout);
  97. if (nepoll < 0) {
  98. if (errno == EINTR) {
  99. return 0;
  100. }
  101. perror("epoll");
  102. return nepoll;
  103. }
  104. if (nepoll == 0) return 0;
  105. int nevents = 0;
  106. for (int i = 0; i < epoll_ctx->events.size; ++i) {
  107. struct epoll_event* ee = epoll_ctx->events.ptr + i;
  108. int fd = ee->data.fd;
  109. uint32_t revents = ee->events;
  110. if (revents) {
  111. ++nevents;
  112. hio_t* io = loop->ios.ptr[fd];
  113. if (io) {
  114. if (revents & (EPOLLIN | EPOLLHUP | EPOLLERR)) {
  115. io->revents |= HV_READ;
  116. }
  117. if (revents & (EPOLLOUT | EPOLLHUP | EPOLLERR)) {
  118. io->revents |= HV_WRITE;
  119. }
  120. EVENT_PENDING(io);
  121. }
  122. }
  123. if (nevents == nepoll) break;
  124. }
  125. return nevents;
  126. }
  127. #endif