[PATCH xserver 2/2] os: Add epoll-like port implementation for Solaris

Peter Harris pharris at opentext.com
Thu Oct 12 20:48:37 UTC 2017


x11perf -noop with 200 xlogos connected is slightly faster with ports:

  before           after         Operation
----------   -----------------   --------------------
18400000.0   19200000.0 (1.04)   X protocol NoOperation

Signed-off-by: Peter Harris <pharris at opentext.com>
---
 include/meson.build |   1 +
 os/ospoll.c         | 128 +++++++++++++++++++++++++++++++++++++++++++++++++---
 2 files changed, 122 insertions(+), 7 deletions(-)

diff --git a/include/meson.build b/include/meson.build
index e0ebee258..8eec9ce36 100644
--- a/include/meson.build
+++ b/include/meson.build
@@ -126,6 +126,7 @@ conf_data.set('HAVE_MMAP', cc.has_function('mmap'))
 conf_data.set('HAVE_POLL', cc.has_function('poll'))
 conf_data.set('HAVE_POLLSET_CREATE', cc.has_function('pollset_create'))
 conf_data.set('HAVE_POSIX_FALLOCATE', cc.has_function('posix_fallocate'))
+conf_data.set('HAVE_PORT_CREATE', cc.has_function('port_create'))
 conf_data.set('HAVE_REALLOCARRAY', cc.has_function('reallocarray', dependencies: libbsd_dep))
 conf_data.set('HAVE_SETEUID', cc.has_function('seteuid'))
 conf_data.set('HAVE_SETITIMER', cc.has_function('setitimer'))
diff --git a/os/ospoll.c b/os/ospoll.c
index 4a59a5e6b..db9e73811 100644
--- a/os/ospoll.c
+++ b/os/ospoll.c
@@ -38,6 +38,12 @@
 #define HAVE_OSPOLL     1
 #endif
 
+#if !HAVE_OSPOLL && defined(HAVE_PORT_CREATE)
+#include <port.h>
+#define PORT            1
+#define HAVE_OSPOLL     1
+#endif
+
 #if !HAVE_OSPOLL && defined(HAVE_EPOLL_CREATE1)
 #include <sys/epoll.h>
 #define EPOLL           1
@@ -71,7 +77,7 @@ struct ospoll {
 
 #endif
 
-#if EPOLL
+#if EPOLL || PORT
 #include <sys/epoll.h>
 
 /* epoll-based implementation */
@@ -128,7 +134,7 @@ ospoll_find(struct ospoll *ospoll, int fd)
 
     while (lo <= hi) {
         int m = (lo + hi) >> 1;
-#if EPOLL
+#if EPOLL || PORT
         int t = ospoll->fds[m]->fd;
 #endif
 #if POLL || POLLSET
@@ -145,7 +151,7 @@ ospoll_find(struct ospoll *ospoll, int fd)
     return -(lo + 1);
 }
 
-#if EPOLL
+#if EPOLL || PORT
 static void
 ospoll_clean_deleted(struct ospoll *ospoll)
 {
@@ -205,6 +211,17 @@ ospoll_create(void)
     }
     return ospoll;
 #endif
+#if PORT
+    struct ospoll *ospoll = calloc(1, sizeof (struct ospoll));
+
+    ospoll->epoll_fd = port_create();
+    if (ospoll->epoll_fd < 0) {
+        free (ospoll);
+        return NULL;
+    }
+    xorg_list_init(&ospoll->deleted);
+    return ospoll;
+#endif
 #if EPOLL
     struct ospoll       *ospoll = calloc(1, sizeof (struct ospoll));
 
@@ -232,7 +249,7 @@ ospoll_destroy(struct ospoll *ospoll)
         free(ospoll);
     }
 #endif
