[PATCH] Add APIs for selecting on write fds.
Peter Hutterer
peter.hutterer at who-t.net
Tue Jun 19 18:04:28 PDT 2012
On Tue, Jun 19, 2012 at 12:00:12PM -0700, Keith Packard wrote:
> This adds API support for waking the server when an fd becomes
> writable.
>
> void AddWriteSocket(int fd);
>
> Add an FD to the select write mask; the server will wake when
> this fd is writable.
>
> void RemoveWriteSocket(int fd);
>
> Remove the FD from the select write mask.
>
> Note that there is no automated mechanism for emptying the set of
> fds. The caller is responsible for removing the fd whenever
> appropriate, including when the fd is closed, and when the
> user no longer has pending write data.
>
> Bool CheckWriteSocket(int fd);
>
> Checks if the last select call marked this fd as
> writable. This value persists until select is called again.
>
> This patch also adds a helper function for sockets used for reading:
>
> Bool CheckReadSocket(int fd);
>
> A matching function that checks for fds marked as readable
> that have been added with AddGeneralSocket or
> AddEnabledDevice.
shouldn't the documentatin for the calls be in the code? looking up git
commits to understand functions doesn't scale too well.
> The mechanism used is to keep a separate fd_set of write sockets, and
> OR that with the client write mask to create a global select write
> mask. The only other change necessary in WaitFor is to mask out the
> resulting non-client fds when checking for unblocked client sockets.
>
> Signed-off-by: Keith Packard <keithp at keithp.com>
> ---
> include/os.h | 8 ++++++
> os/WaitFor.c | 79 +++++++++++++++++++++++++++++++++++++++++++++++++++-------
> 2 files changed, 78 insertions(+), 9 deletions(-)
>
> diff --git a/include/os.h b/include/os.h
> index 276eb52..efb2b65 100644
> --- a/include/os.h
> +++ b/include/os.h
> @@ -157,6 +157,14 @@ extern _X_EXPORT void MakeClientGrabImpervious(ClientPtr /*client */ );
>
> extern _X_EXPORT void MakeClientGrabPervious(ClientPtr /*client */ );
>
> +extern _X_EXPORT void AddWriteSocket(int fd);
> +
> +extern _X_EXPORT void RemoveWriteSocket(int fd);
> +
> +extern _X_EXPORT Bool CheckWriteSocket(int fd);
> +
> +extern _X_EXPORT Bool CheckReadSocket(int fd);
> +
> #ifdef XQUARTZ
> extern void ListenOnOpenFD(int /* fd */ , int /* noxauth */ );
> #endif
> diff --git a/os/WaitFor.c b/os/WaitFor.c
> index 393890f..bf03273 100644
> --- a/os/WaitFor.c
> +++ b/os/WaitFor.c
> @@ -123,6 +123,62 @@ struct _OsTimerRec {
> static void DoTimer(OsTimerPtr timer, CARD32 now, OsTimerPtr *prev);
> static void CheckAllTimers(void);
> static OsTimerPtr timers = NULL;
> +static fd_set WriteSelectMask;
> +static Bool AnyWriteSelectMask;
> +static fd_set LastSelectWriteMask;
> +
> +/*****************
> + * AddWriteSocket:
> + * Add 'fd' to the list of write descriptors that will
> + * wake the server from select.
> + */
> +
> +void
> +AddWriteSocket(int fd)
> +{
> + FD_SET(fd, &WriteSelectMask);
> + AnyWriteSelectMask = TRUE;
> +}
> +
> +/*****************
> + * RemoveWriteSocket:
> + * Remove 'fd' from the list of write descriptors that will
> + * wake the server from select.
> + */
> +
> +void
> +RemoveWriteSocket(int fd)
> +{
> + FD_CLR(fd, &WriteSelectMask);
> + AnyWriteSelectMask = XFD_ANYSET(&WriteSelectMask);
> +}
> +
> +/*****************
> + * CheckWriteSocket:
> + * Called from a WakeupHandler to check of 'fd'
> + * was marked as writable during the last select
> + * call
> + */
> +
> +Bool
> +CheckWriteSocket(int fd)
> +{
> + return AnyWriteSelectMask && FD_ISSET(fd, &LastSelectWriteMask);
> +}
> +
> +/*****************
> + * CheckReadSocket:
> + * Called from a WakeupHandler to check of 'fd'
s/of/if/
> + * was marked as readable during the last select
> + * call
> + */
> +
> +Bool
> +CheckReadSocket(int fd)
> +{
> + return FD_ISSET(fd, &LastSelectMask);
> +}
> +
>
> /*****************
> * WaitForSomething:
> @@ -213,9 +269,11 @@ WaitForSomething(int *pClientsReady)
> /* keep this check close to select() call to minimize race */
> if (dispatchException)
> i = -1;
> - else if (AnyClientsWriteBlocked) {
> - XFD_COPYSET(&ClientsWriteBlocked, &clientsWritable);
> - i = Select(MaxClients, &LastSelectMask, &clientsWritable, NULL, wt);
> + else if (AnyClientsWriteBlocked || AnyWriteSelectMask) {
> + XFD_COPYSET(&ClientsWriteBlocked, &LastSelectWriteMask);
> + if (AnyWriteSelectMask)
> + XFD_ORSET(&LastSelectWriteMask, &WriteSelectMask, &LastSelectWriteMask);
> + i = Select(MaxClients, &LastSelectMask, &LastSelectWriteMask, NULL, wt);
> }
> else {
> i = Select(MaxClients, &LastSelectMask, NULL, NULL, wt);
> @@ -285,12 +343,15 @@ WaitForSomething(int *pClientsReady)
> }
> if (someReady)
> XFD_ORSET(&LastSelectMask, &ClientsWithInput, &LastSelectMask);
> - if (AnyClientsWriteBlocked && XFD_ANYSET(&clientsWritable)) {
> - NewOutputPending = TRUE;
> - XFD_ORSET(&OutputPending, &clientsWritable, &OutputPending);
> - XFD_UNSET(&ClientsWriteBlocked, &clientsWritable);
> - if (!XFD_ANYSET(&ClientsWriteBlocked))
> - AnyClientsWriteBlocked = FALSE;
> + if (AnyClientsWriteBlocked) {
> + XFD_ANDSET(&clientsWritable, &LastSelectWriteMask, &ClientsWriteBlocked);
> + if (XFD_ANYSET(&clientsWritable)) {
> + NewOutputPending = TRUE;
> + XFD_ORSET(&OutputPending, &clientsWritable, &OutputPending);
> + XFD_UNSET(&ClientsWriteBlocked, &clientsWritable);
> + if (!XFD_ANYSET(&ClientsWriteBlocked))
> + AnyClientsWriteBlocked = FALSE;
> + }
> }
>
> XFD_ANDSET(&devicesReadable, &LastSelectMask, &EnabledDevices);
> --
> 1.7.10
please fix your indentation settings, these should be spaces, not tabs.
Acked-by: Peter Hutterer <peter.hutterer at who-t.net> otherwise
Cheers,
Peter
More information about the xorg-devel
mailing list