[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