ChorusOS 5.0 Application Developer's Guide

Setting Scheduling Attributes

To set the scheduling attributes of threads at thread creation time, use the void* schedParams parameter of threadCreate(2K). To obtain and modify the scheduling attributes of a thread dynamically, use the following call:

#include <chorus.h>
#include <sched/chFifo.h>
#include <sched/chRr.h>
#include <sched/chRt.h>

int threadScheduler(KnCap*       actorCap,
                    KnThreadLid  thLi,
                    void*        oldParam,
                    void*        newParam);

The previous service enables you to get or set the scheduling parameters for any thread of any actor, provided both the actor capability and the thread identifier are known. The threadScheduler(2K) call returns the current scheduling attributes of the target thread at the location defined by oldParam (if non-NULL). It also sets the attributes of the target thread according to the description provided at the location defined by newParam (if non-NULL).

Because the size, layout, and semantics of scheduling parameters can vary (depending on the scheduler configured in the system, or on the class of the ROUND_ROBIN framework) the parameters are left empty in the generic interface definition. However, all scheduling parameter descriptions are similar, at least for the initial fields:

struct KnFifoThParms {     
		KnSchedClass     fifoClass;      /* Always set to K_SCHED_FIFO */
		KnFifoPriority   fifoPriority; 
} KnFifoThParms;
struct KnRrThParms {
		KnSchedClass     rrClass;        /* Always set to K_SCHED_RR */
		KnRrPriority     rrPriority; 
} KnRrThParms;

In the previous example, the first field defines the scheduling policy applied (or to be applied) to the thread. The second field defines the priority of the thread within the scheduling policy.

Code Example 9-1 demonstrates how the childCreate() routine receives the scheduling attributes of the thread to be created. The main thread invokes the modified routine so that the created thread will start as soon as it is created, rather than waiting for the main thread to give up the processor. Therefore, the created thread must be attributed a higher priority than the main thread. For more information, refer to the threadScheduler(2K) and threadCreate(2K) man pages.


Example 9-1 Changing Scheduling Attributes

This example applies only in the case of the FIFO and RR scheduling classes.

(file: progov/thSched.c)
#include <stdio.h>
#include <stdlib.h>
#include <chorus.h>
#define USER_STACK_SIZE (1024 * sizeof(long))
KnSem   sampleSem;
    int
childSchedCreate(KnPc entry, void* schedParams)
{
  KnActorPrivilege      actorP;
  KnDefaultStartInfo_f  startInfo;
  char*                 userStack;
  int                   childLid = -1;
  int                   res;
      /* Set defaults startInfo fields */
  startInfo.dsType            = K_DEFAULT_START_INFO;
  startInfo.dsSystemStackSize = K_DEFAULT_STACK_SIZE;
      /* Get actor's privilege */
  res = actorPrivilege(K_MYACTOR, &actorP, NULL);
  if (res != K_OK) {            
    printf("Cannot get the privilege of the actor, error %d\n", res); 
    exit(1);             
  }              
      /* Set thread privilege */
  if (actorP == K_SUPACTOR) {
    startInfo.dsPrivilege = K_SUPTHREAD;
  } else {
    startInfo.dsPrivilege = K_USERTHREAD;
  }
      /* Allocate a stack for user threads */
  if (actorP != K_SUPACTOR) {
    userStack = malloc(USER_STACK_SIZE);
    if (userStack == NULL) {           
      printf("Cannot allocate user stack\n");         
      exit(1);             
    }              
    startInfo.dsUserStackPointer = userStack + USER_STACK_SIZE;
  } 
      /* Set entry point for the new thread */
  startInfo.dsEntry = entry;
      /* Create the thread in the active state */
  res = threadCreate(K_MYACTOR, &childLid, K_ACTIVE, 
        schedParams, &startInfo);
  if (res != K_OK) {            
    printf("Cannot create the thread, error %d\n", res);
    exit(1);
  }              
  return childLid;
}
    void
sampleThread()
{
  int myThreadLi;
  int res;
  myThreadLi = threadSelf();
  printf("I am the new thread. My thread identifier is: %d\n", myThreadLi);
  res  = semV(&sampleSem);
  if (res != K_OK){            
    printf("Cannot perform the semV operation, error %d\n", res);
    exit(1);             
  }              
  (void) threadDelete(K_MYACTOR, K_MYSELF);
}
int main(int argc, char** argv, char**envp)
{
  int                  myThreadLi;
  int                  newThreadLi;
  int                  res;
  KnThreadDefaultSched schedParams;
  res = semInit(&sampleSem, 0);
  if (res != K_OK) {            
    printf("Cannot initialize the semaphore, error %d\n", res);       
    exit(1);             
  }              
      /* acquire my own scheduling attributes  */
  res = threadScheduler(K_MYACTOR, K_MYSELF, &schedParams, NULL);
  if (res != K_OK) {
			printf("threadScheduler failed, res=%d\n", res);
			exit(1);
  }
      /* Increase priority of thread to be created */
  schedParams.tdPriority -= 1;
  newThreadLi = childSchedCreate((KnPc)sampleThread, &schedParams);
  myThreadLi = threadSelf();
  printf("Parent thread identifier = %d, Child thread identifier = %d\n",
      myThreadLi, newThreadLi);
  res = semP(&sampleSem, K_NOTIMEOUT);
  if (res != K_OK) {            
    printf("Cannot perform the semP operation, error %d\n", res);     
    exit(1);             
  }              
  return 0;
}