📄 aiopxlib.c
字号:
* `aio_reqprio' lower than the calling task priority.** The call returns when the write request has been initiated or queued to* the device. aio_error() can be used to determine the error status and of* the AIO operation. On completion, aio_return() can be used to determine* the return status.** `aio_sigevent' defines the signal to be generated on completion * of the write request. If this value is zero, no signal is generated. ** RETURNS: OK if write queued successfully, otherwise ERROR.** ERRNO: EBADF, EINVAL** INCLUDE FILES: aio.h** SEE ALSO: aio_error(), aio_return(), write()**/int aio_write ( struct aiocb * pAiocb /* AIO control block */ ) { return (aioSubmit (pAiocb, IO_WRITE, NULL)); }/********************************************************************************* lio_listio - initiate a list of asynchronous I/O requests (POSIX)** This routine submits a number of I/O operations (up to AIO_LISTIO_MAX)* to be performed asynchronously. <list> is a pointer to an array of * `aiocb' structures that specify the AIO operations to be performed. * The array is of size <nEnt>. ** The `aio_lio_opcode' field of the `aiocb' structure specifies the AIO* operation to be performed. Valid entries include LIO_READ, LIO_WRITE, and* LIO_NOP. LIO_READ corresponds to a call to aio_read(), LIO_WRITE* corresponds to a call to aio_write(), and LIO_NOP is ignored.** The <mode> argument can be either LIO_WAIT or LIO_NOWAIT. If <mode> is * LIO_WAIT, lio_listio() does not return until all the AIO operations * complete and the <pSig> argument is ignored. If <mode> is LIO_NOWAIT, the * lio_listio() returns as soon as the operations are queued. In this case, * if <pSig> is not NULL and the signal number indicated by* `pSig->sigev_signo' is not zero, the signal `pSig->sigev_signo' is* delivered when all requests have completed.** RETURNS: OK if requests queued successfully, otherwise ERROR.** ERRNO: EINVAL, EAGAIN, EIO** INCLUDE FILES: aio.h** SEE ALSO: aio_read(), aio_write(), aio_error(), aio_return().*/int lio_listio ( int mode, /* LIO_WAIT or LIO_NOWAIT */ struct aiocb * list[], /* list of operations */ int nEnt, /* size of list */ struct sigevent * pSig /* signal on completion */ ) { AIO_CLUST * pClust; /* cluster */ int errorVal = 0; /* error value */ STATUS retVal = OK; /* return value */ BOOL submitFailed = FALSE; /* submit failed */ /* Validate parameters */ if (((mode != LIO_WAIT) && (mode != LIO_NOWAIT)) || (nEnt > AIO_LISTIO_MAX)) { errno = EINVAL; return (ERROR); /* invalid parameter */ } if ((pSig != NULL) && (pSig->sigev_notify == SIGEV_SIGNAL) && ((pSig->sigev_signo < 1) || (pSig->sigev_signo > _NSIGS))) { errno = EINVAL; return (ERROR); /* safety check */ } /* Obtain a free cluster */ if ((pClust = aioClustGet ()) == NULL) return (ERROR); /* no clusters available */ if ((mode == LIO_NOWAIT) && (pSig != NULL) && (pSig->sigev_notify == SIGEV_SIGNAL)) { sigPendInit (&pClust->sigpend); pClust->sigpend.sigp_info.si_signo = pSig->sigev_signo; pClust->sigpend.sigp_info.si_value = pSig->sigev_value; pClust->sigpend.sigp_info.si_code = SI_ASYNCIO; } else pClust->sigpend.sigp_info.si_signo = 0; /* Link up cluster and submit AIO requests */ aioListEach (list, nEnt, aioListClust, (int) pClust, 0); aioListEach (list, nEnt, aioListSubmit, (int) pClust, (int) &submitFailed); if (mode == LIO_NOWAIT) { if (submitFailed) { errno = EIO; return (ERROR); /* submit failed */ } else return (OK); /* don't wait for I/O */ } /* Wait for I/O completion */ mutex_lock (&pClust->lock); retVal = OK; while ((pClust->refCnt > 0) && (retVal == OK)) retVal = cond_timedwait (&pClust->wake, &pClust->lock, NULL); mutex_unlock (&pClust->lock); if (retVal != OK) { errno = retVal; return (ERROR); /* signal */ } /* Check for I/O errors */ aioListEach (list, nEnt, aioListError, (int) &errorVal, 0); if (errorVal) { errno = EIO; return (ERROR); /* an AIO request failed */ } return (OK); /* I/O completed successfully */ }/********************************************************************************* aio_suspend - wait for asynchronous I/O request(s) (POSIX)** This routine suspends the caller until one of the following occurs:* .iP* at least one of the previously submitted asynchronous I/O operations* referenced by <list> has completed,* .iP* a signal interrupts the function, or* .iP* the time interval specified by <timeout> has passed* (if <timeout> is not NULL).* .LP* * RETURNS: OK if an AIO request completes, otherwise ERROR.** ERRNO: EAGAIN, EINTR ** INCLUDE FILES: aio.h** INTERNAL: We make the task safe from deletion so the (stack) variables * that were added to the wait list don't get hosed. This could have * been implemented with taskDeleteHooks.*/int aio_suspend ( const struct aiocb * list[], /* AIO requests */ int nEnt, /* number of requests */ const struct timespec * timeout /* wait timeout */ ) { AIO_WAIT_ID aioId; /* AIO Id */ int numDone; /* num completed */ STATUS retVal = OK; /* return value */ int savtype; /* saved cancellation type */ /* Initialize the wait structure */ bzero ((caddr_t) &aioId, sizeof (AIO_WAIT_ID)); aioId.done = FALSE; /* Link into pthreads support code */ if (_func_pthread_setcanceltype != NULL) { _func_pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &savtype); } mutex_init (&aioId.lock, NULL); cond_init (&aioId.wake, NULL); taskSafe (); /* TASK_SAFE */ /* Submit wait requests */ numDone = aioListEach ((struct aiocb **) list, nEnt, aioListWait, (int) &aioId, 0); if (numDone == nEnt) { /* All wait requests got submitted - wait for one to complete */ mutex_lock (&aioId.lock); retVal = OK; while ((!aioId.done) && (retVal == OK)) retVal = cond_timedwait (&aioId.wake, &aioId.lock, timeout); mutex_unlock (&aioId.lock); } else { /* Wait requests didn't all get submited */ if (errno != AIO_COMPLETED) /* not completed successfully */ retVal = errno; numDone = nEnt; /* cancel to the one failed */ } /* Cancel outstanding wait requests */ aioListEach ((struct aiocb **) list, numDone, aioListUnwait, (int) &aioId, 0); taskUnsafe (); /* TASK_UNSAFE */ /* Link into pthreads support code */ if (_func_pthread_setcanceltype != NULL) { _func_pthread_setcanceltype(savtype, NULL); } if (retVal != OK) { errno = retVal; return (ERROR); /* error occurred */ } return (OK); }/******************************************************************************* *** aio_cancel - cancel an asynchronous I/O request (POSIX)** This routine attempts to cancel one or more asynchronous I/O request(s) * currently outstanding against the file descriptor <fildes>. <pAiocb> * points to the asynchronous I/O control block for a particular request to* be cancelled. If <pAiocb> is NULL, all outstanding cancelable * asynchronous I/O requests associated with <fildes> are cancelled.* * Normal signal delivery occurs for AIO operations that are successfully * cancelled. If there are requests that cannot be cancelled, then the normal * asynchronous completion process takes place for those requests when they * complete.** Operations that are cancelled successfully have a return status of -1* and an error status of ECANCELED.** RETURNS:* AIO_CANCELED if requested operations were cancelled,* AIO_NOTCANCELED if at least one operation could not be cancelled,* AIO_ALLDONE if all operations have already completed, or* ERROR if an error occurred.** ERRNO: EBADF** INCLUDE FILES: aio.h** SEE ALSO: aio_return(), aio_error()*/int aio_cancel ( int fildes, /* file descriptor */ struct aiocb * pAiocb /* AIO control block */ ) { FUNCPTR ioctlRtn; /* ioctl routine */ AIO_FD_ENTRY * pEntry; /* fd entry */ DL_NODE * pNode; /* fd node */ AIO_SYS * pReq; /* AIO request */ int value; /* driver parameter */ int cancelled = 0; /* num cancelled */ int retVal = OK; /* return value */ if ((pEntry = aioEntryFind (fildes)) == NULL) return (ERROR); ioctlRtn = aioDrvTable [pEntry->drv_num].ioctl; value = pEntry->drv_value; if (pAiocb != NULL) /* cancel a single request */ { if (pAiocb->aio_state == AIO_COMPLETED) return (AIO_ALLDONE); if (((* ioctlRtn) (value, FAIO_CANCEL, pAiocb)) == OK) return (AIO_CANCELED); return (AIO_NOTCANCELED); } /* Cancel all requests on the file descriptor */ semTake (&pEntry->ioQSem, WAIT_FOREVER); for (pNode = DLL_FIRST (&pEntry->ioQ); pNode != NULL; pNode = DLL_NEXT (pNode)) { pReq = FD_NODE_TO_SYS (pNode); if (pReq->state != AIO_COMPLETED) { if ((* ioctlRtn) (value, FAIO_CANCEL, pReq->pAiocb) == ERROR) retVal = AIO_NOTCANCELED; else cancelled ++; } } semGive (&pEntry->ioQSem); if (retVal == AIO_NOTCANCELED) return (AIO_NOTCANCELED); /* couldn't cancel */ if (cancelled) return (AIO_CANCELED); /* cancelled */ return (AIO_ALLDONE); }#if FALSE /* not ready for primetime - kdl 1/26/94 *//********************************************************************************* aio_fsync - asynchronous file synchronization (POSIX)** This routine asynchronously forces all I/O operations associated * with the file, indicated by `aio_fildes', queued at the time aio_fsync() is * called to the synchronized I/O completion state. aio_fsync() returns * when the synchronization request has be initiated or queued to the file or * device.* * The value of <op> is ignored. It currently has no meaning in VxWorks.** If the call fails, the outstanding I/O operations are not guaranteed to* have completed. If it succeeds, only the I/O that was queued at the time* of the call is guaranteed to the relevant completion state.* * The `aio_sigevent' member of the <pAiocb> defines an optional signal to be * generated on completion of aio_fsync().** RETURNS: OK if queued successfully, otherwise ERROR.** ERRNO: EINVAL, EBADF** INCLUDE FILES: aio.h** SEE ALSO: aio_error(), aio_return() ** INTERNAL* Asynchronously synchronize a file?????? Excuse me? Sounds like an * oxymoron (or at least moronic). At any rate this is hard to implement* correctly. ** NOMANUAL*/int aio_fsync ( int op, /* operation */ struct aiocb * pAiocb /* AIO control block */ ) { FUNCPTR ioctlRtn; /* ioctl routine */ AIO_FD_ENTRY * pEntry; /* fd entry */ if (pAiocb == NULL) return (OK); /* not sure what POSIX means */ if ((pEntry = aioEntryFind (pAiocb->aio_fildes)) == NULL) return (ERROR); /* Submit sync request */ if (aioSubmit (pAiocb, IO_SYNC, NULL) == ERROR) return (ERROR); /* Push request to head of work queue */ ioctlRtn = aioDrvTable [pEntry->drv_num].ioctl; (* ioctlRtn) (pEntry->drv_value, FAIO_PUSH, pAiocb); return (OK); }#endif /* FALSE *//********************************************************************************* aio_error - retrieve error status of asynchronous I/O operation (POSIX)** This routine returns the error status associated with the I/O operation * specified by <pAiocb>. If the operation is not yet completed, the error * status will be EINPROGRESS.** RETURNS:* EINPROGRESS if the AIO operation has not yet completed,* OK if the AIO operation completed successfully,* the error status if the AIO operation failed, * otherwise ERROR.** ERRNO: EINVAL** INCLUDE FILES: aio.h**/int aio_error ( const struct aiocb * pAiocb /* AIO control block */ ) { int state; /* AIO request state */ if (pAiocb != NULL) { state = pAiocb->aio_state; if (state == AIO_COMPLETED) return (pAiocb->aio_errorVal); /* return error value */ if ((state >= AIO_READY) && (state <= AIO_RUNNING)) return (EINPROGRESS); /* still running */ } errno = EINVAL; return (ERROR); /* unsure about pAiocb */ }/********************************************************************************* aio_return - retrieve return status of asynchronous I/O operation (POSIX)** This routine returns the return status associated with the I/O operation* specified by <pAiocb>. The return status for an AIO operation is the * value that would be returned by the corresponding read(), write(), or * fsync() call. aio_return() may be called only after the AIO operation* has completed (aio_error() returns a valid error code--not EINPROGRESS).* Furthermore, aio_return() may be called only once; subsequent * calls will fail.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -