epoll optimization, add ff_kevent_do_each

dev
Ron 2017-06-13 17:50:51 +08:00
parent 61a488cc9b
commit 1a78ce8ea6
7 changed files with 90 additions and 152 deletions

View File

@ -17,6 +17,7 @@ LIBS+= -Wl,--no-whole-archive -lrt -lm -ldl -lcrypto -pthread
TARGET="helloworld" TARGET="helloworld"
all: all:
cc -O -gdwarf-2 -I../lib -o ${TARGET} main.c ${LIBS} 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 .PHONY: clean
clean: clean:

View File

@ -128,8 +128,7 @@ FF_SRCS+= \
ff_syscall_wrapper.c \ ff_syscall_wrapper.c \
ff_subr_prf.c \ ff_subr_prf.c \
ff_vfs_ops.c \ ff_vfs_ops.c \
ff_veth.c \ ff_veth.c
ff_epoll.c
FF_HOST_SRCS+= \ FF_HOST_SRCS+= \
ff_host_interface.c \ ff_host_interface.c \
@ -138,6 +137,7 @@ FF_HOST_SRCS+= \
ff_dpdk_if.c \ ff_dpdk_if.c \
ff_dpdk_kni.c \ ff_dpdk_kni.c \
ff_dpdk_pcap.c \ ff_dpdk_pcap.c \
ff_epoll.c \
ff_init.c ff_init.c
ifdef FF_IPSEC ifdef FF_IPSEC

View File

@ -101,6 +101,9 @@ int ff_poll(struct pollfd fds[], nfds_t nfds, int timeout);
int ff_kqueue(void); int ff_kqueue(void);
int ff_kevent(int kq, const struct kevent *changelist, int nchanges, int ff_kevent(int kq, const struct kevent *changelist, int nchanges,
struct kevent *eventlist, int nevents, const struct timespec *timeout); 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 #ifdef __cplusplus
} }

View File

@ -29,10 +29,7 @@ ff_shutdown
ff_sysctl ff_sysctl
ff_kqueue ff_kqueue
ff_kevent ff_kevent
ff_epoll_create ff_kevent_do_each
ff_epoll_ctl
ff_epoll_wait
ff_epoll_close
ff_veth_attach ff_veth_attach
ff_veth_detach ff_veth_detach
ff_veth_process_packet ff_veth_process_packet

View File

