+++ /dev/null
-/*\r
- * Copyright (c) 1982, 1986, 1989, 1993\r
- * The Regents of the University of California. All rights reserved.\r
- * (c) UNIX System Laboratories, Inc.\r
- * All or some portions of this file are derived from material licensed\r
- * to the University of California by American Telephone and Telegraph\r
- * Co. or Unix System Laboratories, Inc. and are reproduced herein with\r
- * the permission of UNIX System Laboratories, Inc.\r
- *\r
- * Portions copyright (c) 1999, 2000\r
- * Intel Corporation.\r
- * All rights reserved.\r
- *\r
- * Redistribution and use in source and binary forms, with or without\r
- * modification, are permitted provided that the following conditions\r
- * are met:\r
- *\r
- * 1. Redistributions of source code must retain the above copyright\r
- * notice, this list of conditions and the following disclaimer.\r
- *\r
- * 2. Redistributions in binary form must reproduce the above copyright\r
- * notice, this list of conditions and the following disclaimer in the\r
- * documentation and/or other materials provided with the distribution.\r
- *\r
- * 3. All advertising materials mentioning features or use of this software\r
- * must display the following acknowledgement:\r
- *\r
- * This product includes software developed by the University of\r
- * California, Berkeley, Intel Corporation, and its contributors.\r
- *\r
- * 4. Neither the name of University, Intel Corporation, or their respective\r
- * contributors may be used to endorse or promote products derived from\r
- * this software without specific prior written permission.\r
- *\r
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS, INTEL CORPORATION AND\r
- * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,\r
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS\r
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS,\r
- * INTEL CORPORATION OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,\r
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT\r
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\r
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\r
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\r
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF\r
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
- *\r
- * @(#)sys_generic.c 8.5 (Berkeley) 1/21/94\r
- * $Id: select.c,v 1.1.1.1 2003/11/19 01:50:30 kyu3 Exp $\r
- */\r
-#include <Library/UefiBootServicesTableLib.h>\r
-\r
-#include <LibConfig.h>\r
-\r
-#include <stdlib.h>\r
-#include <unistd.h>\r
-#include <strings.h>\r
-#include <sys/poll.h>\r
-#include <sys/param.h>\r
-#include <sys/time.h>\r
-#ifndef KERNEL\r
-#define KERNEL\r
-#include <errno.h>\r
-#undef KERNEL\r
-#else\r
-#include <errno.h>\r
-#endif\r
-\r
-#ifdef EFI_NT_EMULATOR\r
-#define _SELECT_DELAY_ 10000\r
-#else\r
-#define _SELECT_DELAY_ 1000\r
-#endif\r
-\r
-#define MAX_SLEEP_DELAY 0xfffffffe\r
-\r
-/** Sleep for the specified number of Microseconds.\r
-\r
- Implements the usleep(3) function.\r
-\r
- @param[in] Microseconds Number of microseconds to sleep.\r
-\r
- @retval 0 Always returns zero.\r
-**/\r
-int\r
-usleep( useconds_t Microseconds )\r
-{\r
- while ( MAX_SLEEP_DELAY < Microseconds ) {\r
- gBS->Stall ( MAX_SLEEP_DELAY );\r
- Microseconds -= MAX_SLEEP_DELAY;\r
- }\r
- gBS->Stall((UINTN)Microseconds );\r
- return (0);\r
-}\r
-\r
-unsigned int\r
-sleep( unsigned int Seconds )\r
-{\r
- return (usleep( (useconds_t)(Seconds * 1000000) ));\r
-}\r
-\r
-static int\r
-selscan(\r
- fd_mask **ibits,\r
- fd_mask **obits,\r
- int nfd,\r
- int *nselected\r
- )\r
-{\r
- int msk;\r
- int i;\r
- int j;\r
- int fd;\r
- int n;\r
- struct pollfd pfd;\r
- int FdCount;\r
- fd_mask bits;\r
- /* Note: backend also returns POLLHUP/POLLERR if appropriate. */\r
- static int16_t flag[3] = { POLLRDNORM, POLLWRNORM, POLLRDBAND };\r
-\r
- for (msk = 0, n = 0; msk < 3; msk++) {\r
- if (ibits[msk] == NULL)\r
- continue;\r
- for (i = 0; i < nfd; i += NFDBITS) {\r
- bits = ibits[ msk ][ i / NFDBITS ];\r
- while (( 0 != (j = ffs(bits))) && ((fd = i + --j) < nfd)) {\r
- bits &= ~(1 << j);\r
-\r
- pfd.fd = fd;\r
- pfd.events = flag[msk];\r
- pfd.revents = 0;\r
- FdCount = poll ( &pfd, 1, 0 );\r
- if ( -1 == FdCount ) {\r
- return errno;\r
- }\r
- if ( 0 != FdCount ) {\r
- obits[msk][(fd)/NFDBITS] |=\r
- (1 << ((fd) % NFDBITS));\r
- n++;\r
- break;\r
- }\r
- }\r
- }\r
- }\r
- *nselected = n;\r
- return (0);\r
-}\r
-\r
-int\r
-select(\r
- int nd,\r
- fd_set *in,\r
- fd_set *ou,\r
- fd_set *ex,\r
- struct timeval *tv\r
- )\r
-{\r
- fd_mask *ibits[3], *obits[3], *selbits, *sbp;\r
- int error, forever, nselected;\r
- u_int nbufbytes, ncpbytes, nfdbits;\r
- int64_t timo;\r
-\r
- if (nd < 0)\r
- return (EINVAL);\r
-\r
- /*\r
- * Allocate just enough bits for the non-null fd_sets. Use the\r
- * preallocated auto buffer if possible.\r
- */\r
- nfdbits = roundup(nd, NFDBITS);\r
- ncpbytes = nfdbits / NBBY;\r
- nbufbytes = 0;\r
- if (in != NULL)\r
- nbufbytes += 2 * ncpbytes;\r
- if (ou != NULL)\r
- nbufbytes += 2 * ncpbytes;\r
- if (ex != NULL)\r
- nbufbytes += 2 * ncpbytes;\r
- selbits = malloc(nbufbytes);\r
-\r
- /*\r
- * Assign pointers into the bit buffers and fetch the input bits.\r
- * Put the output buffers together so that they can be bzeroed\r
- * together.\r
- */\r
- sbp = selbits;\r
-#define getbits(name, x) \\r
- do { \\r
- if (name == NULL) \\r
- ibits[x] = NULL; \\r
- else { \\r
- ibits[x] = sbp + nbufbytes / 2 / sizeof *sbp; \\r
- obits[x] = sbp; \\r
- sbp += ncpbytes / sizeof *sbp; \\r
- bcopy(name, ibits[x], ncpbytes); \\r
- } \\r
- } while (0)\r
- getbits(in, 0);\r
- getbits(ou, 1);\r
- getbits(ex, 2);\r
-#undef getbits\r
- if (nbufbytes != 0)\r
- memset(selbits, 0, nbufbytes / 2);\r
-\r
- if (tv) {\r
- timo = tv->tv_usec + (tv->tv_sec * 1000000);\r
- forever = 0;\r
- } else {\r
- timo = 0;\r
- forever = 1;\r
- }\r
-\r
- /*\r
- * Poll for I/O events\r
- */\r
- nselected = 0;\r
- do {\r
- /*\r
- * Scan for pending I/O\r
- */\r
- error = selscan(ibits, obits, nd, &nselected);\r
- if (error || nselected)\r
- break;\r
-\r
- /*\r
- * Adjust timeout is needed\r
- */\r
- if (timo) {\r
- /*\r
- * Give it a rest\r
- */\r
- usleep( _SELECT_DELAY_ );\r
- timo -= _SELECT_DELAY_;\r
- }\r
-\r
- } while (timo > 0 || forever);\r
-\r
- /* select is not restarted after signals... */\r
- if (error == ERESTART)\r
- error = EINTR;\r
- else if (error == EWOULDBLOCK)\r
- error = 0;\r
-\r
-#define putbits(name, x) if (name) bcopy(obits[x], name, ncpbytes)\r
- if (error == 0) {\r
- putbits(in, 0);\r
- putbits(ou, 1);\r
- putbits(ex, 2);\r
-#undef putbits\r
- } else {\r
- errno = error;\r
- nselected = -1;\r
- }\r
-\r
- free( selbits );\r
- return ( nselected );\r
-}\r