]> git.proxmox.com Git - mirror_edk2.git/blame - StdLib/LibC/Uefi/select.c
StdLib/LibC: Fix transcription error from submitted patch.
[mirror_edk2.git] / StdLib / LibC / Uefi / select.c
CommitLineData
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 85int\r
86usleep( 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 96unsigned int\r
97sleep( unsigned int Seconds )\r
98{\r
6f5e1c03 99 return (usleep( (useconds_t)(Seconds * 1000000) ));\r
5252c292 100}\r
101\r
d7ce7006 102static int\r
103selscan(\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
149int\r
150select(\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