http://www.linuxforums.org/forum/linux-programming-scripting/114957-linux-thread-scheduling-question.html

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <sched.h>
#include <time.h>
#include <unistd.h>

/*--------------------------------------------------------------------------*/

#define DESIRED_WORKLOAD_SECONDS  2
#define TIME_ARRAY_ELEMENTS      10

#define  DESIRED_MAJOR_PRIORITY  93
#define  DESIRED_MINOR_PRIORITY  91

int       requested_major_priority;
int       requested_minor_priority;
int       observed_max_priority;
int       observed_min_priority;

long long iterations_before_checking_time;

time_t    major_work_array[TIME_ARRAY_ELEMENTS];
time_t    minor_work_array[TIME_ARRAY_ELEMENTS];

/*--------------------------------------------------------------------------*/

void calculate_workload(void);

void check_error(char *activity,
                 int   status
                );

void do_work(time_t *time_array);

void *major_code(void *something);

void *minor_code(void *something);

/*--------------------------------------------------------------------------*/

void calculate_workload(void)
{
  volatile long long counter;

           long long limit;

           time_t    start;

  /*
   * We want something that will last between DESIRED_WORKLOAD_SECONDS and
   * twice that.
   */

  printf("calculating workload\n"
         "could take up to %d seconds\n"
         "trying limit =",
         4*DESIRED_WORKLOAD_SECONDS
        );

  fflush(stdout);

  for(limit=1;
      ;
      limit<<=1
     )
  {
    printf(" %lld",
           limit
          );

    fflush(stdout);

    start=time(NULL);

    for(counter=0;
        counter<limit;
        counter++
       )
    {
      /* Empty block. */
    }

    if(time(NULL)-start>=DESIRED_WORKLOAD_SECONDS)
    {
      break;   /* <--------- */
    }
  }

  iterations_before_checking_time=limit;

  printf("\ndone calculating workload\n");

} /* calculate_workload() */

/*--------------------------------------------------------------------------*/

void check_error(char *activity,
                 int   status
                )
{
  if(status)
  {
    fprintf(stderr,
            "error %d %s\n",
            status,
            activity
           );

    exit(1);
  }

} /* check_error() */

/*--------------------------------------------------------------------------*/

void do_work(time_t *time_array)
{
           int       slice_number;

  volatile long long counter;

  for(slice_number=0;
      slice_number<TIME_ARRAY_ELEMENTS;
      slice_number++
     )
  {
    for(counter=0;
        counter<iterations_before_checking_time;
        counter++
       )
    {
      /* Empty block. */
    }

    time_array[slice_number]=time(NULL);
  }

} /* do_work() */

/*--------------------------------------------------------------------------*/

void *major_code(void *something)
{
  pthread_t          minor_thread_id;

  pthread_attr_t     thread_attributes;

  struct sched_param thread_parameters;

  check_error("pthread_attr_init()",
              pthread_attr_init(&thread_attributes)
             );

  check_error("setting SCHED_RR for minor thread",
              pthread_attr_setschedpolicy(&thread_attributes,
                                          SCHED_RR
                                         )
             );

  thread_parameters.sched_priority=requested_minor_priority;

  check_error("setting scheduling parameters for minor thread",
              pthread_attr_setschedparam(&thread_attributes,
                                         &thread_parameters
                                        )
             );

  check_error("setting explicit (not inherited) scheduling for minor thread",
              pthread_attr_setinheritsched(&thread_attributes,
                                           PTHREAD_EXPLICIT_SCHED
                                          )
             );

  check_error("creating minor thread (maybe because you\'re not root?)",
              pthread_create(&minor_thread_id,
                             &thread_attributes,
                             minor_code,
                             NULL
                            )
             );

  do_work(major_work_array);

  check_error("joining minor thread",
              pthread_join(minor_thread_id,
                           NULL
                          )
             );

  return NULL;

} /* major_code() */

/*--------------------------------------------------------------------------*/

void *minor_code(void *something)
{
  do_work(minor_work_array);

  return NULL;

} /* minor_code() */

/*--------------------------------------------------------------------------*/

