⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 selectlib.c

📁 VxWorks操作系统内核源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
    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 int 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 */    )    {    SEL_CONTEXT *pSelectContext;    pSelectContext = ((WIND_TCB *)pWakeupNode->taskId)->pSelectContext;    switch (pWakeupNode->type)	{	case SELREAD:	    FD_SET(pWakeupNode->fd, pSelectContext->pReadFds);	    break;	case SELWRITE:	    FD_SET(pWakeupNode->fd, pSelectContext->pWriteFds);	    break;	}    semGive (&pSelectContext->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->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);    }/******************************************************************************** selWakeupListTerm - terminate a select() wake-up list** This routine should be called in a device's terminate routine to* terminate the SEL_WAKEUP_LIST structure.** RETURNS: N/A**/void selWakeupListTerm    (    SEL_WAKEUP_LIST *pWakeupList	/* wake-up list to terminate */    )    {    semTerminate (&pWakeupList->listMutex);    }/******************************************************************************** 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);    }/******************************************************************************** selTaskCreateHook - select task create hook** This routine creates a select context for the task.  The select context * for the root task is not created by this routine.  Instead, it is created * by the selectInit() routine.** The memory for the context is allocated from the system heap.  The amount* of memory allocated for the context is enough to support fd_sets of size* maxFiles, instead of the compile time value of FD_SETSIZE.** This routine is installed as a create hook by selectInit.*/LOCAL STATUS selTaskCreateHook    (    WIND_TCB *pNewTcb    )    {    SEL_CONTEXT *pSelectContext;    int		 fdSetBytes;    /*     * Allocate sufficient memory from the heap to contain the select     * context.  This memory includes space for the various fd_sets to     * handle file descriptors up to maxFiles, i.e. select() will not be     * limited to FD_SETSIZE.     */     fdSetBytes = sizeof (fd_mask) * howmany (maxFiles, NFDBITS);     pSelectContext = (SEL_CONTEXT *) malloc (sizeof (SEL_CONTEXT) + 		       				   2 * fdSetBytes);     if (pSelectContext == NULL)	return (ERROR);     /* assign various convenience fd_set pointers */     pSelectContext->pOrigReadFds   = (fd_set *) ((int) pSelectContext +						 sizeof (SEL_CONTEXT));     pSelectContext->pOrigWriteFds  = (fd_set *)				      ((int) pSelectContext->pOrigReadFds +					     fdSetBytes);     pSelectContext->pendedOnSelect = FALSE;   /* task is not pending */     /* initialize the task's wakeup binary semaphore */     if (semBInit (&pSelectContext->wakeupSem, SEM_Q_PRIORITY, 		   SEM_EMPTY) != OK)	 {	 free ((char*) pSelectContext);	 return (ERROR);	 }    /* initialization succeeded so set task's select context pointer */    pNewTcb->pSelectContext = pSelectContext;    return (OK);    }/******************************************************************************** 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 * selTaskDeleteHookAdd().  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    )    {    SEL_CONTEXT *pSelectContext = pTcb->pSelectContext;    /*      * A wakeup node is created on the deleting task's stack since     * the work node on the stack of the task being deleting may     * be inaccessible to the current task.     */    SEL_WAKEUP_NODE wakeupNode;    if (pSelectContext != NULL)	{	/* task pended in select()? */	if (pSelectContext->pendedOnSelect == TRUE)	    {	    wakeupNode.taskId = (int) pTcb;	    /* unregister all the read fd's */	    wakeupNode.type   = SELREAD;	    selDoIoctls (pSelectContext->pOrigReadFds, pSelectContext->width,			 FIOUNSELECT, &wakeupNode, FALSE);	    /* unregister all the write fd's */	    wakeupNode.type = SELWRITE;	    selDoIoctls (pSelectContext->pOrigWriteFds, pSelectContext->width,			 FIOUNSELECT, &wakeupNode, FALSE);	    }	semTerminate (&pSelectContext->wakeupSem);	free ((char *) pSelectContext);	}    }		/********************************************************************************* 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);    }/********************************************************************************* selPtyAdd - ptyLib FIOSELECT ioctl** This is located here to keep ptyLib from dragging in selectLib.*/LOCAL void selPtyAdd     (    PSEUDO_DEV *pPtyDev,    int arg     )    {    selNodeAdd (&pPtyDev->masterSelWakeupList, (SEL_WAKEUP_NODE *) arg);    if ((selWakeupType ((SEL_WAKEUP_NODE *) arg) == SELREAD) &&		  rngNBytes (pPtyDev->tyDev.wrtBuf) > 0)		/* reversed read criteria for master */	{	selWakeup ((SEL_WAKEUP_NODE *) arg);	}    if ((selWakeupType ((SEL_WAKEUP_NODE *) arg) == SELWRITE) &&		 rngFreeBytes (pPtyDev->tyDev.rdBuf) > 0 )		/* reversed write criteria for master */	{	selWakeup ((SEL_WAKEUP_NODE *) arg);	}    }/********************************************************************************* selPtyDelete - ptyLib FIOUNSELECT ioctl** This is located here to keep ptyLib from dragging in selectLib.*/LOCAL void selPtyDelete    (    PSEUDO_DEV *pPtyDev,    int arg     )    {    selNodeDelete (&pPtyDev->masterSelWakeupList, (SEL_WAKEUP_NODE *)arg);    }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -