📄 selectlib.c
字号:
/* selectLib.c - UNIX BSD 4.3 select library *//* Copyright 1984-1995 Wind River Systems, Inc. */#include "copyright_wrs.h"/*modification history--------------------01x,10jul97,dgp doc: fix SPR 6476, correct no. bits examined by select()01w,09jul97,dgp doc: add max number of file descripters (SPR 7695)01v,13feb95,jdi doc tweaks.01u,03feb93,jdi doc changes based on review by rdc.01t,21jan93,jdi documentation cleanup for 5.1.01s,23aug92,jcf added tyLib select stuff here to make tyLib standalone.01r,18jul92,smb Changed errno.h to errnoLib.h.01q,04jul92,jcf scalable/ANSI/cleanup effort.01p,26may92,rrr the tree shuffle01o,10jan92,rdc Fixed bug in selNodeAdd - release semaphore after malloc error.01n,09jan92,rdc integrated fix from 5.0.2 that fixed timeout bug in select causing incorrect return fdsets.01m,13dec91,gae ANSI cleanup.01l,04oct91,rrr passed through the ansification filter -changed functions to ansi style -changed includes to have absolute path from h/ -changed VOID to void -changed copyright notice01k,01aug91,yao fixed to pass 6 args to excJobAdd() call.01j,29apr91,hdn changed how quitTime is calculated to optimize code01i,05apr91,jdi documentation -- removed header parens and x-ref numbers; doc review by rdc.01h,24mar91,jaa documentation cleanup.01g,25oct90,dnw deleted include of utime.h.01f,01aug90,jcf changed tcb selWakeupNode to pSelWakeupNode.01e,13jul90,rdc added mechanism to clean up after tasks that get deleted while pended in select.01d,26jun90,jcf changed binary semaphore interface01c,17may90,rdc changed to use binary sem's and timeouts instead of WDOGS.01b,14apr90,jcf removed tcb extension dependencies.01a,02jan90,rdc written.*//*DESCRIPTIONThis library provides a BSD 4.3 compatible \f2select\fP facility to waitfor activity on a set of file descriptors. selectLib provides a mechanismthat gives a driver the ability to detect pended tasks that are awaitingactivity on the driver's device. This allows a driver's interrupt serviceroutine to wake up such tasks directly, eliminating the need for polling.The maximum number of file descriptors supported is 256.Applications can use select() with pipes and serial devices, in additionto sockets. Also, select() examines \f2write\f1 file descriptors in additionto \f2read\f1 file descriptors; however, exception file descriptors remainunsupported.Typically, application developers need concern themselves only with theselect() call. However, driver developers should become familiar with theother routines that may be used with select(), if they wish to support theselect() mechanism.INCLUDE FILES: selectLib.hSEE ALSO:.pG "I/O System"*/#include "vxWorks.h"#include "ioLib.h"#include "memLib.h"#include "errnoLib.h"#include "vwModNum.h"#include "net/systm.h"#include "semLib.h"#include "logLib.h"#include "string.h"#include "sysLib.h"#include "intLib.h"#include "stdlib.h"#include "taskHookLib.h"#include "selectLib.h"#include "tyLib.h"#include "private/funcBindP.h"/* global variables */int mutexOptionsSelectLib = SEM_Q_FIFO | SEM_DELETE_SAFE;/* forward declarations */void selWakeupAll ();/* forward static functions */LOCAL void selTyAdd (TY_DEV *pTyDev, int arg);LOCAL void selTyDelete (TY_DEV *pTyDev, int arg);LOCAL void selTaskDeleteHook (WIND_TCB *pTcb);LOCAL STATUS selDoIoctls (fd_set *pFdSet, int fdSetWidth, int ioctlFunc, SEL_WAKEUP_NODE *pWakeupNode, BOOL stopOnErr);/********************************************************************************* selectInit - initialize the select facility** This routine initializes the UNIX BSD 4.3 select facility. It should be* called only once, and typically is called from the root task, usrRoot(),* in usrConfig.c. It installs a task delete hook that cleans up after a* task if the task is deleted while pended in select().** RETURNS: N/A*/void selectInit (void) { _func_selTyAdd = (FUNCPTR) selTyAdd; _func_selTyDelete = (FUNCPTR) selTyDelete; _func_selWakeupAll = (FUNCPTR) selWakeupAll; _func_selWakeupListInit = (FUNCPTR) selWakeupListInit; if (taskDeleteHookAdd ((FUNCPTR) selTaskDeleteHook) != OK) { logMsg ("selectInit: couldn't install task delete hook!\n", 0, 0, 0, 0, 0, 0); } }/********************************************************************************* select - pend on a set of file descriptors** This routine permits a task to pend until one of a set of file descriptors* becomes ready. Three parameters -- <pReadFds>, <pWriteFds>, and* <pExceptFds> -- point to file descriptor sets in which each bit* corresponds to a particular file descriptor. Bits set in the read file* descriptor set (<pReadFds>) will cause select() to pend until data is* available on any of the corresponding file descriptors, while bits set in* the write file descriptor set (<pWriteFds>) will cause select() to pend* until any of the corresponding file descriptors become writable. (The* <pExceptFds> parameter is currently unused, but is provided for UNIX call* compatibility.)** The following macros are available for setting the appropriate bits* in the file descriptor set structure:* .CS* FD_SET(fd, &fdset)* FD_CLR(fd, &fdset)* FD_ZERO(&fdset)* .CE** If either <pReadFds> or <pWriteFds> is NULL, they are ignored. The* <width> parameter defines how many bits will be examined in the file* descriptor sets, and should be set to either the maximum file descriptor* value in use plus one, or simply to FD_SETSIZE. When select() returns, * it zeros out the file descriptor sets, and sets only the bits that * correspond to file descriptors that are ready. The FD_ISSET macro may * be used to determine which bits are set.** If <pTimeOut> is NULL, select() will block indefinitely. If <pTimeOut> is* not NULL, but points to a `timeval' structure with an effective time of* zero, the file descriptors in the file descriptor sets will be polled and* the results returned immediately. If the effective time value is greater* than zero, select() will return after the specified time has elapsed, even* if none of the file descriptors are ready.** Applications can use select() with pipes and serial devices, in addition* to sockets. Also, select() now examines write file descriptors in* addition to read file descriptors; however, exception file descriptors* remain unsupported.** Driver developers should consult the * .I "VxWorks Programmer's Guide: I/O System"* for details on writing drivers that will use select().** RETURNS:* The number of file descriptors with activity, 0 if timed out, or* ERROR if an error occurred when the driver's select() routine* was invoked via ioctl().** SEE ALSO:* .pG "I/O System"*/int select ( int width, /* number of bits to examine from 0 */ FAST fd_set *pReadFds, /* read fds */ FAST fd_set *pWriteFds, /* write fds */ fd_set *pExceptFds, /* exception fds (unsupported) */ struct timeval *pTimeOut /* max time to wait, NULL = forever */ ) { FAST int fd; FAST int partMask; SEL_WAKEUP_NODE wakeupNode; fd_set copyOfReadFds; fd_set copyOfWriteFds; int widthInBytes; int status; int numFound = 0; int quitTime = 0; int clockRate; if (pReadFds != NULL) copyOfReadFds = *pReadFds; else FD_ZERO (©OfReadFds); if (pWriteFds != NULL) copyOfWriteFds = *pWriteFds; else FD_ZERO (©OfWriteFds); if (pTimeOut != NULL) { clockRate = sysClkRateGet (); /* convert to ticks */ quitTime = (pTimeOut->tv_sec * clockRate) + ((((pTimeOut->tv_usec * clockRate) / 100)/100)/100); } wakeupNode.pReadFds = pReadFds; wakeupNode.pWriteFds = pWriteFds; wakeupNode.pExceptFds = pExceptFds; wakeupNode.pOrigReadFds = ©OfReadFds; wakeupNode.pOrigWriteFds = ©OfWriteFds; wakeupNode.taskId = taskIdSelf (); semBInit (&taskIdCurrent->selectSem, SEM_Q_PRIORITY, SEM_EMPTY); wakeupNode.wakeupSem = &taskIdCurrent->selectSem; /* we don't use FD_ZERO to maintain backward compatibility * with 4.2 select */ widthInBytes = howmany(width, NFDBITS) * sizeof (fd_mask); if (pReadFds != NULL) bzero ((char *)pReadFds, widthInBytes); if (pWriteFds != NULL) bzero ((char *)pWriteFds, widthInBytes); if (pExceptFds != NULL) bzero ((char *)pExceptFds, widthInBytes); status = OK; /* do the read fd's */ if (pReadFds != NULL) { wakeupNode.type = SELREAD; if (selDoIoctls (©OfReadFds, width, FIOSELECT, &wakeupNode, TRUE) != OK) { status = ERROR; } } /* do the write fd's */ if (status != ERROR) if (pWriteFds != NULL) { wakeupNode.type = SELWRITE; if (selDoIoctls (©OfWriteFds, width, FIOSELECT, &wakeupNode, TRUE) != OK) { status = ERROR; } } if (status != OK) { status = errnoGet (); wakeupNode.type = SELREAD; selDoIoctls (©OfReadFds, width, FIOUNSELECT, &wakeupNode, FALSE); wakeupNode.type = SELWRITE; selDoIoctls (©OfWriteFds, width, FIOUNSELECT, &wakeupNode, FALSE); /* if no select support in driver, inform the naive user */ if (status == S_ioLib_UNKNOWN_REQUEST) errnoSet (S_selectLib_NO_SELECT_SUPPORT_IN_DRIVER); return (ERROR); } /* if the user specified a zero quittime, we don't pend. * a NULL pointer indicates wait for ever */ if ((pTimeOut != NULL) && (quitTime == 0)) quitTime = NO_WAIT; else if (pTimeOut == NULL) quitTime = WAIT_FOREVER; /* stash a pointer to the wake-up node in the task's tcb, so we can * clean up if the task get's deleted while we're pended in select */ taskIdCurrent->pSelWakeupNode = &wakeupNode; semTake (wakeupNode.wakeupSem, quitTime); /* clean up after ourselves */ /* first the read fd's ... */ status = OK; if (pReadFds != NULL) { wakeupNode.type = SELREAD; if (selDoIoctls (©OfReadFds, width, FIOUNSELECT, &wakeupNode, FALSE) != OK) { status = ERROR; } } /* ... now the write fd's. */ if (pWriteFds != NULL) { wakeupNode.type = SELWRITE; if (selDoIoctls (©OfWriteFds, width, FIOUNSELECT, &wakeupNode, FALSE) != OK) { status = ERROR; } } /* clear the pointer to the selWakup node in the task's tcb now * that we're all cleaned up. */ taskIdCurrent->pSelWakeupNode = NULL; if (status == ERROR) return (ERROR); /* find out how many bits are set in the read and write fd sets */ if (pReadFds != NULL) for (fd = 0; fd < width; fd++) { /* look at the fd_set a long word at a time */ partMask = pReadFds->fds_bits[((unsigned)fd) / NFDBITS]; if (partMask == 0) { fd += NFDBITS - 1; } else if (partMask & (1 << (((unsigned) fd) % NFDBITS))) { numFound++;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -