xserver: Branch 'master' - 2 commits

Adam Jackson ajax at kemper.freedesktop.org
Wed Dec 13 16:22:07 UTC 2017


 include/meson.build |    2 
 os/ospoll.c         |  274 ++++++++++++++++++++++++++++++++++++++++++++++++++--
 2 files changed, 268 insertions(+), 8 deletions(-)

New commits:
commit edda951fa5145a50915611ee0e9e459074117700
Author: Peter Harris <pharris at opentext.com>
Date:   Thu Oct 12 16:48:37 2017 -0400

    os: Add epoll-like port implementation for Solaris
    
    x11perf -noop with 200 xlogos connected is slightly faster with ports:
    
      before           after         Operation
    ----------   -----------------   --------------------
    18400000.0   19200000.0 (1.04)   X protocol NoOperation
    
    Acked-by: Keith Packard <keithp at keithp.com>
    Signed-off-by: Peter Harris <pharris at opentext.com>

diff --git a/include/meson.build b/include/meson.build
index 01da3dbb1..216744ca2 100644
--- a/include/meson.build
+++ b/include/meson.build
@@ -125,6 +125,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
commit 83c04ee6eae1edc80528203fb515425108171cd8
Author: Peter Harris <pharris at opentext.com>
Date:   Thu Oct 12 16:48:36 2017 -0400

    os: Add epoll-like pollset implementation for AIX
    
    AIX's poll only allows FD_SETSIZE entries in the fd list, which is
    insufficient for expanded MaxClients.
    
    As a bonus, x11perf -noop with ~250 xlogos connected is slightly faster
    with pollset:
    
     before          after         Operation
    ---------   ----------------   --------------------
    5750000.0   5990000.0 (1.04)   X protocol NoOperation
    
    Signed-off-by: Peter Harris <pharris at opentext.com>
    Acked-by: Keith Packard <keithp at keithp.com>

diff --git a/include/meson.build b/include/meson.build
index 471014610..01da3dbb1 100644
--- a/include/meson.build
+++ b/include/meson.build
@@ -123,6 +123,7 @@ conf_data.set('HAVE_GETPROGNAME', cc.has_function('getprogname'))
 conf_data.set('HAVE_GETZONEID', cc.has_function('getzoneid'))
 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_REALLOCARRAY', cc.has_function('reallocarray', dependencies: libbsd_dep))
 conf_data.set('HAVE_SETEUID', cc.has_function('seteuid'))
diff --git a/os/ospoll.c b/os/ospoll.c
index ca14a0c8c..4a59a5e6b 100644
--- a/os/ospoll.c
+++ b/os/ospoll.c
@@ -32,6 +32,12 @@
 #include "ospoll.h"
 #include "list.h"
 
+#if !HAVE_OSPOLL && defined(HAVE_POLLSET_CREATE)
+#include <sys/pollset.h>
+#define POLLSET         1
+#define HAVE_OSPOLL     1
+#endif
+
 #if !HAVE_OSPOLL && defined(HAVE_EPOLL_CREATE1)
 #include <sys/epoll.h>
 #define EPOLL           1
@@ -44,6 +50,27 @@
 #define HAVE_OSPOLL     1
 #endif
 
+#if POLLSET
+
+// pollset-based implementation (as seen on AIX)
+struct ospollfd {
+    int                 fd;
+    int                 xevents;
+    short               revents;
+    enum ospoll_trigger trigger;
+    void                (*callback)(int fd, int xevents, void *data);
+    void                *data;
+};
+
+struct ospoll {
+    pollset_t           ps;
+    struct ospollfd     *fds;
+    int                 num;
+    int                 size;
+};
+
+#endif
+
 #if EPOLL
 #include <sys/epoll.h>
 
@@ -104,7 +131,7 @@ ospoll_find(struct ospoll *ospoll, int fd)
 #if EPOLL
         int t = ospoll->fds[m]->fd;
 #endif
-#if POLL
+#if POLL || POLLSET
         int t = ospoll->fds[m].fd;
 #endif
 
