// SPDX-License-Identifier: LGPL-2.1+ // Copyright (C) 2022, Linaro Ltd - Daniel Lezcano #include #include #include #include #include #include "mainloop.h" #include "log.h" static int epfd = -1; static sig_atomic_t exit_mainloop; struct mainloop_data { mainloop_callback_t cb; void *data; int fd; }; #define MAX_EVENTS 10 int mainloop(unsigned int timeout) { int i, nfds; struct epoll_event events[MAX_EVENTS]; struct mainloop_data *md; if (epfd < 0) return -1; for (;;) { nfds = epoll_wait(epfd, events, MAX_EVENTS, timeout); if (exit_mainloop || !nfds) return 0; if (nfds < 0) { if (errno == EINTR) continue; return -1; } for (i = 0; i < nfds; i++) { md = events[i].data.ptr; if (md->cb(md->fd, md->data) > 0) return 0; } } } int mainloop_add(int fd, mainloop_callback_t cb, void *data) { struct epoll_event ev = { .events = EPOLLIN, }; struct mainloop_data *md; md = malloc(sizeof(*md)); if (!md) return -1; md->data = data; md->cb = cb; md->fd = fd; ev.data.ptr = md; if (epoll_ctl(epfd, EPOLL_CTL_ADD, fd, &ev) < 0) { free(md); return -1; } return 0; } int mainloop_del(int fd) { if (epoll_ctl(epfd, EPOLL_CTL_DEL, fd, NULL) < 0) return -1; return 0; } int mainloop_init(void) { epfd = epoll_create(2); if (epfd < 0) return -1; return 0; } void mainloop_exit(void) { exit_mainloop = 1; } void mainloop_fini(void) { close(epfd); }