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