mainloop.c (1781B)
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 11static int epfd = -1; 12static unsigned short nrhandler; 13static sig_atomic_t exit_mainloop; 14 15struct mainloop_data { 16 mainloop_callback_t cb; 17 void *data; 18 int fd; 19}; 20 21static struct mainloop_data **mds; 22 23#define MAX_EVENTS 10 24 25int 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 56int 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 90int 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 103int mainloop_init(void) 104{ 105 epfd = epoll_create(2); 106 if (epfd < 0) 107 return -1; 108 109 return 0; 110} 111 112void mainloop_exit(void) 113{ 114 exit_mainloop = 1; 115} 116 117void mainloop_fini(void) 118{ 119 close(epfd); 120}