1
0

epoll.c 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  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. SAFE_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. SAFE_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. ee.events = 0;
  39. ee.data.fd = fd;
  40. // pre events
  41. if (io->events & READ_EVENT) {
  42. ee.events |= EPOLLIN;
  43. }
  44. if (io->events & WRITE_EVENT) {
  45. ee.events |= EPOLLOUT;
  46. }
  47. // now events
  48. if (events & READ_EVENT) {
  49. ee.events |= EPOLLIN;
  50. }
  51. if (events & WRITE_EVENT) {
  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. ee.events = 0;
  70. ee.data.fd = fd;
  71. // pre events
  72. if (io->events & READ_EVENT) {
  73. ee.events |= EPOLLIN;
  74. }
  75. if (io->events & WRITE_EVENT) {
  76. ee.events |= EPOLLOUT;
  77. }
  78. // now events
  79. if (events & READ_EVENT) {
  80. ee.events &= ~EPOLLIN;
  81. }
  82. if (events & WRITE_EVENT) {
  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. perror("epoll");
  99. return nepoll;
  100. }
  101. if (nepoll == 0) return 0;
  102. int nevents = 0;
  103. for (int i = 0; i < epoll_ctx->events.size; ++i) {
  104. struct epoll_event* ee = epoll_ctx->events.ptr + i;
  105. int fd = ee->data.fd;
  106. uint32_t revents = ee->events;
  107. if (revents) {
  108. ++nevents;
  109. hio_t* io = loop->ios.ptr[fd];
  110. if (io) {
  111. if (revents & EPOLLIN) {
  112. io->revents |= READ_EVENT;
  113. }
  114. if (revents & EPOLLOUT) {
  115. io->revents |= WRITE_EVENT;
  116. }
  117. EVENT_PENDING(io);
  118. }
  119. }
  120. if (nevents == nepoll) break;
  121. }
  122. return nevents;
  123. }
  124. #endif