Albert Lee : server: Support event ports on Solaris.

Alexandre Julliard julliard at winehq.org
Tue Nov 24 12:40:23 CST 2009


Module: wine
Branch: master
Commit: 01b972d63905a42688e8b8ce8f9ed5cf65e2d731
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=01b972d63905a42688e8b8ce8f9ed5cf65e2d731

Author: Albert Lee <trisk at forkgnu.org>
Date:   Fri Nov 20 18:35:26 2009 -0500

server: Support event ports on Solaris.

---

 configure           |    2 +
 configure.ac        |    2 +
 include/config.h.in |    6 +++
 server/fd.c         |  105 +++++++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 115 insertions(+), 0 deletions(-)

diff --git a/configure b/configure
index 15652b4..5893216 100755
--- a/configure
+++ b/configure
@@ -5727,6 +5727,7 @@ for ac_header in \
 	openssl/ssl.h \
 	png.h \
 	poll.h \
+	port.h \
 	process.h \
 	pthread.h \
 	pwd.h \
@@ -12109,6 +12110,7 @@ for ac_func in \
 	pipe2 \
 	poll \
 	popen \
+	port_create \
 	prctl \
 	pread \
 	pwrite \
diff --git a/configure.ac b/configure.ac
index a5f1b8a..9a382f3 100644
--- a/configure.ac
+++ b/configure.ac
@@ -364,6 +364,7 @@ AC_CHECK_HEADERS(\
 	openssl/ssl.h \
 	png.h \
 	poll.h \
+	port.h \
 	process.h \
 	pthread.h \
 	pwd.h \
@@ -1709,6 +1710,7 @@ AC_CHECK_FUNCS(\
 	pipe2 \
 	poll \
 	popen \
+	port_create \
 	prctl \
 	pread \
 	pwrite \
diff --git a/include/config.h.in b/include/config.h.in
index 16b2e90..7a77d1f 100644
--- a/include/config.h.in
+++ b/include/config.h.in
@@ -591,6 +591,12 @@
 /* Define to 1 if you have the `popen' function. */
 #undef HAVE_POPEN
 
+/* Define to 1 if you have the `port_create' function. */
+#undef HAVE_PORT_CREATE
+
+/* Define to 1 if you have the <port.h> header file. */
+#undef HAVE_PORT_H
+
 /* Define if we can use ppdev.h for parallel port access */
 #undef HAVE_PPDEV
 
diff --git a/server/fd.c b/server/fd.c
index 9d2ac9d..9d8a06f 100644
--- a/server/fd.c
+++ b/server/fd.c
@@ -162,6 +162,10 @@ static inline int epoll_wait( int epfd, struct epoll_event *events, int maxevent
 
 #endif /* linux && __i386__ && HAVE_STDINT_H */
 
+#if defined(HAVE_PORT_H) && defined(HAVE_PORT_CREATE)
+# include <port.h>
+# define USE_EVENT_PORTS
+#endif /* HAVE_PORT_H && HAVE_PORT_CREATE */
 
 /* Because of the stupid Posix locking semantics, we need to keep
  * track of all file descriptors referencing a given file, and not
@@ -676,6 +680,107 @@ static inline void main_loop_epoll(void)
     }
 }
 
+#elif defined(USE_EVENT_PORTS)
+
+static int port_fd = -1;
+
+static inline void init_epoll(void)
+{
+    port_fd = port_create();
+}
+
+static inline void set_fd_epoll_events( struct fd *fd, int user, int events )
+{
+    int ret;
+
+    if (port_fd == -1) return;
+
+    if (events == -1)  /* stop waiting on this fd completely */
+    {
+        if (pollfd[user].fd == -1) return;  /* already removed */
+        port_dissociate( port_fd, PORT_SOURCE_FD, fd->unix_fd );
+    }
+    else if (pollfd[user].fd == -1)
+    {
+        if (pollfd[user].events) return;  /* stopped waiting on it, don't restart */
+        ret = port_associate( port_fd, PORT_SOURCE_FD, fd->unix_fd, events, (void *)user );
+    }
+    else
+    {
+        if (pollfd[user].events == events) return;  /* nothing to do */
+        ret = port_associate( port_fd, PORT_SOURCE_FD, fd->unix_fd, events, (void *)user );
+    }
+
+    if (ret == -1)
+    {
+        if (errno == ENOMEM)  /* not enough memory, give up on port_associate */
+        {
+            close( port_fd );
+            port_fd = -1;
+        }
+        else perror( "port_associate" );  /* should not happen */
+    }
+}
+
+static inline void remove_epoll_user( struct fd *fd, int user )
+{
+    if (port_fd == -1) return;
+
+    if (pollfd[user].fd != -1)
+    {
+        port_dissociate( port_fd, PORT_SOURCE_FD, fd->unix_fd );
+    }
+}
+
+static inline void main_loop_epoll(void)
+{
+    int i, nget, ret, timeout;
+    port_event_t events[128];
+
+    if (port_fd == -1) return;
+
+    while (active_users)
+    {
+        timeout = get_next_timeout();
+        nget = 1;
+
+        if (!active_users) break;  /* last user removed by a timeout */
+        if (port_fd == -1) break;  /* an error occurred with event completion */
+
+        if (timeout != -1)
+        {
+            struct timespec ts;
+
+            ts.tv_sec = timeout / 1000;
+            ts.tv_nsec = (timeout % 1000) * 1000000;
+            ret = port_getn( port_fd, events, sizeof(events)/sizeof(events[0]), &nget, &ts );
+        }
+        else ret = port_getn( port_fd, events, sizeof(events)/sizeof(events[0]), &nget, NULL );
+
+	if (ret == -1) break;  /* an error occurred with event completion */
+
+        set_current_time();
+
+        /* put the events into the pollfd array first, like poll does */
+        for (i = 0; i < nget; i++)
+        {
+            long user = (long)events[i].portev_user;
+            pollfd[user].revents = events[i].portev_events;
+        }
+
+        /* read events from the pollfd array, as set_fd_events may modify them */
+        for (i = 0; i < nget; i++)
+        {
+            long user = (long)events[i].portev_user;
+            if (pollfd[user].revents) fd_poll_event( poll_users[user], pollfd[user].revents );
+            /* if we are still interested, reassociate the fd */
+            if (pollfd[user].fd != -1) {
+                port_associate( port_fd, PORT_SOURCE_FD, pollfd[user].fd, pollfd[user].events, (void *)user );
+            }
+        }
+    }
+}
+
 #else /* HAVE_KQUEUE */
 
 static inline void init_epoll(void) { }




More information about the wine-cvs mailing list