JSR-282 SI 1.5: Supporting Sporadic and Aperiodic Releases in Real-Time Threads -------------------------------------------- Last Updated: 18th August, 2006 ----------------------- Summary ------------- The proposal is to add waitForNextRelease(), waitForNextReleaseInterruptible(), release(), schedule() and deschedule() methods to RealtimeThread so real-time threads will be better able to handle sporadic and aperiodic processing. Specification References ----------------------- Chapter 5: Semantics and Requirements for Real-Time Threads Chapter 6: Scheduling: Semantics and Requirements: Periodic Release of Real-Time Threads; Aperiodic Real-Time Threads Problem being address ------------------------------ The current specifications supports a range of ReleaseParameters that can be associated with schedulable objects. Asynchronous event handlers support the full range, however, currently there is no appropriate mechanisms to support associating AperiodicParameters and SporadicParameters with real-time threads. This is because there is no notion of a real-time thread waiting for a next release. It can only call waitForNextPeriod (which throws an exception if the real-time thread does not have PeriodicParameters). This also means that it is impossible to support the deadline miss and cost overrun detection mechanisms. Also aperiodic and sporadic threads cannot be descheduled in the same way as periodic threads. The current workaround is either not to use aperiodic/sporadic real-time threads or to assume that aperiodic/sporadic real-time threads are single shot (that is they are released by a call to the start method and they complete by termination - this is what the current spec says). Both these approaches undermine the consistency of the specification. Proposed Solution Summary -------------------------------------- The proposed solution is to 1) Add the following methods to the RealtimeThread class a) waitForNextRelease and waitForNextReleaseInterruptible b) release c) deschedule d) schedule 2) Define waitForNextRelease (when the real-time thread has aperiodic or sporadic release parameters) to be subjected to the semantics defined in Aperiodic Release Control (page 73 in the 2nd Edition) and Sporadic Release Control (page 75 in the 2nd Edition). (These sections are already written in terms of schedulable objects.) 3) Define deschedule and schedule (when the real-time thread has aperiodic or sporadic release parameters) to be consistent with that defined in Periodic Release of Real-Time threads (page 69 of the 2nd Edition). 4) Apply the current semantics for deadline miss and cost overrun (for a real-time thread that has periodic release parameters) to all release parameter types 5) Apply the methods defined in 1) above to real-time threads with PeriodicParameters: such that 5a) waitForNextRelease is defined to have the same semantics as waitForNextPeriod. 5b) deschedule is defined to have the same semantics as deschedulePeriodic 5c) schedule is defined to have the same semantics as schedulePeriodic. 6) Treat the changing of release parameter types as a pseudo re-start of the real-time thread. Semantics of Proposed Solution ---------------------------------------- The proposal is to provide a set of consistent mechanisms for controlling the release and completion of real-time threads. The current specification for cost monitoring is already defined in terms of releases of schedulable objects. Hence these semantics automatically apply to real-time threads with sporadic and aperiodic release parameters. The full semantics of this proposal can be generated from the current specification of the semantics in the "Periodic Release of Real-Time Threads" (page 69 of the 2nd Edition) modified to take into account the semantics defined in Aperiodic Release Control (page 73) and Sporadic Release Control (page 75). Essentially the proposed semantics are identical if you view a release event as coming from either the passage of time (for a periodic thread only) or the call of the release method (if and when it generates a release event). Deadline misses are handled in an identical way. public static boolean waitForNextRelease() Signals completion of the current release of the real-time thread and (in the absence of any missed deadline) blocks the real-time thread until a release event occurs waitForNextRelease() has comparable semantics to wFNP. In the normal case, it returns true when the real-time thread is next release. It returns false immediately if the real-time thread has missed its deadline and no deadline miss handler has been released. Real-time threads are automatically descheduled (at the end of the current released) when a deadline has been missed and a handler has been released. Alternatively, they can be descheduled explicitly by calling the deschedule method. public void release() Signals that the associated real-time thread should be released. May throw an exception if the thread is periodic (see Discussion point 1). public void deschedule() Indicates that the associated real-time thread should be removed from the list of threads eligible for scheduling at the end of its current release. public void schedule () Indicates that the associate thread can be added to the list of threads eligible for scheduling when the next release event for that thread occurs (subject to any MIT constraints if it has sporadic release parameters). Full Semantics of Aperiodic and Sporadic Release Control for Real-time Threads ------------------------------------------------------------------------------- ***The following assumes that the new methods are defined her for aperiodic real-time threads. The semantics for periodic real-time threads are unchanged. No attempt is made to unify the description of the semantics of periodic and aperiodic threads. (This would need to be done in the revised Specification.) The psuedo code given at the end is, however, for the general case. A schedulable object with release parameters of type AperiodicParameters is expected to be released non periodically. For real-time threads non-periodic release behavior is achieved by executing in a loop and invoking the RealtimeThread.waitForNextRelease method, or its interruptible equivalent RealtimeThread.waitForNextReleaseInterruptible within that loop. For simplicity, unless otherwise stated, the semantics in this section apply to both forms of that method. When the release method of a real-time thread (with aperiodic or sporadic release parameters) is called, the associated real-time thread is released according to the semantics below: 1. A non-periodic real-time thread's release characteristics are determined by the following: a. The invocation of the real-time thread's start method. b. The action of the RealtimeThread methods waitForNextRelease, waitForNextReleaseInterruptible, schedule and deschedule; c. The occurrence of deadline misses and whether or not a miss handler is installed; and d. The calling of the release method that generates non-periodic release events 2. Each call to the release method is an arrival. If the real-time thread has release parameters of type AperiodicParameters, then the arrival may become a release event for the real-time thread, according to the semantics given in Aperiodic Release Control (see page 73 of the 2nd Edition of the book). If the real-time thread has release parameters of type SporadicParameters, then the arrival may become a release event for the real-time thread, according to the semantics given in Sporadic Release Control (see page 79 of the 2nd Edition of the book). If the real-time thread has release parameters of PeriodicParameters then the arrival has no effect. 3. For each release arrival that is accepted for a real-time thread, an entry is made in the arrival-time queue. 4. The initial release event of a non-periodic real-time thread occurs in response to the invocation of its start method. 5. The deadline for a release is relative to the release event time and determined at the release event time according to the value of the deadline contained in the real-time threads release parameters. This value does not change, except as described previously for real-time threads using a REPLACE policy for MIT violation or arrival-time queue overflow. 6. Subsequent release events occur with each call of the release method, except as described in Aperiodic Release Control and Sporadic Release Control, and below in 7(e). 7. The implementation should behave effectively as if the following state variables were added to a real-time thread's state, and manipulated by the actions in (1) as described below: boolean descheduled, integer pendingReleases, integer missCount, boolean lastReturn. a. Initially: descheduled = false, pendingReleases = 0, missCount = 0, and lastReturn = true. b. When the real-time thread's deschedule method is invoked: set the value of descheduled to true. c. When the real-time thread's schedule method is invoked: set the value of descheduled to false; then if the thread is blocked-for-release-event, set the value of pendingReleases to zero, and tell the cost monitoring system to reset for this thread. d. When descheduled is true, the real-time thread is said to be descheduled. e. A real-time thread that has been descheduled and is blocked-for-release-event will not receive any further release events until after it has been rescheduled by a call to schedule; this means that no deadline misses can occur until the thread has been rescheduled. The descheduling of a real-time thread has no effect on its initial release. f. When each release event is due: i. If the state of the real-time thread is blocked-for-release-event (that is, it is waiting in waitForNextRelease), then if the thread is descheduled then do nothing, else increment the value of pendingReleases, inform cost monitoring that the next release event has occurred, and notify the thread to make it eligible for execution; ii. Otherwise, increment the value of pendingReleases, and inform cost monitoring that the next release event has occurred. g. On each deadline miss: i. If the real-time thread has a deadline miss handler: set the value of descheduled to true, atomically release the handler with its fireCount increased by the value of missCount+1 and zero missCount; ii. Otherwise add one to the missCount value. h. When the waitForNextRelease method is invoked by the current real-time thread there are two possible behaviors depending on the value of missCount: i. If missCount is greater than zero: decrement the missCount value; then if the lastReturn value is false, completion occurs: apply any pending parameter changes, decrement pendingReleases, inform cost monitoring the real-time thread has completed and return false; otherwise set the lastReturn value to false and return false. ii. Otherwise, apply any pending parameter changes, inform cost monitoring of completion, and then wait while descheduled is true, or pendingReleases is zero. Then set the lastReturn value to true, decrement pendingReleases, and return true. 8. An invocation of the waitForNextReleaseInterruptible method behaves as described above with the following additions: a. If the invocation commences when an instance of AsynchronouslyInterrupted- Exception (AIE) is pending on the real-time thread, then the invocation immediately completes abruptly by throwing that pending instance as an InterruptedException. If this occurs, the most recent release has not completed. If the pending instance is the generic AIE instance then the interrupt state of the real-time thread is cleared. b. If an instance of AIE becomes pending on the real-time thread while it is blocked-for-release-event, and the real-time thread is descheduled, then the AIE remains pending until the real-time thread is no longer descheduled. Execution then continues as in (c). c. If an instance of AIE becomes pending on the real-time thread while it is blocked-for-release-event, and it is not descheduled, then this acts as a release event: i. The real-time thread is made eligible for execution. ii. Upon execution the invocation completes abruptly by throwing the pending AIE instance as an InterruptedException. If the pending instance is the generic AIE instance then the interrupt state of the real-time thread is cleared. iii. If the AIE becomes pending at a time tint then: * The deadline associated with this release is the time tint+Dint, where Dint is the value of the deadline stored in the real-time thread's release parameters object at the time tint. * The next release time for the real-time thread will be when the next release event occur.. iv. Cost monitoring is informed of the release event When the thrown AIE instance is caught, the AIE becomes pending again (as per the usual semantics for AIE) until it is explicitly cleared. 9. Changes to release parameter types are treated as a pseudo RE-START of the release-time thread and a) any old pending releases are cleared b) any old arrival queue is flushed c) any outstanding call to deschedule is cleared d) any outstanding deadline misses are cleared The semantics are described below: i) Feasibility set issue Parameters are changed immediately (as specified in current spec) Given the following, the scheduler knows when the impact will take effect. ii) Effect on real-time thread if it is not waiting for next release event (and is not descheduled) a) no effect until the end of current release -- as implied by current spec b) when change occurs Pseudo re-start of the thread. i.e. if new RP are aperiodic - release immediately if periodic - use periodic start time algorithm iii) Effect on real-time thread if it is not waiting for next release event (but there is an outstanding descheduled) Immediate implied schedule. a) no futher effect until end of current release -- as implied by current spec b) when change occurs Pseudo re-start of the thread i.e. if new RP are aperiodic - release immediately if periodic - use periodic start time algorithm 4) Effect on real-time thread if waiting for next release event (and not descheduled) a) From Periodic to Aperiodic - when next periodic release event, it now becomes aperiodic with an immediate release a) From Aperiodic to Periodic - Immediate pseudo re-start of the thread using periodic start time algorithm 5) Effect on real-time thread if waiting for next release event (but there is an outstanding descheduled) Immediate implied schedule. a) From Periodic to Aperiodic - when next periodic release event, it now becomes aperiodic with an immediate release a) From Aperiodic to Periodic - Immediate pseudo re-start of the thread using periodic start time algorithm Pseudo Code ------------ The semantics of the previous section (and how they are integrated with periodic scheduling) can be more clearly understood by viewing them in pseudo-code form for each of the methods and actions involved. In the following no mechanism for blocking and unblocking a thread is prescribed. The use of the wait and notify terminology in places is purely an aid to expressing the desired semantics in familiar terms. // These values are part of thread state. boolean descheduled = false; int pendingReleases = 0; boolean lastReturn = true; int missCount = 0; int currentRP; int newRP; int periodic = 1; int aperiodic = 2; int sporadic = 3; boolean RPchange = false; boolean started = false; // set to true on first release; changeReleaseParameters(int newP) { newRP = newP; // Change Feasibility set descheduled = false; // automatic re-schedule if(blocked-for-release-event) { if (currentRP == periodic) { // defer until next release RPChange = true; } else { // immediate change performParameterChanges(); // current is aperiodic or sporadic assert pendingReleases = 0 assert missCount = 0; started = false; // flush arrival queue costMonitoringReset(); currentRP = newRP; if(newRP == periodic) { // consider this as the equivalent of call the // start method of the RT thread. // If start time has passed, generate a // an "onNextPeriodDue" event. // Otherwise, arrange for the event to be // generate at the appropriate time } else { // aperiodic or sporadic // generate a releaseArrivalEvent } } } else { // not at end of release, defer change RPChange = true; } } deschedule(){ if (!RPChange && started) { // no deschedule if outstanding RPchange // or not started descheduled = true; } } schedule(){ descheduled = false; if (blocked-for-release-event) { pendingReleases = 0; // flush arrival time queue costMonitoringReset(); } } onAperiodicReleaseArrival() { if(!started) started = true; if (currentRP == periodic) throw IllegalThreadStateException; if (descheduled) { ; // do nothing } else { perform_any_execution_regulation // For a sporadic thread, the onReleaseDue event // will be generated when MIT concerns have been satisfied // For an aperiodic thread, this will // immediately generate an onReleaseDue event. } } onAperiodicReleaseDue(){ if(currentRP == periodic) throw panic; if (blocked-for-release-event) { if (descheduled) { ; // do nothing } else { pendingReleases++; notifyCostMonitoringOfReleaseEvent(); notify it; // make eligible for execution } } else { pendingReleases++; notifyCostMonitoringOfReleaseEvent(); } } onNextPeriodeDue(){ // also called on first release if(!started) started = true; if (currentRP != periodic) panic; if (blocked-for-release-event) { if (descheduled) { ; // do nothing } else { pendingReleases++; notifyCostMonitoringOfReleaseEvent(); notify it; // make eligible for execution } } else { pendingReleases++; notifyCostMonitoringOfReleaseEvent(); } } onDeadlineMiss(){ if (there is a miss handler) { descheduled = true; release miss handler with fireCount increased by missCount+1 missCount = 0; } else { missCount++; } } waitForNextRelease{ assert(pendingReleases >= 0); if (missCount > 0 ) { // Missed a deadline without a miss handler missCount--; if (lastReturn == false) { // Changes on completion take place here performParameterChanges(); notifyCostMonitoringOfCompletion(); if(RPchange) { RPChangeNow(); return true; } else { pendingReleases--; } } lastReturn = false; return false; } else { // Changes on completion take place here performParameterChanges(); notifyCostMonitoringOfCompletion(); if(RPchange) { RPChangeNow(); return True; } wait while (descheduled || pendingReleases == 0);// blocked-for-release-event // check again for RP change if(RPchange) { RPChangeNow(); } pendingReleases--; lastReturn = true; return true; } } changeRPNow { // Changing over RP // Assuming clean slate! RPchange = false; pendingReleases = 0; flushArrivalQueue(); // this removes all outstanding releases missCount = 0; // restart here if(newRP == periodic) { // consider this as the equivalent of call the // start method of the RT thread. if !start time has passed { // arrange for timing event to be generated started = false; currentRP = newRP; wait while (pendingReleases == 0);// blocked-for-release-event } } else { // aperiodic or sporadic // record a releaseArrivalEvent } started = true; currentRP = newRP; lastReturn = true; } Discussion Points --------- 1. Should pendingReleases variable be visible to the programmer and should we provides methods to manipulate it in the same way that fireCount is visible? The current proposal assumes not. Arguments For: Asynchronous event handlers have access to a fireCount that contains the number of outstanding calls to their associated fire methods (for which there is no call to handleAsyncEvent). The equivalent for this in real-time threads is the pendingRelease count in the pseudo code. In order to achieve consistency across the models, a real-time thread should be able to access the pendingRelease count. Also, without this facility it would not be possible for the program to handle all outstanding releases in one go. That is: "clear all pending releases". Arguments Against: Asynchronous event handlers has a dynamic association between event handler and server thread. One of the motivations for the fireCount was to optimize the handling of the events to avoid some of the overheads associated with this dynamic association. By definition, real-time threads don't have this overhead and, therefore, don't need the access. There is no equivalent facilities for periodic threads. 2. Should the program be able to force a release of a periodic thread by calling release directly? The current proposal assumes not. Arguments for: Currently the specification defines that changes to some release parameter attributes don't take place until the next release of the schedulable objects (in particular a new periodic and a new deadline). Consider the case of a mode change where a periodic real-time thread needs to have its period and deadline changed from a long deadline to a short deadline. Currently, the start of the new mode could be delayed for a significant time. The work around in the current specification is to make the real-time thread use wFNPI and to interrupt it. This is subject to race conditions(the thread is potentially interrupted whilst executing the code for the last release of the old mode). With the proposal here, the thread initiating the mode change can force a new release of the real-time thread to occur immediately after the current release has completed by calling the release method. The new parameters are then installed and the the real-time threads starts the new mode with the new period and deadline. Hence allowing release to be applied to periodic threads gives extra flexibility and avoids having to raise an exception (which would be needed if we disallowed it). Arguments against: Releasing the real-time thread early will undermine the periodic thread model and cause extra complexity for feasibility analysis. It, therefore, has to be used in a very controlled way. 3) Should schedule and deschedule be moved to the Schedulable interface so that they can be applied to all schedulable objects? The current proposal assumes not. Arguments For: Currently they is no methods in the current specification for deschduling an ASEH other than detaching it from all its associated events (which may be difficult to determine). During transient overloads, it may be necessary to reduce the load on the processor by descheduling some ASEH. Arguments against: There is some concern as to whether this would be an incompatible change. Certainly, the specification would need to be revised to add deschedule and schedule to ASEH. However, it is not clear whether an RTSJ program compiled using 1.0.1 would execute correctly is run on a 1.1 implementation. Compatibility Issues -------------------- Any application that has extended the RealtimeThread classes and provided its own version of these methods may cause some confusion but should not be broken.