From 01b972d63905a42688e8b8ce8f9ed5cf65e2d731 Mon Sep 17 00:00:00 2001 From: Albert Lee Date: Fri, 20 Nov 2009 18:35:26 -0500 Subject: [PATCH] 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(+) diff --git a/configure b/configure index 15652b4100e..589321692e0 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 a5f1b8a1f60..9a382f3e48d 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 16b2e90bc70..7a77d1f85be 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 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 9d2ac9d6639..9d8a06f7a5a 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 +# 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) { }