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 <phar...@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 _______________________________________________ xorg-devel@lists.x.org: X.Org development Archives: http://lists.x.org/archives/xorg-devel Info: https://lists.x.org/mailman/listinfo/xorg-devel