ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/gvpe/lib/poll.c
Revision: 1.1
Committed: Tue Oct 14 17:24:19 2003 UTC (20 years, 7 months ago) by pcg
Content type: text/plain
Branch: MAIN
Log Message:
*** empty log message ***

File Contents

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