]> git.proxmox.com Git - mirror_edk2.git/blame - StdLib/LibC/Uefi/select.c
StdLib: Fix IIO_Write() to return the number of bytes consumed, not characters output.
[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
feb1422b 56#include <strings.h>\r
d7ce7006 57#include <sys/poll.h>\r
58#include <sys/param.h>\r
59#include <sys/time.h>\r
d7ce7006 60#ifndef KERNEL\r
61#define KERNEL\r
62#include <errno.h>\r
63#undef KERNEL\r
64#else\r
65#include <errno.h>\r
66#endif\r
67\r
68#ifdef EFI_NT_EMULATOR\r
69#define _SELECT_DELAY_ 10000\r
70#else\r
71#define _SELECT_DELAY_ 1000\r
72#endif\r
73\r
74#define MAX_SLEEP_DELAY 0xfffffffe\r
75\r
5252c292 76/** Sleep for the specified number of Microseconds.\r
77\r
78 Implements the usleep(3) function.\r
79\r
80 @param[in] Microseconds Number of microseconds to sleep.\r
81\r
82 @retval 0 Always returns zero.\r
83**/\r
d7ce7006 84int\r
85usleep( useconds_t Microseconds )\r
86{\r
87 while ( MAX_SLEEP_DELAY < Microseconds ) {\r
88 gBS->Stall ( MAX_SLEEP_DELAY );\r
89 Microseconds -= MAX_SLEEP_DELAY;\r
90 }\r
91 gBS->Stall((UINTN)Microseconds );\r
92 return (0);\r
93}\r
94\r
5252c292 95unsigned int\r
96sleep( unsigned int Seconds )\r
97{\r
6f5e1c03 98 return (usleep( (useconds_t)(Seconds * 1000000) ));\r
5252c292 99}\r
100\r
d7ce7006 101static int\r
102selscan(\r
103 fd_mask **ibits,\r
104 fd_mask **obits,\r
105 int nfd,\r
106 int *nselected\r
107 )\r
108{\r
109 int msk;\r
110 int i;\r
111 int j;\r
112 int fd;\r
113 int n;\r
114 struct pollfd pfd;\r
115 int FdCount;\r
116 fd_mask bits;\r
117 /* Note: backend also returns POLLHUP/POLLERR if appropriate. */\r
118 static int16_t flag[3] = { POLLRDNORM, POLLWRNORM, POLLRDBAND };\r
119\r
120 for (msk = 0, n = 0; msk < 3; msk++) {\r
121 if (ibits[msk] == NULL)\r
122 continue;\r
123 for (i = 0; i < nfd; i += NFDBITS) {\r
124 bits = ibits[ msk ][ i / NFDBITS ];\r
125 while (( 0 != (j = ffs(bits))) && ((fd = i + --j) < nfd)) {\r
126 bits &= ~(1 << j);\r
127\r
128 pfd.fd = fd;\r
129 pfd.events = flag[msk];\r
130 pfd.revents = 0;\r
131 FdCount = poll ( &pfd, 1, 0 );\r
132 if ( -1 == FdCount ) {\r
133 return errno;\r
134 }\r
135 if ( 0 != FdCount ) {\r
136 obits[msk][(fd)/NFDBITS] |=\r
137 (1 << ((fd) % NFDBITS));\r
138 n++;\r
139 break;\r
140 }\r
141 }\r
142 }\r
143 }\r
144 *nselected = n;\r
145 return (0);\r
146}\r
147\r
148int\r
149select(\r
150 int nd,\r
151 fd_set *in,\r
152 fd_set *ou,\r
153 fd_set *ex,\r
154 struct timeval *tv\r
155 )\r
156{\r
157 fd_mask *ibits[3], *obits[3], *selbits, *sbp;\r
158 int error, forever, nselected;\r
159 u_int nbufbytes, ncpbytes, nfdbits;\r
160 int64_t timo;\r
161\r
162 if (nd < 0)\r
163 return (EINVAL);\r
164\r
165 /*\r
166 * Allocate just enough bits for the non-null fd_sets. Use the\r
167 * preallocated auto buffer if possible.\r
168 */\r
169 nfdbits = roundup(nd, NFDBITS);\r
170 ncpbytes = nfdbits / NBBY;\r
171 nbufbytes = 0;\r
172 if (in != NULL)\r
173 nbufbytes += 2 * ncpbytes;\r
174 if (ou != NULL)\r
175 nbufbytes += 2 * ncpbytes;\r
176 if (ex != NULL)\r
177 nbufbytes += 2 * ncpbytes;\r
178 selbits = malloc(nbufbytes);\r
179\r
180 /*\r
181 * Assign pointers into the bit buffers and fetch the input bits.\r
182 * Put the output buffers together so that they can be bzeroed\r
183 * together.\r
184 */\r
185 sbp = selbits;\r
186#define getbits(name, x) \\r
187 do { \\r
188 if (name == NULL) \\r
189 ibits[x] = NULL; \\r
190 else { \\r
191 ibits[x] = sbp + nbufbytes / 2 / sizeof *sbp; \\r
192 obits[x] = sbp; \\r
193 sbp += ncpbytes / sizeof *sbp; \\r
194 bcopy(name, ibits[x], ncpbytes); \\r
195 } \\r
196 } while (0)\r
197 getbits(in, 0);\r
198 getbits(ou, 1);\r
199 getbits(ex, 2);\r
200#undef getbits\r
201 if (nbufbytes != 0)\r
202 memset(selbits, 0, nbufbytes / 2);\r
203\r
204 if (tv) {\r
205 timo = tv->tv_usec + (tv->tv_sec * 1000000);\r
206 forever = 0;\r
207 } else {\r
208 timo = 0;\r
209 forever = 1;\r
210 }\r
211\r
212 /*\r
213 * Poll for I/O events\r
214 */\r
215 nselected = 0;\r
216 do {\r
217 /*\r
218 * Scan for pending I/O\r
219 */\r
220 error = selscan(ibits, obits, nd, &nselected);\r
221 if (error || nselected)\r
222 break;\r
223\r
224 /*\r
225 * Adjust timeout is needed\r
226 */\r
227 if (timo) {\r
228 /*\r
229 * Give it a rest\r
230 */\r
231 usleep( _SELECT_DELAY_ );\r
232 timo -= _SELECT_DELAY_;\r
233 }\r
234\r
235 } while (timo > 0 || forever);\r
236\r
237 /* select is not restarted after signals... */\r
238 if (error == ERESTART)\r
239 error = EINTR;\r
240 else if (error == EWOULDBLOCK)\r
241 error = 0;\r
242\r
243#define putbits(name, x) if (name) bcopy(obits[x], name, ncpbytes)\r
244 if (error == 0) {\r
245 putbits(in, 0);\r
246 putbits(ou, 1);\r
247 putbits(ex, 2);\r
248#undef putbits\r
249 } else {\r
250 errno = error;\r
251 nselected = -1;\r
252 }\r
253\r
254 free( selbits );\r
255 return ( nselected );\r
256}\r