 |
|  |
 |
| Implementation of Periodic Threads |
 |
 |
 |
 |
 |
 |
 |
| Periodic Threads |
To implement periodic threads you must use the following classes: PeriodicThread and PianoRoll.
The aJile's Mutiple JVM Manager (MJM) has two piano roll timer registers. One register to each of the JVM which can be executed on the aJile. The piano roll timer register is used to provide deterministic periodic thread scheduling for the JVM context. You can read more about MJM registers in the aJ-100™ Reference Manual, chapter 4.
The class PianoRoll has a data structure created for the aJ-100 scheduler and is only used by the scheduler. The piano roll is a table that contains priority bit masks to enable periodic threads. The aJ-100 maintains a piano roll index pointer that is advanced by periodic interrupt specified by a beat variable. The length of the piano roll table is specified by a playing duration variable.
These two variables can be initialized by the constructor:
PianoRoll (int duration, int beat)
Here the duration and the beat are expressed in msecs.
The PianoRoll class has also a constructor where the duration and the beat are expressed in nanosecs.
The number of entries in the table is duration divided by beat, that is duration / beat. Note that the maximum beat for the aJ-100 based boards is 65 msecs.
When the index advances to the next entry in the table, the periodic threads at the priorities set by the bit mask are enabled to run. The index runs through the table cyclically so the table is the entire frame.
The implementation of a periodic thread can be done as follows:
class PThread1 extends PeriodicThread
{
private static final int PRIORITY = ...; // 0 <= PRIORITY <= 14
PThread1 (...)
{
super ();
makePeriodic (PConst.PERIOD1, PConst.INITDELAY, PRIORITY, this);
}
public void run()
{
while (true)
{
PeriodicThread.cycle(); // block until next wakeup. // do some activity here;
}
}
}
Before you start the thread object, you must create a PianoRoll object. This looks as the following: public static void main(String Args[])
{
PeriodicThread th1 = new PThread1(...);
PianoRoll pianoRoll = new PianoRoll (PConst.DURATION, PConst.BEAT);
th1.start();
pianoRoll.start(); // Start Piano Roll.
}
For the above I have implemented and used the following class of constants: class PConst
{
// The unit deltaT in msecs:
private static final int deltaT = 10;
private static final int n = 100;
private static final int m1 = 10;
private static final int m2 = 0;
// PianoRoll (PR) constants in msec:
public static final int BEAT = deltaT;
public static final int DURATION = n*deltaT;
// PeriodicThread (PT) constants in msec:
public static final int PERIOD1 = m1*deltaT; public static final int INITDELAY = m2*deltaT;
}
Below you can find the whole program.
Program: Implementation of periodic threads. |
 |
 |
 |
 |
 |
 |
 |
| Conditions to be satisfied for the Pianoroll object |
|
In the following deltaT
is the time unit for the setup of the piano roll and the periodic threads. This time unit will then determine how fine-grained the piano roll will be. The time unit can be in msecs or in nanosecs.
For the class PianoRoll we have: beat - the time distance between each ″tick″
duration - the size of the cyclic data structure.
The following must hold: beat = deltaT , - the time unit we have chosen
duration = n * beat, - n >= 1, i.e. the duration is a multiple
of beat and at least one beat
beat <= 65 msecs, - for the aJ-100 based boards.
|
|
 Music box with a copper-plated disc with perforations punched in the disc. The Edison Museum, Fort Myers, Florida. |
 |
 |
 |
 |
 |
 |
 |
| Conditions to be satisfied for all PeriodicThread objects |
For the class PeriodicThread we have the following parameters in the method makePeriodic:
period - the time between cycle returns
initDelay - the time before the initial cycle returns
Here the following must hold: beat <= period <= duration
period = m1 * beat, - m1 >= 1, i.e. the period is a multiple of beat and at least one beat
initDelay = m2 * beat, - m2 >= 0, i.e. the initDelay is a multiple of beat and greater than or equal zero
period * k = duration, - for some k >= 1, i.e. the period must divide duration
0 <= initDelay < period
initDelay + period <= duration. |
 |
 |
 |
 |
 |
 |
 |
