JSR-282 SI 16:2.0 Cost Enforcement and Periodic Real-Time Threads -------------------------------------------- Last Updated: 5 October, 2006 ----------------------- Summary ------------- Currently, the RTSJ allows under some rare situations a periodic SO to consume more than its cost during a single period. This SI updates the semantics to take remove this anomaly. There are now two types of cost overrun: a cost overrun per release and a cost overrun per period. Two alternative APIs are provided: one that assumes the use of RichAsyncEventHandlers and one that doesn't. Specification References ----------------------- Chapter 6: Semantics: Cost Monitoring Problem being address ------------------------------ The goal of the RTSJ cost enforcement monitor is to ensure that the run-time behaviour of the program does not violate the feasibility analysis without the explicit intervention of the programme. The current version of the RTSJ defines the following (page 67, 2nd Edition of the book) 4) When a cost overrun is triggered, the cost overrun handler associated with the SO, if any, is released. If the most recent release of the SO is the ith release, and the i+1 release event has not yet occurred, then: a) If the state of the SO is either executing or eligible-for-execution, then the SO is placed into the state blocked-by-cost-overrun. There may be a bounded delay between the time at which a cost overrun occurs and the time at which the SO becomes blocked-by-cost-overrun. b) Otherwise, the SO must have been blocked for a reason other than blocked-by-cost-overrun. In this case, the state change to blocked-by-cost-overrun is left pending: if the blocking condition for the SO is removed, then its state changes to blocked-by-cost-overrun. There may be a bounded delay between the time at which the blocking condition is removed and the time at which the SO becomes blocked-by-cost-overrun. Otherwise, if the i+1 release event has occurred, the current CPU consumption is set to zero, the SO remains in its current state and the cost monitoring system considers the most recent release to now be the i+1 release. The cost enforcement model is independent of the scheduler. The priority scheduler assumes that all schedulable objects have a deadline less than or equal to the period. However, the following behaviour is possible: 1. A periodic schedulable object SO is released (the ith release) and immediately blocks waiting for an event. 2. It has set no deadline miss handler. 3. SO remains block until it next (ith +1) release event occurs. 4. Just after its ith + 1 release event it becomes unblocked and executes for its full cost value 5. It then suffers a cost overrun. By semantic 4 (above) it continues to run for another cost value. 6. Hence, it the period i+1 to i+2 it has consumed twice its maximum cost value without the programmer's direct intervention. Simply resetting the CPU consumption on each new release will solve the above problem but this will now not allow the programmer to detect cost overrun on a per release basis. Consider the following: 1. A periodic schedulable object SO is released (the ith release) and executes for just less than its cost. It then blocks waiting for an event. 2. It has set no deadline miss handler. 3. SO remains block until it next (ith +1) release event occurs. At this event, the CPU consumption is reset to zero 4. Just after its ith + 1 release event it becomes unblocked and executes beyond it cost value. No cost overrun occurs, as the SO hasn't consumed cost since the last release event. Proposed Solution Summary -------------------------------------- Two possible APIs for determining which type of overrun has occured are presented. 1) Assuming RichAsynEventHandlers Add the following somewhere (in the Scheduler class?) public static final Object OVERRUN_ON_RELEASE; public static final Object OVERRUN_PER_PERIOD; 2) Assuming NO RichAsynEventHandlers Add the following method and constants somewhere (in the Scheduler class?) public int getLastOverrunCondition(SO: Schedulable); // returns the reason for the last overrun detected in SO public static final int NO_CURRENT_OVERRUN; public static final int OVERRUN_ON_RELEASE; public static final int OVERRUN_PER_PERIOD; public static final int OVERRUN_PER_INTERARRIVAL_TIME; Semantics of Proposed Solution ---------------------------------------- The cost monitoring semantics needs to be modified to add a consumption-per-period (or MIT). Here is the proposed new semantics. (a) Initial release: consumption and consumption-period are zero and increase as the SO executes; (b) Cost overrun: if consumption or consumption-period becomes equal or greater than cost -- due to execution of the SO or change in the cost value -- the overrun asynchronous event handler, if any, is released; (c1) On the occurrence of a cost overrun (due to a release overrun): (1) if the most recent release of the SO is the ith release and the ith+1 release has not yet occurred: (i) if the SO is executing or eligible-for-execution, then it becomes blocked-by-cost-overrun; (ii) if the SO is blocked for a reason other than blocked-by-cost-overrun, t then a pending for blocked-by-cost-overrun is set; (2) else if the ith+1 release has occurred, then consumption is set to zero, the SO remains in its current state and the new release being considered by the cost monitoring system is the ith+1 release; (c2) On the occurrence of a cost overrun (due to a period overrun): (1) if the SO is executing or eligible-for-execution, then it becomes blocked-by-cost-overrun; (2) if the SO is blocked for a reason other than blocked-by-cost-overrun, then a pending for blocked-by-cost-overrun is set; (d) Occurrence of a new ith release event for an SO: (1) if the SO is blocked-by-cost-overrun, then consumption and consumption-period are set to zero, the SO is made eligible-for-execution and the most recent release being considered by the cost monitoring is the ith release; (2) if the SO is blocked for a reason other then blocked-by-cost-overrun: (i) if a pending for blocked-by-cost-overrun is set, then the pending is cleared, consumption and consumption-period are set to zero, the SO remains in its current state, and the most recent release being considered by the cost monitoring is the ith release; (ii) otherwise, consumption-period is set to zero; (3) otherwise, consumption-period is set to zero; (e) Completion of the ith release for an SO: and the most recent release for the cost monitoring is the ith, then consumption is set to zero and the most recent release being considered becomes the ith+1 release; (f) Changes to the cost value: (1) if the old value was greater than consumption and consumption-period and if the: (i) new value is lower or equal to consumption and greater than consumption-period: a cost overrun due to a release overrun occurs; (ii) new value is lower or equal to consumption and consumption-period: a cost overrun due to a release and a period overrun occurs; (iii) new value is lower or equal to consumption-period and greater than consumption: a cost overrun due to a period overrun occurs; (2) if the new value is greater than consumption-period: (i) if the SO is block-by-cost-overrun, then the SO is made eligible-for-execution; (ii) if the SO is blocked and a pending for blocked-by-cost-overrun is set, then the pending is cleared; (iii) otherwise, no cost monitoring actions occurs; (g) Reset the cost monitoring: if the most recent release being considered is the mth release and the SO is in the nth release (n > m), then a reset makes the cost monitoring to consider the most recent release nth and consumption and consumption-period are set to zero (This can happen because the RTSJ introduce mechanisms whereby an SO can be descheduled and afterwards scheduled again.) For the case where RichHandlers are supported by the RTSJ ---------------------------------------------------------- When a handler is to be released, if handler is a RichAsyncEventHandler then the appropriate Object is passed OVERRUN_ON_RELEASE or OVERRUN_PER_PERIOD object is passed as a parameter. In the usual simple case of cost overrun, the OVERRUN_ON_RELEASE object is passed. The OVERRUN_PER_PERIOD object is intended for the situation where the associated schedulable object is running passed its next release. If the handler is a simple AsyncEventHandler, the type of overrun information is lost. For the case where RichHandlers are NOT supported by the RTSJ ------------------------------------------------------------- The Scheduler keeps track of the type of last overrun incurred by the current release. This can be obtained by calling the getLastOverrunCondition method. Discussion Points --------- 1) There is the usual problem with cost overrun (and deadline miss handlers) that if the handler is attached to more than one SO, it is difficult to determine what SO overran. With the 2nd approach, the handler can poll all its associated Sos. 2) Currently cost monitoring is independent of the scheduler. Certainly cost-per-release is independent of the feasibility analysis performed. However, cost-per-period is rather feasibility-analysis depenedent. We are currently investigating whether it would, for example, be appropriate for a scheduler which allowed the deadline to be greater than the period. Compatibility Issues --------------------