Exemplo n.º 1
0
static void aio_read_worker(FAR void *arg)
{
	FAR struct aio_container_s *aioc = (FAR struct aio_container_s *)arg;
	FAR struct aiocb *aiocbp;
	pid_t pid;
#ifdef CONFIG_PRIORITY_INHERITANCE
	uint8_t prio;
#endif
	ssize_t nread = 0;

	/* Get the information from the container, decant the AIO control block,
	 * and free the container before starting any I/O.  That will minimize
	 * the delays by any other threads waiting for a pre-allocated container.
	 */

	DEBUGASSERT(aioc && aioc->aioc_aiocbp);
	pid = aioc->aioc_pid;
#ifdef CONFIG_PRIORITY_INHERITANCE
	prio = aioc->aioc_prio;
#endif
	aiocbp = aioc_decant(aioc);

#ifdef AIO_HAVE_FILEP
	{
		/* Perform the file read using:
		 *
		 *   u.aioc_filep - File structure pointer
		 *   aio_buf      - Location of buffer
		 *   aio_nbytes   - Length of transfer
		 *   aio_offset   - File offset
		 */

		nread = file_pread(aioc->u.aioc_filep, (FAR void *)aiocbp->aio_buf, aiocbp->aio_nbytes, aiocbp->aio_offset);
	}
#endif

	/* Set the result of the read */

	if (nread < 0) {
		int errcode = get_errno();
		fdbg("ERROR: pread failed: %d\n", errcode);
		DEBUGASSERT(errcode > 0);
		aiocbp->aio_result = -errcode;
	} else {
		aiocbp->aio_result = nread;
	}

	/* Signal the client */

	(void)aio_signal(pid, aiocbp);

#ifdef CONFIG_PRIORITY_INHERITANCE
	/* Restore the low priority worker thread default priority */

	lpwork_restorepriority(prio);
#endif
}
Exemplo n.º 2
0
static void aio_fsync_worker(FAR void *arg)
{
  FAR struct aio_container_s *aioc = (FAR struct aio_container_s *)arg;
  FAR struct aiocb *aiocbp;
  pid_t pid;
#ifdef CONFIG_PRIORITY_INHERITANCE
  uint8_t prio;
#endif
  int ret;

  /* Get the information from the container, decant the AIO control block,
   * and free the container before starting any I/O.  That will minimize
   * the delays by any other threads waiting for a pre-allocated container.
   */

  DEBUGASSERT(aioc && aioc->aioc_aiocbp);
  pid    = aioc->aioc_pid;
#ifdef CONFIG_PRIORITY_INHERITANCE
  prio   = aioc->aioc_prio;
#endif
  aiocbp = aioc_decant(aioc);

  /* Perform the fsync using u.aioc_filep */

  ret = file_fsync(aioc->u.aioc_filep);
  if (ret < 0)
    {
      int errcode = get_errno();
      ferr("ERROR: fsync failed: %d\n", errcode);
      DEBUGASSERT(errcode > 0);
      aiocbp->aio_result = -errcode;
    }
  else
    {
      aiocbp->aio_result = OK;
    }

  /* Signal the client */

  (void)aio_signal(pid, aiocbp);

#ifdef CONFIG_PRIORITY_INHERITANCE
  /* Restore the low priority worker thread default priority */

  lpwork_restorepriority(prio);
#endif
}
Exemplo n.º 3
0
int aio_cancel(int fildes, FAR struct aiocb *aiocbp)
{
	FAR struct aio_container_s *aioc;
	FAR struct aio_container_s *next;
	int status;
	int ret;

	/* Check if a non-NULL aiocbp was provided */

	/* Lock the scheduler so that no I/O events can complete on the worker
	 * thread until we set complete this operation.
	 */

	ret = AIO_ALLDONE;
	sched_lock();
	aio_lock();

	if (aiocbp) {
		/* Check if the I/O has completed */

		if (aiocbp->aio_result == -EINPROGRESS) {
			/* No.. Find the container for this AIO control block */

			for (aioc = (FAR struct aio_container_s *)g_aio_pending.head; aioc && aioc->aioc_aiocbp != aiocbp; aioc = (FAR struct aio_container_s *)aioc->aioc_link.flink) ;

			/* Did we find a container for this fildes?  We should; the aio_result says
			 * that the transfer is pending.  If not we return AIO_ALLDONE.
			 */

			if (aioc) {
				/* Yes... attempt to cancel the I/O.  There are two
				 * possibilities:* (1) the work has already been started and
				 * is no longer queued, or (2) the work has not been started
				 * and is still in the work queue.  Only the second case can
				 * be cancelled.  work_cancel() will return -ENOENT in the
				 * first case.
				 */

				status = work_cancel(LPWORK, &aioc->aioc_work);
				if (status >= 0) {
					aiocbp->aio_result = -ECANCELED;
					ret = AIO_CANCELED;
				} else {
					ret = AIO_NOTCANCELED;
				}

				/* Remove the container from the list of pending transfers */

				(void)aioc_decant(aioc);
			}
		}
	} else {
		/* No aiocbp.. cancel all outstanding I/O for the fildes */

		next = (FAR struct aio_container_s *)g_aio_pending.head;
		do {
			/* Find the next container with this AIO control block */

			for (aioc = next; aioc && aioc->aioc_aiocbp->aio_fildes != fildes; aioc = (FAR struct aio_container_s *)aioc->aioc_link.flink) ;

			/* Did we find the container?  We should; the aio_result says
			 * that the transfer is pending.  If not we return AIO_ALLDONE.
			 */

			if (aioc) {
				/* Yes... attempt to cancel the I/O.  There are two
				 * possibilities:* (1) the work has already been started and
				 * is no longer queued, or (2) the work has not been started
				 * and is still in the work queue.  Only the second case can
				 * be cancelled.  work_cancel() will return -ENOENT in the
				 * first case.
				 */

				status = work_cancel(LPWORK, &aioc->aioc_work);

				/* Remove the container from the list of pending transfers */

				next = (FAR struct aio_container_s *)aioc->aioc_link.flink;
				aiocbp = aioc_decant(aioc);
				DEBUGASSERT(aiocbp);

				if (status >= 0) {
					aiocbp->aio_result = -ECANCELED;
					if (ret != AIO_NOTCANCELED) {
						ret = AIO_CANCELED;
					}
				} else {
					ret = AIO_NOTCANCELED;
				}
			}
		} while (aioc);
	}

	aio_unlock();
	sched_unlock();
	return ret;
}
Exemplo n.º 4
0
static void aio_write_worker(FAR void *arg)
{
  FAR struct aio_container_s *aioc = (FAR struct aio_container_s *)arg;
  FAR struct aiocb *aiocbp;
  pid_t pid;
#ifdef CONFIG_PRIORITY_INHERITANCE
  uint8_t prio;
#endif
  ssize_t nwritten = 0;
#ifdef AIO_HAVE_FILEP
  int oflags;
#endif

  /* Get the information from the container, decant the AIO control block,
   * and free the container before starting any I/O.  That will minimize
   * the delays by any other threads waiting for a pre-allocated container.
   */

  DEBUGASSERT(aioc && aioc->aioc_aiocbp);
  pid    = aioc->aioc_pid;
#ifdef CONFIG_PRIORITY_INHERITANCE
  prio   = aioc->aioc_prio;
#endif
  aiocbp = aioc_decant(aioc);

#if defined(AIO_HAVE_FILEP) && defined(AIO_HAVE_PSOCK)
  if (aiocbp->aio_fildes < CONFIG_NFILE_DESCRIPTORS)
#endif
#ifdef AIO_HAVE_FILEP
    {
      /* Call fcntl(F_GETFL) to get the file open mode. */

      oflags = file_fcntl(aioc->u.aioc_filep, F_GETFL);
      if (oflags < 0)
        {
          int errcode = get_errno();
          fdbg("ERROR: fcntl failed: %d\n", errcode);
          aiocbp->aio_result = -errcode;
          goto errout;
        }

      /* Perform the write using:
       *
       *   u.aioc_filep - File structure pointer
       *   aio_buf      - Location of buffer
       *   aio_nbytes   - Length of transfer
       *   aio_offset   - File offset
       */

      /* Check if O_APPEND is set in the file open flags */

      if ((oflags & O_APPEND) != 0)
        {
          /* Append to the current file position */

          nwritten = file_write(aioc->u.aioc_filep,
                                (FAR const void *)aiocbp->aio_buf,
                                aiocbp->aio_nbytes);
        }
      else
        {
          nwritten = file_pwrite(aioc->u.aioc_filep,
                                 (FAR const void *)aiocbp->aio_buf,
                                 aiocbp->aio_nbytes,
                                 aiocbp->aio_offset);
        }
    }
#endif
#if defined(AIO_HAVE_FILEP) && defined(AIO_HAVE_PSOCK)
  else
#endif
#ifdef AIO_HAVE_PSOCK
    {
      /* Perform the send using:
       *
       *   u.aioc_psock - Socket structure pointer
       *   aio_buf      - Location of buffer
       *   aio_nbytes   - Length of transfer
       */

      nwritten = psock_send(aioc->u.aioc_psock,
                            (FAR const void *)aiocbp->aio_buf,
                            aiocbp->aio_nbytes, 0);
    }
#endif

  /* Check the result of the write */

  if (nwritten < 0)
    {
      int errcode = get_errno();
      fdbg("ERROR: write/pwrite failed: %d\n", errcode);
      DEBUGASSERT(errcode > 0);
      aiocbp->aio_result = -errcode;
    }
  else
    {
      aiocbp->aio_result = nwritten;
    }

#ifdef AIO_HAVE_FILEP
errout:
#endif

  /* Signal the client */

  (void)aio_signal(pid, aiocbp);

#ifdef CONFIG_PRIORITY_INHERITANCE
  /* Restore the low priority worker thread default priority */

  lpwork_restorepriority(prio);
#endif
}