void signest_test()

in testing/ostest/signest.c [239:561]


void signest_test(void)
{
  struct sched_param param;
  pid_t waiterpid;
  pid_t interferepid;
  int total_signals;
  int total_handled;
  int total_nested;
  int even_signals;
  int odd_signals;
  int prio;
  int ret;
  int i;
  int j;

  sem_init(&g_waiter_sem, 0, 0);
  sem_init(&g_interferer_sem, 0, 0);
  sem_init(&g_sem_thread_started, 0, 0);
  sem_init(&g_sem_signal_finish, 0, 0);
  g_waiter_running = false;
  g_interferer_running = false;
  g_done = false;
  g_nestlevel = 0;

  even_signals = 0;
  odd_signals = 0;

  g_even_handled = 0;
  g_odd_handled = 0;
  g_even_nested = 0;
  g_odd_nested = 0;

  g_nest_level = 0;

  ret = sched_getparam(0, &param);
  if (ret < 0)
    {
      printf("signest_test: ERROR sched_getparam() failed\n");
      ASSERT(false);
      param.sched_priority = PTHREAD_DEFAULT_PRIORITY;
    }

  /* Start waiter thread  */

  prio = param.sched_priority + 1;
  printf("signest_test: Starting signal waiter task at priority %d\n", prio);
  waiterpid = task_create("waiter", prio, STACKSIZE,
                          waiter_main, NULL);
  if (waiterpid == ERROR)
    {
      printf("signest_test: ERROR failed to start waiter_main\n");
      ASSERT(false);
      return;
    }

  printf("signest_test: Started waiter_main pid=%d\n", waiterpid);

  /* Start interfering thread  */

  prio++;
  printf("signest_test: Starting interfering task at priority %d\n", prio);
  interferepid = task_create("interfere", prio, STACKSIZE,
                             interfere_main, NULL);
  if (interferepid == ERROR)
    {
      printf("signest_test: ERROR failed to start interfere_main\n");
      ASSERT(false);
      goto errout_with_waiter;
    }

  printf("signest_test: Started interfere_main pid=%d\n", interferepid);

  /* Wait a bit */

  FFLUSH();
  sem_wait(&g_sem_thread_started);

  /* Then signal the waiter thread with back-to-back signals, one masked
   * and the other unmasked.
   */

  for (i = 0; i < 10; i++)
    {
      for (j = 1; j < MAX_SIGNO; j += 2)
        {
          if (signest_catchable(j))
            {
              kill(waiterpid, j);
              odd_signals++;
            }

          if (signest_catchable(j + 1))
            {
              kill(waiterpid, j + 1);
              even_signals++;
            }

          wait_finish(waiterpid, j);

          /* Even then odd */

          if (signest_catchable(j + 1))
            {
              kill(waiterpid, j + 1);
              even_signals++;
            }

          if (signest_catchable(j))
            {
              kill(waiterpid, j);
              odd_signals++;
            }

          wait_finish(waiterpid, j);
        }
    }

  /* Check the test results so far */

  total_signals = odd_signals + even_signals;
  total_handled = g_odd_handled + g_even_handled;
  total_nested  = g_odd_nested + g_even_nested;

  printf("signest_test: Simple case:\n");
  printf("  Total signalled %-3d  Odd=%-3d Even=%-3d\n",
         total_signals, odd_signals, even_signals);
  printf("  Total handled   %-3d  Odd=%-3d Even=%-3d\n",
         total_handled, g_odd_handled, g_even_handled);
  printf("  Total nested    %-3d  Odd=%-3d Even=%-3d\n",
         total_nested, g_odd_nested, g_even_nested);

  /* Then signal the waiter thread with two signals pending.  The
   * sched_lock() assures that the first signal was not processed
   * before the second was delivered.
   */

  for (i = 0; i < 10; i++)
    {
      for (j = 1; j < MAX_SIGNO; j += 2)
        {
          /* Odd then even */

          sched_lock();

          if (signest_catchable(j))
            {
              kill(waiterpid, j);
              odd_signals++;
            }

          if (signest_catchable(j + 1))
            {
              kill(waiterpid, j + 1);
              even_signals++;
            }

          sched_unlock();

          wait_finish(waiterpid, j);

          /* Even then odd */

          sched_lock();

          if (signest_catchable(j + 1))
            {
              kill(waiterpid, j + 1);
              even_signals++;
            }

          if (signest_catchable(j))
            {
              kill(waiterpid, j);
              odd_signals++;
            }

          sched_unlock();

          wait_finish(waiterpid, j);
        }
    }

  /* Check the test results so far */

  total_signals = odd_signals + even_signals;
  total_handled = g_odd_handled + g_even_handled;
  total_nested  = g_odd_nested + g_even_nested;

  printf("signest_test: With task locking\n");
  printf("  Total signalled %-3d  Odd=%-3d Even=%-3d\n",
         total_signals, odd_signals, even_signals);
  printf("  Total handled   %-3d  Odd=%-3d Even=%-3d\n",
         total_handled, g_odd_handled, g_even_handled);
  printf("  Total nested    %-3d  Odd=%-3d Even=%-3d\n",
         total_nested, g_odd_nested, g_even_nested);

  /* Then do it all over again with the interfering thread. */

  for (i = 0; i < 10; i++)
    {
      for (j = 1; j < MAX_SIGNO; j += 2)
        {
          /* Odd then even */

          sched_lock();

          if (signest_catchable(j))
            {
              kill(waiterpid, j);
              odd_signals++;
            }

          sem_post(&g_interferer_sem);

          if (signest_catchable(j + 1))
            {
              kill(waiterpid, j + 1);
              even_signals++;
            }

          sched_unlock();

          wait_finish(waiterpid, j);

          /* Even then odd */

          sched_lock();
          if (signest_catchable(j + 1))
            {
              kill(waiterpid, j + 1);
              even_signals++;
            }

          sem_post(&g_interferer_sem);

          if (signest_catchable(j))
            {
              kill(waiterpid, j);
              odd_signals++;
            }

          sched_unlock();

          wait_finish(waiterpid, j);
        }
    }

  /* Stop the threads */

errout_with_waiter:
  g_done = true;
  sem_post(&g_waiter_sem);
  sem_post(&g_interferer_sem);
  do
    {
      usleep(500 * 1000L);
    }
  while (g_waiter_running || g_interferer_running);

  /* Check the final test results */

  total_signals = odd_signals + even_signals;
  total_handled = g_odd_handled + g_even_handled;
  total_nested  = g_odd_nested + g_even_nested;

  printf("signest_test: With intefering thread\n");
  printf("  Total signalled %-3d  Odd=%-3d Even=%-3d\n",
         total_signals, odd_signals, even_signals);
  printf("  Total handled   %-3d  Odd=%-3d Even=%-3d\n",
         total_handled, g_odd_handled, g_even_handled);
  printf("  Total nested    %-3d  Odd=%-3d Even=%-3d\n",
         total_nested, g_odd_nested, g_even_nested);

  /* Check for error */

  if (g_waiter_running)
    {
      printf("signest_test: ERROR waiter is still running\n");
      ASSERT(false);
    }

  if (g_interferer_running)
    {
      printf("signest_test: ERROR interferer is still running\n");
      ASSERT(false);
    }

  if (total_signals != total_handled)
    {
      printf("signest_test: ERROR only %d of %d signals were handled\n",
             total_handled, total_signals);
      ASSERT(false);
    }

  if (odd_signals != g_odd_handled)
    {
      printf("signest_test: ERROR only %d of %d ODD signals were handled\n",
             g_odd_handled, odd_signals);
      ASSERT(false);
    }

  if (even_signals != g_even_handled)
    {
      printf("signest_test: ERROR only %d of %d EVEN signals were handled\n",
             g_even_handled, even_signals);
      ASSERT(false);
    }

  if (g_odd_nested > 0)
    {
      printf("signest_test: ERROR %d ODD signals were nested\n",
             g_odd_nested);
      ASSERT(false);
    }

  sem_destroy(&g_waiter_sem);
  sem_destroy(&g_interferer_sem);
  sem_destroy(&g_sem_thread_started);
  sem_destroy(&g_sem_signal_finish);

  printf("signest_test: done\n");
  FFLUSH();
}