]>
Commit | Line | Data |
---|---|---|
d7ce7006 | 1 | /*\r |
2 | * Copyright (c) 1982, 1986, 1989, 1993\r | |
3 | * The Regents of the University of California. All rights reserved.\r | |
4 | * (c) UNIX System Laboratories, Inc.\r | |
5 | * All or some portions of this file are derived from material licensed\r | |
6 | * to the University of California by American Telephone and Telegraph\r | |
7 | * Co. or Unix System Laboratories, Inc. and are reproduced herein with\r | |
8 | * the permission of UNIX System Laboratories, Inc.\r | |
9 | *\r | |
10 | * Portions copyright (c) 1999, 2000\r | |
11 | * Intel Corporation.\r | |
12 | * All rights reserved.\r | |
13 | *\r | |
14 | * Redistribution and use in source and binary forms, with or without\r | |
15 | * modification, are permitted provided that the following conditions\r | |
16 | * are met:\r | |
17 | *\r | |
18 | * 1. Redistributions of source code must retain the above copyright\r | |
19 | * notice, this list of conditions and the following disclaimer.\r | |
20 | *\r | |
21 | * 2. Redistributions in binary form must reproduce the above copyright\r | |
22 | * notice, this list of conditions and the following disclaimer in the\r | |
23 | * documentation and/or other materials provided with the distribution.\r | |
24 | *\r | |
25 | * 3. All advertising materials mentioning features or use of this software\r | |
26 | * must display the following acknowledgement:\r | |
27 | *\r | |
28 | * This product includes software developed by the University of\r | |
29 | * California, Berkeley, Intel Corporation, and its contributors.\r | |
30 | *\r | |
31 | * 4. Neither the name of University, Intel Corporation, or their respective\r | |
32 | * contributors may be used to endorse or promote products derived from\r | |
33 | * this software without specific prior written permission.\r | |
34 | *\r | |
35 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS, INTEL CORPORATION AND\r | |
36 | * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,\r | |
37 | * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS\r | |
38 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS,\r | |
39 | * INTEL CORPORATION OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,\r | |
40 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT\r | |
41 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\r | |
42 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\r | |
43 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\r | |
44 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF\r | |
45 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r | |
46 | *\r | |
47 | * @(#)sys_generic.c 8.5 (Berkeley) 1/21/94\r | |
48 | * $Id: select.c,v 1.1.1.1 2003/11/19 01:50:30 kyu3 Exp $\r | |
49 | */\r | |
50 | #include <Library/UefiBootServicesTableLib.h>\r | |
51 | \r | |
52 | #include <LibConfig.h>\r | |
53 | \r | |
54 | #include <stdlib.h>\r | |
55 | #include <unistd.h>\r | |
56 | #include <string.h>\r | |
57 | #include <sys/poll.h>\r | |
58 | #include <sys/param.h>\r | |
59 | #include <sys/time.h>\r | |
60 | #include <extern.h> /* For ffs() */\r | |
61 | #ifndef KERNEL\r | |
62 | #define KERNEL\r | |
63 | #include <errno.h>\r | |
64 | #undef KERNEL\r | |
65 | #else\r | |
66 | #include <errno.h>\r | |
67 | #endif\r | |
68 | \r | |
69 | #ifdef EFI_NT_EMULATOR\r | |
70 | #define _SELECT_DELAY_ 10000\r | |
71 | #else\r | |
72 | #define _SELECT_DELAY_ 1000\r | |
73 | #endif\r | |
74 | \r | |
75 | #define MAX_SLEEP_DELAY 0xfffffffe\r | |
76 | \r | |
5252c292 | 77 | /** Sleep for the specified number of Microseconds.\r |
78 | \r | |
79 | Implements the usleep(3) function.\r | |
80 | \r | |
81 | @param[in] Microseconds Number of microseconds to sleep.\r | |
82 | \r | |
83 | @retval 0 Always returns zero.\r | |
84 | **/\r | |
d7ce7006 | 85 | int\r |
86 | usleep( useconds_t Microseconds )\r | |
87 | {\r | |
88 | while ( MAX_SLEEP_DELAY < Microseconds ) {\r | |
89 | gBS->Stall ( MAX_SLEEP_DELAY );\r | |
90 | Microseconds -= MAX_SLEEP_DELAY;\r | |
91 | }\r | |
92 | gBS->Stall((UINTN)Microseconds );\r | |
93 | return (0);\r | |
94 | }\r | |
95 | \r | |
5252c292 | 96 | unsigned int\r |
97 | sleep( unsigned int Seconds )\r | |
98 | {\r | |
6f5e1c03 | 99 | return (usleep( (useconds_t)(Seconds * 1000000) ));\r |
5252c292 | 100 | }\r |
101 | \r | |
d7ce7006 | 102 | static int\r |
103 | selscan(\r | |
104 | fd_mask **ibits,\r | |
105 | fd_mask **obits,\r | |
106 | int nfd,\r | |
107 | int *nselected\r | |
108 | )\r | |
109 | {\r | |
110 | int msk;\r | |
111 | int i;\r | |
112 | int j;\r | |
113 | int fd;\r | |
114 | int n;\r | |
115 | struct pollfd pfd;\r | |
116 | int FdCount;\r | |
117 | fd_mask bits;\r | |
118 | /* Note: backend also returns POLLHUP/POLLERR if appropriate. */\r | |
119 | static int16_t flag[3] = { POLLRDNORM, POLLWRNORM, POLLRDBAND };\r | |
120 | \r | |
121 | for (msk = 0, n = 0; msk < 3; msk++) {\r | |
122 | if (ibits[msk] == NULL)\r | |
123 | continue;\r | |
124 | for (i = 0; i < nfd; i += NFDBITS) {\r | |
125 | bits = ibits[ msk ][ i / NFDBITS ];\r | |
126 | while (( 0 != (j = ffs(bits))) && ((fd = i + --j) < nfd)) {\r | |
127 | bits &= ~(1 << j);\r | |
128 | \r | |
129 | pfd.fd = fd;\r | |
130 | pfd.events = flag[msk];\r | |
131 | pfd.revents = 0;\r | |
132 | FdCount = poll ( &pfd, 1, 0 );\r | |
133 | if ( -1 == FdCount ) {\r | |
134 | return errno;\r | |
135 | }\r | |
136 | if ( 0 != FdCount ) {\r | |
137 | obits[msk][(fd)/NFDBITS] |=\r | |
138 | (1 << ((fd) % NFDBITS));\r | |
139 | n++;\r | |
140 | break;\r | |
141 | }\r | |
142 | }\r | |
143 | }\r | |
144 | }\r | |
145 | *nselected = n;\r | |
146 | return (0);\r | |
147 | }\r | |
148 | \r | |
149 | int\r | |
150 | select(\r | |
151 | int nd,\r | |
152 | fd_set *in,\r | |
153 | fd_set *ou,\r | |
154 | fd_set *ex,\r | |
155 | struct timeval *tv\r | |
156 | )\r | |
157 | {\r | |
158 | fd_mask *ibits[3], *obits[3], *selbits, *sbp;\r | |
159 | int error, forever, nselected;\r | |
160 | u_int nbufbytes, ncpbytes, nfdbits;\r | |
161 | int64_t timo;\r | |
162 | \r | |
163 | if (nd < 0)\r | |
164 | return (EINVAL);\r | |
165 | \r | |
166 | /*\r | |
167 | * Allocate just enough bits for the non-null fd_sets. Use the\r | |
168 | * preallocated auto buffer if possible.\r | |
169 | */\r | |
170 | nfdbits = roundup(nd, NFDBITS);\r | |
171 | ncpbytes = nfdbits / NBBY;\r | |
172 | nbufbytes = 0;\r | |
173 | if (in != NULL)\r | |
174 | nbufbytes += 2 * ncpbytes;\r | |
175 | if (ou != NULL)\r | |
176 | nbufbytes += 2 * ncpbytes;\r | |
177 | if (ex != NULL)\r | |
178 | nbufbytes += 2 * ncpbytes;\r | |
179 | selbits = malloc(nbufbytes);\r | |
180 | \r | |
181 | /*\r | |
182 | * Assign pointers into the bit buffers and fetch the input bits.\r | |
183 | * Put the output buffers together so that they can be bzeroed\r | |
184 | * together.\r | |
185 | */\r | |
186 | sbp = selbits;\r | |
187 | #define getbits(name, x) \\r | |
188 | do { \\r | |
189 | if (name == NULL) \\r | |
190 | ibits[x] = NULL; \\r | |
191 | else { \\r | |
192 | ibits[x] = sbp + nbufbytes / 2 / sizeof *sbp; \\r | |
193 | obits[x] = sbp; \\r | |
194 | sbp += ncpbytes / sizeof *sbp; \\r | |
195 | bcopy(name, ibits[x], ncpbytes); \\r | |
196 | } \\r | |
197 | } while (0)\r | |
198 | getbits(in, 0);\r | |
199 | getbits(ou, 1);\r | |
200 | getbits(ex, 2);\r | |
201 | #undef getbits\r | |
202 | if (nbufbytes != 0)\r | |
203 | memset(selbits, 0, nbufbytes / 2);\r | |
204 | \r | |
205 | if (tv) {\r | |
206 | timo = tv->tv_usec + (tv->tv_sec * 1000000);\r | |
207 | forever = 0;\r | |
208 | } else {\r | |
209 | timo = 0;\r | |
210 | forever = 1;\r | |
211 | }\r | |
212 | \r | |
213 | /*\r | |
214 | * Poll for I/O events\r | |
215 | */\r | |
216 | nselected = 0;\r | |
217 | do {\r | |
218 | /*\r | |
219 | * Scan for pending I/O\r | |
220 | */\r | |
221 | error = selscan(ibits, obits, nd, &nselected);\r | |
222 | if (error || nselected)\r | |
223 | break;\r | |
224 | \r | |
225 | /*\r | |
226 | * Adjust timeout is needed\r | |
227 | */\r | |
228 | if (timo) {\r | |
229 | /*\r | |
230 | * Give it a rest\r | |
231 | */\r | |
232 | usleep( _SELECT_DELAY_ );\r | |
233 | timo -= _SELECT_DELAY_;\r | |
234 | }\r | |
235 | \r | |
236 | } while (timo > 0 || forever);\r | |
237 | \r | |
238 | /* select is not restarted after signals... */\r | |
239 | if (error == ERESTART)\r | |
240 | error = EINTR;\r | |
241 | else if (error == EWOULDBLOCK)\r | |
242 | error = 0;\r | |
243 | \r | |
244 | #define putbits(name, x) if (name) bcopy(obits[x], name, ncpbytes)\r | |
245 | if (error == 0) {\r | |
246 | putbits(in, 0);\r | |
247 | putbits(ou, 1);\r | |
248 | putbits(ex, 2);\r | |
249 | #undef putbits\r | |
250 | } else {\r | |
251 | errno = error;\r | |
252 | nselected = -1;\r | |
253 | }\r | |
254 | \r | |
255 | free( selbits );\r | |
256 | return ( nselected );\r | |
257 | }\r |