Example #1
0
int
rtems_aio_enqueue (rtems_aio_request *req)
{

  rtems_aio_request_chain *r_chain;
  rtems_chain_control *chain;
  pthread_t thid;
  int result, policy;
  struct sched_param param;

  /* The queue should be initialized */
  AIO_assert (aio_request_queue.initialized == AIO_QUEUE_INITIALIZED);

  result = pthread_mutex_lock (&aio_request_queue.mutex);
  if (result != 0) {
    free (req);
    return result;
  }

  /* _POSIX_PRIORITIZED_IO and _POSIX_PRIORITY_SCHEDULING are defined, 
     we can use aio_reqprio to lower the priority of the request */
  pthread_getschedparam (pthread_self(), &policy, &param);

  req->caller_thread = pthread_self ();
  req->priority = param.sched_priority - req->aiocbp->aio_reqprio;
  req->policy = policy;
  req->aiocbp->error_code = EINPROGRESS;
  req->aiocbp->return_value = 0;

  if ((aio_request_queue.idle_threads == 0) &&
      aio_request_queue.active_threads < AIO_MAX_THREADS)
    /* we still have empty places on the active_threads chain */
    {
      chain = &aio_request_queue.work_req;
      r_chain = rtems_aio_search_fd (chain, req->aiocbp->aio_fildes, 1);
      
      if (r_chain->new_fd == 1) {
	rtems_chain_prepend (&r_chain->perfd, &req->next_prio);
	r_chain->new_fd = 0;
	pthread_mutex_init (&r_chain->mutex, NULL);
	pthread_cond_init (&r_chain->cond, NULL);
	    
	AIO_printf ("New thread \n");
	result = pthread_create (&thid, &aio_request_queue.attr,
				 rtems_aio_handle, (void *) r_chain);
	if (result != 0) {
	  pthread_mutex_unlock (&aio_request_queue.mutex);
	  return result;
	}
	++aio_request_queue.active_threads;
      }
      else {
	/* put request in the fd chain it belongs to */
	pthread_mutex_lock (&r_chain->mutex);
	rtems_aio_insert_prio (&r_chain->perfd, req);
	pthread_cond_signal (&r_chain->cond);
	pthread_mutex_unlock (&r_chain->mutex);
      }
    }
  else 
    {
      /* the maximum number of threads has been already created
	 even though some of them might be idle.
	 The request belongs to one of the active fd chain */
      r_chain = rtems_aio_search_fd (&aio_request_queue.work_req,
				     req->aiocbp->aio_fildes, 0);
      if (r_chain != NULL)
	{
	  pthread_mutex_lock (&r_chain->mutex);
	  rtems_aio_insert_prio (&r_chain->perfd, req);
	  pthread_cond_signal (&r_chain->cond);
	  pthread_mutex_unlock (&r_chain->mutex);
	    
	} else {
      
	/* or to the idle chain */
	chain = &aio_request_queue.idle_req;
	r_chain = rtems_aio_search_fd (chain, req->aiocbp->aio_fildes, 1);
      
	if (r_chain->new_fd == 1) {
	  /* If this is a new fd chain we signal the idle threads that
	     might be waiting for requests */
	  AIO_printf (" New chain on waiting queue \n ");
	  rtems_chain_prepend (&r_chain->perfd, &req->next_prio);
	  r_chain->new_fd = 0;
	  pthread_mutex_init (&r_chain->mutex, NULL);
	  pthread_cond_init (&r_chain->cond, NULL);
	} else
	  /* just insert the request in the existing fd chain */
	  rtems_aio_insert_prio (&r_chain->perfd, req);
	if (aio_request_queue.idle_threads > 0)
	  pthread_cond_signal (&aio_request_queue.new_req);
      }
    }

  pthread_mutex_unlock (&aio_request_queue.mutex);
  return 0;
}
Example #2
0
int aio_cancel(int fildes, struct aiocb  *aiocbp)
{
  rtems_chain_control *idle_req_chain = &aio_request_queue.idle_req;
  rtems_chain_control *work_req_chain = &aio_request_queue.work_req;
  rtems_aio_request_chain *r_chain;
  int result;
  
  pthread_mutex_lock (&aio_request_queue.mutex);

  if (fcntl (fildes, F_GETFD) < 0) {
    pthread_mutex_unlock(&aio_request_queue.mutex);
    rtems_set_errno_and_return_minus_one (EBADF);
  }

  /* if aiocbp is NULL remove all request for given file descriptor */
  if (aiocbp == NULL) {
    AIO_printf ("Cancel all requests\n");        
         
    r_chain = rtems_aio_search_fd (work_req_chain, fildes, 0);
    if (r_chain == NULL) {
      AIO_printf ("Request chain not on [WQ]\n");

      if (!rtems_chain_is_empty (idle_req_chain)) {
        r_chain = rtems_aio_search_fd (idle_req_chain, fildes, 0);
        if (r_chain == NULL) {
          pthread_mutex_unlock(&aio_request_queue.mutex);
          return AIO_ALLDONE;
        }

        AIO_printf ("Request chain on [IQ]\n");

        rtems_chain_extract (&r_chain->next_fd);
        rtems_aio_remove_fd (r_chain);
        pthread_mutex_destroy (&r_chain->mutex);
        pthread_cond_destroy (&r_chain->mutex);
        free (r_chain);

        pthread_mutex_unlock (&aio_request_queue.mutex);
        return AIO_CANCELED;
      }

      pthread_mutex_unlock (&aio_request_queue.mutex);
      return AIO_ALLDONE;
    }

    AIO_printf ("Request chain on [WQ]\n");

    pthread_mutex_lock (&r_chain->mutex);
    rtems_chain_extract (&r_chain->next_fd);
    rtems_aio_remove_fd (r_chain);
    pthread_mutex_unlock (&r_chain->mutex);
    pthread_mutex_unlock (&aio_request_queue.mutex);
    return AIO_CANCELED;
  } else {
    AIO_printf ("Cancel request\n");

    if (aiocbp->aio_fildes != fildes) {
      pthread_mutex_unlock (&aio_request_queue.mutex);
      rtems_set_errno_and_return_minus_one (EINVAL);
    }
      
    r_chain = rtems_aio_search_fd (work_req_chain, fildes, 0);
    if (r_chain == NULL) {
      if (!rtems_chain_is_empty (idle_req_chain)) {
        r_chain = rtems_aio_search_fd (idle_req_chain, fildes, 0);
        if (r_chain == NULL) { 
          pthread_mutex_unlock (&aio_request_queue.mutex);
          rtems_set_errno_and_return_minus_one (EINVAL);
        }      
           
        AIO_printf ("Request on [IQ]\n");                     
   
        result = rtems_aio_remove_req (&r_chain->perfd, aiocbp);
        pthread_mutex_unlock (&aio_request_queue.mutex);
        return result;
      } else {
        pthread_mutex_unlock (&aio_request_queue.mutex);
        return AIO_ALLDONE;
      }
    }  
      AIO_printf ("Request on [WQ]\n");
      
      pthread_mutex_lock (&r_chain->mutex);
      result = rtems_aio_remove_req (&r_chain->perfd, aiocbp);
      pthread_mutex_unlock (&r_chain->mutex);
      pthread_mutex_unlock (&aio_request_queue.mutex);
      return result;
  }
  return AIO_ALLDONE;
}