/* * Power debug tool (powerdebug) * * Copyright (C) 2016, Linaro Limited. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * */ #include #include #include #include #include #include "mainloop.h" static int epfd = -1; static unsigned short nrhandler; struct mainloop_data { mainloop_callback_t cb; void *data; int fd; }; struct mainloop_data **mds; #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 (nfds < 0) { if (errno == EINTR) continue; return -1; } /* * A timeout occured. Let's send to ourself a SIGWINCH * so the window get refreshed automatically. No need * to use exported functions and this code stay self * contained. */ if (!nfds) { kill(getpid(), SIGWINCH); continue; } 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; if (fd >= nrhandler) { mds = realloc(mds, sizeof(*mds) * (fd + 1)); if (!mds) return -1; nrhandler = fd + 1; } md = malloc(sizeof(*md)); if (!md) return -1; md->data = data; md->cb = cb; md->fd = fd; mds[fd] = md; 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 (fd >= nrhandler) return -1; if (epoll_ctl(epfd, EPOLL_CTL_DEL, fd, NULL) < 0) return -1; free(mds[fd]); return 0; } int mainloop_init(void) { epfd = epoll_create(2); if (epfd < 0) return -1; return 0; } void mainloop_fini(void) { close(epfd); }