-#if EPOLL
+#if EPOLL || PORT
     if (ospoll) {
         assert (ospoll->num == 0);
         close(ospoll->epoll_fd);
@@ -282,6 +299,41 @@ ospoll_add(struct ospoll *ospoll, int fd,
     ospoll->fds[pos].callback = callback;
     ospoll->fds[pos].data = data;
 #endif
+#if PORT
+    struct ospollfd *osfd;
+
+    if (pos < 0) {
+        osfd = calloc(1, sizeof (struct ospollfd));
+        if (!osfd)
+            return FALSE;
+
+        if (ospoll->num >= ospoll->size) {
+            struct ospollfd **new_fds;
+            int new_size = ospoll->size ? ospoll->size * 2 : MAXCLIENTS * 2;
+
+            new_fds = reallocarray(ospoll->fds, new_size, sizeof (ospoll->fds[0]));
+            if (!new_fds) {
+                free (osfd);
+                return FALSE;
+            }
+            ospoll->fds = new_fds;
+            ospoll->size = new_size;
+        }
+
+        osfd->fd = fd;
+        osfd->xevents = 0;
+
+        pos = -pos - 1;
+        array_insert(ospoll->fds, ospoll->num, sizeof (ospoll->fds[0]), pos);
+        ospoll->fds[pos] = osfd;
+        ospoll->num++;
+    } else {
+        osfd = ospoll->fds[pos];
+    }
+    osfd->data = data;
+    osfd->callback = callback;
+    osfd->trigger = trigger;
+#endif
 #if EPOLL
     struct ospollfd *osfd;
 
@@ -378,6 +430,16 @@ ospoll_remove(struct ospoll *ospoll, int fd)
         array_delete(ospoll->fds, ospoll->num, sizeof (ospoll->fds[0]), pos);
         ospoll->num--;
 #endif
+#if PORT
+        struct ospollfd *osfd = ospoll->fds[pos];
+        port_dissociate(ospoll->epoll_fd, PORT_SOURCE_FD, fd);
+
+        array_delete(ospoll->fds, ospoll->num, sizeof (ospoll->fds[0]), pos);
+        ospoll->num--;
+        osfd->callback = NULL;
+        osfd->data = NULL;
+        xorg_list_add(&osfd->deleted, &ospoll->deleted);
+#endif
 #if EPOLL
         struct ospollfd *osfd = ospoll->fds[pos];
         struct epoll_event ev;
@@ -400,6 +462,19 @@ ospoll_remove(struct ospoll *ospoll, int fd)
     }
 }
 
+#if PORT
+static void
+epoll_mod(struct ospoll *ospoll, struct ospollfd *osfd)
+{
+    int events = 0;
+    if (osfd->xevents & X_NOTIFY_READ)
+        events |= EPOLLIN;
+    if (osfd->xevents & X_NOTIFY_WRITE)
+        events |= EPOLLOUT;
+    port_associate(ospool->epoll_fd, PORT_SOURCE_FD, osfd->fd, events, osfd);
+}
+#endif
+
 #if EPOLL
 static void
 epoll_mod(struct ospoll *ospoll, struct ospollfd *osfd)
@@ -436,7 +511,7 @@ ospoll_listen(struct ospoll *ospoll, int fd, int xevents)
         pollset_ctl(ospoll->ps, &ctl, 1);
         ospoll->fds[pos].xevents |= xevents;
 #endif
-#if EPOLL
+#if EPOLL || PORT
         struct ospollfd *osfd = ospoll->fds[pos];
         osfd->xevents |= xevents;
         epoll_mod(ospoll, osfd);
@@ -476,7 +551,7 @@ ospoll_mute(struct ospoll *ospoll, int fd, int xevents)
             pollset_ctl(ospoll->ps, &ctl, 1);
         }
 #endif
-#if EPOLL
+#if EPOLL || PORT
         struct ospollfd *osfd = ospoll->fds[pos];
         osfd->xevents &= ~xevents;
         epoll_mod(ospoll, osfd);
@@ -522,6 +597,37 @@ ospoll_wait(struct ospoll *ospoll, int timeout)
         }
     }
 #endif
+#if PORT
+#define MAX_EVENTS      256
+    port_event_t events[MAX_EVENTS];
+    uint_t nget = 1;
+
+    nready = 0;
+    if (port_getn(ospoll->epoll_fd, events, MAX_EVENTS, &nget, &timeout) == 0) {
+        nready = nget;
+    }
+    for (int i = 0; i < nready; i++) {
+        port_event_t *ev = &events[i];
+        struct ospollfd *osfd = ev->portev_user;
+        uint32_t revents = ev->portev_events;
+        int xevents = 0;
+
+        if (revents & EPOLLIN)
+            xevents |= X_NOTIFY_READ;
+        if (revents & EPOLLOUT)
+            xevents |= X_NOTIFY_WRITE;
+        if (revents & (~(EPOLLIN|EPOLLOUT)))
+            xevents |= X_NOTIFY_ERROR;
+
+        if (osfd->callback)
+            osfd->callback(osfd->fd, xevents, osfd->data);
+
+        if (osfd->trigger == ospoll_trigger_level && !osfd->deleted) {
+            epoll_mod(ospoll, osfd);
+        }
+    }
+    ospoll_clean_deleted(ospoll);
+#endif
 #if EPOLL
 #define MAX_EVENTS      256
     struct epoll_event events[MAX_EVENTS];
@@ -592,6 +698,14 @@ ospoll_reset_events(struct ospoll *ospoll, int fd)
 
     ospoll->fds[pos].revents = 0;
 #endif
+#if PORT
+    int pos = ospoll_find(ospoll, fd);
+
+    if (pos < 0)
+        return;
+
+    epoll_mod(ospoll, ospoll->fds[pos]);
+#endif
 #if POLL
     int pos = ospoll_find(ospoll, fd);
 
@@ -612,7 +726,7 @@ ospoll_data(struct ospoll *ospoll, int fd)
 #if POLLSET
     return ospoll->fds[pos].data;
 #endif
-#if EPOLL
+#if EPOLL || PORT
     return ospoll->fds[pos]->data;
 #endif
 #if POLL
-- 
2.11.0



More information about the xorg-devel mailing list