Epoll patch (rev 7)
Mike McCormack
mike at codeweavers.com
Wed Sep 22 03:34:53 CDT 2004
Updated with Marcus's suggested configure update.
Mike
ChangeLog:
* add support for using epoll instead of select to the wineserver
-------------- next part --------------
Index: server/fd.c
===================================================================
RCS file: /home/wine/wine/server/fd.c,v
retrieving revision 1.26
diff -u -r1.26 fd.c
--- server/fd.c 20 Sep 2004 19:14:35 -0000 1.26
+++ server/fd.c 22 Sep 2004 06:55:22 -0000
@@ -2,6 +2,8 @@
* Server-side file descriptor management
*
* Copyright (C) 2000, 2003 Alexandre Julliard
+ * Copyright (C) 2004 Shachar Shemesh for Lingnu Open Source Consulting ltd.
+ * Copyright (C) 2004 Mike McCormack
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -33,6 +35,10 @@
#ifdef HAVE_SYS_POLL_H
#include <sys/poll.h>
#endif
+#include <stdint.h>
+#ifdef HAVE_SYS_EPOLL_H
+#include <sys/epoll.h>
+#endif
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/types.h>
@@ -227,6 +233,103 @@
/****************************************************************/
+/* epoll support */
+
+#if defined(HAVE_SYS_EPOLL_H) && defined(HAVE_LIBEPOLL)
+
+#define EPOLL_SIZE 1024
+#define MAX_EVENTS 10
+
+static int epoll_fd;
+
+/* this should optimize away if the poll constants are the same as the epoll ones */
+static inline int epoll_events( int events )
+{
+ int r = 0;
+
+ if ((POLLIN == EPOLLIN) && (POLLOUT == EPOLLOUT) &&
+ (POLLERR == EPOLLERR) && (POLLHUP == EPOLLHUP))
+ return events;
+ if (POLLIN&events) r |= EPOLLIN;
+ if (POLLOUT&events) r |= EPOLLOUT;
+ if (POLLERR&events) r |= EPOLLERR;
+ if (POLLHUP&events) r |= EPOLLHUP;
+ return r;
+}
+
+static inline void do_epoll_add( int fd, int events, unsigned int user )
+{
+ struct epoll_event eev;
+ int r;
+
+ if (epoll_fd < 0)
+ return;
+ if (fd < 0)
+ return;
+ if (!events)
+ return;
+ eev.events = events;
+ eev.data.u32 = user;
+ r = epoll_ctl( epoll_fd, EPOLL_CTL_ADD, fd, &eev );
+ assert( 0 == r );
+}
+
+static inline void do_epoll_mod( int fd, int events, unsigned int user )
+{
+ struct epoll_event eev;
+ int r;
+
+ if (epoll_fd < 0)
+ return;
+ if (fd < 0)
+ return;
+ eev.events = events;
+ eev.data.u32 = user;
+ r = epoll_ctl( epoll_fd, EPOLL_CTL_MOD, fd, &eev );
+ assert( 0 == r );
+}
+
+static inline void do_epoll_remove( int fd, int old_events, unsigned int user )
+{
+ struct epoll_event eev;
+ int r;
+
+ if (epoll_fd < 0)
+ return;
+ if (fd < 0)
+ return;
+ if (!old_events)
+ return;
+ r = epoll_ctl( epoll_fd, EPOLL_CTL_DEL, fd, &eev );
+ assert( 0 == r );
+}
+
+void init_fd(void)
+{
+ epoll_fd = epoll_create(EPOLL_SIZE);
+}
+
+#else
+
+static inline void do_epoll_add( int fd, int events, unsigned int user )
+{
+}
+
+static inline void do_epoll_mod( int fd, int events, unsigned int user )
+{
+}
+
+static inline void do_epoll_remove( int fd, int old_events, unsigned int user )
+{
+}
+
+void init_fd(void)
+{
+}
+
+#endif
+
+/****************************************************************/
/* poll support */
static struct fd **poll_users; /* users array */
@@ -280,6 +383,7 @@
{
assert( user >= 0 );
assert( poll_users[user] == fd );
+ do_epoll_remove( pollfd[user].fd, pollfd[user].events, user );
pollfd[user].fd = -1;
pollfd[user].events = 0;
pollfd[user].revents = 0;
@@ -335,8 +439,57 @@
return -1; /* no pending timeouts */
}
+#if defined(HAVE_SYS_EPOLL_H) && defined(HAVE_LIBEPOLL)
+
+/* server main poll() loop using epoll */
+static int epoll_loop(void)
+{
+ struct epoll_event ev[MAX_EVENTS];
+ int ret, i, user, timeout;
+
+ if( epoll_fd < 0 )
+ return 0;
+
+ while (active_users)
+ {
+ timeout = get_next_timeout();
+
+ if (!active_users) break; /* last user removed by a timeout */
+
+ ret = epoll_wait( epoll_fd, &ev[0], MAX_EVENTS, timeout );
+
+ /* put the events into the pollfd array first, like select does */
+ for (i = 0; i < ret; i++)
+ {
+ user = ev[i].data.u32;
+ assert( user < nb_users );
+ pollfd[user].revents = ev[i].events;
+ }
+
+ /* read events from the pollfd array, as set_fd_events may modify them */
+ for (i = 0; i < ret; i++)
+ {
+ user = ev[i].data.u32;
+ if (pollfd[user].revents)
+ fd_poll_event( poll_users[user], pollfd[user].revents );
+ }
+ }
+ close( epoll_fd );
+
+ return 1;
+}
+
+#else
+
+static int epoll_loop(void)
+{
+ return 0;
+}
+
+#endif
+
/* server main poll() loop */
-void main_loop(void)
+void select_loop(void)
{
int i, ret, timeout;
@@ -361,6 +514,12 @@
}
}
+void main_loop(void)
+{
+ if (epoll_loop())
+ return;
+ select_loop();
+}
/****************************************************************/
/* inode functions */
@@ -843,12 +1002,24 @@
assert( poll_users[user] == fd );
if (events == -1) /* stop waiting on this fd completely */
{
+ do_epoll_remove( pollfd[user].fd, pollfd[user].events, user );
pollfd[user].fd = -1;
pollfd[user].events = POLLERR;
pollfd[user].revents = 0;
}
else if (pollfd[user].fd != -1 || !pollfd[user].events)
{
+ /* remove the old fd */
+ if (fd->unix_fd != pollfd[user].fd || !events)
+ do_epoll_remove( pollfd[user].fd, pollfd[user].events, user );
+ if (events)
+ {
+ /* add the new fd or update the old one */
+ if ( pollfd[user].fd == -1 || !pollfd[user].events)
+ do_epoll_add( fd->unix_fd, events, user );
+ else if (pollfd[user].events != events)
+ do_epoll_mod( fd->unix_fd, events, user );
+ }
pollfd[user].fd = fd->unix_fd;
pollfd[user].events = events;
}
Index: server/main.c
===================================================================
RCS file: /home/wine/wine/server/main.c,v
retrieving revision 1.31
diff -u -r1.31 main.c
--- server/main.c 26 Mar 2003 01:32:18 -0000 1.31
+++ server/main.c 22 Sep 2004 06:55:22 -0000
@@ -122,6 +122,7 @@
signal( SIGTERM, sigterm_handler );
signal( SIGABRT, sigterm_handler );
+ init_fd();
sock_init();
open_master_socket();
sync_namespace = create_namespace( 37, TRUE );
Index: server/file.h
===================================================================
RCS file: /home/wine/wine/server/file.h,v
retrieving revision 1.17
diff -u -r1.17 file.h
--- server/file.h 18 Aug 2004 00:04:58 -0000 1.17
+++ server/file.h 22 Sep 2004 06:55:22 -0000
@@ -44,6 +44,7 @@
/* file descriptor functions */
+extern void init_fd(void);
extern struct fd *alloc_fd( const struct fd_ops *fd_user_ops, struct object *user );
extern struct fd *open_fd( struct fd *fd, const char *name, int flags, mode_t *mode,
unsigned int access, unsigned int sharing, unsigned int options );
Index: server/Makefile.in
===================================================================
RCS file: /home/wine/wine/server/Makefile.in,v
retrieving revision 1.51
diff -u -r1.51 Makefile.in
--- server/Makefile.in 23 Jun 2004 20:44:58 -0000 1.51
+++ server/Makefile.in 22 Sep 2004 06:55:22 -0000
@@ -5,6 +5,8 @@
VPATH = @srcdir@
MODULE = none
+LIBEPOLL = @LIBEPOLL@
+
C_SRCS = \
async.c \
atom.c \
@@ -52,7 +54,7 @@
@MAKE_RULES@
wineserver: $(OBJS)
- $(CC) -o $(PROGRAMS) $(OBJS) $(LIBWINE) $(LIBUNICODE) $(LIBPORT) $(LDFLAGS) $(LIBS)
+ $(CC) -o $(PROGRAMS) $(OBJS) $(LIBWINE) $(LIBUNICODE) $(LIBPORT) $(LDFLAGS) $(LIBS) $(LIBEPOLL)
install:: $(PROGRAMS)
$(MKINSTALLDIRS) $(bindir)
Index: configure.ac
===================================================================
RCS file: /home/wine/wine/configure.ac,v
retrieving revision 1.310
diff -u -r1.310 configure.ac
--- configure.ac 22 Sep 2004 04:08:38 -0000 1.310
+++ configure.ac 22 Sep 2004 06:55:22 -0000
@@ -132,6 +132,14 @@
AC_CHECK_LIB(xpg4,_xpg4_setrunelocale)
dnl Check for -lpoll for Mac OS X/Darwin
AC_CHECK_LIB(poll,poll)
+dnl Check for -lepoll
+LIBEPOLL=
+AC_SUBST(LIBEPOLL)
+AC_CHECK_FUNC(epoll_create,
+ [AC_DEFINE(HAVE_LIBEPOLL)],
+ [AC_CHECK_LIB(epoll,epoll_create,
+ [LIBEPOLL="-lepoll"
+ AC_DEFINE(HAVE_LIBEPOLL)])])
dnl Check for -lresolv for Mac OS X/Darwin
AC_CHECK_LIB(resolv,res_9_init)
dnl Check for -lpthread
@@ -1156,6 +1164,7 @@
sys/cdio.h \
sys/elf32.h \
sys/errno.h \
+ sys/epoll.h \
sys/exec_elf.h \
sys/file.h \
sys/filio.h \
Index: include/config.h.in
===================================================================
RCS file: /home/wine/wine/include/config.h.in,v
retrieving revision 1.198
diff -u -r1.198 config.h.in
--- include/config.h.in 22 Sep 2004 04:08:38 -0000 1.198
+++ include/config.h.in 22 Sep 2004 06:55:22 -0000
@@ -254,6 +254,9 @@
/* Define if you have the curses library (-lcurses) */
#undef HAVE_LIBCURSES
+/* Define to 1 if you have the `epoll' library (-lepoll). */
+#undef HAVE_LIBEPOLL
+
/* Define to 1 if you have the `i386' library (-li386). */
#undef HAVE_LIBI386
@@ -616,6 +619,9 @@
/* Define to 1 if you have the <sys/elf32.h> header file. */
#undef HAVE_SYS_ELF32_H
+
+/* Define to 1 if you have the <sys/epoll.h> header file. */
+#undef HAVE_SYS_EPOLL_H
/* Define to 1 if you have the <sys/errno.h> header file. */
#undef HAVE_SYS_ERRNO_H
More information about the wine-patches
mailing list