@ -1,34 +1,24 @@
#include <sys/param.h> #include <stdio.h>
#include <sys/limits.h> #include <stdint.h>
#include <sys/uio.h> #include <string.h>
#include <sys/proc.h> #include <stdlib.h>
#include <sys/syscallsubr.h> #include <stdarg.h>
#include <sys/module.h> #include <sched.h>
#include <sys/param.h> #include <fcntl.h>
#include <sys/malloc.h> #include <errno.h>
#include <sys/socketvar.h> #include <assert.h>
#include <sys/event.h> #include <unistd.h>
#include <sys/kernel.h>
#include <sys/refcount.h>
#include <sys/sysctl.h>
#include <sys/pcpu.h>
#include <sys/select.h>
#include <sys/poll.h>
#include <sys/event.h>
#include <sys/file.h>
#include <netinet/in.h> #include <netinet/in.h>
#include <netinet/tcp.h> #include <sys/types.h>
#include <sys/ttycom.h> #include <sys/socket.h>
#include <sys/filio.h> #include <sys/time.h>
#include <sys/sysproto.h> #include <sys/select.h>
#include <sys/fcntl.h> #include <sys/syscall.h>
#include <machine/stdarg.h> #include <arpa/inet.h>
#include <sys/epoll.h>
#include "ff_api.h" #include "ff_api.h"
#include "ff_epoll.h"
#include "ff_errno.h" #include "ff_errno.h"
#include "ff_host_interface.h"
int int
@ -37,16 +27,16 @@ ff_epoll_create(int size __attribute__((__unused__)))
return ff_kqueue(); return ff_kqueue();
} }
int int
ff_epoll_ctl(int epfd, int op, int fd, struct epoll_event *event) ff_epoll_ctl(int epfd, int op, int fd, struct epoll_event *event)
{ {
struct kevent kev[3];
if (!event && op != EPOLL_CTL_DEL) { if (!event && op != EPOLL_CTL_DEL) {
ff_os_errno(ff_EINVAL); errno = EINVAL;
return -1; return -1;
} }
struct kevent kev[3];
if (op == EPOLL_CTL_ADD){ if (op == EPOLL_CTL_ADD){
EV_SET(&kev[0], fd, EVFILT_READ, EV_SET(&kev[0], fd, EVFILT_READ,
EV_ADD | (event->events & EPOLLIN ? 0 : EV_DISABLE), 0, 0, NULL); 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, EV_SET(&kev[2], fd, EVFILT_USER, 0,
NOTE_FFCOPY | (event->events & EPOLLRDHUP ? 1 : 0), 0, NULL); NOTE_FFCOPY | (event->events & EPOLLRDHUP ? 1 : 0), 0, NULL);
} else { } else {
ff_os_errno(ff_EINVAL); errno = EINVAL;
return -1; return -1;
} }
return ff_kevent(epfd, kev, 3, NULL, 0, NULL); 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 int
ff_epoll_wait(int epfd, struct epoll_event *events, int maxevents, int timeout) ff_epoll_wait(int epfd, struct epoll_event *events, int maxevents, int timeout)
{ {
int i, ret;
if (!events || maxevents < 1) { if (!events || maxevents < 1) {
ff_os_errno(ff_EINVAL); errno = EINVAL;
return -1; return -1;
} }
struct kevent *evlist = malloc(sizeof(struct kevent)*maxevents, M_DEVBUF, M_ZERO|M_NOWAIT); return ff_kevent_do_each(epfd, NULL, 0, events, maxevents, NULL, ff_event_to_epoll);
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);
} }

View File

@ -1,73 +1,11 @@
#ifndef _FF_EPOLL_H #ifndef _FF_EPOLL_H
#define _FF_EPOLL_H #define _FF_EPOLL_H
//#include <sys/stdint.h> #include <sys/epoll.h>
//#include <sys/queue.h>
#ifndef _KERNEL
#include <stdint.h>
#else
#include <sys/stdint.h>
#include <sys/types.h>
#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_create(int size);
int ff_epoll_ctl(int epfd, int op, int fd, struct epoll_event *event); 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_wait(int epfd, struct epoll_event *events, int maxevents, int timeout);
int ff_epoll_close(int epfd);
#endif #endif

View File

@ -936,20 +936,31 @@ struct sys_kevent_args {
int fd; int fd;
const struct kevent *changelist; const struct kevent *changelist;
int nchanges; int nchanges;
struct kevent *eventlist; void *eventlist;
int nevents; int nevents;
const struct timespec *timeout; const struct timespec *timeout;
void (*do_each)(void **, struct kevent *);
}; };
static int static int
kevent_copyout(void *arg, struct kevent *kevp, int count) kevent_copyout(void *arg, struct kevent *kevp, int count)
{ {
int i;
struct kevent *ke, **el;
struct sys_kevent_args *uap; struct sys_kevent_args *uap;
uap = (struct sys_kevent_args *)arg; 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); return (0);
} }
@ -971,21 +982,25 @@ kevent_copyin(void *arg, struct kevent *kevp, int count)
} }
int int
ff_kevent(int kq, const struct kevent *changelist, int nchanges, ff_kevent_do_each(int kq, const struct kevent *changelist, int nchanges,
struct kevent *eventlist, int nevents, const struct timespec *timeout) void *eventlist, int nevents, const struct timespec *timeout,
void (*do_each)(void **, struct kevent *))
{ {
int rc; int rc;
struct timespec ts; struct timespec ts;
ts.tv_sec = 0; ts.tv_sec = 0;
ts.tv_nsec = 0; ts.tv_nsec = 0;
struct sys_kevent_args ska = { struct sys_kevent_args ska = {
kq, kq,
changelist, changelist,
nchanges, nchanges,
eventlist, eventlist,
nevents, nevents,
&ts &ts,
do_each
}; };
struct kevent_copyops k_ops = { struct kevent_copyops k_ops = {
&ska, &ska,
kevent_copyout, kevent_copyout,
@ -1002,3 +1017,11 @@ kern_fail:
ff_os_errno(rc); ff_os_errno(rc);
return (-1); 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);
}