int main(void)
{
  int                 jndex;

  pthread_t           major_thread_id;

  pthread_attr_t      thread_attributes;

  struct sched_param  thread_parameters;

  struct tm          *the_local_time;

#if defined (_POSIX_THREAD_PRIORITY_SCHEDULING) && !defined (sun)
#else
  fprintf(stderr,
          "priority scheduling not supported\n"
         );

  exit(1);
#endif

  calculate_workload();

  observed_min_priority=sched_get_priority_min(SCHED_RR);
  observed_max_priority=sched_get_priority_max(SCHED_RR);

  if((observed_min_priority>=observed_max_priority) &&
     (DESIRED_MAJOR_PRIORITY!=DESIRED_MINOR_PRIORITY)
    )
  {
    fprintf(stderr,
            "observed minimum priority %d >= observed maximum priority %d\n",
            observed_min_priority,
            observed_max_priority
           );

    exit(1);
  }

  requested_major_priority=DESIRED_MAJOR_PRIORITY;
  requested_minor_priority=DESIRED_MINOR_PRIORITY;

  if(requested_major_priority==requested_minor_priority)
  {
    if(requested_major_priority>observed_max_priority)
    {
      requested_major_priority=observed_max_priority;
      requested_minor_priority=observed_max_priority;
    }

    if(requested_major_priority<observed_min_priority)
    {
      requested_major_priority=observed_min_priority;
      requested_minor_priority=observed_min_priority;
    }
  }
  else
  if(requested_major_priority<requested_minor_priority)
  {
    if(requested_minor_priority>observed_max_priority)
    {
      requested_minor_priority=observed_max_priority;

      if(requested_major_priority>=requested_minor_priority)
      {
        requested_major_priority=requested_minor_priority-1;
      }
    }

    if(requested_major_priority<observed_min_priority)
    {
      requested_major_priority=observed_min_priority;

      if(requested_minor_priority<=requested_major_priority)
      {
        requested_minor_priority=requested_major_priority+1;
      }
    }
  }
  else   /* requested_major_priority>requested_minor_priority */
  {
    if(requested_major_priority>observed_max_priority)
    {
      requested_major_priority=observed_max_priority;

      if(requested_minor_priority>=requested_major_priority)
      {
        requested_minor_priority=requested_major_priority-1;
      }
    }

    if(requested_minor_priority<observed_min_priority)
    {
      requested_minor_priority=observed_min_priority;

      if(requested_major_priority<=requested_minor_priority)
      {
        requested_major_priority=requested_minor_priority+1;
      }
    }
  }

  if((requested_major_priority!=DESIRED_MAJOR_PRIORITY)
     ||
     (requested_minor_priority!=DESIRED_MINOR_PRIORITY)
    )
  {
    printf("The desired major and minor priorities were %d and %d.\n"
           "We adjusted them to %d and %d,\n"
           "because the minimum priority is %d\n"
           "and the maximum priority is %d\n",
           DESIRED_MAJOR_PRIORITY,
           DESIRED_MINOR_PRIORITY,
           requested_major_priority,
           requested_minor_priority,
           observed_min_priority,
           observed_max_priority
          );
  }

  check_error("pthread_attr_init()",
              pthread_attr_init(&thread_attributes)
             );

  check_error("setting SCHED_RR for major thread",
              pthread_attr_setschedpolicy(&thread_attributes,
                                          SCHED_RR
                                         )
             );

  thread_parameters.sched_priority=requested_major_priority;

  check_error("setting scheduling parameters for major thread",
              pthread_attr_setschedparam(&thread_attributes,
                                         &thread_parameters
                                        )
             );

  check_error("setting explicit (not inherited) scheduling for major thread",
              pthread_attr_setinheritsched(&thread_attributes,
                                           PTHREAD_EXPLICIT_SCHED
                                          )
             );

  printf("about to begin the work, which could take up to %d seconds\n",
         4*DESIRED_WORKLOAD_SECONDS*TIME_ARRAY_ELEMENTS
        );

  check_error("creating major thread (maybe because you\'re not root?)",
              pthread_create(&major_thread_id,
                             &thread_attributes,
                             major_code,
                             NULL
                            )
             );

  check_error("joining major thread",
              pthread_join(major_thread_id,
                           NULL
                          )
             );

  printf("major thread:\n");

  for(jndex=0;
      jndex<TIME_ARRAY_ELEMENTS;
      jndex++
     )
  {
    the_local_time=localtime(major_work_array+jndex);

    printf("%02d:%02d:%02d\n",
           the_local_time->tm_hour,
           the_local_time->tm_min,
           the_local_time->tm_sec
          );
  }

  printf("minor thread:\n");

  for(jndex=0;
      jndex<TIME_ARRAY_ELEMENTS;
      jndex++
     )
  {
    the_local_time=localtime(minor_work_array+jndex);

    printf("%02d:%02d:%02d\n",
           the_local_time->tm_hour,
           the_local_time->tm_min,
           the_local_time->tm_sec
          );
  }

  return 0;

} /* main() */

Reply via email to