[PATCH 1/2] Add APIs for selecting on write fds.

Keith Packard keithp at keithp.com
Wed Jun 20 12:09:07 PDT 2012


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.

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.

v2: (from review by Peter Hutterer)
	Clean up whitespace (spaces, not tabs)
	Extend documentation in the code to include everything
	in the commit message.

Signed-off-by: Keith Packard <keithp at keithp.com>
---
 include/os.h |    8 ++++++
 os/WaitFor.c |   87 ++++++++++++++++++++++++++++++++++++++++++++++++++++------
 2 files changed, 86 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..537d678 100644
--- a/os/WaitFor.c
+++ b/os/WaitFor.c
@@ -123,6 +123,70 @@ 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.
+ *
+ *     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.
+ */
+
+void
+RemoveWriteSocket(int fd)
+{
+    FD_CLR(fd, &WriteSelectMask);
+    AnyWriteSelectMask = XFD_ANYSET(&WriteSelectMask);
+}
+
+/*****************
+ * CheckWriteSocket:
+ *     Called from a WakeupHandler to check if 'fd'
+ *     was marked as writable during the last select
+ *     call. This value persists until select is called again.
+ */
+
+Bool
+CheckWriteSocket(int fd)
+{
+    return AnyWriteSelectMask && FD_ISSET(fd, &LastSelectWriteMask);
+}
+
+/*****************
+ * CheckReadSocket:
+ *     Called from a WakeupHandler to check of 'fd'
+ *     was marked as readable during the last select
+ *     call
+ *
+ *     A matching function that checks for fds marked as readable that
+ *     have been added with AddGeneralSocket or AddEnabledDevice.
+ */
+
+Bool
+CheckReadSocket(int fd)
+{
+    return FD_ISSET(fd, &LastSelectMask);
+}
+
 
 /*****************
  * WaitForSomething:
@@ -213,9 +277,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 +351,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



More information about the xorg-devel mailing list