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 11 static int epfd = -1; 12 static unsigned short nrhandler; 13 static sig_atomic_t exit_mainloop; 14 15 struct mainloop_data { 16 mainloop_callback_t cb; 17 void *data; 18 int fd; 19 }; 20 21 static struct mainloop_data **mds; 22 23 #define MAX_EVENTS 10 24 25 int mainloop(unsigned int timeout) 26 { 27 int i, nfds; 28 struct epoll_event events[MAX_EVENTS]; 29 struct mainloop_data *md; 30 31 if (epfd < 0) 32 return -1; 33 34 for (;;) { 35 36 nfds = epoll_wait(epfd, events, MAX_EVENTS, timeout); 37 38 if (exit_mainloop || !nfds) 39 return 0; 40 41 if (nfds < 0) { 42 if (errno == EINTR) 43 continue; 44 return -1; 45 } 46 47 for (i = 0; i < nfds; i++) { 48 md = events[i].data.ptr; 49 50 if (md->cb(md->fd, md->data) > 0) 51 return 0; 52 } 53 } 54 } 55 56 int mainloop_add(int fd, mainloop_callback_t cb, void *data) 57 { 58 struct epoll_event ev = { 59 .events = EPOLLIN, 60 }; 61 62 struct mainloop_data *md; 63 64 if (fd >= nrhandler) { 65 mds = realloc(mds, sizeof(*mds) * (fd + 1)); 66 if (!mds) 67 return -1; 68 nrhandler = fd + 1; 69 } 70 71 md = malloc(sizeof(*md)); 72 if (!md) 73 return -1; 74 75 md->data = data; 76 md->cb = cb; 77 md->fd = fd; 78 79 mds[fd] = md; 80 ev.data.ptr = md; 81 82 if (epoll_ctl(epfd, EPOLL_CTL_ADD, fd, &ev) < 0) { 83 free(md); 84 return -1; 85 } 86 87 return 0; 88 } 89 90 int mainloop_del(int fd) 91 { 92 if (fd >= nrhandler) 93 return -1; 94 95 if (epoll_ctl(epfd, EPOLL_CTL_DEL, fd, NULL) < 0) 96 return -1; 97 98 free(mds[fd]); 99 100 return 0; 101 } 102 103 int mainloop_init(void) 104 { 105 epfd = epoll_create(2); 106 if (epfd < 0) 107 return -1; 108 109 return 0; 110 } 111 112 void mainloop_exit(void) 113 { 114 exit_mainloop = 1; 115 } 116 117 void mainloop_fini(void) 118 { 119 close(epfd); 120 } 121