📄 selectlib.c
字号:
} } if (pWriteFds != NULL) for (fd = 0; fd < width; fd++) { /* look at the fd_set a long word at a time */ partMask = pWriteFds->fds_bits[((unsigned)fd)/NFDBITS]; if (partMask == 0) fd += NFDBITS - 1; else if (partMask & (1 << (((unsigned) fd) % NFDBITS))) { numFound++; } } return (numFound); }/******************************************************************************** selDoIoctls - perform the given ioctl on all the fd's in a mask** RETURNS: OK or ERROR if ioctl failed.*/LOCAL STATUS selDoIoctls ( FAST fd_set *pFdSet, FAST fdSetWidth, FAST int ioctlFunc, FAST SEL_WAKEUP_NODE *pWakeupNode, BOOL stopOnErr ) { FAST int fd; FAST int partMask; int status = OK; for (fd = 0; fd < fdSetWidth; fd++) { /* look at the fd_set a long word at a time */ partMask = pFdSet->fds_bits[((unsigned)fd)/NFDBITS]; if (partMask == 0) fd += NFDBITS - 1; else if (partMask & (1 << (((unsigned) fd) % NFDBITS))) { pWakeupNode->fd = fd; if (ioctl (fd, ioctlFunc, (int)pWakeupNode) != OK) { status = ERROR; if (stopOnErr) break; } } } return (status); }/* The following routines are available to drivers to manage wake-up lists *//******************************************************************************** selWakeup - wake up a task pended in select()** This routine wakes up a task pended in select(). Once a driver's* FIOSELECT function installs a wake-up node in a device's wake-up list* (using selNodeAdd()) and checks to make sure the device is ready, this* routine ensures that the select() call does not pend.** RETURNS: N/A*/void selWakeup ( SEL_WAKEUP_NODE *pWakeupNode /* node to wake up */ ) { switch (pWakeupNode->type) { case SELREAD: FD_SET(pWakeupNode->fd, pWakeupNode->pReadFds); break; case SELWRITE: FD_SET(pWakeupNode->fd, pWakeupNode->pWriteFds); break; } semGive (pWakeupNode->wakeupSem); }/******************************************************************************** selWakeupAll - wake up all tasks in a select() wake-up list** This routine wakes up all tasks pended in select() that are waiting for* a device; it is called by a driver when the device becomes ready. The* <type> parameter specifies the task to be awakened, either reader tasks* (SELREAD) or writer tasks (SELWRITE).** RETURNS: N/A*/void selWakeupAll ( SEL_WAKEUP_LIST *pWakeupList, /* list of tasks to wake up */ FAST SELECT_TYPE type /* readers (SELREAD) or writers (SELWRITE) */ ) { FAST SEL_WAKEUP_NODE *pWakeupNode; if (lstCount (&pWakeupList->wakeupList) == 0) return; if (intContext ()) { excJobAdd (selWakeupAll, (int)pWakeupList, (int)type, 0, 0, 0, 0); return; } semTake (&pWakeupList->listMutex, WAIT_FOREVER); for (pWakeupNode = (SEL_WAKEUP_NODE *) lstFirst (&pWakeupList->wakeupList); pWakeupNode != NULL; pWakeupNode = (SEL_WAKEUP_NODE *) lstNext ((NODE *) pWakeupNode)) { if (pWakeupNode->type == type) selWakeup(pWakeupNode); } semGive (&pWakeupList->listMutex); }/******************************************************************************** selNodeAdd - add a wake-up node to a select() wake-up list** This routine adds a wake-up node to a device's wake-up list. It is * typically called from a driver's FIOSELECT function.** RETURNS: OK, or ERROR if memory is insufficient.*/STATUS selNodeAdd ( SEL_WAKEUP_LIST *pWakeupList, /* list of tasks to wake up */ SEL_WAKEUP_NODE *pWakeupNode /* node to add to list */ ) { SEL_WAKEUP_NODE *pCopyOfNode; BOOL dontFree; semTake (&pWakeupList->listMutex, WAIT_FOREVER); if (lstCount (&pWakeupList->wakeupList) == 0) { pCopyOfNode = &pWakeupList->firstNode; dontFree = TRUE; } else { pCopyOfNode = (SEL_WAKEUP_NODE *) malloc (sizeof (SEL_WAKEUP_NODE)); dontFree = FALSE; } if (pCopyOfNode == NULL) { semGive (&pWakeupList->listMutex); return (ERROR); } *pCopyOfNode = *pWakeupNode; pCopyOfNode->dontFree = dontFree; lstAdd (&pWakeupList->wakeupList, (NODE *) pCopyOfNode); semGive (&pWakeupList->listMutex); return (OK); }/******************************************************************************** selNodeDelete - find and delete a node from a select() wake-up list** This routine deletes a specified wake-up node from a specified wake-up* list. Typically, it is called by a driver's FIOUNSELECT function.** RETURNS: OK, or ERROR if the node is not found in the wake-up list.*/STATUS selNodeDelete ( SEL_WAKEUP_LIST *pWakeupList, /* list of tasks to wake up */ SEL_WAKEUP_NODE *pWakeupNode /* node to delete from list */ ) { FAST SEL_WAKEUP_NODE *pWorkNode; semTake (&pWakeupList->listMutex, WAIT_FOREVER); /* get exclusion */ for (pWorkNode = (SEL_WAKEUP_NODE *) lstFirst (&pWakeupList->wakeupList); pWorkNode != NULL; pWorkNode = (SEL_WAKEUP_NODE *) lstNext ((NODE *) pWorkNode)) { if ((pWorkNode->taskId == pWakeupNode->taskId) && (pWorkNode->wakeupSem == pWakeupNode->wakeupSem) && (pWorkNode->type == pWakeupNode->type)) { lstDelete (&pWakeupList->wakeupList, (NODE *) pWorkNode); if (!(pWorkNode->dontFree)) free ((char *) pWorkNode); /* deallocate node */ semGive (&pWakeupList->listMutex); /* release exclusion */ return (OK); } } semGive (&pWakeupList->listMutex); /* release exclusion */ return (ERROR); }/******************************************************************************** selWakeupListInit - initialize a select() wake-up list** This routine should be called in a device's create routine to* initialize the SEL_WAKEUP_LIST structure.** RETURNS: N/A**/void selWakeupListInit ( SEL_WAKEUP_LIST *pWakeupList /* wake-up list to initialize */ ) { lstInit (&pWakeupList->wakeupList); semMInit (&pWakeupList->listMutex, mutexOptionsSelectLib); }/******************************************************************************** selWakeupListLen - get the number of nodes in a select() wake-up list** This routine returns the number of nodes in a specified SEL_WAKEUP_LIST.* It can be used by a driver to determine if any tasks are currently* pended in select() on this device, and whether these tasks need to be* activated with selWakeupAll().** RETURNS:* The number of nodes currently in a select() wake-up list, or ERROR.**/int selWakeupListLen ( SEL_WAKEUP_LIST *pWakeupList /* list of tasks to wake up */ ) { return (lstCount (&pWakeupList->wakeupList)); }/******************************************************************************** selWakeupType - get the type of a select() wake-up node** This routine returns the type of a specified SEL_WAKEUP_NODE.* It is typically used in a device's FIOSELECT function to determine* if the device is being selected for read or write operations.** RETURNS: SELREAD (read operation) or SELWRITE (write operation).**/SELECT_TYPE selWakeupType ( SEL_WAKEUP_NODE *pWakeupNode /* node to get type of */ ) { return (pWakeupNode->type); }/******************************************************************************** selTaskDeleteHook - select task delete hook** If a task is deleted while it is pended in select, this delete hook* tells all the relevent devices to delete the wake-up node associated* with this task. This routine is installed as a delete hook by selectInit.* RPC adds a delete hook to close the client and server handle sockets --* we insure that the select delete hook gets called before the RPC delete* hook (so that the socket device still exists) by installing it AFTER* RPC initialization (see usrConfig.c).*/LOCAL void selTaskDeleteHook ( WIND_TCB *pTcb ) { FAST SEL_WAKEUP_NODE *pWakeupNode = pTcb->pSelWakeupNode; if (pWakeupNode) { /* un register all the read fd's */ selDoIoctls (pWakeupNode->pOrigReadFds, FD_SETSIZE, FIOUNSELECT, pWakeupNode, FALSE); /* un register all the write fd's */ selDoIoctls (pWakeupNode->pOrigWriteFds, FD_SETSIZE, FIOUNSELECT, pWakeupNode, FALSE); } } /********************************************************************************* selTyAdd - tyLib FIOSELECT ioctl** This is located here to keep tyLib from dragging in selectLib.*/LOCAL void selTyAdd ( TY_DEV *pTyDev, int arg ) { selNodeAdd (&pTyDev->selWakeupList, (SEL_WAKEUP_NODE *) arg); if ((selWakeupType ((SEL_WAKEUP_NODE *) arg) == SELREAD) && (rngNBytes (pTyDev->rdBuf) > 0)) { selWakeup ((SEL_WAKEUP_NODE *) arg); } if ((selWakeupType ((SEL_WAKEUP_NODE *) arg) == SELWRITE) && rngFreeBytes (pTyDev->wrtBuf) > 0) { selWakeup ((SEL_WAKEUP_NODE *) arg); } }/********************************************************************************* selTyDelete - tyLib FIOUNSELECT ioctl** This is located here to keep tyLib from dragging in selectLib.*/LOCAL void selTyDelete ( TY_DEV *pTyDev, int arg ) { selNodeDelete (&pTyDev->selWakeupList, (SEL_WAKEUP_NODE *)arg); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -