void priority_inheritance()

in testing/ostest/prioinherit.c [489:754]


void priority_inheritance(void)
{
#if defined(CONFIG_PRIORITY_INHERITANCE) && !defined(CONFIG_DISABLE_PTHREAD)
  pthread_t lowpri[NLOWPRI_THREADS];
  pthread_t medpri;
  pthread_t highpri[NHIGHPRI_THREADS];
  pthread_addr_t result;
  pthread_attr_t attr;
  struct sched_param sparam;
  int my_pri;
  int status;
  int i;
  pid_t pids[NUMBER_OF_COMPETING_THREADS];
  char args[3][32];
  FAR char *argv[4];
  char name[32];
  int priority;
  int restoration_result;

  printf("priority_inheritance: Started\n");

  g_middlestate = NOTSTARTED;
  for (i = 0; i < NHIGHPRI_THREADS; i++) g_highstate[i] = NOTSTARTED;
  for (i = 0; i < NLOWPRI_THREADS; i++)  g_lowstate[i]  = NOTSTARTED;

  status = sched_getparam(gettid(), &sparam);
  if (status != 0)
    {
      printf("priority_inheritance: ERROR sched_getparam failed\n");
      ASSERT(false);
      sparam.sched_priority = PTHREAD_DEFAULT_PRIORITY;
    }

  my_pri = sparam.sched_priority;

  g_highpri = sched_get_priority_max(SCHED_FIFO);
  g_lowpri = sched_get_priority_min(SCHED_FIFO);
  g_medpri = my_pri - 1;

  sem_init(&g_sem, 0, NLOWPRI_THREADS);
  sem_setprotocol(&g_sem, SEM_PRIO_INHERIT);

  dump_nfreeholders("priority_inheritance:");

  /* Start the low priority threads */

  for (i = 0; i < NLOWPRI_THREADS; i++)
    {
      int threadno = i + 1;
      printf("priority_inheritance: "
             "Starting lowpri_thread-%d (of %d) at %d\n",
             threadno, NLOWPRI_THREADS, g_lowpri);
      status = pthread_attr_init(&attr);
      if (status != 0)
        {
          printf("priority_inheritance: "
                 "ERROR pthread_attr_init failed, status=%d\n",
                 status);
          ASSERT(false);
        }

      sparam.sched_priority = g_lowpri;
      status = pthread_attr_setschedparam(&attr, &sparam);
      if (status != OK)
        {
          printf("priority_inheritance: "
                 "ERROR pthread_attr_setschedparam failed, status=%d\n",
                 status);
          ASSERT(false);
        }
      else
        {
          printf("priority_inheritance: "
                 "Set lowpri_thread-%d priority to %d\n",
                 threadno, sparam.sched_priority);
        }

      status = pthread_create(&lowpri[i], &attr, lowpri_thread,
                              (FAR void *)((uintptr_t)threadno));
      if (status != 0)
        {
          printf("priority_inheritance: "
                 "ERROR pthread_create failed, status=%d\n", status);
          ASSERT(false);
        }
    }

  printf("priority_inheritance: Waiting...\n");
  sleep(2);
  dump_nfreeholders("priority_inheritance:");

  /* Start the medium priority thread */

  printf("priority_inheritance: Starting medpri_thread at %d\n", g_medpri);
  status = pthread_attr_init(&attr);
  if (status != 0)
    {
      printf("priority_inheritance: "
             "ERROR pthread_attr_init failed, status=%d\n", status);
      ASSERT(false);
    }

  sparam.sched_priority = g_medpri;
  status = pthread_attr_setschedparam(&attr, &sparam);
  if (status != OK)
    {
      printf("priority_inheritance: "
             "ERROR pthread_attr_setschedparam failed, status=%d\n",
              status);
      ASSERT(false);
    }
  else
    {
      printf("priority_inheritance: Set medpri_thread priority to %d\n",
             sparam.sched_priority);
    }

  FFLUSH();

  status = pthread_create(&medpri, &attr, medpri_thread, NULL);
  if (status != 0)
    {
      printf("priority_inheritance: "
             "ERROR pthread_create failed, status=%d\n",
             status);
      ASSERT(false);
    }

  printf("priority_inheritance: Waiting...\n");
  sleep(1);
  dump_nfreeholders("priority_inheritance:");

  /* Start the high priority threads */

  for (i = 0; i < NHIGHPRI_THREADS; i++)
    {
      int threadno = i + 1;
      printf("priority_inheritance: "
             "Starting highpri_thread-%d (of %d) at %d\n",
             threadno, NHIGHPRI_THREADS, g_highpri);
      status = pthread_attr_init(&attr);
      if (status != 0)
        {
          printf("priority_inheritance: "
                 "ERROR pthread_attr_init failed, status=%d\n", status);
          ASSERT(false);
        }

      sparam.sched_priority = g_highpri - i;
      status = pthread_attr_setschedparam(&attr, &sparam);
      if (status != OK)
        {
          printf("priority_inheritance: "
                 "ERROR pthread_attr_setschedparam failed, status=%d\n",
                 status);
          ASSERT(false);
        }
      else
        {
          printf("priority_inheritance: "
                 "Set highpri_thread-%d priority to %d\n",
                 threadno, sparam.sched_priority);
        }

      FFLUSH();

      status = pthread_create(&highpri[i], &attr, highpri_thread,
                              (FAR void *)((uintptr_t)threadno));
      if (status != 0)
        {
          printf("priority_inheritance: "
                 "ERRROR pthread_create failed, status=%d\n", status);
          ASSERT(false);
        }
    }

  dump_nfreeholders("priority_inheritance:");
  FFLUSH();

  /* Wait for all thread instances to complete */

  for (i = 0; i < NHIGHPRI_THREADS; i++)
    {
      printf("priority_inheritance: "
             "Waiting for highpri_thread-%d to complete\n", i + 1);
      FFLUSH();
      pthread_join(highpri[i], &result);
      dump_nfreeholders("priority_inheritance:");
    }

  printf("priority_inheritance: Waiting for medpri_thread to complete\n");
  FFLUSH();
  pthread_join(medpri, &result);
  dump_nfreeholders("priority_inheritance:");

  for (i = 0; i < NLOWPRI_THREADS; i++)
    {
      printf("priority_inheritance: "
             "Waiting for lowpri_thread-%d to complete\n", i + 1);
      FFLUSH();
      pthread_join(lowpri[i], &result);
      dump_nfreeholders("priority_inheritance:");
    }

  /* Perform restoration test */

  printf("priority_inheritance: Restoration Test:\n");

  sem_init(&g_sem, 0, 1);
  priority = COMPETING_THREAD_START_PRIORITY;
  argv[0] = args[0];
  argv[1] = args[1];
  argv[2] = args[2];
  argv[3] = NULL;

  for (i = 0; i < NUMBER_OF_COMPETING_THREADS; i++)
    {
      g_priority_tracking[i] = 0;
      snprintf(name, sizeof(name), "Task%1d", i);
      snprintf(args[0], sizeof(args[0]), "%d", i);
      snprintf(args[1], sizeof(args[1]), "%d", i * 10000);
      snprintf(args[2], sizeof(args[2]), "%d", i == 0 ? 100000 : 1000);

      pids[i] = task_create(name, priority, CONFIG_DEFAULT_TASK_STACKSIZE,
                            adversary, argv);
      priority += PRIORIY_SPREED;
    }

  priority = COMPETING_THREAD_START_PRIORITY;
  restoration_result = 0;
  for (i = 0; i < NUMBER_OF_COMPETING_THREADS; i++)
    {
      printf("priority_inheritance: "
             "Waiting for Task-%d to complete\n", i);

      waitpid(pids[i], &status, 0);
      if (priority != g_priority_tracking[i])
        {
          printf("priority_inheritance: "
                 "Task-%d Priority is %d, and was not restored to %d\n",
                  i, g_priority_tracking[i], priority);

          restoration_result |= 1 << i;
        }

      priority += PRIORIY_SPREED;
    }

  if (restoration_result != 0)
    {
      printf("priority_inheritance: ERROR: FAIL Priorities were not "
             "correctly restored.\n");
      ASSERT(false);
    }
  else
    {
      printf("priority_inheritance: PASSED Priority were correctly"
             " restored.\n");
    }

  printf("priority_inheritance: Finished\n");
  sem_destroy(&g_sem);
  dump_nfreeholders("priority_inheritance:");
  FFLUSH();
#endif /* CONFIG_PRIORITY_INHERITANCE && !CONFIG_DISABLE_PTHREAD */
}