Exercise 1: Creating Periodic Real-Time Threads
Expected duration: 30 minutes — 15 minute introduction then 15 minutes for lab
The goal of this exercise is to create a periodic real-time thread and observe
the regularity of its execution, even in the face of other system
activities. The requirements are:
- Create a periodic
NoHeapRealtimeThread
in the ImmortalMemory
area
- Set a period of 5ms and measure the interval between periods over
100 periods
Warning: Threads with real-time priorities run to the exclusion of all non-realtime processes on the system, including operating system services, shells and GUIs! If your real-time thread does not explicitly block it will consume 100% of a CPU. If you have less CPUs than real-time threads doing this then you system may appear to lock-up. So take care with experimentation: an infinite loop may require a reboot to fix!
Background Information
Read the material in the presentation, up to the slide titled "Exercise 1".
- The only threads that can execute without any interference from
the garbage collector are no-heap real-time threads (NHRT's) — so
called because they don't (and can't) use the heap for memory
allocation. So in this exercise you will create such a thread in the
immortal-memory area (a memory area unaffected by GC and from which
objects are not removed).
- To simulate system activity and show that it does not impede the
regularity of the release of the periodic no-heap real-time thread,
the code also starts a number of plain Java threads that interact
with each other, creating objects and allowing them to become
garbage, such that garbage collection will occasionally occur.
- To avoid unpredictable delays due to class-loading we're utilizing the Initialization Time Compilation (ITC) feature of Sun Java RTS. This is handled by the settings defined under Project Properties -> Real-Time Configuration. The use of ITC should be transparent to you for the purposes of these exercises, but you may see messages in the console output referring to the files itc.precompile and/or itc.preinit — these files have been provided for you in each of the project directories.
- A few tips:
- All NHRT's require at least a
SchedulingParameters
and an initial MemoryArea
. When using the default
scheduler (PriorityScheduler
), the SchedulingParameters
must be an instance of PriorityParameters
. Note, in
general, that for a NHRT, the initial memory area cannot be the
heap, but it could be either an instance of ScopedMemory
or the singleton instance of ImmortalMemory
(ImmortalMemory.instance()
) — use immortal memory in this exercise.
- Realtime priorities values are provided by the
PriorityScheduler
class. They are consecutive integer values in a range given by:
- PriorityScheduler.instance().getMinPriority() ; to
- PriorityScheduler.instance().getMaxPriority()
The minimum real-time priority in Java RTS is 11. The maximum real-time priority is system dependent and can be configured, but by default in Java RTS on Solaris it is 69. For the purpose of this, and the following exercise use the priority PriorityScheduler.instance().getMinPriority().
- The period must be specified in a
PeriodicParameters
object (which extends ReleaseParameters
).
- A NHRT cannot access objects allocated in the heap, so all the
objects accessed by this thread must be allocated in either
immortal memory, or a scoped memory area.
- In the RTSJ, the static initializers (the
static { }
blocks and static variable initializers) in a class are automatically executed in the ImmortalMemory
instance (this feature may help you to write simpler code)
- To have good timing precision, your time measurement must be
done either using the
RealtimeClock
returned by Clock.getRealtimeClock()
and its getTime()
method; or by using the Java 5 System.nanoTime
method.
- Calculations involving time objects can be a little tricky — if pressed for time
just use
System.nanoTime
. If you do use time objects then preallocate the
ones you will need, outside the loop and use the time/clock methods that accept a
destination time object as a parameter. This will avoid allocation in the loop.
- Use multiple
print
statements to avoid string concatenation, and hence
allocation within the loop.
In general I/O should be avoided in tight control
loops due to the latency of such operations. It should be okay in this exercise, however.
- The return value from
waitForNextPeriod
, when no deadline-miss handler
is installed, indicates if a deadline was missed, and hence the next periodic
release was later than expected. This would cause strange results (an extra long time
between periods, followed by a number of a short ones as the thread caught up —
assuming it did). To check there are no deadline misses use waitForNextPeriod
as follows:
if (!RealtimeThread.waitForNextPeriod())
throw new Error("Deadline missed!");
Steps to Follow
- Start the Netbeans IDE if not already started.
There are projects defined for each exercise and its solution.
Expand the project Ex1 by clicking on the "lollypop" icon to the far left
of the project name, in the project pane. Click on the same icon next to the Source Packages item to show
the packages defined in this project. Click on the same icon next to the ex1 package name to show all the source
files defined in this project. To edit a source file, double-click on its name and an editing tab for that file
will appear in the right-hand pane.
- Edit the
PeriodicNHRT
class (in PeriodicNHRT.java
) and fill in the logic of the run()
method to print the time between periodic releases for 100 releases.
- Edit the
Main
class (in Main.java
) and add the code to create an instance of the PeriodicNHRT
class with a period of 5ms. This instance must be assigned to the predefined static field worker
.
You must create suitable PriorityParameters
and PeriodicParameters
objects
to pass to the PeriodicNHRT
constructor, along with a suitable MemoryArea
.
- Build the project by right-clicking on the project name in the project pane, and then clicking on Build.
Correct any compilation errors and build again, repeating as necessary.
- Run the project:
- From within Netbeans by right-clicking on the project name in the project pane, and then clicking on Run.
The output will be displayed in the output pane at the bottom of the window.
- From a terminal window by executing
the command:
<INSTALL_DIR>/bin/java -jar /export/home/lab5538/realtimejava/exercises/exercise1/dist/Ex1.jar
Here's an example of part of what you might see using HighResolutionTime
objects to measure the elapsed time:
# > /opt/SUNWrtjv/bin/java -jar /export/home/lab5538/realtimejava/exercises/exercise1/dist/Ex1.jar
Elapsed time is (5ms, 500ns)
Elapsed time is (5ms, 833ns)
Elapsed time is (5ms, 1251ns)
Elapsed time is (4ms, 996750ns)
Note: the application will attempt to terminate after 60 seconds, in case your real-time thread does not terminate when it should.
Did your application complete successfully? Or did you see an exception like the following?
Elapsed time is (4 ms, 999916 ns)
Elapsed time is (167 ms, 756833 ns)
Exception in thread "PeriodicNHRT" java.lang.Error: Deadline missed!
at ex1.PeriodicNHRT.run(PeriodicNHRT.java:29)
If you did, you won't be alone — there's something interfering with the timely execution of our periodic thread, and in the next exercise we'll find out what it is.
Solution
The solution of this exercise is provided as a "ready to build and run" NetBeans project: <lab_root>/realtimejava/solutions/exercise1/Ex1Soln.
Summary
In this exercise, you learned how to create periodic real-time threads — a fundamental building block in many real-time systems.
You may have also seen a problem with a deadline miss occurring — a typical timing constraint violation that needs to be investigated and eliminated.
Back to top
Next exercise