Permalink
Browse files

Add evloop, btpd's new event loop. This will replace libevent.

  • Loading branch information...
rmn64k committed Jan 9, 2009
1 parent 4457c12 commit 59905999ce145a81e0003766d468945c2444a90e
Showing with 722 additions and 0 deletions.
  1. +8 −0 evloop/Makefile.am
  2. +118 −0 evloop/epoll.c
  3. +57 −0 evloop/evloop.h
  4. +122 −0 evloop/kqueue.c
  5. +142 −0 evloop/poll.c
  6. +152 −0 evloop/timeheap.c
  7. +19 −0 evloop/timeheap.h
  8. +104 −0 evloop/timer.c
View
@@ -0,0 +1,8 @@
+noinst_LIBRARIES=libevloop.a
+EXTRA_libevloop_a_SOURCES=epoll.c poll.c
+libevloop_a_SOURCES=\
+ evloop.h\
+ timeheap.c timeheap.h timer.c
+CFLAGS=@CFLAGS@ -D@EVLOOP_METHOD@ -I$(top_srcdir)/misc
+libevloop_a_LIBADD=@EVLOOP_IMPL@
+libevloop_a_DEPENDENCIES=@EVLOOP_IMPL@
View
@@ -0,0 +1,118 @@
+#include <sys/epoll.h>
+#include <errno.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "evloop.h"
+
+static int m_epfd;
+
+static struct epoll_event m_evs[100];
+static uint8_t m_valid[100];
+
+int
+evloop_init(void)
+{
+ if (timeheap_init() != 0)
+ return -1;
+ m_epfd = epoll_create(getdtablesize());
+ return m_epfd >= 0 ? 0 : -1;
+}
+
+int
+fdev_new(struct fdev *ev, int fd, uint16_t flags, evloop_cb_t cb, void *arg)
+{
+ ev->fd = fd;
+ ev->cb = cb;
+ ev->arg = arg;
+ ev->flags = 0;
+ ev->index = -1;
+ return fdev_enable(ev, flags);
+}
+
+int
+fdev_enable(struct fdev *ev, uint16_t flags)
+{
+ struct epoll_event epev;
+ int err = 0;
+ uint16_t sf = ev->flags;
+ ev->flags |= flags;
+ if (sf != ev->flags) {
+ epev.data.ptr = ev;
+ epev.events =
+ ((ev->flags & EV_READ) ? EPOLLIN : 0) |
+ ((ev->flags & EV_WRITE) ? EPOLLOUT : 0);
+ if (sf == 0)
+ err = epoll_ctl(m_epfd, EPOLL_CTL_ADD, ev->fd, &epev);
+ else
+ err = epoll_ctl(m_epfd, EPOLL_CTL_MOD, ev->fd, &epev);
+ }
+ return err;
+}
+
+int
+fdev_disable(struct fdev *ev, uint16_t flags)
+{
+ struct epoll_event epev;
+ int err = 0;
+ uint16_t sf = ev->flags;
+ ev->flags &= ~flags;
+ if (sf != ev->flags) {
+ epev.data.ptr = ev;
+ epev.events =
+ ((ev->flags & EV_READ) ? EPOLLIN : 0) |
+ ((ev->flags & EV_WRITE) ? EPOLLOUT : 0);
+ if (ev->flags == 0)
+ err = epoll_ctl(m_epfd, EPOLL_CTL_DEL, ev->fd, &epev);
+ else
+ err = epoll_ctl(m_epfd, EPOLL_CTL_MOD, ev->fd, &epev);
+ }
+ return err;
+}
+
+int
+fdev_del(struct fdev *ev)
+{
+ if (ev->index >= 0)
+ m_valid[ev->index] = 0;
+ return fdev_disable(ev, EV_READ|EV_WRITE);
+}
+
+int
+evloop(void)
+{
+ int nev, i, millisecs;
+ struct timespec delay;
+ while (1) {
+ timers_run();
+ delay = timer_delay();
+ if (delay.tv_sec >= 0)
+ millisecs = delay.tv_sec * 1000 + delay.tv_nsec / 1000000;
+ else
+ millisecs = -1;
+
+ if ((nev = epoll_wait(m_epfd, m_evs, 100, millisecs)) < 0) {
+ if (errno == EINTR)
+ continue;
+ else
+ return -1;
+ }
+ memset(m_valid, 1, nev);
+ for (i = 0; i < nev; i++) {
+ struct fdev *ev = m_evs[i].data.ptr;
+ ev->index = i;
+ }
+ for (i = 0; i < nev; i++) {
+ struct fdev *ev = m_evs[i].data.ptr;
+ if ((m_valid[i] &&
+ ev->flags & EV_READ &&
+ m_evs[i].events & (EPOLLIN|EPOLLERR|EPOLLHUP)))
+ ev->cb(ev->fd, EV_READ, ev->arg);
+ if ((m_valid[i] && ev->flags & EV_WRITE &&
+ m_evs[i].events & (EPOLLOUT|EPOLLERR|EPOLLHUP)))
+ ev->cb(ev->fd, EV_WRITE, ev->arg);
+ if (m_valid[i])
+ ev->index = -1;
+ }
+ }
+}
View
@@ -0,0 +1,57 @@
+#ifndef BTPD_EVLOOP_H
+#define BTPD_EVLOOP_H
+
+#include <sys/time.h>
+#include <stdint.h>
+
+#include "timeheap.h"
+
+#define EV_READ 1
+#define EV_WRITE 2
+#define EV_TIMEOUT 3
+
+typedef void (*evloop_cb_t)(int fd, short type, void *arg);
+
+#if defined(EVLOOP_EPOLL) || defined(EVLOOP_KQUEUE)
+
+struct fdev {
+ evloop_cb_t cb;
+ void *arg;
+ int fd;
+ uint16_t flags;
+ int16_t index;
+};
+
+#elif defined(EVLOOP_POLL)
+
+struct fdev {
+ int i;
+};
+
+#else
+#error No evloop method defined.
+#endif
+
+struct timeout {
+ evloop_cb_t cb;
+ void *arg;
+ struct th_handle th;
+};
+
+int evloop_init(void);
+int evloop(void);
+
+int fdev_new(struct fdev *ev, int fd, uint16_t flags, evloop_cb_t cb,
+ void *arg);
+int fdev_del(struct fdev *ev);
+int fdev_enable(struct fdev *ev, uint16_t flags);
+int fdev_disable(struct fdev *ev, uint16_t flags);
+
+void timer_init(struct timeout *, evloop_cb_t, void *);
+int timer_add(struct timeout *, struct timespec *);
+void timer_del(struct timeout *);
+
+void timers_run(void);
+struct timespec timer_delay(void);
+
+#endif
View
@@ -0,0 +1,122 @@
+#include <sys/types.h>
+#include <sys/event.h>
+#include <sys/time.h>
+
+#include <errno.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "evloop.h"
+
+static int m_kq;
+
+static struct kevent m_evs[100];
+static uint8_t m_valid[100];
+
+int
+evloop_init(void)
+{
+ if (timeheap_init() != 0)
+ return -1;
+ m_kq = kqueue();
+ return m_kq >= 0 ? 0 : -1;
+}
+
+int
+fdev_new(struct fdev *ev, int fd, uint16_t flags, evloop_cb_t cb, void *arg)
+{
+ ev->fd = fd;
+ ev->cb = cb;
+ ev->arg = arg;
+ ev->flags = 0;
+ ev->index = -1;
+ return fdev_enable(ev, flags);
+}
+
+int
+fdev_enable(struct fdev *ev, uint16_t flags)
+{
+ struct kevent kev[2], *kp = NULL;
+ int count = 0;
+ uint16_t sf = ev->flags;
+ ev->flags |= flags;
+ if ((sf & EV_READ) == 0 && (flags & EV_READ) != 0) {
+ EV_SET(&kev[0], ev->fd, EVFILT_READ, EV_ADD, 0, 0, ev);
+ kp = kev;
+ count = 1;
+ }
+ if ((sf & EV_WRITE) == 0 && (flags & EV_WRITE) != 0) {
+ EV_SET(&kev[1], ev->fd, EVFILT_WRITE, EV_ADD, 0, 0, ev);
+ if (count == 0)
+ kp = &kev[1];
+ count++;
+ }
+ return count > 0 ? kevent(m_kq, kp, count, NULL, 0, NULL) : 0;
+}
+
+int
+fdev_disable(struct fdev *ev, uint16_t flags)
+{
+ struct kevent kev[2], *kp = NULL;
+ int count = 0;
+ uint16_t sf = ev->flags;
+ ev->flags &= ~flags;
+ if ((sf & EV_READ) != 0 && (flags & EV_READ) != 0) {
+ EV_SET(&kev[0], ev->fd, EVFILT_READ, EV_DELETE, 0, 0, ev);
+ kp = kev;
+ count = 1;
+ }
+ if ((sf & EV_WRITE) != 0 && (flags & EV_WRITE) != 0) {
+ EV_SET(&kev[1], ev->fd, EVFILT_WRITE, EV_DELETE, 0, 0, ev);
+ if (count == 0)
+ kp = &kev[1];
+ count++;
+ }
+ return count > 0 ? kevent(m_kq, kp, count, NULL, 0, NULL) : 0;
+}
+
+int
+fdev_del(struct fdev *ev)
+{
+ if (ev->index >= 0)
+ m_valid[ev->index] = 0;
+ return fdev_disable(ev, EV_READ|EV_WRITE);
+}
+
+int
+evloop(void)
+{
+ int nev, i;
+ struct timespec delay;
+ while (1) {
+ timers_run();
+ delay = timer_delay();
+
+ if ((nev = kevent(m_kq, NULL, 0, m_evs, 100, &delay)) < 0) {
+ if (errno == EINTR)
+ continue;
+ else
+ return -1;
+ }
+ memset(m_valid, 1, nev);
+ for (i = 0; i < nev; i++) {
+ struct fdev *ev = (struct fdev *)m_evs[i].udata;
+ ev->index = i;
+ }
+ for (i = 0; i < nev; i++) {
+ if (m_evs[i].flags & EV_ERROR) {
+ errno = m_evs[i].data;
+ return -1;
+ }
+ struct fdev *ev = (struct fdev *)m_evs[i].udata;
+ if (m_valid[i] && ev->flags & EV_READ &&
+ m_evs[i].filter == EVFILT_READ)
+ ev->cb(ev->fd, EV_READ, ev->arg);
+ if (m_valid[i] && ev->flags & EV_WRITE &&
+ m_evs[i].filter == EVFILT_WRITE)
+ ev->cb(ev->fd, EV_WRITE, ev->arg);
+ if (m_valid[i])
+ ev->index = -1;
+ }
+ }
+}
Oops, something went wrong.

0 comments on commit 5990599

Please sign in to comment.