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