From 1a78ce8ea6d719c56a8bc2ea2e75ad5a95012617 Mon Sep 17 00:00:00 2001 From: Ron Date: Tue, 13 Jun 2017 17:50:51 +0800 Subject: [PATCH] epoll optimization, add ff_kevent_do_each --- example/Makefile | 1 + lib/Makefile | 4 +- lib/ff_api.h | 3 + lib/ff_api.symlist | 7 +-- lib/ff_epoll.c | 124 ++++++++++++++++----------------------- lib/ff_epoll.h | 68 +-------------------- lib/ff_syscall_wrapper.c | 35 +++++++++-- 7 files changed, 90 insertions(+), 152 deletions(-) diff --git a/example/Makefile b/example/Makefile index 8f399eb0..e97f3a72 100644 --- a/example/Makefile +++ b/example/Makefile @@ -17,6 +17,7 @@ LIBS+= -Wl,--no-whole-archive -lrt -lm -ldl -lcrypto -pthread TARGET="helloworld" all: cc -O -gdwarf-2 -I../lib -o ${TARGET} main.c ${LIBS} + cc -O -gdwarf-2 -I../lib -o ${TARGET}_epoll main_epoll.c ${LIBS} .PHONY: clean clean: diff --git a/lib/Makefile b/lib/Makefile index 8a00e4e7..bb42fe78 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -128,8 +128,7 @@ FF_SRCS+= \ ff_syscall_wrapper.c \ ff_subr_prf.c \ ff_vfs_ops.c \ - ff_veth.c \ - ff_epoll.c + ff_veth.c FF_HOST_SRCS+= \ ff_host_interface.c \ @@ -138,6 +137,7 @@ FF_HOST_SRCS+= \ ff_dpdk_if.c \ ff_dpdk_kni.c \ ff_dpdk_pcap.c \ + ff_epoll.c \ ff_init.c ifdef FF_IPSEC diff --git a/lib/ff_api.h b/lib/ff_api.h index 760b161a..5fc94168 100644 --- a/lib/ff_api.h +++ b/lib/ff_api.h @@ -101,6 +101,9 @@ int ff_poll(struct pollfd fds[], nfds_t nfds, int timeout); int ff_kqueue(void); int ff_kevent(int kq, const struct kevent *changelist, int nchanges, struct kevent *eventlist, int nevents, const struct timespec *timeout); +int ff_kevent_do_each(int kq, const struct kevent *changelist, int nchanges, + void *eventlist, int nevents, const struct timespec *timeout, + void (*do_each)(void **, struct kevent *)); #ifdef __cplusplus } diff --git a/lib/ff_api.symlist b/lib/ff_api.symlist index 9545a677..25c6095d 100644 --- a/lib/ff_api.symlist +++ b/lib/ff_api.symlist @@ -29,10 +29,7 @@ ff_shutdown ff_sysctl ff_kqueue ff_kevent -ff_epoll_create -ff_epoll_ctl -ff_epoll_wait -ff_epoll_close +ff_kevent_do_each ff_veth_attach ff_veth_detach ff_veth_process_packet @@ -40,4 +37,4 @@ ff_mbuf_gethdr ff_mbuf_get ff_mbuf_free ff_mbuf_copydata -ff_mbuf_tx_offload \ No newline at end of file +ff_mbuf_tx_offload diff --git a/lib/ff_epoll.c b/lib/ff_epoll.c index 39222d74..81d457e8 100644 --- a/lib/ff_epoll.c +++ b/lib/ff_epoll.c @@ -1,34 +1,24 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include -#include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include +#include #include "ff_api.h" -#include "ff_epoll.h" #include "ff_errno.h" -#include "ff_host_interface.h" - int @@ -37,16 +27,16 @@ ff_epoll_create(int size __attribute__((__unused__))) return ff_kqueue(); } - int ff_epoll_ctl(int epfd, int op, int fd, struct epoll_event *event) { + struct kevent kev[3]; + if (!event && op != EPOLL_CTL_DEL) { - ff_os_errno(ff_EINVAL); + errno = EINVAL; return -1; } - struct kevent kev[3]; if (op == EPOLL_CTL_ADD){ EV_SET(&kev[0], fd, EVFILT_READ, EV_ADD | (event->events & EPOLLIN ? 0 : EV_DISABLE), 0, 0, NULL); @@ -66,62 +56,48 @@ ff_epoll_ctl(int epfd, int op, int fd, struct epoll_event *event) EV_SET(&kev[2], fd, EVFILT_USER, 0, NOTE_FFCOPY | (event->events & EPOLLRDHUP ? 1 : 0), 0, NULL); } else { - ff_os_errno(ff_EINVAL); + errno = EINVAL; return -1; } return ff_kevent(epfd, kev, 3, NULL, 0, NULL); } +static void +ff_event_to_epoll(void **ev, struct kevent *kev) +{ + unsigned int event_one = 0; + struct epoll_event **ppev = (struct epoll_event **)ev; + + if (kev->filter & EVFILT_READ) { + event_one |= EPOLLIN; + } + if (kev->filter & EVFILT_WRITE) { + event_one |= EPOLLOUT; + } + + if (kev->flags & EV_ERROR) { + event_one |= EPOLLERR; + } + + if (kev->flags & EV_EOF) { + event_one |= EPOLLIN; + } + + (*ppev)->events = event_one; + (*ppev)->data.fd = kev->ident; + (*ppev)++; +} + int ff_epoll_wait(int epfd, struct epoll_event *events, int maxevents, int timeout) { + int i, ret; if (!events || maxevents < 1) { - ff_os_errno(ff_EINVAL); + errno = EINVAL; return -1; } - - struct kevent *evlist = malloc(sizeof(struct kevent)*maxevents, M_DEVBUF, M_ZERO|M_NOWAIT); - if(NULL == evlist){ - ff_os_errno(ff_EINVAL); - return -1; - } - memset(evlist, 0, sizeof(struct kevent)*maxevents); - - int ret = ff_kevent(epfd, NULL, 0, evlist, maxevents, NULL); - if (ret == -1) { - free(evlist, M_DEVBUF); - return ret; - } - unsigned int event_one = 0; - for (int i = 0; i < ret; ++i) { - event_one = 0; - if (evlist[i].filter & EVFILT_READ) { - event_one |= EPOLLIN; - } - if (evlist[i].filter & EVFILT_WRITE) { - event_one |= EPOLLOUT; - } - - if (evlist[i].flags & EV_ERROR) { - event_one |= EPOLLERR; - } - - if (evlist[i].flags & EV_EOF) { - event_one |= EPOLLIN; - } - events[i].events = event_one; - events[i].data.fd = evlist[i].ident; - } - - free(evlist, M_DEVBUF); - return ret; -} - -int -ff_epoll_close(int epfd) -{ - return ff_close(epfd); + return ff_kevent_do_each(epfd, NULL, 0, events, maxevents, NULL, ff_event_to_epoll); } diff --git a/lib/ff_epoll.h b/lib/ff_epoll.h index 973251af..b43ef064 100644 --- a/lib/ff_epoll.h +++ b/lib/ff_epoll.h @@ -1,73 +1,11 @@ #ifndef _FF_EPOLL_H #define _FF_EPOLL_H -//#include -//#include +#include -#ifndef _KERNEL -#include -#else -#include -#include -#endif - -enum EPOLL_EVENTS - { - EPOLLIN = 0x001, -#define EPOLLIN EPOLLIN - EPOLLPRI = 0x002, -#define EPOLLPRI EPOLLPRI - EPOLLOUT = 0x004, -#define EPOLLOUT EPOLLOUT - EPOLLRDNORM = 0x040, -#define EPOLLRDNORM EPOLLRDNORM - EPOLLRDBAND = 0x080, -#define EPOLLRDBAND EPOLLRDBAND - EPOLLWRNORM = 0x100, -#define EPOLLWRNORM EPOLLWRNORM - EPOLLWRBAND = 0x200, -#define EPOLLWRBAND EPOLLWRBAND - EPOLLMSG = 0x400, -#define EPOLLMSG EPOLLMSG - EPOLLERR = 0x008, -#define EPOLLERR EPOLLERR - EPOLLHUP = 0x010, -#define EPOLLHUP EPOLLHUP - EPOLLRDHUP = 0x2000, -#define EPOLLRDHUP EPOLLRDHUP - EPOLLWAKEUP = 1u << 29, -#define EPOLLWAKEUP EPOLLWAKEUP - EPOLLONESHOT = 1u << 30, -#define EPOLLONESHOT EPOLLONESHOT - EPOLLET = 1u << 31 -#define EPOLLET EPOLLET - }; - - -/* Valid opcodes ( "op" parameter ) to issue to epoll_ctl(). */ -#define EPOLL_CTL_ADD 1 /* Add a file descriptor to the interface. */ -#define EPOLL_CTL_DEL 2 /* Remove a file descriptor from the interface. */ -#define EPOLL_CTL_MOD 3 /* Change file descriptor epoll_event structure. */ - - -typedef union epoll_data -{ - void *ptr; - int fd; - uint32_t u32; - uint64_t u64; -} epoll_data_t; - -struct epoll_event -{ - uint32_t events; /* Epoll events */ - epoll_data_t data; /* User data variable */ -}; - -/*warpper epoll api.*/ int ff_epoll_create(int size); int ff_epoll_ctl(int epfd, int op, int fd, struct epoll_event *event); -int ff_epoll_wait(int epfd, struct epoll_event *events, int maxevents, int timeout); -int ff_epoll_close(int epfd); +int ff_epoll_wait(int epfd, struct epoll_event *events, int maxevents, int timeout); #endif + diff --git a/lib/ff_syscall_wrapper.c b/lib/ff_syscall_wrapper.c index da3f4d3e..3d25796d 100644 --- a/lib/ff_syscall_wrapper.c +++ b/lib/ff_syscall_wrapper.c @@ -936,20 +936,31 @@ struct sys_kevent_args { int fd; const struct kevent *changelist; int nchanges; - struct kevent *eventlist; + void *eventlist; int nevents; const struct timespec *timeout; + void (*do_each)(void **, struct kevent *); }; static int kevent_copyout(void *arg, struct kevent *kevp, int count) { + int i; + struct kevent *ke, **el; struct sys_kevent_args *uap; uap = (struct sys_kevent_args *)arg; - bcopy(kevp, uap->eventlist, count * sizeof *kevp); - uap->eventlist += count; + for (ke = kevp, i = 0; i < count; i++, ke++) { + if (uap->do_each) { + uap->do_each(&(uap->eventlist), ke); + + } else { + el = (struct kevent **)(&uap->eventlist); + **el = *ke; + (*el)++; + } + } return (0); } @@ -971,21 +982,25 @@ kevent_copyin(void *arg, struct kevent *kevp, int count) } int -ff_kevent(int kq, const struct kevent *changelist, int nchanges, - struct kevent *eventlist, int nevents, const struct timespec *timeout) +ff_kevent_do_each(int kq, const struct kevent *changelist, int nchanges, + void *eventlist, int nevents, const struct timespec *timeout, + void (*do_each)(void **, struct kevent *)) { int rc; struct timespec ts; ts.tv_sec = 0; ts.tv_nsec = 0; + struct sys_kevent_args ska = { kq, changelist, nchanges, eventlist, nevents, - &ts + &ts, + do_each }; + struct kevent_copyops k_ops = { &ska, kevent_copyout, @@ -1002,3 +1017,11 @@ kern_fail: ff_os_errno(rc); return (-1); } + +int +ff_kevent(int kq, const struct kevent *changelist, int nchanges, + struct kevent *eventlist, int nevents, const struct timespec *timeout) +{ + return ff_kevent_do_each(kq, changelist, nchanges, eventlist, nevents, timeout, NULL); +} +