mainloop.c 1.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. // SPDX-License-Identifier: LGPL-2.1+
  2. // Copyright (C) 2022, Linaro Ltd - Daniel Lezcano <daniel.lezcano@linaro.org>
  3. #include <stdlib.h>
  4. #include <errno.h>
  5. #include <unistd.h>
  6. #include <signal.h>
  7. #include <sys/epoll.h>
  8. #include "mainloop.h"
  9. #include "log.h"
  10. static int epfd = -1;
  11. static sig_atomic_t exit_mainloop;
  12. struct mainloop_data {
  13. mainloop_callback_t cb;
  14. void *data;
  15. int fd;
  16. };
  17. #define MAX_EVENTS 10
  18. int mainloop(unsigned int timeout)
  19. {
  20. int i, nfds;
  21. struct epoll_event events[MAX_EVENTS];
  22. struct mainloop_data *md;
  23. if (epfd < 0)
  24. return -1;
  25. for (;;) {
  26. nfds = epoll_wait(epfd, events, MAX_EVENTS, timeout);
  27. if (exit_mainloop || !nfds)
  28. return 0;
  29. if (nfds < 0) {
  30. if (errno == EINTR)
  31. continue;
  32. return -1;
  33. }
  34. for (i = 0; i < nfds; i++) {
  35. md = events[i].data.ptr;
  36. if (md->cb(md->fd, md->data) > 0)
  37. return 0;
  38. }
  39. }
  40. }
  41. int mainloop_add(int fd, mainloop_callback_t cb, void *data)
  42. {
  43. struct epoll_event ev = {
  44. .events = EPOLLIN,
  45. };
  46. struct mainloop_data *md;
  47. md = malloc(sizeof(*md));
  48. if (!md)
  49. return -1;
  50. md->data = data;
  51. md->cb = cb;
  52. md->fd = fd;
  53. ev.data.ptr = md;
  54. if (epoll_ctl(epfd, EPOLL_CTL_ADD, fd, &ev) < 0) {
  55. free(md);
  56. return -1;
  57. }
  58. return 0;
  59. }
  60. int mainloop_del(int fd)
  61. {
  62. if (epoll_ctl(epfd, EPOLL_CTL_DEL, fd, NULL) < 0)
  63. return -1;
  64. return 0;
  65. }
  66. int mainloop_init(void)
  67. {
  68. epfd = epoll_create(2);
  69. if (epfd < 0)
  70. return -1;
  71. return 0;
  72. }
  73. void mainloop_exit(void)
  74. {
  75. exit_mainloop = 1;
  76. }
  77. void mainloop_fini(void)
  78. {
  79. close(epfd);
  80. }