Date: Mon, 16 Jul 2007 15:57:30 GMT From: Roman Divacky <rdivacky@FreeBSD.org> To: Perforce Change Reviews <perforce@FreeBSD.org> Subject: PERFORCE change 123595 for review Message-ID: <200707161557.l6GFvUpo007245@repoman.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=123595 Change 123595 by rdivacky@rdivacky_witten on 2007/07/16 15:56:33 Epoll milestone.. Implement epoll_ctl in a way that seems to work ;) Please DONT bother reviewing this as this is really WIP. I just want to have this milestone commited. Affected files ... .. //depot/projects/soc2007/rdivacky/linux_epoll/sys/compat/linux/linux_epoll.c#4 edit .. //depot/projects/soc2007/rdivacky/linux_epoll/sys/compat/linux/linux_epoll.h#4 edit Differences ... ==== //depot/projects/soc2007/rdivacky/linux_epoll/sys/compat/linux/linux_epoll.c#4 (text+ko) ==== @@ -29,33 +29,174 @@ #include "opt_compat.h" -#include <linux_epoll.h> +#include <sys/types.h> +#include <sys/systm.h> +#include <sys/errno.h> +#include <sys/event.h> +#include <sys/sysproto.h> +#include <sys/syscallsubr.h> +#include <sys/timespec.h> +#include <compat/linux/linux_epoll.h> #ifdef COMPAT_LINUX32 #include <machine/../linux32/linux.h> +#include <machine/../linux32/linux32_proto.h> #else #include <machine/../linux/linux.h> +#include <machine/../linux/linux_proto.h> #endif int linux_epoll_create(struct thread *td, struct linux_epoll_create_args *args) { - struct kqueue_args args; + struct kqueue_args k_args; /* XXX: args->size is ignored. Linux ignores it as well. */ - return kqueue(td, args); + return kqueue(td, &k_args); +} + +static void +linux_epoll_to_kevent(int fd, struct linux_epoll_event *event, struct kevent *kevent) +{ + int filter = 0; + int flags = kevent->flags; + + if (event->events & LINUX_EPOLLIN) + filter |= EVFILT_READ; + if (event->events & LINUX_EPOLLOUT) + filter |= EVFILT_WRITE; + if (event->events & LINUX_EPOLLPRI) + filter |= EVFILT_READ; + if (event->events & LINUX_EPOLLET) /* XXX: ? */ + flags |= EV_CLEAR; + if (event->events & LINUX_EPOLLONESHOT) + flags |= EV_ONESHOT; + + EV_SET(kevent, fd, filter, flags, 0, 0, 0); +} + +static void +linux_kevent_to_epoll(struct kevent *kevent, struct linux_epoll_event *event) +{ + /* XXX: testing only!!! */ + if (kevent->data > 0) + event->events = LINUX_EPOLLIN; + + event->data = LINUX_EPOLL_CTL_ADD; +} + +static int +linux_kev_copyout(void *arg, struct kevent *kevp, int count) +{ + struct kevent_args *uap; + struct linux_epoll_event *eep; + int error, i; + + uap = (struct kevent_args*) arg; + printf("Copyout: %i\n", count); + + eep = malloc(sizeof(*eep) * count, M_TEMP, M_WAITOK | M_ZERO); + + for (i = 0; i < count; i++) { + linux_kevent_to_epoll(&kevp[i], &eep[i]); + } + + error = copyout(eep, uap->changelist, count * sizeof(*eep)); + if (error) + uap->eventlist += count; + + free(eep, M_TEMP); + return (0); +} + +static int +linux_kev_copyin(void *arg, struct kevent *kevp, int count) +{ + struct kevent_args *uap; + + uap = (struct kevent_args*) arg; + printf("count: %i\n", count); + + memcpy(kevp, uap->changelist, count * sizeof(*kevp)); + + printf("KeventX: %i, %i, %i, %i\n", kevp->ident, kevp->filter, kevp->flags, kevp->fflags); + printf("KeventY: %i, %i, %i, %i\n", uap->changelist->ident, uap->changelist->filter, uap->changelist->flags, uap->changelist->fflags); + + uap->changelist += count; + + return (0); } + int linux_epoll_ctl(struct thread *td, struct linux_epoll_ctl_args *args) { - return (ENOSYS); + struct kevent_args k_args; + struct kevent kev; + struct kevent_copyops k_ops = { &k_args, + linux_kev_copyout, + linux_kev_copyin}; + struct linux_epoll_event le; + int error; + + error = copyin(args->event, &le, sizeof(le)); + if (error) + return (error); + printf("epoll_ctl: %i, %i, %i, %u\n", args->epfd, args->op, + args->fd, le.events); + k_args.fd = args->epfd; + k_args.changelist = &kev; /* epoll can register only 1 filter at once*/ + k_args.nchanges = 1; + k_args.eventlist = NULL; + k_args.nevents = 0; + k_args.timeout = NULL; + + switch (args->op) { + case LINUX_EPOLL_CTL_ADD: + kev.flags = EV_ADD | EV_ENABLE; + break; + case LINUX_EPOLL_CTL_MOD: + /* XXX: DELETE && ADD maybe? */ + return (EINVAL); + break; + case LINUX_EPOLL_CTL_DEL: + kev.flags = EV_DELETE | EV_DISABLE; + break; + } + linux_epoll_to_kevent(args->fd, &le, &kev); + + printf("Kevent: %i, %i, %i, %i\n", kev.ident, kev.filter, kev.flags, kev.fflags); + return kern_kevent(td, args->epfd, 1, 0, &k_ops, NULL); } int linux_epoll_wait(struct thread *td, struct linux_epoll_wait_args *args) { - return (ENOSYS); + struct timespec ts; + struct kevent_args k_args; + struct kevent_copyops k_ops = { &k_args, + linux_kev_copyout, + linux_kev_copyin}; + int error; + + ts.tv_sec = args->timeout / 1000000; + ts.tv_nsec = (args->timeout % 1000000) * 1000; + + k_args.fd = args->epfd; + k_args.changelist = NULL; + k_args.nchanges = 0; + /* + * we dont mind the wrong type-cast because + * our copyout function handles this + */ + k_args.eventlist = (struct kevent *)args->events; + k_args.nevents = args->maxevents; + k_args.timeout = &ts; + + error = kern_kevent(td, args->epfd, 0, args->maxevents, &k_ops, &ts); + + /* XXX: translation? */ + return (error); } ==== //depot/projects/soc2007/rdivacky/linux_epoll/sys/compat/linux/linux_epoll.h#4 (text+ko) ==== @@ -40,4 +40,14 @@ uint64_t data; } EPOLL_PACKED; +#define LINUX_EPOLLIN 0x001 +#define LINUX_EPOLLPRI 0x002 +#define LINUX_EPOLLOUT 0x004 +#define LINUX_EPOLLONESHOT (1 << 30) +#define LINUX_EPOLLET (1 << 31) + +#define LINUX_EPOLL_CTL_ADD 1 +#define LINUX_EPOLL_CTL_DEL 2 +#define LINUX_EPOLL_CTL_MOD 3 + #endif /* !_LINUX_EPOLL_H_ */
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200707161557.l6GFvUpo007245>