ChorusOS 5.0 Application Developer's Guide

Using Timers

The following example illustrates the use of timer services for both user and supervisor actors.


Example 12-4 Using Timers

(file: opt/examples/progov/timers.c)
#include <stdio.h>
#include <stdlib.h>
#include <chorus.h>
#include <etimer.h>

KnThreadPool samplePool;
int          periodic;
int          oneShot;
int          periodicLid;
int          oneShotLid;

#define USER_STACK_SIZE (1024 * sizeof(long))			      
								      
KnSem   sampleSem; /* Semaphore allocated as global variable */

    int
childCreate(KnPc entry)
{
  KnActorPrivilege      actorP;
  KnDefaultStartInfo_f  startInfo;
  char*                 userStack;
  int                   childLid = -1;
  int                   res;

  startInfo.dsType            = K_DEFAULT_START_INFO;
  startInfo.dsSystemStackSize = K_DEFAULT_STACK_SIZE;

  res = actorPrivilege(K_MYACTOR, &actorP, NULL);
  if (res != K_OK) {
    printf("Cannot get the privilege of the actor, error %d\n", res);
    exit(1);
  }

  if (actorP == K_SUPACTOR) {
    startInfo.dsPrivilege = K_SUPTHREAD;
  } else {
    startInfo.dsPrivilege = K_USERTHREAD;
  }

  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;
  } 

  startInfo.dsEntry = entry;

  res = threadCreate(K_MYACTOR, &childLid, K_ACTIVE, 0, &startInfo);
  if (res != K_OK) {
    printf("Cannot create the thread, error %d\n", res);
    exit(1);
  }

  return childLid;
}

    void
timerWait(int myThLi)
{
}

    void
sampleThread()
{
  int      myThLi;
  int      res;
  void*    cookie;
  int      overrun;
  KnITimer periodicTimer;
  KnTimeVal tv;

  myThLi = threadSelf();
  printf("Thread %d started\n", myThLi);

  for(;;) {
      res = timerThreadPoolWait(&samplePool, &cookie, 
            &overrun, K_NOTIMEOUT);
      if (res != K_OK) {					      
          printf("Cannot wait on thread pool, error %d\n", res);      
          exit(1);						      
      }								      
      if (overrun != 0) {
          printf("Thread %d. We were late! overrun set to : %d\n", 
                  myThLi, overrun);
      }
      if (cookie == &periodic) {
         printf("Thread %d. Time is flying away!\n", myThLi);
      } else if (cookie == &oneShot) {
         printf("Thread %d. Isn't it time to go home?\n", myThLi);
         periodicTimer.ITmValue.tmSec   = 0; /* seconds */
         periodicTimer.ITmValue.tmNSec  = 0; /* nanoseconds */
         periodicTimer.ITmReload.tmSec  = 0; /* seconds */
         periodicTimer.ITmReload.tmNSec = 0; /* nanoseconds */
         res = timerSet(K_MYACTOR, periodicLid, 
	       NULL, &periodicTimer, NULL);
         if (res != K_OK) {					      
            printf("Cannot cancel periodic timer, error %d\n", res);  
            exit(1);						      
         }							      
         /* 
          * Periodic timer is cancelled 
          * Get current time,
          * Wait for a short while (3 seconds) and quit
          */
         res = sysTime(&tv);
         if (res != K_OK) {					      
            printf("Cannot get system time, error %d\n", res);	      
            exit(1);						      
         }							      
         printf("Current system time is %d seconds\n", tv.tmSec);
         printf("No more periodic messages should be printed now!\n");
         K_MILLI_TO_TIMEVAL(&tv, 3000);
         (void) threadDelay(&tv);
         /* We are all done ! */
         exit(0);
      } else {
         printf("Spurious timer!\n");
      }
  } /* for() */
}

int main(int argc, char** argv, char** envp) 
{
   int       res;
   KnTimeVal tv;
   int       thLi1;
   int       thLi2;
   KnITimer  periodicTimer;
   KnITimer  oneShotTimer;
	
   res = timerThreadPoolInit(&samplePool);
   if (res != K_OK) {						      
      printf("Cannot initialize thread pool, error %d\n", res);	      
      exit(1);							      
   }								      

   res = timerCreate(K_MYACTOR, K_CLOCK_REALTIME, &samplePool,
			   &periodic, &periodicLid);
   if (res != K_OK) {						      
      printf("Cannot create periodic timer, error %d\n", res);	      
      exit(1);							      
   }								      

   res = timerCreate(K_MYACTOR, K_CLOCK_REALTIME, &samplePool,
			   &oneShot, &oneShotLid);
   if (res != K_OK) {						      
      printf("Cannot create one shot timer, error %d\n", res);	      
      exit(1);							      
   }								      

   thLi1 = childCreate((KnPc)sampleThread);
   thLi2 = childCreate((KnPc)sampleThread);
      
   res = sysTime(&tv);
   if (res != K_OK) {						      
      printf("Cannot get system time, error %d\n", res);	      
      exit(1);							      
   }								      
   printf("Current system time is %d seconds\n", tv.tmSec);

   periodicTimer.ITmValue.tmSec   = 1; /* seconds */
   periodicTimer.ITmValue.tmNSec  = 0; /* nanoseconds */
   periodicTimer.ITmReload.tmSec  = 1; /* seconds */
   periodicTimer.ITmReload.tmNSec = 0; /* nanoseconds */
   res = timerSet(K_MYACTOR, periodicLid, NULL, &periodicTimer, NULL);
   if (res != K_OK) {						      
      printf("Cannot arm periodic timer, error %d\n", res);	      
      exit(1);							      
   }								      
   
   oneShotTimer.ITmValue.tmSec   = tv.tmSec + 30; /* seconds */
   oneShotTimer.ITmValue.tmNSec  = 0; /* nanoseconds */
   oneShotTimer.ITmReload.tmSec  = 0; /* seconds */
   oneShotTimer.ITmReload.tmNSec = 0; /* nanoseconds */

   res = timerSet(K_MYACTOR, oneShotLid, K_TIMER_ABSOLUTE, 
	          &oneShotTimer, NULL);
   if (res != K_OK) {						      
      printf("Cannot arm one shot timer, error %d\n", res);	      
      exit(1);							      
   }								      

   res = threadDelete(K_MYACTOR, K_MYSELF);
   if (res != K_OK) {						      
      printf("Cannot kill myself, error %d\n", res);		      
      exit(1);							      
   }								      

   return 0;
}

The previous example includes the following step: