From 86110d6edadef2d9fbcd3ee0d008696bfcf7dcd4 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 9 Feb 2017 13:45:12 +0100 Subject: os: Add NotifyFd interfaces Backported from X.org: commit 0c41b7af4ab0c8d22b88f201293f59524d1e7317 Author: Keith Packard Date: Wed Nov 11 22:02:02 2015 -0800 os: Add NotifyFd interfaces This provides a callback-based interface to monitor file descriptors beyond the usual client and device interfaces. Modules within the server using file descriptors for reading and/or writing can call Bool SetNotifyFd(int fd, NotifyFdProcPtr notify_fd, int mask, void *data); mask can be any combination of X_NOTIFY_READ and X_NOTIFY_WRITE. When 'fd' becomes readable or writable, the notify_fd function will be called with the 'fd', the ready conditions and 'data' values as arguments, When the module no longer needs to monitor the fd, it will call void RemoveNotifyFd(int fd); RemoveNotifyFd may be called from the notify function. Reviewed-by: Adam Jackson Signed-off-by: Keith Packard Backported-to-NX-by: Mike Gabriel --- nx-X11/programs/Xserver/include/os.h | 13 +++++ nx-X11/programs/Xserver/os/WaitFor.c | 5 ++ nx-X11/programs/Xserver/os/connection.c | 94 +++++++++++++++++++++++++++++++++ nx-X11/programs/Xserver/os/osdep.h | 5 ++ nx-X11/programs/Xserver/os/osinit.c | 1 + 5 files changed, 118 insertions(+) diff --git a/nx-X11/programs/Xserver/include/os.h b/nx-X11/programs/Xserver/include/os.h index 0fd687d18..dfcc639d3 100644 --- a/nx-X11/programs/Xserver/include/os.h +++ b/nx-X11/programs/Xserver/include/os.h @@ -147,6 +147,19 @@ extern void AddEnabledDevice(int /*fd*/); extern void RemoveEnabledDevice(int /*fd*/); +typedef void (*NotifyFdProcPtr)(int fd, int ready, void *data); + +#define X_NOTIFY_NONE 0 +#define X_NOTIFY_READ 1 +#define X_NOTIFY_WRITE 2 + +extern Bool SetNotifyFd(int fd, NotifyFdProcPtr notify_fd, int mask, void *data); + +static inline void RemoveNotifyFd(int fd) +{ + (void) SetNotifyFd(fd, NULL, X_NOTIFY_NONE, NULL); +} + extern void OnlyListenToOneClient(ClientPtr /*client*/); extern void ListenToAllClients(void); diff --git a/nx-X11/programs/Xserver/os/WaitFor.c b/nx-X11/programs/Xserver/os/WaitFor.c index 0ecca8b7a..19a1b9809 100644 --- a/nx-X11/programs/Xserver/os/WaitFor.c +++ b/nx-X11/programs/Xserver/os/WaitFor.c @@ -504,6 +504,11 @@ WaitForSomething(int *pClientsReady) if (XFD_ANYSET(&tmp_set)) QueueWorkProc(EstablishNewConnections, NULL, (void *)&LastSelectMask); + + XFD_ANDSET(&tmp_set, &LastSelectMask, &NotifyReadFds); + if (XFD_ANYSET(&tmp_set)) + HandleNotifyFds(); + #ifdef DPMSExtension if (XFD_ANYSET (&devicesReadable) && (DPMSPowerLevel != DPMSModeOn)) DPMSSet(DPMSModeOn); diff --git a/nx-X11/programs/Xserver/os/connection.c b/nx-X11/programs/Xserver/os/connection.c index 458daab54..23df49883 100644 --- a/nx-X11/programs/Xserver/os/connection.c +++ b/nx-X11/programs/Xserver/os/connection.c @@ -108,6 +108,7 @@ SOFTWARE. #include #include "opaque.h" #include "dixstruct.h" +#include "list.h" #ifdef XCSECURITY #define _SECURITY_SERVER #include @@ -123,6 +124,7 @@ 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 */ @@ -1013,6 +1015,98 @@ RemoveEnabledDevice(int fd) FD_CLR(fd, &SavedAllSockets); } +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/nx-X11/programs/Xserver/os/osdep.h b/nx-X11/programs/Xserver/os/osdep.h index f0e8b707b..dce44e612 100644 --- a/nx-X11/programs/Xserver/os/osdep.h +++ b/nx-X11/programs/Xserver/os/osdep.h @@ -188,6 +188,10 @@ extern void FreeOsBuffers( OsCommPtr /*oc*/ ); +extern void InitNotifyFds(void); + +extern void HandleNotifyFds(void); + #include "dix.h" extern ConnectionInputPtr AllocateInputBuffer(void); @@ -199,6 +203,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/nx-X11/programs/Xserver/os/osinit.c b/nx-X11/programs/Xserver/os/osinit.c index adafa3cf4..e1986a577 100644 --- a/nx-X11/programs/Xserver/os/osinit.c +++ b/nx-X11/programs/Xserver/os/osinit.c @@ -203,6 +203,7 @@ OsInit(void) #endif been_here = TRUE; } + InitNotifyFds(); TimerInit(); #ifdef DDXOSINIT OsVendorInit(); -- cgit v1.2.3