void aio_test()

in testing/ostest/aio.c [282:664]


void aio_test(void)
{
  struct sigevent sig;
  sigset_t oset;
  sigset_t set;
  int completed;
  int total;
  int ret;
  int i;

  /* Block all signals except for SIGUSR1 and SIGALRM (for sleep) */

  sigfillset(&set);
  sigdelset(&set, SIGUSR1);
  sigdelset(&set, SIGALRM);
  sigprocmask(SIG_SETMASK, &set, &oset);

  /* Case 1: Poll for transfer complete */

  printf("AIO test case 1: Poll for transfer complete\n");
  g_fildes = open(AIO_FILEPATH, O_RDWR | O_CREAT | O_TRUNC);
  if (g_fildes < 0)
    {
      printf("aio_test: ERROR: Failed to open %s: %d\n",
             AIO_FILEPATH, errno);
      ASSERT(false);
      goto errout_with_procmask;
    }

  init_aiocb(false);
  ret = lio_listio(LIO_NOWAIT, g_aiocb, AIO_NCTRLBLKS, NULL);
  if (ret < 0)
    {
      printf("aio_test: ERROR: lio_listio failed: %d\n", errno);
      ASSERT(false);
      goto errout_with_fildes;
    }

  do
    {
      usleep(500 * 1000);
      ret = check_done();
    }
  while (ret < 0);

  close(g_fildes);
  g_fildes = -1;

  /* Case 2: Wait in lio_listio */

  /* Try to assure that this test does not overlap any activity from the
   * task end of the last test case -- especially the dangling SIGPOLL.
   */

  usleep(500 * 1000);

  printf("AIO test case 2: Use LIO_WAIT for transfer complete\n");
  g_fildes = open(AIO_FILEPATH, O_RDWR | O_CREAT | O_TRUNC);
  if (g_fildes < 0)
    {
      printf("aio_test: ERROR: Failed to open %s: %d\n",
             AIO_FILEPATH, errno);
      ASSERT(false);
      goto errout_with_procmask;
    }

  init_aiocb(false);
  ret = lio_listio(LIO_WAIT, g_aiocb, AIO_NCTRLBLKS, NULL);
  if (ret < 0)
    {
      printf("aio_test: ERROR: lio_listio failed: %d\n", errno);
      ASSERT(false);
      goto errout_with_fildes;
    }

  ret = check_done();
  if (ret < 0)
    {
      printf("aio_test: ERROR: Not done\n");
      ASSERT(false);
      goto errout_with_fildes;
    }

  close(g_fildes);
  g_fildes = -1;

  /* Case 3: Use aio_suspend() until complete */

  /* Try to assure that this test does not overlap any activity from the
   * task end of the last test case -- especially the dangling SIGPOLL.
   */

  usleep(500 * 1000);

  printf("AIO test case 3: Use aio_suspend for transfer complete\n");
  g_fildes = open(AIO_FILEPATH, O_RDWR | O_CREAT | O_TRUNC);
  if (g_fildes < 0)
    {
      printf("aio_test: ERROR: Failed to open %s: %d\n",
              AIO_FILEPATH, errno);
      ASSERT(false);
      goto errout_with_procmask;
    }

  init_aiocb(false);
  ret = lio_listio(LIO_NOWAIT, g_aiocb, AIO_NCTRLBLKS, NULL);
  if (ret < 0)
    {
      printf("aio_test: ERROR: lio_listio failed: %d\n", errno);
      ASSERT(false);
      goto errout_with_fildes;
    }

  total = 1; /* One entry was initially NULL */
  for (i = 1; i <= AIO_NCTRLBLKS; i++)
    {
      printf("  Calling aio_suspend #%d\n", i);
      ret = aio_suspend((FAR const struct aiocb *const *)g_aiocb,
                         AIO_NCTRLBLKS, NULL);
      if (ret < 0)
        {
          printf("aio_test: ERROR: aio_suspend failed: %d\n", errno);
          ASSERT(false);
          goto errout_with_fildes;
        }

      completed = remove_done();
      if (completed < 1)
        {
          printf("aio_test: ERROR: Signalled, but no I/O completed\n");
          ASSERT(false);
          goto errout_with_fildes;
        }

      total += completed;
      printf("  Completed=%d\n", total);

      if (total >= AIO_NCTRLBLKS)
        {
          break;
        }
    }

  if (total != AIO_NCTRLBLKS)
    {
      printf("aio_test: ERROR: Total is %d, should be %d\n",
              total, AIO_NCTRLBLKS);
      ASSERT(false);
      goto errout_with_fildes;
    }

  close(g_fildes);
  g_fildes = -1;

  /* Case 4: Use individual signals */

  /* Try to assure that this test does not overlap any activity from the
   * task end of the last test case -- especially the dangling SIGPOLL.
   */

  usleep(500 * 1000);

  printf("AIO test case 4: Use individual signals for transfer complete\n");
  g_fildes = open(AIO_FILEPATH, O_RDWR | O_CREAT | O_TRUNC);
  if (g_fildes < 0)
    {
      printf("aio_test: ERROR: Failed to open %s: %d\n",
              AIO_FILEPATH, errno);
      ASSERT(false);
      goto errout_with_procmask;
    }

  init_aiocb(true);

  ret = lio_listio(LIO_NOWAIT, g_aiocb, AIO_NCTRLBLKS, NULL);
  if (ret < 0)
    {
      printf("aio_test: ERROR: lio_listio failed: %d\n", errno);
      ASSERT(false);
      goto errout_with_fildes;
    }

  sigemptyset(&set);
  sigaddset(&set, SIGUSR1);

  do
    {
      ret = check_done();
      if (ret < 0)
        {
          int status = sigwaitinfo(&set, NULL);
          if (status < 0)
            {
              int errcode = errno;
              if (errcode == EINTR)
                {
                  printf("  Interrupted by a signal)\n");
                }
              else
                {
                  printf("aio_test: ERROR: sigwaitinfo failed: %d\n",
                          errcode);
                  ASSERT(false);
                  goto errout_with_fildes;
                }
            }
          else
            {
              printf("  Received signal %d\n", status);
            }
        }
    }
  while (ret < 0);

  close(g_fildes);
  g_fildes = -1;

  /* Case 5: Use list complete signal */

  /* Try to assure that this test does not overlap any activity from the
   * task end of the last test case -- especially the dangling SIGPOLL.
   */

  usleep(500 * 1000);

  printf("AIO test case 5:"
         " Use list complete signal for transfer complete\n");
  g_fildes = open(AIO_FILEPATH, O_RDWR | O_CREAT | O_TRUNC);
  if (g_fildes < 0)
    {
      printf("aio_test: ERROR: Failed to open %s: %d\n",
              AIO_FILEPATH, errno);
      ASSERT(false);
      goto errout_with_procmask;
    }

  init_aiocb(false);

  sig.sigev_notify = SIGEV_SIGNAL;
  sig.sigev_signo = SIGUSR1;
  sig.sigev_value.sival_ptr = NULL;

  ret = lio_listio(LIO_NOWAIT, g_aiocb, AIO_NCTRLBLKS, &sig);
  if (ret < 0)
    {
      printf("aio_test: ERROR: lio_listio failed: %d\n", errno);
      ASSERT(false);
      goto errout_with_fildes;
    }

  sigemptyset(&set);
  sigaddset(&set, SIGUSR1);

  do
    {
      ret = check_done();
      if (ret < 0)
        {
          int status = sigwaitinfo(&set, NULL);
          if (status < 0)
            {
              int errcode = errno;
              if (errcode == EINTR)
                {
                  printf("aio_test: Interrupted by a signal\n");
                }
              else
                {
                  printf("aio_test: ERROR: sigwaitinfo failed: %d\n",
                          errcode);
                  ASSERT(false);
                  goto errout_with_fildes;
                }
            }
        }
    }
  while (ret < 0);

  close(g_fildes);
  g_fildes = -1;

  /* Case 6: Cancel I/O by AIO control block */

  /* Try to assure that this test does not overlap any activity from the
   * task end of the last test case -- especially the dangling SIGPOLL.
   */

  usleep(500 * 1000);

  printf("AIO test case 6: Cancel I/O by AIO control block\n");
  g_fildes = open(AIO_FILEPATH, O_RDWR | O_CREAT | O_TRUNC);
  if (g_fildes < 0)
    {
      printf("aio_test: ERROR: Failed to open %s: %d\n",
              AIO_FILEPATH, errno);
      ASSERT(false);
      goto errout_with_procmask;
    }

  init_aiocb(false);
  ret = lio_listio(LIO_NOWAIT, g_aiocb, AIO_NCTRLBLKS, NULL);
  if (ret < 0)
    {
      printf("aio_test: ERROR: lio_listio failed: %d\n", errno);
      ASSERT(false);
      goto errout_with_fildes;
    }

  ret = aio_cancel(g_fildes, g_aiocb[2]);
  if (ret < 0)
    {
      printf("aio_test: ERROR: aio_cancel failed: %d\n", errno);
      ASSERT(false);
      goto errout_with_fildes;
    }

  printf("  aio_cancel return %d\n", ret);

  do
    {
      usleep(500 * 1000);
      ret = check_done();
    }
  while (ret < 0);

  close(g_fildes);
  g_fildes = -1;

  /* Case 7: Cancel I/O by file descriptor */

  /* Try to assure that this test does not overlap any activity from the
   * task end of the last test case -- especially the dangling SIGPOLL.
   */

  usleep(500 * 1000);

  printf("AIO test case 7:Cancel I/O by file descriptor\n");
  g_fildes = open(AIO_FILEPATH, O_RDWR | O_CREAT | O_TRUNC);
  if (g_fildes < 0)
    {
      printf("aio_test: ERROR: Failed to open %s: %d\n",
              AIO_FILEPATH, errno);
      ASSERT(false);
      goto errout_with_procmask;
    }

  init_aiocb(false);
  ret = lio_listio(LIO_NOWAIT, g_aiocb, AIO_NCTRLBLKS, NULL);
  if (ret < 0)
    {
      printf("aio_test: ERROR: lio_listio failed: %d\n", errno);
      ASSERT(false);
      goto errout_with_fildes;
    }

  ret = aio_cancel(g_fildes, NULL);
  if (ret < 0)
    {
      printf("aio_test: ERROR: aio_cancel failed: %d\n", errno);
      ASSERT(false);
      goto errout_with_fildes;
    }

  printf("  aio_cancel return %d\n", ret);

  do
    {
      usleep(500 * 1000);
      ret = check_done();
    }
  while (ret < 0);

  sigprocmask(SIG_SETMASK, &oset, NULL);
  printf("aio_test: Test completed successfully\n");
  return;

errout_with_fildes:
  close(g_fildes);
  g_fildes = -1;
errout_with_procmask:
  sigprocmask(SIG_SETMASK, &oset, NULL);
  printf("aio_test: ERROR: Test aborted\n");
}