mirror of https://github.com/F-Stack/f-stack.git
epoll optimization, add ff_kevent_do_each
This commit is contained in:
parent
61a488cc9b
commit
1a78ce8ea6
|
@ -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:
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
ff_mbuf_tx_offload
|
||||
|
|
124
lib/ff_epoll.c
124
lib/ff_epoll.c
|
@ -1,34 +1,24 @@
|
|||
#include <sys/param.h>
|
||||
#include <sys/limits.h>
|
||||
#include <sys/uio.h>
|
||||
#include <sys/proc.h>
|
||||
#include <sys/syscallsubr.h>
|
||||
#include <sys/module.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/socketvar.h>
|
||||
#include <sys/event.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 <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
#include <sched.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <assert.h>
|
||||
#include <unistd.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/tcp.h>
|
||||
#include <sys/ttycom.h>
|
||||
#include <sys/filio.h>
|
||||
#include <sys/sysproto.h>
|
||||
#include <sys/fcntl.h>
|
||||
#include <machine/stdarg.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/select.h>
|
||||
#include <sys/syscall.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <sys/epoll.h>
|
||||
|
||||
#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);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,73 +1,11 @@
|
|||
#ifndef _FF_EPOLL_H
|
||||
#define _FF_EPOLL_H
|
||||
|
||||
//#include <sys/stdint.h>
|
||||
//#include <sys/queue.h>
|
||||
#include <sys/epoll.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_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
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue