0001
0002
0003 #include <stdlib.h>
0004 #include <errno.h>
0005 #include <unistd.h>
0006 #include <signal.h>
0007 #include <sys/epoll.h>
0008 #include "mainloop.h"
0009 #include "log.h"
0010
0011 static int epfd = -1;
0012 static unsigned short nrhandler;
0013 static sig_atomic_t exit_mainloop;
0014
0015 struct mainloop_data {
0016 mainloop_callback_t cb;
0017 void *data;
0018 int fd;
0019 };
0020
0021 static struct mainloop_data **mds;
0022
0023 #define MAX_EVENTS 10
0024
0025 int mainloop(unsigned int timeout)
0026 {
0027 int i, nfds;
0028 struct epoll_event events[MAX_EVENTS];
0029 struct mainloop_data *md;
0030
0031 if (epfd < 0)
0032 return -1;
0033
0034 for (;;) {
0035
0036 nfds = epoll_wait(epfd, events, MAX_EVENTS, timeout);
0037
0038 if (exit_mainloop || !nfds)
0039 return 0;
0040
0041 if (nfds < 0) {
0042 if (errno == EINTR)
0043 continue;
0044 return -1;
0045 }
0046
0047 for (i = 0; i < nfds; i++) {
0048 md = events[i].data.ptr;
0049
0050 if (md->cb(md->fd, md->data) > 0)
0051 return 0;
0052 }
0053 }
0054 }
0055
0056 int mainloop_add(int fd, mainloop_callback_t cb, void *data)
0057 {
0058 struct epoll_event ev = {
0059 .events = EPOLLIN,
0060 };
0061
0062 struct mainloop_data *md;
0063
0064 if (fd >= nrhandler) {
0065 mds = realloc(mds, sizeof(*mds) * (fd + 1));
0066 if (!mds)
0067 return -1;
0068 nrhandler = fd + 1;
0069 }
0070
0071 md = malloc(sizeof(*md));
0072 if (!md)
0073 return -1;
0074
0075 md->data = data;
0076 md->cb = cb;
0077 md->fd = fd;
0078
0079 mds[fd] = md;
0080 ev.data.ptr = md;
0081
0082 if (epoll_ctl(epfd, EPOLL_CTL_ADD, fd, &ev) < 0) {
0083 free(md);
0084 return -1;
0085 }
0086
0087 return 0;
0088 }
0089
0090 int mainloop_del(int fd)
0091 {
0092 if (fd >= nrhandler)
0093 return -1;
0094
0095 if (epoll_ctl(epfd, EPOLL_CTL_DEL, fd, NULL) < 0)
0096 return -1;
0097
0098 free(mds[fd]);
0099
0100 return 0;
0101 }
0102
0103 int mainloop_init(void)
0104 {
0105 epfd = epoll_create(2);
0106 if (epfd < 0)
0107 return -1;
0108
0109 return 0;
0110 }
0111
0112 void mainloop_exit(void)
0113 {
0114 exit_mainloop = 1;
0115 }
0116
0117 void mainloop_fini(void)
0118 {
0119 close(epfd);
0120 }