Skip site navigation (1)Skip section navigation (2)
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>