The following example illustrates the use of timer services for both user and supervisor actors.
(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:
The main thread sets up everything that is required, so that the two newly-created threads will respond to a single periodic timer of one second for a duration of thirty seconds.
The thirty-second period is bounded by a one-shot timer handled by the same pool of two threads.
Before starting, the current system time is printed.
When the thirty second timer has elapsed, the periodic timer is cancelled and the current system time is displayed again.
A small delay occurs before the actor terminates, enabling you to check that the periodic timer has been cancelled correctly.