@@ -168,6 +195,16 @@ array_delete(void *base, size_t num, size_t size, size_t pos)
 struct ospoll *
 ospoll_create(void)
 {
+#if POLLSET
+    struct ospoll *ospoll = calloc(1, sizeof (struct ospoll));
+
+    ospoll->ps = pollset_create(-1);
+    if (ospoll->ps < 0) {
+        free (ospoll);
+        return NULL;
+    }
+    return ospoll;
+#endif
 #if EPOLL
     struct ospoll       *ospoll = calloc(1, sizeof (struct ospoll));
 
@@ -187,6 +224,14 @@ ospoll_create(void)
 void
 ospoll_destroy(struct ospoll *ospoll)
 {
+#if POLLSET
+    if (ospoll) {
+        assert (ospoll->num == 0);
+        pollset_destroy(ospoll->ps);
+        free(ospoll->fds);
+        free(ospoll);
+    }
+#endif
 #if EPOLL
     if (ospoll) {
         assert (ospoll->num == 0);
@@ -213,6 +258,30 @@ ospoll_add(struct ospoll *ospoll, int fd,
            void *data)
 {
     int pos = ospoll_find(ospoll, fd);
+#if POLLSET
+    if (pos < 0) {
+        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)
+                return FALSE;
+            ospoll->fds = new_fds;
+            ospoll->size = new_size;
+        }
+        pos = -pos - 1;
+        array_insert(ospoll->fds, ospoll->num, sizeof (ospoll->fds[0]), pos);
+        ospoll->num++;
+
+        ospoll->fds[pos].fd = fd;
+        ospoll->fds[pos].xevents = 0;
+        ospoll->fds[pos].revents = 0;
+    }
+    ospoll->fds[pos].trigger = trigger;
+    ospoll->fds[pos].callback = callback;
+    ospoll->fds[pos].data = data;
+#endif
 #if EPOLL
     struct ospollfd *osfd;
 
@@ -301,6 +370,14 @@ ospoll_remove(struct ospoll *ospoll, int fd)
 
     pos = ospoll_find(ospoll, fd);
     if (pos >= 0) {
+#if POLLSET
+        struct ospollfd *osfd = &ospoll->fds[pos];
+        struct poll_ctl ctl = { .cmd = PS_DELETE, .fd = fd };
+        pollset_ctl(ospoll->ps, &ctl, 1);
+
+        array_delete(ospoll->fds, ospoll->num, sizeof (ospoll->fds[0]), pos);
+        ospoll->num--;
+#endif
 #if EPOLL
         struct ospollfd *osfd = ospoll->fds[pos];
         struct epoll_event ev;
@@ -346,6 +423,19 @@ ospoll_listen(struct ospoll *ospoll, int fd, int xevents)
     int pos = ospoll_find(ospoll, fd);
 
     if (pos >= 0) {
+#if POLLSET
+        struct poll_ctl ctl = { .cmd = PS_MOD, .fd = fd };
+        if (xevents & X_NOTIFY_READ) {
+            ctl.events |= POLLIN;
+            ospoll->fds[pos].revents &= ~POLLIN;
+        }
+        if (xevents & X_NOTIFY_WRITE) {
+            ctl.events |= POLLOUT;
+            ospoll->fds[pos].revents &= ~POLLOUT;
+        }
+        pollset_ctl(ospoll->ps, &ctl, 1);
+        ospoll->fds[pos].xevents |= xevents;
+#endif
 #if EPOLL
         struct ospollfd *osfd = ospoll->fds[pos];
         osfd->xevents |= xevents;
@@ -370,6 +460,22 @@ ospoll_mute(struct ospoll *ospoll, int fd, int xevents)
     int pos = ospoll_find(ospoll, fd);
 
     if (pos >= 0) {
+#if POLLSET
+        struct ospollfd *osfd = &ospoll->fds[pos];
+        osfd->xevents &= ~xevents;
+        struct poll_ctl ctl = { .cmd = PS_DELETE, .fd = fd };
+        pollset_ctl(ospoll->ps, &ctl, 1);
+        if (osfd->xevents) {
+            ctl.cmd = PS_ADD;
+            if (osfd->xevents & X_NOTIFY_READ) {
+                ctl.events |= POLLIN;
+            }
+            if (osfd->xevents & X_NOTIFY_WRITE) {
+                ctl.events |= POLLOUT;
+            }
+            pollset_ctl(ospoll->ps, &ctl, 1);
+        }
+#endif
 #if EPOLL
         struct ospollfd *osfd = ospoll->fds[pos];
         osfd->xevents &= ~xevents;
@@ -389,6 +495,33 @@ int
 ospoll_wait(struct ospoll *ospoll, int timeout)
 {
     int nready;
+#if POLLSET
+#define MAX_EVENTS      256
+    struct pollfd events[MAX_EVENTS];
+
+    nready = pollset_poll(ospoll->ps, events, MAX_EVENTS, timeout);
+    for (int i = 0; i < nready; i++) {
+        struct pollfd *ev = &events[i];
+        int pos = ospoll_find(ospoll, ev->fd);
+        struct ospollfd *osfd = &ospoll->fds[pos];
+        short revents = ev->revents;
+        short oldevents = osfd->revents;
+
+        osfd->revents = (revents & (POLLIN|POLLOUT));
+        if (osfd->trigger == ospoll_trigger_edge)
+            revents &= ~oldevents;
+        if (revents) {
+            int xevents = 0;
+            if (revents & POLLIN)
+                xevents |= X_NOTIFY_READ;
+            if (revents & POLLOUT)
+                xevents |= X_NOTIFY_WRITE;
+            if (revents & (~(POLLIN|POLLOUT)))
+                xevents |= X_NOTIFY_ERROR;
+            osfd->callback(osfd->fd, xevents, osfd->data);
+        }
+    }
+#endif
 #if EPOLL
 #define MAX_EVENTS      256
     struct epoll_event events[MAX_EVENTS];
@@ -451,6 +584,14 @@ ospoll_wait(struct ospoll *ospoll, int timeout)
 void
 ospoll_reset_events(struct ospoll *ospoll, int fd)
 {
+#if POLLSET
+    int pos = ospoll_find(ospoll, fd);
+
+    if (pos < 0)
+        return;
+
+    ospoll->fds[pos].revents = 0;
+#endif
 #if POLL
     int pos = ospoll_find(ospoll, fd);
 
@@ -468,6 +609,9 @@ ospoll_data(struct ospoll *ospoll, int fd)
 
     if (pos < 0)
         return NULL;
+#if POLLSET
+    return ospoll->fds[pos].data;
+#endif
 #if EPOLL
     return ospoll->fds[pos]->data;
 #endif


More information about the xorg-commit mailing list