Ejemplo n.º 1
0
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--;
}
Ejemplo n.º 2
0
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 ;

}
Ejemplo n.º 3
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;
}
Ejemplo n.º 4
0
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    
}