diff options
Diffstat (limited to 'os')
-rw-r--r-- | os/WaitFor.c | 4 | ||||
-rw-r--r-- | os/connection.c | 93 | ||||
-rw-r--r-- | os/osdep.h | 5 | ||||
-rw-r--r-- | os/osinit.c | 1 |
4 files changed, 103 insertions, 0 deletions
diff --git a/os/WaitFor.c b/os/WaitFor.c index 732543086..12b21bb21 100644 --- a/os/WaitFor.c +++ b/os/WaitFor.c @@ -306,6 +306,10 @@ WaitForSomething(int *pClientsReady) QueueWorkProc(EstablishNewConnections, NULL, (void *) &LastSelectMask); + XFD_ANDSET(&tmp_set, &LastSelectMask, &NotifyReadFds); + if (XFD_ANYSET(&tmp_set)) + HandleNotifyFds(); + if (XFD_ANYSET(&devicesReadable) || XFD_ANYSET(&clientsReadable)) break; /* check here for DDXes that queue events during Block/Wakeup */ diff --git a/os/connection.c b/os/connection.c index 3d33c4170..0df439189 100644 --- a/os/connection.c +++ b/os/connection.c @@ -123,6 +123,7 @@ static int lastfdesc; /* maximum file descriptor */ fd_set WellKnownConnections; /* Listener mask */ fd_set EnabledDevices; /* mask for input devices that are on */ +fd_set NotifyReadFds; /* mask for other file descriptors */ fd_set AllSockets; /* select on this */ fd_set AllClients; /* available clients */ fd_set LastSelectMask; /* mask returned from last select call */ @@ -1090,6 +1091,98 @@ RemoveEnabledDevice(int fd) RemoveGeneralSocket(fd); } +struct notify_fd { + struct xorg_list list; + int fd; + int mask; + NotifyFdProcPtr notify; + void *data; +}; + +static struct xorg_list notify_fds; + +void +InitNotifyFds(void) +{ + struct notify_fd *s, *next; + static int been_here; + + if (been_here) + xorg_list_for_each_entry_safe(s, next, ¬ify_fds, list) + RemoveNotifyFd(s->fd); + + xorg_list_init(¬ify_fds); + been_here = 1; +} + +/***************** + * SetNotifyFd + * Registers a callback to be invoked when the specified + * file descriptor becomes readable. + *****************/ + +Bool +SetNotifyFd(int fd, NotifyFdProcPtr notify, int mask, void *data) +{ + struct notify_fd *n; + int changes; + + xorg_list_for_each_entry(n, ¬ify_fds, list) + if (n->fd == fd) + break; + + if (&n->list == ¬ify_fds) { + if (mask == 0) + return TRUE; + + n = calloc(1, sizeof (struct notify_fd)); + if (!n) + return FALSE; + n->fd = fd; + xorg_list_add(&n->list, ¬ify_fds); + } + + changes = n->mask ^ mask; + + if (changes & X_NOTIFY_READ) { + if (mask & X_NOTIFY_READ) { + FD_SET(fd, &NotifyReadFds); + AddGeneralSocket(fd); + } else { + RemoveGeneralSocket(fd); + FD_CLR(fd, &NotifyReadFds); + } + } + if (mask == 0) { + xorg_list_del(&n->list); + free(n); + } else { + n->mask = mask; + n->data = data; + n->notify = notify; + } + + return TRUE; +} + +/***************** + * HandlNotifyFds + * A WorkProc to be called when any of the registered + * file descriptors are readable. + *****************/ + +void +HandleNotifyFds(void) +{ + struct notify_fd *s, *next; + + xorg_list_for_each_entry_safe(s, next, ¬ify_fds, list) { + if (FD_ISSET(s->fd, &LastSelectMask)) { + s->notify(s->fd, X_NOTIFY_READ, s->data); + } + } +} + /***************** * OnlyListenToOneClient: * Only accept requests from one client. Continue to handle new diff --git a/os/osdep.h b/os/osdep.h index 86263a53e..2bfc783f0 100644 --- a/os/osdep.h +++ b/os/osdep.h @@ -159,6 +159,10 @@ extern int FlushClient(ClientPtr /*who */ , extern void FreeOsBuffers(OsCommPtr /*oc */ ); +extern void InitNotifyFds(void); + +extern void HandleNotifyFds(void); + #include "dix.h" extern fd_set AllSockets; @@ -166,6 +170,7 @@ extern fd_set AllClients; extern fd_set LastSelectMask; extern fd_set WellKnownConnections; extern fd_set EnabledDevices; +extern fd_set NotifyReadFds; extern fd_set ClientsWithInput; extern fd_set ClientsWriteBlocked; extern fd_set OutputPending; diff --git a/os/osinit.c b/os/osinit.c index 6ec2f1167..54b39a0e8 100644 --- a/os/osinit.c +++ b/os/osinit.c @@ -314,6 +314,7 @@ OsInit(void) LockServer(); been_here = TRUE; } + InitNotifyFds(); TimerInit(); OsVendorInit(); OsResetSignals(); |