[PATCH xserver 1/2] os: Add poll emulation for mingw [v2]

Keith Packard keithp at keithp.com
Mon Jul 18 23:28:18 UTC 2016


From: "Brian M. Clapper" <bmc at clapper.org>

v2: rename as 'xserver_poll' to avoid potential library name
    collisions. Provide 'xserver_poll.h' which uses the system
    poll where available and falls back to this emulation otherwise.
    Autodetects when this is required, building the emulation only
    then

Source: https://github.com/bmc/poll
Signed-off-by: Adam Jackson <ajax at redhat.com>
---
 configure.ac            |   3 +-
 include/dix-config.h.in |   3 +
 include/xserver_poll.h  |  55 ++++++++++
 os/Makefile.am          |   7 ++
 os/xserver_poll.c       | 277 ++++++++++++++++++++++++++++++++++++++++++++++++
 5 files changed, 344 insertions(+), 1 deletion(-)
 create mode 100644 include/xserver_poll.h
 create mode 100644 os/xserver_poll.c

diff --git a/configure.ac b/configure.ac
index 52466d1..58fcf79 100644
--- a/configure.ac
+++ b/configure.ac
@@ -219,9 +219,10 @@ dnl Checks for library functions.
 AC_CHECK_FUNCS([backtrace ffs geteuid getuid issetugid getresuid \
 	getdtablesize getifaddrs getpeereid getpeerucred getprogname getzoneid \
 	mmap posix_fallocate seteuid shmctl64 strncasecmp vasprintf vsnprintf \
-	walkcontext setitimer])
+	walkcontext setitimer poll])
 AC_CONFIG_LIBOBJ_DIR([os])
 AC_REPLACE_FUNCS([reallocarray strcasecmp strcasestr strlcat strlcpy strndup])
