_KeRTESy: A Real-Time Event-Driven Microkernel_ 
by B. Sain and T. A. Gonsalves


Listing One
/* BEGIN: thermostat.c */
#include "kertesy.h"
#eventfile "eventdefs.c"

    typedef prilevels PriDanger, PriNormal, PriLow;
    void Thread1()
{
    InPort(HEATER_DATA_PORT, currTemp);
}
void Thread2()
{
   OutPort(HEATER_CTRL_PORT, ON);
   OutPort(LED_PORT, ON);
}
void Thread3()
{
   OutPort(HEATER_CTRL_PORT, OFF);
   OutPort(LED_PORT, OFF);
}
void Thread4()
{
   OutPort(HEATER_CTRL_PORT, OFF);
   OutPort(ALARM_PORT, ON);
}
void main()
{
/* The first 3 threads have minimal tasks to perform, hence they can be 
preempted after small durations. The priority is lowest for Thread1 because 
its function is less critical than that of the others. Threads 2 and 3 have 
equal priority. Thread 4 has the highest priority because its function is the 
most safety-critical. */

   CreateThread(Thread1, PriLow, PREEMPTIVE(2), PERIODIC(10));
   CreateThread(Thread2, PriNormal, PREEMPTIVE(3), 
                                          EXPRESSION(currTemp <= MIN_TEMP));
   CreateThread(Thread3, PriNormal, PREEMPTIVE(3), 
                                          EXPRESSION(currTemp >= MAX_TEMP));
   CreateThread(Thread4, PriDanger, PREEMPTIVE(0), 
                                          EXPRESSION(currTemp >= DANGER_TEMP));

    /* After creating all the threads, call the kernel to schedule. */
   Kernel();
  }

/* END: thermostat.c */

Listing Two
typedef union 
{ /* The event type for the thread will Timer, Expression, or Intr. no. */

    u_int timerId;         /* for timer type of event */
    BOOLEAN (*funcPtr)();  /* for expression event */
    u_char intrNo;         /* for interrupt handler */
 } DescUnionType;

typedef struct
{
    u_char priority;       /* priority of the thread */
    long preEmptive;       /* whether preemptive or not */
    u_char descType;       /* type of event which schedules this thread */
    DescUnionType desc;    /* event specification */
    void (*psPtr)();       /* pointer to the thread function */
    int next;              /* pointer to next thread with same priority */
} PSStructType;
PSStructType psTab[MAX_PROCESS]; 
/* Thread Table */

Listing Three 
!!!!! This code stores the value of non-preemptible duration of the thread
!!!!! to be scheduled (readyPid), into the variable preEmptTime. If the thread
!!!!! is non-preemptive, -1 is stored into preEmptTime.
    mr=readyPidR*psStructSzR (ss);
    i1=mr0;
    modify(i1,psTabPtrR);      !!!!! i1 = ^(psTab[readyPid]).
    i6=i1;                     !!!!! save i1 to be used later.
    m3=PS_PREEMPTL_OFF;
    modify(i1,m3);
    ay1=dm(i1,m2);
    i1=i6;
    m3=PS_PREEMPTM_OFF;
    modify(i1,m3);
    ax1=dm(i1,m2);                            
    af=pass ax1;               !!!!! if the thread's preempTive field is 0, 
    if ne jump SchedulerL18_;
    af=pass ay1;
    if ne jump SchedulerL18_;
    ax1=-1;                    !!!!! ... then preEmptTime = -1, ... 
    ay1=-1;
SchedulerL18_:
    dm(preEmptTime_)=ax1;      !!!!! ... else preEmptTime = 
    dm(preEmptTime_+1)=ay1;    !!!!!    the value in the field.
SchedulerL19_:    
SchedulerL20_:
!!!!! Disable timer intr. now -- after "currentPid" has been made to store 
!!!!! the new thread's Pid, if timer intr. occurs, it will assume that a 
!!!!! thread is running, and try to preempt it if it is preemptive. We stop 
!!!!! that attempt by disabling timer intr. here.  
    dis timer;
    i1=i6;              !!!!! i1 = ^(psTab[readyPid]) = ^(psTab[readyPid].pid);
    ax1=dm(i1,m2);
    dm(currentPid_)=ax1;  !!!!! Assign thread's Pid to currentPid;
    mr0=dm(currentTime_+1);
    dm(currentThreadStartTime_+1)=mr0;   !!!!! currentThreadStartTime = 
    ar=dm(currentTime_);                 !!!!!    currentTime.
    dm(currentThreadStartTime_)=ar; 
    ena timer; & hspace{-3in}            !!!!! Enable timer intr. again.
    m3=PS_PSPTR_OFF;
    i1=i2;                               !!!!! i2 contains ^(psTab[readyPid])
   

Listing Four 
modify(i1,m3);            !!!!! i1 = ^(psTab[readyPid].psPtr)
ar=dm(i1,m2);
i6=ar;                    !!!!! i6 contains pointer to the thread be scheduled.
                          !!!!! Now empty the internal stack registers.
#define PSE 0x0001        !!!!! PC stack empty
#define CSE 0x0004        !!!!! Counter stack empty
#define SSE 0x0010        !!!!! Status stack empty
#define LSE 0x0040        !!!!! Loop stack empty
                !!!!! Empty the status stack until SSE is set 
    ay0=SSE; 
LOOP_STA: 
    pop sts; 
    ar=sstat; 
    ar=ar AND ay0; 
    if eq jump LOOP_STA; 
               !!!!! Empty the counter stack until CSE is set  
    ay0=CSE; 
LOOP_CTR: 
    pop cntr; 
    ar=sstat; 
    ar=ar AND ay0; 
    if eq jump LOOP_CTR; 
              !!!!! Empty the loop stack until LSE is set 
    ay0=LSE; 
LOOP_LOP: 
    pop loop; 
    ar=sstat; 
    ar=ar AND ay0; 
    if eq jump LOOP_LOP; 
             !!!!! Empty the pc stack until PSE is set 
    ay0=PSE; 
LOOP_PC: 
    ar=toppcstack; 
    ar=sstat; 
    ar=ar AND ay0; 
    if eq jump LOOP_PC; 
               !!!!! Stacks emptying done, now schedule.
    call (i6); !!!!! (*(psTab[readyPid].psPtr))() :  SCHEDULE;