| Check of all those conditions |
Because there are so many conditions that must hold when initializing the piano roll and the periodic threads, we have implemented a simple class CheckCylicSetup to check all those setup conditions.
Set up conditions
- Firstly, the parameters to the PianoRoll and PeriodicThread classes must satisfy all the conditions mentioned above.
- Secondly, the priorities of periodic threads must satisfy: 0 <= priority <= 14.
- Thirdly, the scheduler is a fixed-priority preemptive scheduler, and if there are multiple periodic threads of the same priority, at most one will be eligible to run for each piano roll beat.
Therefore periodic threads with the same priority must satisfy: periodi = periodj ⇒ initDelayi ≠ initDelayi
- Finally, we will let the CheckCylicSetup class implement the Rate Monotonic scheme, where the priority of each periodic thread is assigned according to its period: the shorter the period, the higher the priority:
periodi < periodj ⇒ priorityi > priorityj Consequently two periodic threads with equal priority must have equal period: periodi = periodj ⇔ priorityi = priorityj Because we have chosen to implement the Rate Monotonic scheme we can let the system determine the init delay of the periodic threads. |
 |
 |
 |
 |
 |
 |
 |
| class CheckCyclicSetup |
The above is implemented in a class called CheckCylicSetup: public class CheckCylicSetup
{
public static CheckCylicSetup getInstance() {..}
public void putPianoRollSetupIntoCcs (int pianoDuration, int pianoBeat) {..}
public int putPeriodicThreadSetupIntoCcs (int period, int priority)
// returns the init delay of the periodic thread
{..}
public void checkRateMonotonicSetUp() {..}
}
A new program structure
When using the CheckCylicSetup class, the periodic thread have to be implemented in this way: public class PeriodicThread3 extends PeriodicThread
{
...
public PeriodicThread3 (int period, int priority, ...)
{
super();
...
CheckCylicSetup ccs = CheckCylicSetup.getInstance();
int initDelay = ccs.putPeriodicThreadSetupIntoCcs (period, priority);
makePeriodic (period, initDelay, priority, this);
}
}
Notice that the init delay is now returned from the method putPeriodicThreadSetupIntoCcs.
The piano roll and a periodic thread are started in this way: public class Main2PeriodicThread3
{
public static void main(String[] args)
{
int deltaT = 50; // the unit in msecs
int beat = 1*deltaT;
int duration = 12*beat;
int period = 3 * beat;
int priority = ...; // 0 <= priority <= 14
PianoRoll pianoRoll = new PianoRoll (duration, beat);
CheckCylicSetup ccs = CheckCylicSetup.getInstance();
ccs.putPianoRollSetupIntoCcs (duration, beat);
PeriodicThread th = new PeriodicThread3 (period, priority, ..);
ccs.checkRateMonotonicSetUp(); // if more than one thread
th.start();
PianoRoll.start(); // Start Piano Roll.
}
}
Notice: The putPianoRollSetupIntoCcs method must be called before the periodic threads are created. Also notice: Now the programmer doesn't need to worry about the init delay of the periodic thread.
You can read all the details in this white paper: Periodic threads on aJ-100.
In the paper I have described and tested very thoroughly the conditions which must be satisfied for using the piano roll and the periodic threads.
The whole implementation as well as the javadoc for the classes can be found below.
Here I have also put the new versions of JEM_PianoRoll.class and PeriodicThread.class from aJile Systems (from December 8th 2004).
Source code for CheckCyclicSetup etc. Javadoc for CheckCyclicSetup etc. New class files for JEM_Pianoroll and PeriodicThread |
 |
 |
 |
 |
 |
 |
 |
|
 |
|
|  |
|
|
|
|
 |
|
|
 |
|
|
 |
|
|
 |
|
|
 |
|
|
 |
|
|
 |
|
|
 |
|
|
 |
 |
Implementation of Periodic Threads |
|
 |
|
|
 |
|
|
 |
|
|
 |
|
|
 |
|
|
 |
|
|
 |
|
|
 |
|
|
 |
|
|