📄 aiosysdrv.c
字号:
} if (aioSysBlockingDev (fd) && aioSysOpWillBlock (fd, op)) { /* If the device is a blocking device and the requested * operation will block, then move it from the work queue to * to the wait queue, and notify the aioWaitTask of new waiter. */ semGive (&aioIOSem); IOQ_LOCK (&pDev->ioQ); IOQ_WORK_DELETE (&pDev->ioQ, &pReq->ioNode); IOQ_WAIT_ADD (&pDev->ioQ, &pReq->ioNode, pReq->ioNode.prio); pReq->state = AIO_WAIT; /* wait state */ IOQ_UNLOCK (&pDev->ioQ); waitMsg.op = IO_OP (op); waitMsg.fd = fd; write (aioSysFd, (char *) &waitMsg, sizeof (WAIT_MSG)); continue; } /* Perform the requested I/O */ switch (op) { case IO_READ: retVal = aioSysRead (pReq->pAiocb, &errorVal); break; case IO_WRITE: retVal = aioSysWrite (pReq->pAiocb, &errorVal); break; default: retVal = ERROR; errorVal = EINVAL; break; } semGive (&aioIOSem); /* Mark request as completed and send the request back to aioLib */ IOQ_LOCK (&pDev->ioQ); AIO_DONE_SET (pReq->pAiocb, retVal, errorVal); IOQ_WORK_DELETE (&pDev->ioQ, &pReq->ioNode); IOQ_UNLOCK (&pDev->ioQ); ioQNodeDone (&pReq->ioNode); } }/******************************************************************************* aioSysSyncReq - synchronize an AIO request ** This routine attempts to synchronize the AIO request <pReq> to the * synchronized I/O completion state.* * RETURNS: OK if successful, ERROR otherwise.*/LOCAL STATUS aioSysSyncReq ( AIO_DEV * pDev, /* AIO device */ AIO_SYS * pReq /* AIO request */ ) { int errorVal; /* error value */ IO_Q * pQ = &pDev->ioQ; /* I/O queue */ STATUS retVal = OK; /* return value */ if ((pReq->state == AIO_QUEUED) && (pReq->ioNode.op == IO_WRITE)) { if (aioSysWrite (pReq->pAiocb, &errorVal) == ERROR) retVal = ERROR; /* write failed */ /* complete the AIO operation */ AIO_DONE_SET (pReq->pAiocb, retVal, errorVal); IOQ_LOCK (pQ); IOQ_WORK_DELETE (pQ, &pReq->ioNode); IOQ_UNLOCK (pQ); ioQNodeDone (&pReq->ioNode); } return (retVal); }/******************************************************************************* aioSysWrite - AIO system driver write routine ** This routine performs a write call for the AIO request <pAiocb>.** RETURNS: return value for the write call. ** INTERNAL* POSIX says that writes can append to the file if O_APPEND is set* for the file. When we implement O_APPEND, the following code will * need to be changed.*/ LOCAL STATUS aioSysWrite ( struct aiocb * pAiocb, /* AIO control block */ int * pError ) { int retVal = ERROR; /* return value */ /* lseek protected by aioIOSem */ lseek (pAiocb->aio_fildes, pAiocb->aio_offset, SEEK_SET); retVal = write (pAiocb->aio_fildes, (char *) pAiocb->aio_buf, pAiocb->aio_nbytes); if (aioSysPrintRtn != NULL) (* aioSysPrintRtn) ("aioSysWrite:fd (%d) wrote %d bytes buffer 0x%x loc %d \n", pAiocb->aio_fildes, retVal, pAiocb->aio_buf, pAiocb->aio_offset); *pError = (retVal == ERROR) ? errno : 0; return (retVal); }/******************************************************************************* aioSysRead - AIO system driver read routine** This routine performs a read call for the AIO request <pAiocb>.** RETURNS: return value from the read call. */LOCAL STATUS aioSysRead ( struct aiocb * pAiocb, /* AIO control block */ int * pError ) { int retVal = ERROR; /* return value */ /* lseek protected by aioIOSem */ lseek (pAiocb->aio_fildes, pAiocb->aio_offset, SEEK_SET); retVal = read (pAiocb->aio_fildes, (char *) pAiocb->aio_buf, pAiocb->aio_nbytes); if (aioSysPrintRtn != NULL) (* aioSysPrintRtn) ("aioSysRead:fd (%d) read %d bytes buffer 0x%x loc %d \n", pAiocb->aio_fildes, retVal, pAiocb->aio_buf, pAiocb->aio_offset); *pError = (retVal == ERROR) ? errno : 0; return (retVal); }/********************************************************************************* aioWaitTask - AIO wait task** The AIO wait task is responsible for managing the AIO requests that are* are in AIO_WAIT state. These are requests that can not be completed * immediately because they are waiting for I/O on blocking devices. * When data becomes available on a file descriptor, the aioWaitTask finds* the waiting request and moves it back to the work queue to be executed* by the aioIoTask.** RETURNS: N/A* NOMANUAL*/void aioWaitTask (void) { int ndone; /* num done */ WAIT_MSG waitMsg; /* control message */ IO_Q * pIoQ = &aioDev.ioQ; /* I/O queue */ /* clear out the file descriptors - set control fd */ FD_ZERO (&ioFds.ioWait [READ_OP]); FD_ZERO (&ioFds.ioWait [WRITE_OP]); FD_SET (aioSysFd, &ioFds.ioWait [READ_OP]); FOREVER { ioFds.io [READ_OP] = ioFds.ioWait [READ_OP]; ioFds.io [WRITE_OP] = ioFds.ioWait [WRITE_OP]; /* Wait for data and/or control messages */ ndone = select (FD_SETSIZE, &ioFds.io [READ_OP], &ioFds.io [WRITE_OP], NULL, NULL); if (FD_ISSET (aioSysFd, &ioFds.io [READ_OP])) { /* Got a control message with new fd to wait on */ read (aioSysFd, (caddr_t) &waitMsg, sizeof (WAIT_MSG)); if (aioSysPrintRtn != NULL) (* aioSysPrintRtn) ("aioWaitTask: control op %s fd %d\n", (waitMsg.op == READ_OP) ? "read" : "write", waitMsg.fd); /* mask in the new fd to wait on */ FD_SET (waitMsg.fd, &ioFds.ioWait [waitMsg.op]); if (--ndone == 0) continue; /* only got control info */ } /* Data became available. Find the request(s) this will satisfy */ IOQ_LOCK (pIoQ); FD_ZERO (&ioFds.ioWait [READ_OP]); FD_ZERO (&ioFds.ioWait [WRITE_OP]); ioQEach (&pIoQ->waitQ, aioSysWaitFind, (int) pIoQ, 0); IOQ_UNLOCK (pIoQ); FD_SET (aioSysFd, &ioFds.ioWait [READ_OP]); /* add control fd */ } }/******************************************************************************* aioSysBlockingDev - check if a device is a blocking device** This routine determines if the device associated with file descriptor* <fd> is a blocking (select) device.** RETURNS: TRUE if the device supports select, FALSE otherwise.* NOMANUAL*/BOOL aioSysBlockingDev ( int fd /* file descriptor */ ) { fd_set readFds; /* read fds */ BOOL selectDev; /* device supports select */ int flags; /* driver flags */ struct timeval timeOut = {0, 0}; /* timeout */ if (aioDrvFlagsGet (fd, &flags) == ERROR) return (FALSE); /* check flags if we already know this information */ if (flags & DRV_NOSELECT) return (FALSE); /* no select */ if (flags & DRV_SELECT) return (TRUE); /* has select */ /* Poll driver to see if select fails */ FD_ZERO (&readFds); FD_SET (fd, &readFds); selectDev = select (FD_SETSIZE, &readFds, NULL, NULL, &timeOut) == ERROR ? FALSE : TRUE; aioDrvFlagsSet (fd, selectDev ? DRV_SELECT : DRV_NOSELECT); return (selectDev); }/********************************************************************************* aioSysOpWillBlock - requested operation will block** This routine determines if the the operation specified by <op> will block* on the device associated with file descriptor <fd>.** RETURNS: TRUE if the operation will block, FALSE otherwise.*/LOCAL BOOL aioSysOpWillBlock ( int fd, /* file descriptor */ int op /* operation */ ) { fd_set readFds; /* read fds */ fd_set writeFds; /* write fds */ struct timeval timeOut = {0, 0}; /* timeout */ /* Poll the device to see if the requested operation will block */ FD_ZERO (&readFds); FD_ZERO (&writeFds); FD_SET (fd, (op == IO_READ) ? &readFds : &writeFds); return ((select (FD_SETSIZE, &readFds, &writeFds, NULL, &timeOut) == 0) ? TRUE : FALSE); }/********************************************************************************* aioSysWaitFind - find waiting requests (each routine)** This routine gets called once for each AIO request in the wait queue.* It looks at the AIO request <pReq> to determine if the waiting request may * have been satisfied by the recent wake up. It also reconstructs the * file descriptors for the aioWaitTask to select on.* * RETURNS: TRUE*/LOCAL BOOL aioSysWaitFind ( AIO_SYS * pReq, /* AIO request */ IO_Q * pQ, /* I/O queue */ int bogus /* not used */ ) { int op; /* operation */ int fd; /* file descriptor */ op = IO_OP (pReq->ioNode.op); fd = pReq->pAiocb->aio_fildes; if (FD_ISSET (fd, &ioFds.io [op])) { /* Request may have been satisfied, move it from the * wait queue to the work queue and notify the I/O tasks * of new work. */ IOQ_WAIT_DELETE (pQ, &pReq->ioNode); IOQ_WORK_ADD (pQ, &pReq->ioNode, pReq->ioNode.prio); pReq->pAiocb->aio_sys.state = AIO_QUEUED; FD_CLR (fd, &ioFds.io [op]); semGive (&aioSysWorkSem); /* notify i/o task */ } else FD_SET (fd, &ioFds.ioWait [op]); return (TRUE); /* do entire list */ }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -