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

📄 aiopxlib.c

📁 VXWORKS源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
** RETURNS: The return status of the completed AIO request, or ERROR. ** ERRNO:  EINVAL, EINPROGRESS** INCLUDE FILES: aio.h*/size_t aio_return     (    struct aiocb * 	pAiocb			/* AIO control block */    )    {    int			retVal;			/* return value */    AIO_FD_ENTRY *	pEntry;			/* fd entry */    FAST AIO_SYS *	pReq; 			/* AIO request */    if (pAiocb == NULL)	{	errno = EINVAL; 	return (ERROR);				/* invalid parameter */	}    if ((pEntry = aioEntryFind (pAiocb->aio_fildes)) == NULL)	return (ERROR);    pReq = &pAiocb->aio_sys;    if (pReq->state != AIO_COMPLETED)	{    	errno = EINPROGRESS;	return (ERROR);				/* not done yet */	}    /* Remove the aiocb from the fd list if the aiocb was      * submitted correctly.      */    semTake (&pEntry->ioQSem, WAIT_FOREVER);    if (pReq->pAiocb != NULL)	        dllRemove (&pEntry->ioQ, &pReq->fdNode);    semGive (&pEntry->ioQSem);    /* Wait here until all call to suspend (on this aiocb)      * wake up and are deleted from wait list. aioDone wakes up      * each individual suspend.       * aio_suspend() removes them from the wait list.     */    mutex_lock (&pReq->lock);	    while (lstCount (&pReq->wait) > 0)	cond_timedwait (&pReq->wake, &pReq->lock, NULL);    mutex_unlock (&pReq->lock);    sigPendDestroy (&pReq->sigpend);    retVal = pAiocb->aio_retVal;    bzero ((char *) pReq, sizeof (AIO_SYS));    return (retVal);    }/******************************************************************************** aioSubmit - submit an AIO request * * This routine fills in the AIO_SYS portion, of the AIO control block (pAiocb)* then passes the request to the AIO driver by calling the driver supplied * insert routine.** RETURNS: OK if successful, ERROR otherwise** ERRNO: EINVAL* * INTERNAL* The state leaving this routine is AIO_READY.  The driver provided insert * routine must mark the state as AIO_QUEUED after inserting it onto the * workQ.*/LOCAL STATUS aioSubmit    (    struct aiocb *	pAiocb,			/* AIO control block */    int			op,			/* operation */    AIO_CLUST *		pClust			/* cluster */    )    {    FUNCPTR		insertRtn;		/* insert routine */    AIO_FD_ENTRY *	pEntry;			/* fd entry */    AIO_SYS *		pReq;			/* AIO request */    int			prio = 0;		/* priority */    if (pAiocb == NULL)	{	errno = EINVAL; 	return (ERROR);				/* safety check */	}    if ((pAiocb->aio_sigevent.sigev_notify == SIGEV_SIGNAL) &&	((pAiocb->aio_sigevent.sigev_signo < 1) ||	 (pAiocb->aio_sigevent.sigev_signo > _NSIGS)))	{	errno = EINVAL; 	return (ERROR);				/* safety check */	}    pReq = &pAiocb->aio_sys;			/* clear AIO_SYS */    bzero ((char *) pReq, sizeof (AIO_SYS));	    if ((pEntry = aioEntryFind (pAiocb->aio_fildes)) == NULL)	return (ERROR);    /* #ifdef _POSIX_PRIORITIZED_IO (says POSIX) but implementing      * this here is easy.  Let the driver decide what to do with it.     */    if ((pAiocb->aio_reqprio < 0) || 	(pAiocb->aio_reqprio > AIO_PRIO_DELTA_MAX))	{	errno = EINVAL;	return (ERROR);				/* invalid priority */	}    					    /* Determine the effective priority - use VxWorks numbering */    taskPriorityGet (taskIdSelf (), &prio);	    prio = min ((pAiocb->aio_reqprio + prio), VXWORKS_LOW_PRI);    /* initialize the AIO control block */    pReq->ioNode.op	 = op;			/* fill in the ioNode */    pReq->ioNode.prio	 = prio;    pReq->ioNode.doneRtn = aioDone;		    pReq->ioNode.taskId  = taskIdSelf ();    pReq->ioNode.errorVal= EINPROGRESS;	    pReq->ioNode.retVal  = OK;    pReq->pAiocb         = pAiocb;		/* back pointer */    pReq->pClust	 = pClust;		/* cluster */    lstInit (&pReq->wait);			/* initailize wait */    mutex_init (&pReq->lock, NULL);    cond_init (&pReq->wake, NULL);    pReq->state 	 = AIO_READY;		/* mark it ready */    semTake (&pEntry->ioQSem, WAIT_FOREVER);    if (!pEntry->ioQActive)	{    	semGive (&pEntry->ioQSem);	errno = EBADF;	return (ERROR);				/* was deleted */	}    dllAdd (&pEntry->ioQ, &pReq->fdNode);	/* add it to fd list */    semGive (&pEntry->ioQSem);    insertRtn = aioDrvTable [pEntry->drv_num].insert;    return ((* insertRtn) (pEntry->drv_value, pAiocb, prio));    }/******************************************************************************* aioListEach - call routine for each element in list** This routine calls the passed routine <routine> with arguments <arg1>* and <arg2> for each element in <list> which is non null.  <list>* has <num> elements.  aioListEach calls the passed function <routine> * until <routine> returns a value of FALSE.  ** RETURNS:  the index of in <list> which caused aioList() to stop (return FALSE)* 	    or <num> if all members of the list element returned TRUE.*/LOCAL int aioListEach    (    struct aiocb * 	list[],			/* list of operations */    int			num,			/* size of list */    FUNCPTR		routine,		/* routine to call */    int			arg1,			/* argument */    int			arg2			/* argument */    )    {    int 		ix;			/* index */    for (ix = 0; ix < num; ix++)	{	if (list [ix] != NULL) 	    {	    if (((* routine) (list [ix], arg1, arg2)) == FALSE)		return (ix);	    }	}     return (num);    } /******************************************************************************* aioListSubmit - submit a list of AIO requests (aioListEach routine)** This routine is called from lio_listio() to submit the list of AIO* requests.  aioListSubmit submits each element of the list, even of* on fails.* * RETURNS: TRUE*/LOCAL BOOL aioListSubmit    (    struct aiocb *	pAiocb, 		/* AIO control block */    AIO_CLUST * 	pClust,			/* cluster */    BOOL *		pFailed 		/* set if submit failed */    )    {    int			op = pAiocb->aio_lio_opcode;    switch (op)	{	case LIO_READ  : op = IO_READ; break;	case LIO_WRITE : op = IO_WRITE; break;	case LIO_NOP   : return (TRUE); 	/* NOP is dumb, but valid */	}    if (aioSubmit (pAiocb, op, pClust) == ERROR)	{	AIO_DONE_SET (pAiocb, ERROR, errno);	*pFailed = TRUE;			/* notify caller failure */ 	aioClustRet (pAiocb, pClust);	}    return (TRUE);    }/******************************************************************************* aioListClust - cluster AIO requests together (aioListEach routine)** This routine is called from lio_listio() to cluster the list of AIO* requests together.* * RETURNS: TRUE*/LOCAL BOOL aioListClust    (    struct aiocb *	pAiocb, 		/* AIO control block */    AIO_CLUST *		pClust,			/* cluster */    int			bogus1			/* not used */    )    {    if (pAiocb->aio_lio_opcode != LIO_NOP)	pClust->refCnt++;			/* count number of aiocbs */    return (TRUE);    }/******************************************************************************* aioListError - check for errors in list (aioListEach routine)** This routine is called from lio_listio() to check if any of the completed* AIO requests in the list failed.** RETURNS: FALSE if any request failed, TRUE otherwise.*/LOCAL BOOL aioListError     (    struct aiocb *	pAiocb,			/* AIO control block */    int *		pError,			/* error */    int			bogus			/* not used */    )    {    if ((pAiocb->aio_lio_opcode != LIO_NOP) && 	(pAiocb->aio_state == AIO_COMPLETED) && 	(pAiocb->aio_retVal == ERROR))	{	*pError = pAiocb->aio_errorVal;	return (FALSE);		}    return (TRUE);    }    /******************************************************************************* aioListWait - add wait request to AIO control block (aioListEach routine).** This routine is called from aio_suspend() to add the <pAioId> to the wait * list associated with <pAiocb>.** RETURNS: FALSE if an error occurred or any request had completed*	   TRUE otherwise*/LOCAL BOOL aioListWait    (    struct aiocb *	pAiocb, 		/* AIO control block */    AIO_WAIT_ID *	pAioId,			/* AIO id */    int			bogus			/* not used */    )    {    FAST AIO_FD_ENTRY *	pEntry;			/* fd entry */    STATUS		retVal = TRUE;		/* return value */    AIO_SYS *		pReq   = &pAiocb->aio_sys;    if ((pEntry = aioEntryFind (pAiocb->aio_fildes)) == NULL)	return (FALSE);				/* invalid file */    mutex_lock (&pReq->lock);    if ((pReq->state >= AIO_READY) && (pReq->state <= AIO_RUNNING))	lstAdd (&pReq->wait, &pAioId->node);    else	{	errno = (pReq->state == AIO_COMPLETED) ? AIO_COMPLETED : EINVAL;	retVal = FALSE;	}    mutex_unlock (&pReq->lock);    return (retVal);    }/******************************************************************************* aioListUnwait - delete previous wait request (aioListEach routine).** This routine cancels a previous wait request.  It deletes the <pAioId>* from the wait list associated with <pAiocb>.** RETURNS: TRUE*/LOCAL BOOL aioListUnwait    (    struct aiocb *	pAiocb, 		/* AIO control block */    AIO_WAIT_ID *	pAioId,			/* AIO id */    int			bogus			/* not used */    )    {    mutex_lock (&pAiocb->aio_sys.lock);    lstDelete (&pAiocb->aio_sys.wait, &pAioId->node);    mutex_unlock (&pAiocb->aio_sys.lock);    return (TRUE);    }/******************************************************************************** * aioClustGet - get a free cluster ** RETURNS: A pointer to a cluster structure or NULL.*/LOCAL AIO_CLUST * aioClustGet (void)    {    int 		ix;			/* index */    AIO_CLUST *		pClust;			/* AIO cluster */    AIO_LOCK ();				/* lock access */    for (ix = 0; ix < aioClustMax; ix++)	{        if (!aioClustTable [ix].inuse)	    {	    aioClustTable [ix].inuse = TRUE;	    break;				/* got free cluster */	    }	}    AIO_UNLOCK ();				/* unlock access */    if (ix >= aioClustMax)	{        errno = EAGAIN;	return (NULL);				/* none available */	}    /* Initialize cluster */    pClust = &aioClustTable [ix];    pClust->refCnt = 0;    mutex_init (&pClust->lock, NULL);    cond_init  (&pClust->wake, NULL);    return (pClust);    }/******************************************************************************** * aioDone - AIO completed ** This routine gets called on completion of an AIO operation.  It notifies* any waiting tasks of the AIO completion.  When aioDone is called the * AIO request should not be associated with any driver workQ and the * state should have been set to AIO_COMPLETED and the return and error * values set.  aioDone shouldnt't be called from interrupt service * routine (if so, it gets deffered to excTask).** RETURNS: N/A** NOMANUAL*/void aioDone     (    AIO_SYS * 		pReq			/* AIO request */    )    {    AIO_WAIT_ID *	pWaitId;		/* wait request id */    struct aiocb *	pAiocb = pReq->pAiocb;	/* AIO control block */    if (INT_CONTEXT ())		{	excJobAdd ((VOIDFUNCPTR) aioDone, (int) pReq, 0, 0, 0, 0, 0);	return;	}    if (aioPrintRtn != NULL)	(* aioPrintRtn) ("aioDone: aiocb (0x%x) retVal %d error 0x%x\n", 			 (int) pAiocb, pAiocb->aio_retVal, 			 pAiocb->aio_errorVal, 0, 0, 0);    /* Wake tasks waiting in aio_suspend */    mutex_lock (&pReq->lock);    						    for (pWaitId = (AIO_WAIT_ID *) lstFirst (&pReq->wait); (pWaitId != NULL); 	 pWaitId = (AIO_WAIT_ID *) lstNext (&pWaitId->node))	{	mutex_lock (&pWaitId->lock);	   	if (!pWaitId->done)	    pWaitId->done = TRUE;	cond_signal (&pWaitId->wake);	mutex_unlock (&pWaitId->lock);	}    mutex_unlock (&pReq->lock);    /* We lock out the task because even though we signaled it     * we don't want it to run until we marked it completed.     */         taskLock ();				    if (pReq->pClust != NULL)	aioClustRet (pAiocb, pReq->pClust);    /* Send a caller specified signal */    if (pAiocb->aio_sigevent.sigev_notify == SIGEV_SIGNAL)	{	if (aioPrintRtn != NULL)	    (* aioPrintRtn) ("aioDone: signal %d\n",			     pAiocb->aio_sigevent.sigev_signo, 0, 0, 0, 0, 0);	sigPendInit (&pReq->sigpend);	pReq->sigpend.sigp_info.si_signo = pAiocb->aio_sigevent.sigev_signo;	pReq->sigpend.sigp_info.si_code  = SI_ASYNCIO;	pReq->sigpend.sigp_info.si_value = pAiocb->aio_sigevent.sigev_value;	sigPendKill (pReq->ioNode.taskId, &pReq->sigpend);	}

⌨️ 快捷键说明

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