xserver

xserver with xephyr scale patch
git clone https://git.neptards.moe/u3shit/xserver.git
Log | Files | Refs | README | LICENSE

xserver_poll.c (8662B)


      1 /*---------------------------------------------------------------------------*\
      2   $Id$
      3 
      4   NAME
      5 
      6 	poll - select(2)-based poll() emulation function for BSD systems.
      7 
      8   SYNOPSIS
      9 	#include "poll.h"
     10 
     11 	struct pollfd
     12 	{
     13 	    int     fd;
     14 	    short   events;
     15 	    short   revents;
     16 	}
     17 
     18 	int poll (struct pollfd *pArray, unsigned long n_fds, int timeout)
     19 
     20   DESCRIPTION
     21 
     22 	This file, and the accompanying "poll.h", implement the System V
     23 	poll(2) system call for BSD systems (which typically do not provide
     24 	poll()).  Poll() provides a method for multiplexing input and output
     25 	on multiple open file descriptors; in traditional BSD systems, that
     26 	capability is provided by select().  While the semantics of select()
     27 	differ from those of poll(), poll() can be readily emulated in terms
     28 	of select() -- which is how this function is implemented.
     29 
     30   REFERENCES
     31 	Stevens, W. Richard. Unix Network Programming.  Prentice-Hall, 1990.
     32 
     33   NOTES
     34 	1. This software requires an ANSI C compiler.
     35 
     36   LICENSE
     37 
     38   This software is released under the following BSD license, adapted from
     39   http://opensource.org/licenses/bsd-license.php
     40 
     41   Copyright (c) 1995-2011, Brian M. Clapper
     42   All rights reserved.
     43 
     44   Redistribution and use in source and binary forms, with or without
     45   modification, are permitted provided that the following conditions are met:
     46 
     47   * Redistributions of source code must retain the above copyright notice,
     48     this list of conditions and the following disclaimer.
     49 
     50   * Redistributions in binary form must reproduce the above copyright
     51     notice, this list of conditions and the following disclaimer in the
     52     documentation and/or other materials provided with the distribution.
     53 
     54   * Neither the name of the clapper.org nor the names of its contributors
     55     may be used to endorse or promote products derived from this software
     56     without specific prior written permission.
     57 
     58   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
     59   IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
     60   THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     61   PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
     62   CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
     63   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     64   PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
     65   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
     66   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
     67   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
     68   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     69 \*---------------------------------------------------------------------------*/
     70 
     71 
     72 /*---------------------------------------------------------------------------*\
     73 				 Includes
     74 \*---------------------------------------------------------------------------*/
     75 
     76 #ifdef HAVE_DIX_CONFIG_H
     77 #include <dix-config.h>
     78 #endif
     79 
     80 #include <unistd.h>			     /* standard Unix definitions */
     81 #include <sys/types.h>                       /* system types */
     82 #include <sys/time.h>                        /* time definitions */
     83 #include <assert.h>                          /* assertion macros */
     84 #include <string.h>                          /* string functions */
     85 #include "xserver_poll.h"
     86 
     87 #if defined(WIN32) && !defined(__CYGWIN__)
     88 #include <X11/Xwinsock.h>
     89 #endif
     90 
     91 /*---------------------------------------------------------------------------*\
     92 				  Macros
     93 \*---------------------------------------------------------------------------*/
     94 
     95 #ifndef MAX
     96 #define MAX(a,b)	((a) > (b) ? (a) : (b))
     97 #endif
     98 
     99 /*---------------------------------------------------------------------------*\
    100 			     Private Functions
    101 \*---------------------------------------------------------------------------*/
    102 
    103 static int map_poll_spec
    104 			(struct pollfd *pArray,
    105                          nfds_t         n_fds,
    106 			  fd_set        *pReadSet,
    107 			  fd_set        *pWriteSet,
    108 			  fd_set        *pExceptSet)
    109 {
    110     register nfds_t  i;                      /* loop control */
    111     register struct  pollfd *pCur;           /* current array element */
    112     register int     max_fd = -1;            /* return value */
    113 
    114     /*
    115        Map the poll() structures into the file descriptor sets required
    116        by select().
    117     */
    118     for (i = 0, pCur = pArray; i < n_fds; i++, pCur++)
    119     {
    120         /* Skip any bad FDs in the array. */
    121 
    122         if (pCur->fd < 0)
    123             continue;
    124 
    125 	if (pCur->events & POLLIN)
    126 	{
    127 	    /* "Input Ready" notification desired. */
    128 	    FD_SET (pCur->fd, pReadSet);
    129 	}
    130 
    131 	if (pCur->events & POLLOUT)
    132 	{
    133 	    /* "Output Possible" notification desired. */
    134 	    FD_SET (pCur->fd, pWriteSet);
    135 	}
    136 
    137 	if (pCur->events & POLLPRI)
    138 	{
    139 	    /*
    140 	       "Exception Occurred" notification desired.  (Exceptions
    141 	       include out of band data.
    142 	    */
    143 	    FD_SET (pCur->fd, pExceptSet);
    144 	}
    145 
    146 	max_fd = MAX (max_fd, pCur->fd);
    147     }
    148 
    149     return max_fd;
    150 }
    151 
    152 static struct timeval *map_timeout
    153 			(int poll_timeout, struct timeval *pSelTimeout)
    154 {
    155     struct timeval *pResult;
    156 
    157     /*
    158        Map the poll() timeout value into a select() timeout.  The possible
    159        values of the poll() timeout value, and their meanings, are:
    160 
    161        VALUE	MEANING
    162 
    163        -1	wait indefinitely (until signal occurs)
    164         0	return immediately, don't block
    165        >0	wait specified number of milliseconds
    166 
    167        select() uses a "struct timeval", which specifies the timeout in
    168        seconds and microseconds, so the milliseconds value has to be mapped
    169        accordingly.
    170     */
    171 
    172     assert (pSelTimeout != (struct timeval *) NULL);
    173 
    174     switch (poll_timeout)
    175     {
    176 	case -1:
    177 	    /*
    178 	       A NULL timeout structure tells select() to wait indefinitely.
    179 	    */
    180 	    pResult = (struct timeval *) NULL;
    181 	    break;
    182 
    183 	case 0:
    184 	    /*
    185 	       "Return immediately" (test) is specified by all zeros in
    186 	       a timeval structure.
    187 	    */
    188 	    pSelTimeout->tv_sec  = 0;
    189 	    pSelTimeout->tv_usec = 0;
    190 	    pResult = pSelTimeout;
    191 	    break;
    192 
    193 	default:
    194 	    /* Wait the specified number of milliseconds. */
    195 	    pSelTimeout->tv_sec  = poll_timeout / 1000; /* get seconds */
    196 	    poll_timeout        %= 1000;                /* remove seconds */
    197 	    pSelTimeout->tv_usec = poll_timeout * 1000; /* get microseconds */
    198 	    pResult = pSelTimeout;
    199 	    break;
    200     }
    201 
    202 
    203     return pResult;
    204 }
    205 
    206 static void map_select_results
    207 			 (struct pollfd *pArray,
    208 			  unsigned long  n_fds,
    209 			  fd_set        *pReadSet,
    210 			  fd_set        *pWriteSet,
    211 			  fd_set        *pExceptSet)
    212 {
    213     register unsigned long  i;                   /* loop control */
    214     register struct	    pollfd *pCur;        /* current array element */
    215 
    216     for (i = 0, pCur = pArray; i < n_fds; i++, pCur++)
    217     {
    218         /* Skip any bad FDs in the array. */
    219 
    220         if (pCur->fd < 0)
    221             continue;
    222 
    223 	/* Exception events take priority over input events. */
    224 
    225 	pCur->revents = 0;
    226 	if (FD_ISSET (pCur->fd, pExceptSet))
    227 	    pCur->revents |= POLLPRI;
    228 
    229 	else if (FD_ISSET (pCur->fd, pReadSet))
    230 	    pCur->revents |= POLLIN;
    231 
    232 	if (FD_ISSET (pCur->fd, pWriteSet))
    233 	    pCur->revents |= POLLOUT;
    234     }
    235 
    236     return;
    237 }
    238 
    239 /*---------------------------------------------------------------------------*\
    240 			     Public Functions
    241 \*---------------------------------------------------------------------------*/
    242 
    243 int xserver_poll
    244 	(struct pollfd *pArray, unsigned long n_fds, int timeout)
    245 {
    246     fd_set  read_descs;                          /* input file descs */
    247     fd_set  write_descs;                         /* output file descs */
    248     fd_set  except_descs;                        /* exception descs */
    249     struct  timeval stime;                       /* select() timeout value */
    250     int	    ready_descriptors;                   /* function result */
    251     int	    max_fd;                              /* maximum fd value */
    252     struct  timeval *pTimeout;                   /* actually passed */
    253 
    254     FD_ZERO (&read_descs);
    255     FD_ZERO (&write_descs);
    256     FD_ZERO (&except_descs);
    257 
    258     assert (pArray != (struct pollfd *) NULL);
    259 
    260     /* Map the poll() file descriptor list in the select() data structures. */
    261 
    262     max_fd = map_poll_spec (pArray, n_fds,
    263 			    &read_descs, &write_descs, &except_descs);
    264 
    265     /* Map the poll() timeout value in the select() timeout structure. */
    266 
    267     pTimeout = map_timeout (timeout, &stime);
    268 
    269     /* Make the select() call. */
    270 
    271     ready_descriptors = select (max_fd + 1, &read_descs, &write_descs,
    272 				&except_descs, pTimeout);
    273 
    274     if (ready_descriptors >= 0)
    275     {
    276 	map_select_results (pArray, n_fds,
    277 			    &read_descs, &write_descs, &except_descs);
    278     }
    279 
    280     return ready_descriptors;
    281 }