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@keithp.com> Signed-off-by: Peter Harris <pharris@opentext.com>
This commit is contained in:
parent
83c04ee6ea
commit
edda951fa5
|
@ -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'))
|
||||
|
|
128
os/ospoll.c
128
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
|
||||
|
|
Loading…
Reference in New Issue