+AM_CONDITIONAL(POLL, [test "x$ac_cv_func_poll" = "xyes"])
 
 AC_CHECK_DECLS([program_invocation_short_name], [], [], [[#include <errno.h>]])
 
diff --git a/include/dix-config.h.in b/include/dix-config.h.in
index fc7d1a1..bf2a9ed 100644
--- a/include/dix-config.h.in
+++ b/include/dix-config.h.in
@@ -527,4 +527,7 @@
 /* Use input thread */
 #undef INPUTTHREAD
 
+/* Have poll() */
+#undef HAVE_POLL
+
 #endif /* _DIX_CONFIG_H_ */
diff --git a/include/xserver_poll.h b/include/xserver_poll.h
new file mode 100644
index 0000000..110d30c
--- /dev/null
+++ b/include/xserver_poll.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright © 2016 Keith Packard
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of the copyright holders not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission.  The copyright holders make no representations
+ * about the suitability of this software for any purpose.  It is provided "as
+ * is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+
+#ifndef _XSERVER_POLL_H_
+#define _XSERVER_POLL_H_
+
+#ifndef _DIX_CONFIG_H_
+#error must inclue dix-config.h to use xserver_poll.h
+#endif
+
+#if HAVE_POLL
+#include <poll.h>
+#define xserver_poll(fds, nfds, timeout) poll(fds, nfds, timeout)
+#else
+
+#define POLLIN		0x01
+#define POLLPRI		0x02
+#define POLLOUT		0x04
+#define POLLERR		0x08
+#define POLLHUP		0x10
+#define POLLNVAL	0x20
+
+struct pollfd
+{
+    int     fd;
+    short   events;
+    short   revents;
+};
+
+typedef unsigned long nfds_t;
+
+int xserver_poll (struct pollfd *pArray, nfds_t n_fds, int timeout);
+
+#endif
+
+#endif /* _XSERVER_POLL_H_ */
diff --git a/os/Makefile.am b/os/Makefile.am
index fc49a73..c449076 100644
--- a/os/Makefile.am
+++ b/os/Makefile.am
@@ -7,6 +7,8 @@ XDMCP_SRCS = xdmcp.c
 XORG_SRCS = log.c
 BUSFAULT_SRCS = busfault.c
 
+XSERVER_POLL_SRCS=xserver_poll.c
+
 libos_la_SOURCES = 	\
 	WaitFor.c	\
 	access.c	\
@@ -32,6 +34,11 @@ if SECURE_RPC
 libos_la_SOURCES += $(SECURERPC_SRCS)
 endif
 
+if POLL
+else
+libos_la_SOURCES += $(XSERVER_POLL_SRCS)
+endif
+
 if XDMCP
 libos_la_SOURCES += $(XDMCP_SRCS)
 endif
diff --git a/os/xserver_poll.c b/os/xserver_poll.c
new file mode 100644
index 0000000..f152cda
--- /dev/null
+++ b/os/xserver_poll.c
@@ -0,0 +1,277 @@
+/*---------------------------------------------------------------------------*\
+  $Id$
+
+  NAME
+
+	poll - select(2)-based poll() emulation function for BSD systems.
+
+  SYNOPSIS
+	#include "poll.h"
+
+	struct pollfd
+	{
+	    int     fd;
+	    short   events;
+	    short   revents;
+	}
+
+	int poll (struct pollfd *pArray, unsigned long n_fds, int timeout)
+
+  DESCRIPTION
+
+	This file, and the accompanying "poll.h", implement the System V
+	poll(2) system call for BSD systems (which typically do not provide
+	poll()).  Poll() provides a method for multiplexing input and output
+	on multiple open file descriptors; in traditional BSD systems, that
+	capability is provided by select().  While the semantics of select()
+	differ from those of poll(), poll() can be readily emulated in terms
+	of select() -- which is how this function is implemented.
+
+  REFERENCES
+	Stevens, W. Richard. Unix Network Programming.  Prentice-Hall, 1990.
+
+  NOTES
+	1. This software requires an ANSI C compiler.
+
+  LICENSE
+
+  This software is released under the following BSD license, adapted from
+  http://opensource.org/licenses/bsd-license.php
+
+  Copyright (c) 1995-2011, Brian M. Clapper
+  All rights reserved.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions are met:
+
+  * Redistributions of source code must retain the above copyright notice,
+    this list of conditions and the following disclaimer.
+
+  * Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimer in the
+    documentation and/or other materials provided with the distribution.
+
+  * Neither the name of the clapper.org nor the names of its contributors
+    may be used to endorse or promote products derived from this software
+    without specific prior written permission.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+  IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+  THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+  PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+\*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*\
+				 Includes
+\*---------------------------------------------------------------------------*/
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#include <unistd.h>			     /* standard Unix definitions */
+#include <sys/types.h>                       /* system types */
+#include <sys/time.h>                        /* time definitions */
+#include <assert.h>                          /* assertion macros */
+#include <string.h>                          /* string functions */
+#include "xserver_poll.h"
+
+/*---------------------------------------------------------------------------*\
+				  Macros
+\*---------------------------------------------------------------------------*/
+
+#ifndef MAX
+#define MAX(a,b)	((a) > (b) ? (a) : (b))
+#endif
+
+/*---------------------------------------------------------------------------*\
+			     Private Functions
+\*---------------------------------------------------------------------------*/
+
+static int map_poll_spec
+			(struct pollfd *pArray,
+                         nfds_t         n_fds,
+			  fd_set        *pReadSet,
+			  fd_set        *pWriteSet,
+			  fd_set        *pExceptSet)
+{
+    register nfds_t  i;                      /* loop control */
+    register struct  pollfd *pCur;           /* current array element */
+    register int     max_fd = -1;            /* return value */
+
+    /*
+       Map the poll() structures into the file descriptor sets required
+       by select().
+    */
+    for (i = 0, pCur = pArray; i < n_fds; i++, pCur++)
+    {
+        /* Skip any bad FDs in the array. */
+
+        if (pCur->fd < 0)
+            continue;
+
+	if (pCur->events & POLLIN)
+	{
+	    /* "Input Ready" notification desired. */
+	    FD_SET (pCur->fd, pReadSet);
+	}
+
+	if (pCur->events & POLLOUT)
+	{
+	    /* "Output Possible" notification desired. */
+	    FD_SET (pCur->fd, pWriteSet);
+	}
+
+	if (pCur->events & POLLPRI)
+	{
+	    /*
+	       "Exception Occurred" notification desired.  (Exceptions
+	       include out of band data.
+	    */
+	    FD_SET (pCur->fd, pExceptSet);
+	}
+
+	max_fd = MAX (max_fd, pCur->fd);
+    }
+
+    return max_fd;
+}
+
+static struct timeval *map_timeout
+			(int poll_timeout, struct timeval *pSelTimeout)
+{
+    struct timeval *pResult;
+
+    /*
+       Map the poll() timeout value into a select() timeout.  The possible
+       values of the poll() timeout value, and their meanings, are:
+
+       VALUE	MEANING
+
+       -1	wait indefinitely (until signal occurs)
+        0	return immediately, don't block
+       >0	wait specified number of milliseconds
+
+       select() uses a "struct timeval", which specifies the timeout in
+       seconds and microseconds, so the milliseconds value has to be mapped
+       accordingly.
+    */
+
+    assert (pSelTimeout != (struct timeval *) NULL);
+
+    switch (poll_timeout)
+    {
+	case -1:
+	    /*
+	       A NULL timeout structure tells select() to wait indefinitely.
+	    */
+	    pResult = (struct timeval *) NULL;
+	    break;
+
+	case 0:
+	    /*
+	       "Return immediately" (test) is specified by all zeros in
+	       a timeval structure.
+	    */
+	    pSelTimeout->tv_sec  = 0;
+	    pSelTimeout->tv_usec = 0;
+	    pResult = pSelTimeout;
+	    break;
+
+	default:
+	    /* Wait the specified number of milliseconds. */
+	    pSelTimeout->tv_sec  = poll_timeout / 1000; /* get seconds */
+	    poll_timeout        %= 1000;                /* remove seconds */
+	    pSelTimeout->tv_usec = poll_timeout * 1000; /* get microseconds */
+	    pResult = pSelTimeout;
+	    break;
+    }
+
+
+    return pResult;
+}
+
+static void map_select_results
+			 (struct pollfd *pArray,
+			  unsigned long  n_fds,
+			  fd_set        *pReadSet,
+			  fd_set        *pWriteSet,
+			  fd_set        *pExceptSet)
+{
+    register unsigned long  i;                   /* loop control */
+    register struct	    pollfd *pCur;        /* current array element */
+
+    for (i = 0, pCur = pArray; i < n_fds; i++, pCur++)
+    {
+        /* Skip any bad FDs in the array. */
+
+        if (pCur->fd < 0)
+            continue;
+
+	/* Exception events take priority over input events. */
+
+	pCur->revents = 0;
+	if (FD_ISSET (pCur->fd, pExceptSet))
+	    pCur->revents |= POLLPRI;
+
+	else if (FD_ISSET (pCur->fd, pReadSet))
+	    pCur->revents |= POLLIN;
+
+	if (FD_ISSET (pCur->fd, pWriteSet))
+	    pCur->revents |= POLLOUT;
+    }
+
+    return;
+}
+
+/*---------------------------------------------------------------------------*\
+			     Public Functions
+\*---------------------------------------------------------------------------*/
+
+int xserver_poll
+	(struct pollfd *pArray, unsigned long n_fds, int timeout)
+{
+    fd_set  read_descs;                          /* input file descs */
+    fd_set  write_descs;                         /* output file descs */
+    fd_set  except_descs;                        /* exception descs */
+    struct  timeval stime;                       /* select() timeout value */
+    int	    ready_descriptors;                   /* function result */
+    int	    max_fd;                              /* maximum fd value */
+    struct  timeval *pTimeout;                   /* actually passed */
+
+    FD_ZERO (&read_descs);
+    FD_ZERO (&write_descs);
+    FD_ZERO (&except_descs);
+
+    assert (pArray != (struct pollfd *) NULL);
+
+    /* Map the poll() file descriptor list in the select() data structures. */
+
+    max_fd = map_poll_spec (pArray, n_fds,
+			    &read_descs, &write_descs, &except_descs);
+
+    /* Map the poll() timeout value in the select() timeout structure. */
+
+    pTimeout = map_timeout (timeout, &stime);
+
+    /* Make the select() call. */
+
+    ready_descriptors = select (max_fd + 1, &read_descs, &write_descs,
+				&except_descs, pTimeout);
+
+    if (ready_descriptors >= 0)
+    {
+	map_select_results (pArray, n_fds,
+			    &read_descs, &write_descs, &except_descs);
+    }
+
+    return ready_descriptors;
+}
-- 
2.8.1



More information about the xorg-devel mailing list