static void wait_for_event(struct timeval *tv) { struct solarisaio_data *sd; struct io_u *io_u; aio_result_t *res; res = aiowait(tv); if (res == (aio_result_t *) -1) { int err = errno; if (err != EINVAL) { log_err("fio: solarisaio got %d in aiowait\n", err); exit(err); } return; } else if (!res) return; io_u = container_of(res, struct io_u, resultp); sd = io_u->engine_data; if (io_u->resultp.aio_return >= 0) { io_u->resid = io_u->xfer_buflen - io_u->resultp.aio_return; io_u->error = 0; } else io_u->error = io_u->resultp.aio_errno; /* * For SIGIO, we need a write barrier between the two, so that * the ->aio_pending store is seen after the ->aio_events store */ sd->aio_events[sd->aio_pending] = io_u; write_barrier(); sd->aio_pending++; sd->nr--; }
int ACE_SUN_Proactor::handle_events_i (ACE_Time_Value *delta) { int retval = 0; aio_result_t *result = 0; if (0 == delta) { if (this->num_started_aio_ == 0) this->wait_for_start (0); result = aiowait (0); } else { if (this->num_started_aio_ == 0) { // Decrement delta with the amount of time spent waiting ACE_Countdown_Time countdown (delta); ACE_Time_Value tv (*delta); tv += ACE_OS::gettimeofday (); if (this->wait_for_start (&tv) == -1) return -1; } struct timeval delta_tv = *delta; result = aiowait (&delta_tv); } if (result == 0) { // timeout, do nothing, // we should process "post_completed" queue } else if (reinterpret_cast<long> (result) == -1) { // Check errno for EINVAL,EAGAIN,EINTR ?? switch (errno) { case EINTR : // aiowait() was interrupted by a signal. case EINVAL: // there are no outstanding asynchronous I/O requests. break; // we should process "post_completed" queue default: // EFAULT ACE_ERROR_RETURN ((LM_ERROR, "%N:%l:(%P | %t)::%p \nNumAIO=%d\n", "ACE_SUN_Proactor::handle_events: aiowait failed", num_started_aio_), -1); } } else { int error_status = 0; size_t transfer_count = 0; ACE_POSIX_Asynch_Result *asynch_result = find_completed_aio (result, error_status, transfer_count); if (asynch_result != 0) { // Call the application code. this->application_specific_code (asynch_result, transfer_count, 0, // No completion key. error_status); // Error retval++; } } // process post_completed results retval += this->process_result_queue (); return retval > 0 ? 1 : 0 ; }
void * usbReapResponse ( UsbDevice *device, unsigned char endpointAddress, UsbResponse *response, int wait ) { UsbEndpoint *endpoint; if ((endpoint = usbGetEndpoint(device, endpointAddress))) { UsbEndpointExtension *eptx = endpoint->extension; struct timeval timeout; UsbAsynchronousRequest *request; timeout.tv_sec = 0; timeout.tv_usec = 0; while (!(request = dequeueItem(eptx->requests))) { aio_result_t *result; doWait: if ((int)(result = aiowait(wait? NULL: &timeout)) == -1) { if (errno == EINTR) goto doWait; if (errno != EINVAL) { logSystemError("USB asynchronous wait"); return NULL; } result = NULL; } if (!result) { errno = EAGAIN; return NULL; } request = (UsbAsynchronousRequest *)result; { UsbEndpoint *ep = request->endpoint; UsbEndpointExtension *epx = ep->extension; if (!enqueueItem(epx->requests, request)) { logSystemError("USB asynchronous enqueue"); } } } response->context = request->context; response->buffer = request->buffer; response->size = request->length; response->count = request->result.aio_return; response->error = request->result.aio_errno; if (response->count == -1) { errno = response->error; logSystemError("USB asynchronous completion"); } else { switch (USB_ENDPOINT_DIRECTION(endpoint->descriptor)) { case UsbEndpointDirection_Input: if (!usbApplyInputFilters(endpoint, response->buffer, response->size, &response->count)) { response->error = EIO; response->count = -1; } break; } } return request; } return NULL; }
void ADIOI_UFS_ReadComplete(ADIO_Request *request, ADIO_Status *status, int *error_code) { #ifndef NO_AIO #ifndef PRINT_ERR_MSG static char myname[] = "ADIOI_UFS_READCOMPLETE"; #endif #ifdef AIO_SUN aio_result_t *result=0, *tmp; #else int err; #endif #ifdef AIO_HANDLE_IN_AIOCB struct aiocb *tmp1; #endif #endif if (*request == ADIO_REQUEST_NULL) { *error_code = MPI_SUCCESS; return; } #ifdef AIO_SUN if ((*request)->queued) { /* dequeue it */ tmp = (aio_result_t *) (*request)->handle; while (tmp->aio_return == AIO_INPROGRESS) usleep(1000); /* sleep for 1 ms., until done. Is 1 ms. a good number? */ /* when done, dequeue any one request */ result = (aio_result_t *) aiowait(0); (*request)->nbytes = tmp->aio_return; #ifdef PRINT_ERR_MSG *error_code = (tmp->aio_return == -1) ? MPI_ERR_UNKNOWN : MPI_SUCCESS; #else if (tmp->aio_return == -1) { *error_code = MPIR_Err_setmsg(MPI_ERR_IO, MPIR_ADIO_ERROR, myname, "I/O Error", "%s", strerror(tmp->aio_errno)); ADIOI_Error((*request)->fd, *error_code, myname); } else *error_code = MPI_SUCCESS; #endif /* aiowait only dequeues a request. The completion of a request can be checked by just checking the aio_return flag in the handle passed to the original aioread()/aiowrite(). Therefore, I need to ensure that aiowait() is called exactly once for each previous aioread()/aiowrite(). This is also taken care of in ADIOI_xxxDone */ } else *error_code = MPI_SUCCESS; #ifdef HAVE_STATUS_SET_BYTES if ((*request)->nbytes != -1) MPIR_Status_set_bytes(status, (*request)->datatype, (*request)->nbytes); #endif #endif #ifdef AIO_HANDLE_IN_AIOCB /* IBM */ if ((*request)->queued) { do { err = aio_suspend(1, (struct aiocb **) &((*request)->handle)); } while ((err == -1) && (errno == EINTR)); tmp1 = (struct aiocb *) (*request)->handle; if (err != -1) { err = aio_return(tmp1->aio_handle); (*request)->nbytes = err; errno = aio_error(tmp1->aio_handle); } else (*request)->nbytes = -1; /* on DEC, it is required to call aio_return to dequeue the request. IBM man pages don't indicate what function to use for dequeue. I'm assuming it is aio_return! POSIX says aio_return may be called only once on a given handle. */ #ifdef PRINT_ERR_MSG *error_code = (err == -1) ? MPI_ERR_UNKNOWN : MPI_SUCCESS; #else if (err == -1) { *error_code = MPIR_Err_setmsg(MPI_ERR_IO, MPIR_ADIO_ERROR, myname, "I/O Error", "%s", strerror(errno)); ADIOI_Error((*request)->fd, *error_code, myname); } else *error_code = MPI_SUCCESS; #endif } else *error_code = MPI_SUCCESS; #ifdef HAVE_STATUS_SET_BYTES if ((*request)->nbytes != -1) MPIR_Status_set_bytes(status, (*request)->datatype, (*request)->nbytes); #endif #elif (!defined(NO_AIO) && !defined(AIO_SUN)) /* DEC, SGI IRIX 5 and 6 */ if ((*request)->queued) { do { err = aio_suspend((const aiocb_t **) &((*request)->handle), 1, 0); } while ((err == -1) && (errno == EINTR)); if (err != -1) { err = aio_return((struct aiocb *) (*request)->handle); (*request)->nbytes = err; errno = aio_error((struct aiocb *) (*request)->handle); } else (*request)->nbytes = -1; #ifdef PRINT_ERR_MSG *error_code = (err == -1) ? MPI_ERR_UNKNOWN : MPI_SUCCESS; #else if (err == -1) { *error_code = MPIR_Err_setmsg(MPI_ERR_IO, MPIR_ADIO_ERROR, myname, "I/O Error", "%s", strerror(errno)); ADIOI_Error((*request)->fd, *error_code, myname); } else *error_code = MPI_SUCCESS; #endif } else *error_code = MPI_SUCCESS; #ifdef HAVE_STATUS_SET_BYTES if ((*request)->nbytes != -1) MPIR_Status_set_bytes(status, (*request)->datatype, (*request)->nbytes); #endif #endif #ifndef NO_AIO if ((*request)->queued != -1) { /* queued = -1 is an internal hack used when the request must be completed, but the request object should not be freed. This is used in ADIOI_Complete_async, because the user will call MPI_Wait later, which would require status to be filled. Ugly but works. queued = -1 should be used only in ADIOI_Complete_async. This should not affect the user in any way. */ /* if request is still queued in the system, it is also there on ADIOI_Async_list. Delete it from there. */ if ((*request)->queued) ADIOI_Del_req_from_list(request); (*request)->fd->async_count--; if ((*request)->handle) ADIOI_Free((*request)->handle); ADIOI_Free_request((ADIOI_Req_node *) (*request)); *request = ADIO_REQUEST_NULL; } #else /* HP, FreeBSD, Linux */ #ifdef HAVE_STATUS_SET_BYTES MPIR_Status_set_bytes(status, (*request)->datatype, (*request)->nbytes); #endif (*request)->fd->async_count--; ADIOI_Free_request((ADIOI_Req_node *) (*request)); *request = ADIO_REQUEST_NULL; *error_code = MPI_SUCCESS; #endif }