Lab-5538: The Real-Time Java™ Platform Programming Challenge: Taming Timing Troubles

Expected Duration: 120 minutes

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

 
  1. 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.
  2. 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.
  3. 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.
  4. 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.
  5. 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