📄 aiopxlib.c
字号:
** 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 + -