ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/gvpe/lib/poll.c
Revision: 1.3
Committed: Sat Jan 17 01:18:36 2004 UTC (20 years, 4 months ago) by pcg
Content type: text/plain
Branch: MAIN
CVS Tags: HEAD
Changes since 1.2: +1 -1 lines
State: FILE REMOVED
Log Message:
*** empty log message ***

File Contents

# User Rev Content
1 pcg 1.2 #if defined(HAVE_SYS_POLL_H) && defined(HAVE_POLL)
2     /* nothing to do, all is well, gore is president. */
3     #else
4    
5 pcg 1.1 /*---------------------------------------------------------------------------*\
6 pcg 1.3 $Id: poll.c,v 1.2 2003/10/14 19:14:27 pcg Exp $
7 pcg 1.1
8     NAME
9    
10     poll - select(2)-based poll() emulation function for BSD systems.
11    
12     SYNOPSIS
13     #include "poll.h"
14    
15     struct pollfd
16     {
17     int fd;
18     short events;
19     short revents;
20     }
21    
22     int poll (struct pollfd *pArray, unsigned long n_fds, int timeout)
23    
24     DESCRIPTION
25    
26     This file, and the accompanying "poll.h", implement the System V
27     poll(2) system call for BSD systems (which typically do not provide
28     poll()). Poll() provides a method for multiplexing input and output
29     on multiple open file descriptors; in traditional BSD systems, that
30     capability is provided by select(). While the semantics of select()
31     differ from those of poll(), poll() can be readily emulated in terms
32     of select() -- which is how this function is implemented.
33    
34     REFERENCES
35     Stevens, W. Richard. Unix Network Programming. Prentice-Hall, 1990.
36    
37     NOTES
38     1. This software requires an ANSI C compiler.
39    
40     LICENSE
41    
42     This software is released under the following license:
43    
44     Copyright (c) 1995-2002 Brian M. Clapper
45     All rights reserved.
46    
47     Redistribution and use in source and binary forms are
48     permitted provided that: (1) source distributions retain
49     this entire copyright notice and comment; (2) modifications
50     made to the software are prominently mentioned, and a copy
51     of the original software (or a pointer to its location) are
52     included; and (3) distributions including binaries display
53     the following acknowledgement: "This product includes
54     software developed by Brian M. Clapper <bmc@clapper.org>"
55     in the documentation or other materials provided with the
56     distribution. The name of the author may not be used to
57     endorse or promote products derived from this software
58     without specific prior written permission.
59    
60     THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS
61     OR IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE
62     IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
63     PARTICULAR PURPOSE.
64    
65     Effectively, this means you can do what you want with the software
66     except remove this notice or take advantage of the author's name.
67     If you modify the software and redistribute your modified version,
68     you must indicate that your version is a modification of the
69     original, and you must provide either a pointer to or a copy of the
70     original.
71     \*---------------------------------------------------------------------------*/
72    
73    
74     /*---------------------------------------------------------------------------*\
75     Includes
76     \*---------------------------------------------------------------------------*/
77    
78     #include <unistd.h> /* standard Unix definitions */
79     #include <sys/types.h> /* system types */
80     #include <sys/time.h> /* time definitions */
81     #include <assert.h> /* assertion macros */
82     #include <string.h> /* string functions */
83     #include "poll.h" /* this package */
84    
85     /*---------------------------------------------------------------------------*\
86     Macros
87     \*---------------------------------------------------------------------------*/
88    
89     #ifndef MAX
90     #define MAX(a,b) ((a) > (b) ? (a) : (b))
91     #endif
92    
93    
94     /*---------------------------------------------------------------------------*\
95     Private Functions
96     \*---------------------------------------------------------------------------*/
97    
98     static int map_poll_spec
99     #if __STDC__ > 0
100     (struct pollfd *pArray,
101     unsigned long n_fds,
102     fd_set *pReadSet,
103     fd_set *pWriteSet,
104     fd_set *pExceptSet)
105     #else
106     (pArray, n_fds, pReadSet, pWriteSet, pExceptSet)
107     struct pollfd *pArray;
108     unsigned long n_fds;
109     fd_set *pReadSet;
110     fd_set *pWriteSet;
111     fd_set *pExceptSet;
112     #endif
113     {
114     register unsigned long i; /* loop control */
115     register struct pollfd *pCur; /* current array element */
116     register int max_fd = -1; /* return value */
117    
118     /*
119     Map the poll() structures into the file descriptor sets required
120     by select().
121     */
122     for (i = 0, pCur = pArray; i < n_fds; i++, pCur++)
123     {
124     /* Skip any bad FDs in the array. */
125    
126     if (pCur->fd < 0)
127     continue;
128    
129     if (pCur->events & POLLIN)
130     {
131     /* "Input Ready" notification desired. */
132     FD_SET (pCur->fd, pReadSet);
133     }
134    
135     if (pCur->events & POLLOUT)
136     {
137     /* "Output Possible" notification desired. */
138     FD_SET (pCur->fd, pWriteSet);
139     }
140    
141     if (pCur->events & POLLPRI)
142     {
143     /*
144     "Exception Occurred" notification desired. (Exceptions
145     include out of band data.
146     */
147     FD_SET (pCur->fd, pExceptSet);
148     }
149    
150     max_fd = MAX (max_fd, pCur->fd);
151     }
152    
153     return max_fd;
154     }
155    
156     static struct timeval *map_timeout
157     #if __STDC__ > 0
158     (int poll_timeout, struct timeval *pSelTimeout)
159     #else
160     (poll_timeout, pSelTimeout)
161     int poll_timeout;
162     struct timeval *pSelTimeout;
163     #endif
164     {
165     struct timeval *pResult;
166    
167     /*
168     Map the poll() timeout value into a select() timeout. The possible
169     values of the poll() timeout value, and their meanings, are:
170    
171     VALUE MEANING
172    
173     -1 wait indefinitely (until signal occurs)
174     0 return immediately, don't block
175     >0 wait specified number of milliseconds
176    
177     select() uses a "struct timeval", which specifies the timeout in
178     seconds and microseconds, so the milliseconds value has to be mapped
179     accordingly.
180     */
181    
182     assert (pSelTimeout != (struct timeval *) NULL);
183    
184     switch (poll_timeout)
185     {
186     case -1:
187     /*
188     A NULL timeout structure tells select() to wait indefinitely.
189     */
190     pResult = (struct timeval *) NULL;
191     break;
192    
193     case 0:
194     /*
195     "Return immediately" (test) is specified by all zeros in
196     a timeval structure.
197     */
198     pSelTimeout->tv_sec = 0;
199     pSelTimeout->tv_usec = 0;
200     pResult = pSelTimeout;
201     break;
202    
203     default:
204     /* Wait the specified number of milliseconds. */
205     pSelTimeout->tv_sec = poll_timeout / 1000; /* get seconds */
206     poll_timeout %= 1000; /* remove seconds */
207     pSelTimeout->tv_usec = poll_timeout * 1000; /* get microseconds */
208     pResult = pSelTimeout;
209     break;
210     }
211    
212    
213     return pResult;
214     }
215    
216     static void map_select_results
217     #if __STDC__ > 0
218     (struct pollfd *pArray,
219     unsigned long n_fds,
220     fd_set *pReadSet,
221     fd_set *pWriteSet,
222     fd_set *pExceptSet)
223     #else
224     (pArray, n_fds, pReadSet, pWriteSet, pExceptSet)
225     struct pollfd *pArray;
226     unsigned long n_fds;
227     fd_set *pReadSet;
228     fd_set *pWriteSet;
229     fd_set *pExceptSet;
230     #endif
231     {
232     register unsigned long i; /* loop control */
233     register struct pollfd *pCur; /* current array element */
234    
235     for (i = 0, pCur = pArray; i < n_fds; i++, pCur++)
236     {
237     /* Skip any bad FDs in the array. */
238    
239     if (pCur->fd < 0)
240     continue;
241    
242     /* Exception events take priority over input events. */
243    
244     pCur->revents = 0;
245     if (FD_ISSET (pCur->fd, pExceptSet))
246     pCur->revents |= POLLPRI;
247    
248     else if (FD_ISSET (pCur->fd, pReadSet))
249     pCur->revents |= POLLIN;
250    
251     if (FD_ISSET (pCur->fd, pWriteSet))
252     pCur->revents |= POLLOUT;
253     }
254    
255     return;
256     }
257    
258     /*---------------------------------------------------------------------------*\
259     Public Functions
260     \*---------------------------------------------------------------------------*/
261    
262     int poll
263    
264     #if __STDC__ > 0
265     (struct pollfd *pArray, unsigned long n_fds, int timeout)
266     #else
267     (pArray, n_fds, timeout)
268     struct pollfd *pArray;
269     unsigned long n_fds;
270     int timeout;
271     #endif
272    
273     {
274     fd_set read_descs; /* input file descs */
275     fd_set write_descs; /* output file descs */
276     fd_set except_descs; /* exception descs */
277     struct timeval stime; /* select() timeout value */
278     int ready_descriptors; /* function result */
279     int max_fd; /* maximum fd value */
280     struct timeval *pTimeout; /* actually passed */
281    
282     FD_ZERO (&read_descs);
283     FD_ZERO (&write_descs);
284     FD_ZERO (&except_descs);
285    
286     assert (pArray != (struct pollfd *) NULL);
287    
288     /* Map the poll() file descriptor list in the select() data structures. */
289    
290     max_fd = map_poll_spec (pArray, n_fds,
291     &read_descs, &write_descs, &except_descs);
292    
293     /* Map the poll() timeout value in the select() timeout structure. */
294    
295     pTimeout = map_timeout (timeout, &stime);
296    
297     /* Make the select() call. */
298    
299     ready_descriptors = select (max_fd + 1, &read_descs, &write_descs,
300     &except_descs, pTimeout);
301    
302     if (ready_descriptors >= 0)
303     {
304     map_select_results (pArray, n_fds,
305     &read_descs, &write_descs, &except_descs);
306     }
307    
308     return ready_descriptors;
309     }
310    
311     #endif
312