📄 aiopxlib.c
字号:
pReq->state = AIO_COMPLETED; taskUnlock (); }/******************************************************************************** * aioClustRet - return a cluster** This routine frees <pClust> and signals/wakes up the initiating task if* <pAiocb> is the last AIO request in the cluster.** RETURN: N/A** NOMANUAL*/LOCAL void aioClustRet ( struct aiocb * pAiocb, /* AIO control block */ AIO_CLUST * pClust /* AIO cluster */ ) { BOOL returnClust; /* cluster goes to table */ int signo; /* signal number */ int taskId; /* lio_listio() task */ if (pClust == NULL) return; mutex_lock (&pClust->lock); returnClust = ((pClust->refCnt > 0) && (--pClust->refCnt == 0)); mutex_unlock (&pClust->lock); /* If we are the last one in the cluster. Signal/wake up the caller * and return the cluster. */ if (returnClust) { signo = pClust->sigpend.sigp_info.si_signo; taskId = pAiocb->aio_sys.ioNode.taskId; if (aioPrintRtn != NULL) (* aioPrintRtn) ("clust done signal (%d) to task %x\n", signo, taskId, 0, 0, 0, 0); /* send the user defined signal */ if (signo != 0) { sigPendKill (taskId, &pClust->sigpend); } else { /* wake up waiting process */ cond_signal (&pClust->wake); } pClust->inuse = FALSE; /* free cluster */ } } /* DRIVER INTERFACE ROUTINES *//******************************************************************************** * aioDrvInstall - install an AIO driver ** This routine is called by an I/O driver to specify it supports AIO and * to insert it's AIO routines into the AIO driver table. <drvnum> is * the driver number to install. <pInsert> is the AIO insert routine.* <pIoctl> the the AIO ioctl routine. <flags> gets filled into the * driver specific flags member of the AIO_DRV_ENTRY structure. ** RETURNS: OK if successful, otherwise ERROR.** ERRNO: S_aioPxLib_DRV_NUM_INVALID** INTERNAL: The aioDrvTable is similar to the drvTable in iosLib. * aioDrvTable (and this routine) might go away if aioLib is more * integrated into iosLib. Don't man this page until driver interface* is documented and supported.** NOMANUAL*/STATUS aioDrvInstall ( int drvnum, /* driver number */ FUNCPTR pInsert, /* insert routine */ FUNCPTR pIoctl, /* ioctl routine */ int flags /* driver flags */ ) { AIO_LOCK (); if ((drvnum < 0) || (drvnum >= maxDrivers) || aioDrvTable [drvnum].inuse) { errno = S_aioPxLib_DRV_NUM_INVALID; return (ERROR); /* invalid driver number */ } aioDrvTable [drvnum].insert = pInsert; /* add to driver table */ aioDrvTable [drvnum].ioctl = pIoctl; aioDrvTable [drvnum].flags = flags; AIO_UNLOCK (); return (OK); }/******************************************************************************** * aioDrvFlagsGet - get AIO driver flags** RETURNS: OK if successful, otherwise ERROR.** NOMANUAL*/STATUS aioDrvFlagsGet ( int fd, /* file descriptor */ int * pFlags /* return flags */ ) { AIO_FD_ENTRY * pEntry; /* fd entry */ if ((pEntry = aioEntryFind (fd)) == NULL) return (ERROR); /* error condition */ *pFlags = aioDrvTable [pEntry->drv_num].flags; return (OK); }/******************************************************************************** * aioDrvFlagsSet - set AIO driver flags** RETURNS: OK if successful, otherwise ERROR.** NOMANUAL*/STATUS aioDrvFlagsSet ( int fd, /* file descriptor */ int flags /* flags to set */ ) { AIO_FD_ENTRY * pEntry; /* fd entry */ if ((pEntry = aioEntryFind (fd)) == NULL) return (ERROR); /* error condition */ aioDrvTable [pEntry->drv_num].flags |= flags; return (OK); }/******************************************************************************** * aioNext - obtain next AIO request to initiate** This routine obtains the next available AIO request in the work queue. * It finds the first request where the state is AIO_QUEUED. ** RETURNS: pointer to next queued AIO control block or NULL** NOMANUAL*/AIO_SYS * aioNext ( AIO_DEV * pDev /* AIO device */ ) { AIO_SYS * pReq = NULL; /* AIO request */ LIST * pWorkQ = &pDev->ioQ.workQ; /* work queue */ IOQ_LOCK (&pDev->ioQ); for (pReq = (AIO_SYS *) lstFirst (pWorkQ); (pReq != NULL); pReq = (AIO_SYS *) lstNext (&pReq->ioNode.node)) { if (pReq->state == AIO_QUEUED) { pReq->state = AIO_RUNNING; break; } } IOQ_UNLOCK (&pDev->ioQ); return (pReq); }/******************************************************************************* aioCancel - cancel an AIO request ** This routine tries to cancel an AIO request. If the state of the AIO* request is not running, the request is deleted from the work queue * <pDev->workQ> and completed with a return value of -1 and an error * value of ECANCELED.** RETURNS: ERROR if request is RUNNING, otherwise OK.** NOMANUAL*/STATUS aioCancel ( AIO_DEV * pDev, /* AIO device */ struct aiocb * pAiocb /* AIO control block */ ) { int state; /* state */ IO_Q * pQ = &pDev->ioQ; /* queue */ AIO_SYS * pReq = &pAiocb->aio_sys;/* AIO request */ IOQ_LOCK (pQ); /* lock the ioQ */ state = pReq->state; if (state == AIO_RUNNING) { IOQ_UNLOCK (pQ); return (ERROR); /* can't cancel running */ } if (state == AIO_QUEUED) IOQ_WORK_DELETE (pQ, &pReq->ioNode); else { if (state == AIO_WAIT) IOQ_WAIT_DELETE (pQ, &pReq->ioNode); } AIO_DONE_SET (pAiocb, ERROR, ECANCELED); /* mark it as cancelled */ IOQ_UNLOCK (pQ); /* unlock ioQ */ ioQNodeDone (&pReq->ioNode); return (OK); }/******************************************************************************* aioPush - push a queued request to head of work queue.** RETURNS: OK if successful, otherwise ERROR.** NOMANUAL*/STATUS aioPush ( AIO_DEV * pDev, /* AIO device */ struct aiocb * pAiocb /* AIO request */ ) { IO_Q * pQ = &pDev->ioQ; IO_NODE * pNode = &pAiocb->aio_sys.ioNode; IOQ_LOCK (pQ); if (pAiocb->aio_state == AIO_QUEUED) { IOQ_WORK_DELETE (pQ, pNode); IOQ_WORK_ADD_HEAD (pQ, pNode); } IOQ_UNLOCK (pQ); return (OK); }/******************************************************************************* aioSync - synchronize** This routine synchronizes all AIO requests assoicated with file descriptor* <pAiocb->aio_fildes>. <syncReqRtn> specifies a driver provided * synchronization routine that gets called for each request associated with * the above specified file. After each AIO request has been synchronized,* it is returned to the library via aioDone.** RETURNS: OK, or ERROR if couldn't find entry.** NOMANUAL*/STATUS aioSync ( AIO_DEV * pDev, /* AIO device */ struct aiocb * pAiocb, /* aio control block */ FUNCPTR syncReqRtn /* routine to sync a request */ ) { FAST AIO_FD_ENTRY * pEntry; /* fd entry */ ARGS args; int fd = pAiocb->aio_fildes; if ((pEntry = aioEntryFind (fd)) == NULL) return (ERROR); args.pDev = pDev; /* device */ args.retVal = OK; /* return */ args.errorVal = 0; /* errno */ args.syncRtn = syncReqRtn; semTake (&pEntry->ioQSem, WAIT_FOREVER); dllEach (&pEntry->ioQ, aioSyncNode, (int) &args); semGive (&pEntry->ioQSem); if (ioctl (fd, FIOSYNC, 0) == ERROR) ioctl (fd, FIOFLUSH, 0); /* one for the aio_fsync() request */ IOQ_LOCK (&pDev->ioQ); AIO_DONE_SET (pAiocb, args.retVal, args.errorVal); IOQ_WORK_DELETE (&pDev->ioQ, &pAiocb->aio_sys.ioNode); IOQ_UNLOCK (&pDev->ioQ); ioQNodeDone (&pAiocb->aio_sys.ioNode); return (OK); }/******************************************************************************* aioSyncNode - synchronize an AIO request* * This routine gets called from aioSync for each AIO request on the fd list.* It calls the driver provided sync routine for each request whose * state is not completed. */LOCAL STATUS aioSyncNode ( DL_NODE * pFdNode, /* node on fd list */ ARGS * pArgs /* arguments */ ) { AIO_SYS * pReq; /* AIO request */ BOOL retVal = TRUE; /* return value */ pReq = FD_NODE_TO_SYS (pFdNode); if (pReq->state != AIO_COMPLETED) { if (((* pArgs->syncRtn) (pArgs->pDev, pReq)) == ERROR) { pArgs->retVal = ERROR; pArgs->errorVal = errno; retVal = FALSE; } } return (retVal); }/* The following routines are support routines for iosLib. They wont * be needed if fully integerated into the I/O system. *//******************************************************************************* aioFdNew - initialize an AIO file descriptor** This routine gets called from iosFdNew when allocating a new file* descriptor. ** RETURNS: N/A*/LOCAL void aioFdNew ( int fd /* file descriptor */ ) { AIO_FD_ENTRY * pEntry = &aioFdTable [STD_UNFIX(fd)]; semTake (&pEntry->ioQSem, WAIT_FOREVER); dllInit (&pEntry->ioQ); pEntry->ioQActive = TRUE; semGive (&pEntry->ioQSem); }/******************************************************************************* aioFdFree - free a file descriptor** This routine gets called from iosFdFree after closing a file descriptor. * It cancels (or waits for, if it can't cancel) all the outstanding AIO* submitted to file descriptor <fd>.** RETURNS: N/A*/LOCAL void aioFdFree ( int fd /* file descriptor */ ) { AIO_SYS * pReq; /* AIO request */ DL_NODE * pNode; /* fd node */ FAST AIO_FD_ENTRY * pEntry = &aioFdTable [STD_UNFIX(fd)]; semTake (&pEntry->ioQSem, WAIT_FOREVER); FOREVER { if ((pNode = DLL_FIRST (&pEntry->ioQ)) == NULL) break; /* list empty */ pReq = FD_NODE_TO_SYS (pNode); /* Try to cancel it. If can't, then wait for it */ if (aio_cancel (fd, pReq->pAiocb) == AIO_NOTCANCELED) aio_suspend ((const struct aiocb **) &pReq->pAiocb, 1, (const struct timespec *) NULL); dllRemove (&pEntry->ioQ, pNode); /* remove it */ } pEntry->ioQActive = FALSE; semGive (&pEntry->ioQSem); }/******************************************************************************* aioEntryFind - find the aio fd entry** aiEntryFind validates <fd> and finds the AIO_FD_ENTRY associated with* <fd>. ** RETURNS: a pointer to the AIO_FD_ENTRY or NULL if error.** NOMANUAL*/AIO_FD_ENTRY * aioEntryFind ( int fd /* file descriptor */ ) { int xfd = STD_MAP (fd); /* mapped fd */ if (FD_CHECK (xfd) == NULL) { errno = EBADF; return (NULL); /* file descriptor invalid */ } return (&aioFdTable [xfd]); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -