aioSysDrv.c
上传用户:nvosite88
上传日期:2007-01-17
资源大小:4983k
文件大小:20k
源码类别:

VxWorks

开发平台:

C/C++

  1. /* aioSysDrv.c - AIO system driver */
  2. /* Copyright 1984-1994 Wind River Systems, Inc. */
  3. #include "copyright_wrs.h"
  4. /*
  5. modification history
  6. -------------------
  7. 1c,01feb94,dvs documentation changes.
  8. 1b,12jan94,kdl  changed name to aioSysDrv.c; general cleanup.
  9. 1a,04apr93,elh  written.
  10. */
  11. /* 
  12. DESCRIPTION
  13. This library is the AIO system driver.  The system driver implements
  14. asynchronous I/O with system AIO tasks performing the AIO requests
  15. in a synchronous manner.  It is installed as the default driver for AIO.
  16. INTERNAL
  17. Two types of tasks are used to implement the system driver: the aioIoTask 
  18. and the aioWaitTask.  The aioIoTask services the work queue and performs 
  19. the I/O.  It gets an AIO request from the work queue, performs the I/O 
  20. on behalf of the task that initiated the I/O request, and then notifies 
  21. the caller of the I/O completion.  The number of aioIoTasks gets specified
  22. by the user in the call to aioSysInit.
  23. The aioWaitTask services the wait queue and is used for AIO requests 
  24. that can not be performed immediately due to blocking I/O.  The aioWaitTask 
  25. waits for data (or events) to arrive that will allow waiting AIO requests 
  26. to complete successfully. 
  27. Therefore, if the aioIoTask gets an AIO request that will block, the 
  28. aioIoTask will not execute the I/O command but instead put the request in 
  29. "wait" state, add it to the wait queue and notify the aioWaitTask that the I/O
  30. request is waiting on data.  
  31. Once the data arrives, the aioWaitTask moves the request back to the 
  32. work queue and notifies the aioIoTask the request can now be completed.
  33. This library uses pipeDrv to communicate between the aioIoTasks and 
  34. aioWaitTask.  Therefore pipeDrv must get dragged in to use the system 
  35. driver.
  36. SEE ALSO: POSIX 1003.1b document
  37. */
  38. /* includes */
  39. #include "vxWorks.h" 
  40. #include "aioSysDrv.h"
  41. #include "stdio.h"
  42. #include "taskLib.h"
  43. #include "private/iosLibP.h"
  44. #include "logLib.h"
  45. #include "selectLib.h"
  46. #include "string.h"
  47. #include "pipeDrv.h"
  48. #include "ioLib.h"
  49. /* defines */
  50. /* other defines */
  51. #define AIO_TASK_BASE_NAME "tAioIoTask" /* task base name */
  52. #define AIO_TASK_NAME_LEN 50 /* expected task name length */
  53. #define AIO_WAIT_TASK_NAME "tAioWait" /* wait task name */
  54. #define AIO_PIPE_NAME "/aioPipe" /* pipe name */
  55. #define AIO_PIPE_MSG_MAX 50 /* max pipe messages */
  56. #define READ_OP 0 /* read operation */
  57. #define WRITE_OP 1 /* write operation */
  58. #define IO_OP(op) ((op) == IO_READ ? READ_OP : WRITE_OP)
  59. /* AIO system driver flags */
  60. #define DRV_SELECT 0x4 /* select device */
  61. #define DRV_NOSELECT 0x8 /* not a select device */
  62. /* typedefs */
  63. typedef struct wait_msg /* wait message */
  64.     {
  65.     int op; /* READ_OP || WRITE_OP */
  66.     int fd; /* file descriptor */
  67.     } WAIT_MSG;
  68. /* globals */
  69. FUNCPTR aioSysPrintRtn = NULL; /* print routine */
  70. struct /* aioWaitTask wait fds */
  71.     {
  72.     fd_set ioWait [2];
  73.     fd_set io [2];
  74.     } ioFds;
  75. /* locals */
  76. LOCAL AIO_DEV aioDev; /* AIO device structure */
  77. LOCAL SEMAPHORE aioIOSem; /* I/O semaphore */
  78. LOCAL SEMAPHORE aioSysQSem; /* Q semaphore (work & done) */
  79. LOCAL SEMAPHORE aioSysWorkSem; /* work semaphore */
  80. LOCAL BOOL aioSysInitialized = FALSE; /* library initialized */
  81. LOCAL int aioSysFd; /* wait task control fd */
  82. /* forward declarations */
  83. void    aioIoTask (AIO_DEV * pDev);
  84. void    aioWaitTask (void);
  85. LOCAL STATUS  aioSysInsert (int value, struct aiocb * pAiocb, int prio);
  86. LOCAL STATUS  aioSysIoctl (int value, int function, int arg);
  87. LOCAL STATUS aioSysRead (struct aiocb * pAiocb, int * pError);
  88. LOCAL STATUS  aioSysWrite (struct aiocb * pAiocb, int * pError);
  89. LOCAL STATUS  aioSysSyncReq (AIO_DEV * pDev, AIO_SYS * pReq);
  90. LOCAL BOOL  aioSysOpWillBlock (int fd, int op);
  91. LOCAL BOOL  aioSysBlockingDev (int fd);
  92. LOCAL BOOL  aioSysWaitFind (AIO_SYS * pReq, IO_Q * pQ, int bogus4);
  93. /*******************************************************************************
  94. *
  95. * aioSysInit - initialize the AIO system driver
  96. * This routine initializes the AIO system driver.  It should be called
  97. * once after the AIO library has been initialized.  It spawns
  98. * <numTasks> system I/O tasks to be executed at <taskPrio> priority level,
  99. * with a stack size of <taskStackSize>.  It also starts the wait task and sets 
  100. * the system driver as the default driver for AIO. If <numTasks>, <taskPrio>,
  101. * or <taskStackSize> is 0, a default value (AIO_IO_TASKS_DFLT, AIO_IO_PRIO_DFLT,
  102. * or AIO_IO_STACK_DFLT, respectively) is used.
  103. *
  104. * RETURNS: OK if successful, otherwise ERROR.
  105. */
  106. STATUS aioSysInit 
  107.     (
  108.     int numTasks, /* number of system tasks */
  109.     int taskPrio, /* AIO task priority */
  110.     int taskStackSize /* AIO task stack size */
  111.     )
  112.     {
  113.     int ix; /* index */
  114.     char  taskName [AIO_TASK_NAME_LEN];
  115. /* area to build task name */
  116.     if (aioSysInitialized)
  117. return (OK); /* already initialized */
  118.     /* Set default parameter values */
  119.     taskStackSize = (taskStackSize == 0) ? AIO_IO_STACK_DFLT : taskStackSize;
  120.     numTasks   = (numTasks == 0) ? AIO_IO_TASKS_DFLT : numTasks;
  121.     taskPrio   = (taskPrio == 0) ? AIO_IO_PRIO_DFLT : min (taskPrio, 254);
  122.     /* Initialize the I/O queues (workQ and waitQ) */
  123.     semMInit (&aioSysQSem, SEM_DELETE_SAFE | SEM_Q_PRIORITY);
  124.     ioQInit (&aioDev.ioQ, ioQLockSem, ioQUnlockSem, (int) &aioSysQSem);
  125.     /* Create IPC pipe for I/O tasks and wait task */
  126.     pipeDrv ();
  127.     if ((pipeDevCreate (AIO_PIPE_NAME, AIO_PIPE_MSG_MAX, 
  128. sizeof (WAIT_MSG)) == ERROR) ||
  129.         (aioSysFd = open (AIO_PIPE_NAME, O_RDWR, 0666)) == ERROR)
  130. return (ERROR); /* pipe driver needed */
  131.     /* Start aioWaitTask.  It must have a lower priority than aioIoTasks. */
  132.     if (taskSpawn (AIO_WAIT_TASK_NAME, taskPrio + 1, AIO_TASK_OPT, 
  133.    AIO_WAIT_STACK, (FUNCPTR) aioWaitTask, 
  134.    0, 0, 0, 0, 0, 0, 0, 0, 0, 0) == ERROR)
  135.   return (ERROR);
  136.     /* Initialize the work and position semaphores */
  137.     semCInit (&aioSysWorkSem, SEM_Q_FIFO, SEM_EMPTY);
  138.     semMInit (&aioIOSem, SEM_DELETE_SAFE | SEM_Q_PRIORITY);
  139.     /* Spawn aioIoTasks */
  140.     while (numTasks-- > 0)
  141. {
  142. sprintf (taskName,"%s%d", AIO_TASK_BASE_NAME, numTasks); 
  143. if (aioSysPrintRtn != NULL)
  144.     (* aioSysPrintRtn) ("aioIoTask: %s startingn", (int) taskName, 
  145. 0, 0, 0, 0, 0);
  146. if (taskSpawn (taskName, taskPrio, AIO_TASK_OPT, taskStackSize, 
  147.        (FUNCPTR) aioIoTask, (int) &aioDev, 0, 0, 0, 0, 0, 0, 
  148.        0, 0, 0) == ERROR)
  149.     return (ERROR);
  150. }
  151.     /* Install AIO system driver as the default driver */
  152.     for (ix = 0 ; ix < maxDrivers; ix++)
  153. aioDrvInstall (ix, aioSysInsert, aioSysIoctl, 0);
  154.     aioSysInitialized = TRUE; /* mark as initialized */
  155.     return (OK);
  156.     }
  157. /*****************************************************************************
  158. *
  159. * aioSysInsert - Insert an AIO request into the system work queue
  160. *
  161. * This routine accepts an AIO request into the driver.  If there are 
  162. * other requests waiting on the fd (for the requested op) it adds 
  163. * the AIO request to the wait queue and notifies the aioWaitTask.  
  164. * Otherwise it adds the request to the work queue and signals the aioIoTask.
  165. *
  166. * RETURNS: OK if successfully inserted, ERROR otherwise.
  167. */
  168. LOCAL STATUS aioSysInsert 
  169.     (
  170.     int  value, /* not used */
  171.     struct aiocb * pAiocb, /* AIO control block */
  172.     int prio /* priority */
  173.     )
  174.     {
  175.     WAIT_MSG  newFd; /* new fd to wait on */
  176.     IO_Q * pQ = &aioDev.ioQ; /* I/O queue */
  177.     AIO_SYS * pReq = &pAiocb->aio_sys;/* AIO request */
  178.     if (aioSysPrintRtn != NULL)
  179. (* aioSysPrintRtn) ("aioSysInsert: aiocb (0%x) prio (%d) op %dn", 
  180.     (int) pAiocb, prio, pReq->ioNode.op, 0, 0, 0);
  181.     IOQ_LOCK (pQ); /* lock access */
  182.      
  183.     if (pReq->state != AIO_READY)
  184.     {
  185.         IOQ_UNLOCK (pQ);
  186. return (ERROR); /* requests been mucked */ 
  187. }
  188.     /* Check if the wait task is already waiting on the file descriptor
  189.      * for the requested op.  
  190.      */
  191.     if (FD_ISSET (pAiocb->aio_fildes, &ioFds.ioWait [IO_OP(pReq->ioNode.op)]))
  192. {
  193.         if (aioSysPrintRtn != NULL)
  194.     (* aioSysPrintRtn) ("aioSysInsert: will block - move wait queuen");
  195. IOQ_WAIT_ADD (pQ, &pReq->ioNode, prio); /* add to wait Q */
  196. pReq->state = AIO_WAIT;
  197.      IOQ_UNLOCK (pQ);
  198. newFd.op = IO_OP (pReq->ioNode.op); /* notify waitTask */
  199. newFd.fd = pAiocb->aio_fildes;
  200. write (aioSysFd, (caddr_t) &newFd, sizeof (WAIT_MSG));
  201. }
  202.     else
  203. {
  204.         if (aioSysPrintRtn != NULL)
  205.     (* aioSysPrintRtn) ("aioSysInsert: move to work queuen");
  206.      IOQ_WORK_ADD (pQ, &pReq->ioNode, prio); /* add it to work Q */ 
  207.      pReq->state = AIO_QUEUED;
  208.      IOQ_UNLOCK (pQ);
  209.      semGive (&aioSysWorkSem); /* notify I/O Task */
  210. }
  211.     return (OK);
  212.     }
  213. /*****************************************************************************
  214. *
  215. * aioSysIoctl - control an AIO request
  216. *
  217. * This routine performs a control operation on a previously submitted AIO 
  218. * request.
  219. *
  220. * RETURNS: OK if successful, otherwise ERROR.
  221. */
  222. LOCAL STATUS aioSysIoctl 
  223.     (
  224.     int value, /* not used */
  225.     int function, /* ioctl function */
  226.     int arg /* argument */
  227.     )
  228.     {
  229.     int retVal = OK; /* return value */
  230.     switch (function)
  231. {
  232.   case FAIO_CANCEL :  /* cancel request */
  233.     retVal = aioCancel (&aioDev, (struct aiocb *) arg); 
  234.     break;
  235. case FAIO_PUSH : /* move to head */
  236.     retVal = aioPush (&aioDev, (struct aiocb *) arg);
  237.     break;
  238. default: /* unknown function */ 
  239.     errno = S_ioLib_UNKNOWN_REQUEST;
  240.     retVal = ERROR;
  241.     break;
  242. }
  243.     return (retVal);
  244.     }
  245. /*******************************************************************************
  246. *
  247. * aioIoTask - AIO I/O task
  248. *
  249. * This routine performs the I/O on behalf of the caller.  It gets a requests 
  250. * from the work queue and if the operation will not block, performs the 
  251. * requested operation.  If the request will block it moves the request to the
  252. * wait queue and notifies the wait server of the new addition.
  253. *
  254. * RETURNS: N/A
  255. * NOMANUAL
  256. */
  257.  
  258. void aioIoTask
  259.     (
  260.     AIO_DEV *           pDev /* AIO device */
  261.     )
  262.  
  263.     {
  264.     AIO_SYS * pReq; /* AIO request */
  265.     int op; /* operation */
  266.     int fd; /* file descriptor */
  267.     int                 retVal; /* return value */
  268.     int                 errorVal;            /* error value */
  269.     WAIT_MSG waitMsg; /* wait msg */ 
  270.  
  271.     FOREVER
  272.         {
  273.         semTake (&aioSysWorkSem, WAIT_FOREVER);     /* wait for work */
  274.         if ((pReq = aioNext (pDev)) == NULL)    /* Get I/O request */
  275.             continue;
  276.   op = pReq->ioNode.op;
  277. fd = pReq->pAiocb->aio_fildes;
  278. if (aioSysPrintRtn != NULL)
  279.     (* aioSysPrintRtn) ("aioIoTask: (0x%x) op: %d fd: %dn", 
  280. (int) pReq->pAiocb, op, fd);
  281.      semTake (&aioIOSem, WAIT_FOREVER);
  282. /* Sync function */
  283.     if (op == IO_SYNC) 
  284.     {
  285.     aioSync (pDev, pReq->pAiocb, aioSysSyncReq);
  286.          semGive (&aioIOSem);
  287.     continue;
  288.     }
  289. if (aioSysBlockingDev (fd) && aioSysOpWillBlock (fd, op))
  290.     {
  291.     /* If the device is a blocking device and the requested
  292.      * operation will block, then move it from the work queue to 
  293.      * to the wait queue, and notify the aioWaitTask of new waiter.
  294.      */
  295.     semGive (&aioIOSem);
  296.          IOQ_LOCK (&pDev->ioQ);
  297.     IOQ_WORK_DELETE (&pDev->ioQ, &pReq->ioNode);
  298.     IOQ_WAIT_ADD (&pDev->ioQ, &pReq->ioNode, pReq->ioNode.prio);
  299.     pReq->state = AIO_WAIT; /* wait state */
  300.          IOQ_UNLOCK (&pDev->ioQ);
  301.     waitMsg.op = IO_OP (op);
  302.     waitMsg.fd = fd;
  303.     write (aioSysFd, (char *) &waitMsg, sizeof (WAIT_MSG));
  304.     continue;
  305.     }
  306. /* Perform the requested I/O */
  307.   switch (op)
  308.     {
  309.     case IO_READ:
  310.      retVal = aioSysRead (pReq->pAiocb, &errorVal); 
  311. break;
  312.     case IO_WRITE:
  313.              retVal = aioSysWrite (pReq->pAiocb, &errorVal);
  314. break;
  315.     default:
  316.      retVal   = ERROR;
  317.      errorVal = EINVAL;
  318. break;
  319.     }
  320. semGive (&aioIOSem);
  321. /* Mark request as completed and send the request back to aioLib */
  322.      IOQ_LOCK (&pDev->ioQ);
  323. AIO_DONE_SET (pReq->pAiocb, retVal, errorVal);
  324.         IOQ_WORK_DELETE (&pDev->ioQ, &pReq->ioNode);
  325. IOQ_UNLOCK (&pDev->ioQ);
  326. ioQNodeDone (&pReq->ioNode);
  327.         }
  328.     }
  329. /*****************************************************************************
  330. *
  331. * aioSysSyncReq - synchronize an AIO request 
  332. *
  333. * This routine attempts to synchronize the AIO request <pReq> to the 
  334. * synchronized I/O completion state.
  335. * RETURNS: OK if successful, ERROR otherwise.
  336. */
  337. LOCAL STATUS aioSysSyncReq
  338.     (
  339.     AIO_DEV * pDev, /* AIO device */
  340.     AIO_SYS * pReq /* AIO request */
  341.     )
  342.     {
  343.     int errorVal; /* error value */
  344.     IO_Q * pQ = &pDev->ioQ; /* I/O queue */
  345.     STATUS  retVal = OK; /* return value */
  346.     if ((pReq->state == AIO_QUEUED) && (pReq->ioNode.op == IO_WRITE))
  347. {
  348. if (aioSysWrite (pReq->pAiocb, &errorVal) == ERROR)
  349.     retVal = ERROR; /* write failed */
  350.     /* complete the AIO operation */
  351.         AIO_DONE_SET (pReq->pAiocb, retVal, errorVal);
  352.         IOQ_LOCK (pQ);
  353. IOQ_WORK_DELETE (pQ, &pReq->ioNode);
  354.      IOQ_UNLOCK (pQ);
  355. ioQNodeDone (&pReq->ioNode);
  356. }
  357.     return (retVal);
  358.     }
  359. /*****************************************************************************
  360. *
  361. * aioSysWrite - AIO system driver write routine 
  362. *
  363. * This routine performs a write call for the AIO request <pAiocb>.
  364. *
  365. * RETURNS: return value for the write call. 
  366. *
  367. * INTERNAL
  368. * POSIX says that writes can append to the file if O_APPEND is set
  369. * for the file.  When we implement O_APPEND, the following code will 
  370. * need to be changed.
  371. */
  372.     
  373. LOCAL STATUS aioSysWrite
  374.     (
  375.     struct aiocb * pAiocb, /* AIO control block */
  376.     int * pError
  377.     )
  378.     {
  379.     int retVal = ERROR; /* return value */
  380.     /* lseek protected by aioIOSem */
  381.     lseek (pAiocb->aio_fildes, pAiocb->aio_offset, SEEK_SET); 
  382.     retVal = write (pAiocb->aio_fildes, (char *) pAiocb->aio_buf, 
  383.     pAiocb->aio_nbytes); 
  384.     if (aioSysPrintRtn != NULL)
  385. (* aioSysPrintRtn) 
  386.     ("aioSysWrite:fd (%d) wrote %d bytes buffer 0x%x loc %d n", 
  387.      pAiocb->aio_fildes, retVal, pAiocb->aio_buf, pAiocb->aio_offset);
  388.     *pError = (retVal == ERROR) ? errno : 0;
  389.     return (retVal); 
  390.     }
  391. /*****************************************************************************
  392. *
  393. * aioSysRead - AIO system driver read routine
  394. *
  395. * This routine performs a read call for the AIO request <pAiocb>.
  396. *
  397. * RETURNS:  return value from the read call. 
  398. */
  399. LOCAL STATUS aioSysRead 
  400.     (
  401.     struct aiocb * pAiocb, /* AIO control block */
  402.     int * pError
  403.     )
  404.     {
  405.     int retVal = ERROR; /* return value */
  406.     /* lseek protected by aioIOSem */
  407.     lseek (pAiocb->aio_fildes, pAiocb->aio_offset, SEEK_SET); 
  408.     retVal = read (pAiocb->aio_fildes, (char *) pAiocb->aio_buf, 
  409.    pAiocb->aio_nbytes);
  410.     if (aioSysPrintRtn != NULL)
  411. (* aioSysPrintRtn) 
  412.     ("aioSysRead:fd (%d) read %d bytes buffer 0x%x loc %d n", 
  413.      pAiocb->aio_fildes, retVal, pAiocb->aio_buf, pAiocb->aio_offset);
  414.     *pError = (retVal == ERROR) ? errno : 0;
  415.     return (retVal); 
  416.     }
  417. /*******************************************************************************
  418. *
  419. * aioWaitTask - AIO wait task
  420. *
  421. * The AIO wait task is responsible for managing the AIO requests that are
  422. * are in AIO_WAIT state.  These are requests that can not be completed 
  423. * immediately because they are waiting for I/O on blocking devices.  
  424. * When data becomes available on a file descriptor, the aioWaitTask finds
  425. * the waiting request and moves it back to the work queue to be executed
  426. * by the aioIoTask.
  427. *
  428. * RETURNS: N/A
  429. * NOMANUAL
  430. */
  431. void aioWaitTask (void)
  432.     {
  433.     int ndone; /* num done */
  434.     WAIT_MSG  waitMsg; /* control message */
  435.     IO_Q * pIoQ = &aioDev.ioQ; /* I/O queue */
  436.     /* clear out the file descriptors - set control fd */
  437.     FD_ZERO (&ioFds.ioWait [READ_OP]);
  438.     FD_ZERO (&ioFds.ioWait [WRITE_OP]);
  439.     FD_SET (aioSysFd, &ioFds.ioWait [READ_OP]);
  440.     FOREVER 
  441. {
  442. ioFds.io [READ_OP] = ioFds.ioWait [READ_OP];
  443. ioFds.io [WRITE_OP] = ioFds.ioWait [WRITE_OP];
  444. /* Wait for data and/or control messages */
  445. ndone = select (FD_SETSIZE, &ioFds.io [READ_OP], &ioFds.io [WRITE_OP], 
  446. NULL, NULL);
  447.    if (FD_ISSET (aioSysFd, &ioFds.io [READ_OP]))
  448.     {     
  449.     /* Got a control message with new fd to wait on */
  450.     read (aioSysFd, (caddr_t) &waitMsg, sizeof (WAIT_MSG));
  451.     if (aioSysPrintRtn != NULL)
  452. (* aioSysPrintRtn) ("aioWaitTask: control op %s fd %dn",  
  453.             (waitMsg.op == READ_OP) ? "read" : "write",
  454.     waitMsg.fd);
  455.     
  456.     /* mask in the new fd to wait on */
  457.     FD_SET (waitMsg.fd, &ioFds.ioWait [waitMsg.op]);
  458.     
  459.     if (--ndone == 0)
  460. continue; /* only got control info */
  461.     }
  462. /* Data became available.  Find the request(s) this will satisfy */
  463.      IOQ_LOCK (pIoQ);
  464. FD_ZERO (&ioFds.ioWait [READ_OP]);
  465. FD_ZERO (&ioFds.ioWait [WRITE_OP]);
  466.         ioQEach (&pIoQ->waitQ, aioSysWaitFind, (int) pIoQ, 0);
  467. IOQ_UNLOCK (pIoQ);
  468.         FD_SET (aioSysFd, &ioFds.ioWait [READ_OP]); /* add control fd */
  469. }
  470.     }
  471. /*****************************************************************************
  472. *
  473. * aioSysBlockingDev - check if a device is a blocking device
  474. *
  475. * This routine determines if the device associated with file descriptor
  476. * <fd> is a blocking (select) device.
  477. *
  478. * RETURNS: TRUE if the device supports select, FALSE otherwise.
  479. * NOMANUAL
  480. */
  481. BOOL aioSysBlockingDev
  482.     (
  483.     int  fd  /* file descriptor */
  484.     )
  485.     {
  486.     fd_set readFds; /* read fds */
  487.     BOOL selectDev; /* device supports select */
  488.     int flags; /* driver flags */
  489.     struct timeval timeOut = {0, 0}; /* timeout */
  490.     if (aioDrvFlagsGet (fd, &flags) == ERROR)
  491. return (FALSE);
  492.     /* check flags if we already know this information */
  493.     if (flags & DRV_NOSELECT)
  494. return (FALSE); /* no select */
  495.     if (flags & DRV_SELECT)
  496. return (TRUE); /* has select */
  497.     /* Poll driver to see if select fails */
  498.     FD_ZERO (&readFds);
  499.     FD_SET (fd, &readFds);
  500.     selectDev = select (FD_SETSIZE, &readFds, NULL, NULL, &timeOut) == ERROR ?
  501. FALSE : TRUE;
  502.     aioDrvFlagsSet (fd, selectDev ? DRV_SELECT : DRV_NOSELECT);
  503.     return (selectDev);
  504.     }
  505. /*******************************************************************************
  506. *
  507. * aioSysOpWillBlock - requested operation will block
  508. *
  509. * This routine determines if the the operation specified by <op> will block
  510. * on the device associated with file descriptor <fd>.
  511. *
  512. * RETURNS: TRUE if the operation will block, FALSE otherwise.
  513. */
  514. LOCAL BOOL aioSysOpWillBlock 
  515.     (
  516.     int fd, /* file descriptor */
  517.     int op /* operation */
  518.     )
  519.     {
  520.     fd_set readFds; /* read fds */
  521.     fd_set writeFds; /* write fds */
  522.     struct timeval timeOut = {0, 0}; /* timeout */
  523.     
  524.     /* Poll the device to see if the requested operation will block */
  525.     FD_ZERO (&readFds); 
  526.     FD_ZERO (&writeFds);
  527.     FD_SET (fd, (op == IO_READ) ? &readFds : &writeFds);
  528.     return ((select (FD_SETSIZE, &readFds, &writeFds, NULL, &timeOut) == 0) ?
  529.       TRUE : FALSE);
  530.     }
  531. /*******************************************************************************
  532. *
  533. * aioSysWaitFind - find waiting requests (each routine)
  534. *
  535. * This routine gets called once for each AIO request in the wait queue.
  536. * It looks at the AIO request <pReq> to determine if the waiting request may 
  537. * have been satisfied by the recent wake up.  It also reconstructs the 
  538. * file descriptors for the aioWaitTask to select on.
  539. *  
  540. * RETURNS: TRUE
  541. */
  542. LOCAL BOOL aioSysWaitFind
  543.     (
  544.     AIO_SYS * pReq, /* AIO request */
  545.     IO_Q * pQ, /* I/O queue */
  546.     int bogus /* not used */
  547.     )
  548.     {
  549.     int op; /* operation */
  550.     int fd;  /* file descriptor */
  551.     op = IO_OP (pReq->ioNode.op);
  552.     fd = pReq->pAiocb->aio_fildes;
  553.     if (FD_ISSET (fd, &ioFds.io [op]))
  554. {
  555. /* Request may have been satisfied, move it from the 
  556.  * wait queue to the work queue and notify the I/O tasks 
  557.  * of new work. 
  558.  */
  559. IOQ_WAIT_DELETE (pQ, &pReq->ioNode);
  560.      IOQ_WORK_ADD (pQ, &pReq->ioNode, pReq->ioNode.prio);
  561.      pReq->pAiocb->aio_sys.state = AIO_QUEUED;
  562. FD_CLR (fd, &ioFds.io [op]);
  563.         semGive (&aioSysWorkSem); /* notify i/o task */
  564. }
  565.     else
  566.      FD_SET (fd, &ioFds.ioWait [op]);
  567.     return (TRUE); /* do entire list */
  568.     }