001    // AperiodicParameters.java, created by cata
002    // Copyright (C) 2001 Catalin Francu <cata@mit.edu>
003    // Licensed under the terms of the GNU GPL; see COPYING for details.
004    
005    package javax.realtime;
006    
007    import java.util.LinkedList;
008    import java.util.Iterator;
009    
010    /** A notice to the scheduler that the associated schedulable object's run
011     *  method witll be released aperiodically but with a minimum time between
012     *  releases. When a reference toa <code>SporadicParameters</code> object
013     *  is given as a parameter to a constructor, the <code>SporadicParameters</code>
014     *  object becomes bound to the object being created. Changes to the values
015     *  in the <code>SporadicParameters</code> object affect the constructed
016     *  object. If given to more than one constructor, then changes to the
017     *  values in the <code>SporadicParameters</code> object affect <i>all</i>
018     *  of the associated objects. Note that this is a one-to-many relationship
019     *  and <i>not</i> a many-to-many.
020     *  <p>
021     *  <b>Caution:</b> This class is explicitly unsafe in multithreaded situations
022     *  when it is being changed. No synchronization is done. It is assumed that
023     *  users of this class who are mutating instances will be doing their own
024     *  synchronization at a higher level.
025     *  <p>
026     *  Correct initiation of the deadline miss and cost overrun handlers require
027     *  that the underlying system know the arrival time of each sporadic task.
028     *  For an instance of <code>RealtimeThread</code> the arrival time is the
029     *  time at which the <code>start()</code> is invoked. For other instances of
030     *  <code>Schedulable</code> it may be required for the implementation to
031     *  save the arrival times. For instances of <code>AsyncEventHandler</code>
032     *  with a <code>ReleaseParameters</code> type of <code>SporadicParameters</code>
033     *  the implementation must maintain a queue of monotonically incraesing arrival
034     *  times which correspond to the execution of the <code>fire()</code> method of
035     *  the instance of <code>AsyncEvent</code> bound to the instance of
036     *  <code>AsyncEventHandler</code>
037     *  <p>
038     *  This class allows the application to specify one of four possible behaviors
039     *  that indicate what to do if an arrival occurs that is closer in time to the
040     *  previous arrival than the value given in this class as minimum interarrival
041     *  time, what to do if, for any reason, the queue overflows, and the initial
042     *  size of the queue.
043     */
044    public class SporadicParameters extends AperiodicParameters {
045        private RelativeTime minInterarrival;
046        private String arrivalTimeQueueOverflowBehavior;
047        private int initialArrivalTimeQueueLength;
048        private String mitViolationBehavior;
049        Schedulable sch;
050    
051        // Fields from specs
052        
053        /** If an arrival time occurs and should be queued but the queue already
054         *  holds a number of times equal to the initial queue length defined by
055         *  <code>this</code> then the <code>fire()</code> method shall throw a
056         *  <code>ResourceLimitError</code>. If the arrival time is a result of
057         *  a happening to which the instance of <code>AsyncEventHandler</code>
058         *  is bound then the arrival time is ignored.
059         */
060        public static final String arrivalTimeQueueOverflowExcept =
061            "ARRIVAL_TIME_QUEUE_OVERFLOW_EXCEPT";
062        /** If an arrival time occurs and should be queued but the queue already
063         *  holds a number of times equal to the initial queue length defined by
064         *  <code>this</code> then the arrival time is ignored.
065         */
066        public static final String arrivalTimeQueueOverflowIgnore =
067            "ARRIVAL_TIME_QUEUE_OVERFLOW_IGNORE";
068        /** If an arrival time occurs and should be queued but the queue already
069         *  holds a number of times equal to the initial queue length defined by
070         *  <code>this</code> then the previous arrival time is overwritten by
071         *  the new arrival time. However, the new time is adjusted so that the
072         *  difference between it and the previous time is equal to the minimum
073         *  intearrival time.
074         */
075        public static final String arrivalTimeQueueOverflowReplace =
076            "ARRIVAL_TIME_QUEUE_OVERFLOW_REPLACE";
077        /** If an arrival time occurs and should be queued but the queue already
078         *  holds a number of times equal to the initial queue length defined by
079         *  <code>this</code> then the queue is lengthened and the arrival time
080         *  is saved.
081         */
082        public static final String arrivalTimeQueueOverflowSave =
083            "ARRIVAL_TIME_QUEUE_OVERFLOW_SAVE";
084        /** If an arrival time for any instance of <code>Schedulable</code> which
085         *  has <code>this</code> as its instance of <code>ReleaseParameters</code>
086         *  occurs at a time les then the minimum interarrival time defined here
087         *  then the <code>fire()</code> method shall throw 
088         *  <code>MITViolationException</code>. If the arrival time is a result of
089         *  a happening to which the instance of <code>AsyncEventHandler</code> is
090         *  bound then the arrival time is ignored.
091         */
092        public static final String mitViolationExcept =
093            "MIT_VIOLATION_EXCEPT";
094        /** If an arrival time for any instance of <code>Schedulable</code> which
095         *  has <code>this</code> as its instance of </code>ReleaseParameters</code>
096         *  occurs at a time less then the minimum interarrival time defined here
097         *  then the new arrival time is ignored.
098         */
099        public static final String mitViolationIgnore =
100            "MIT_VIOLATION_IGNORE";
101        /** If an arrival time for any instance of <code>Schedulable</code> which
102         *  has <code>this</code> as its instance of <code>ReleaseParameters</code>
103         *  occurs at a time less than the minimum interarrival time defined here
104         *  then the previous arrival time is overwritten with the new arrival time.
105         */
106        public static final String mitViolationReplace =
107            "MIT_VIOLATION_REPLACE";
108        /** If an arrival time for any instance of <code>Schedulble</code> which
109         *  has <code>this</code> as its instance of <code>ReleaseParameters</code>
110         *  occurs at a time less then the minimum interarrival time defined here
111         *  then the new arrival time is added to the queue of arrival times.
112         *  However, the new time is adjusted so that the difference between it
113         *  and the previous time is equal to the minimum interarrival time.
114         */
115        public static final String mitViolationSave =
116            "MIT_VIOLATION_SAVE";
117    
118        /** Create a <code>SporadicParameters</code> object.
119         *
120         *  @param minInterarrival The release times of the schedulable object will
121         *                         occur no closer that this interval. Must be greater
122         *                         than zero when entering feasibility analysis.
123         *  @param cost Processing time per minimum interarrival interval. On
124         *              implementations which can measure the amount of time a
125         *              schedulable object is executed, this value is the maximum
126         *              amount of time a schedulable object receives per interval. On
127         *              implementations which cannot measure execution time, this value
128         *              is used s a hint to the feasibility altorithm. On such systems
129         *              it is not possible to determine when any particular object
130         *              exceeds cost. Equivalent to <code>RelativeTime(0, 0)</code> if null.
131         *  @param deadline The latest permissible completion time measured from the
132         *                  release time of the associated invocation of the schedulable
133         *                  object. For a minimum implementation for purposes of feasibility
134         *                  anaysis, the deadline is equal to the minimum interarrival
135         *                  interval. Other implementations may use this parameter to compute
136         *                  execution eligibility. If null, deadline will equal the
137         *                  minimum interarrival time.
138         *  @param overrunHandler This handler is invoked if an invocation of the schedulable
139         *                        object exceeds cost. Not required for minimum implementation.
140         *                        If null, nothing happens on the overrun condition.
141         *  @param missHandler This handler is invoked if the <code>run()</code> method of the
142         *                     schedulable object is still executing after the deadline has
143         *                     passed. Although minimum implementations do not consider
144         *                     deadlines in feasibility calculations, they must recognize
145         *                     variable deadlines and invoke the miss handler as appropriate.
146         *                     If null, nothing happens on the miss deadline condition.
147         */
148        public SporadicParameters(RelativeTime minInterarrival, RelativeTime cost,
149                                  RelativeTime deadline,
150                                  AsyncEventHandler overrunHandler,
151                                  AsyncEventHandler missHandler) {
152            super(cost, deadline, overrunHandler, missHandler);
153            this.minInterarrival = new RelativeTime(minInterarrival);
154        }
155    
156        /** Get the behavior of the arrival time queue in the event of an overflow.
157         *
158         *  @return The behavior of the arrival time queue as a string.
159         */
160        public String getArrivalTimeQueueOverflowBeharior() {
161            return arrivalTimeQueueOverflowBehavior;
162        }
163    
164        /** Get the initial number of elements the arrival time queue can hold.
165         *
166         *  @return The initial length of the queue.
167         */
168        public int getInitialArrivalTimeQueueLength() {
169            return initialArrivalTimeQueueLength;
170        }
171    
172        /** Get the minimum interarrival time.
173         *
174         *  @return The minimum interarrival time.
175         */
176        public RelativeTime getMinimumInterarrival() {
177            return minInterarrival;
178        }
179    
180        /** Get the arrival time queue behavior in the event of a minimum
181         *  interarrival time violation.
182         *
183         *  @return The minimum interarrival time violation behavior as a string.
184         */
185        public String getMitViolationBehavior() {
186            return mitViolationBehavior;
187        }
188    
189        /** Set the behavior of the arrival time queue in the case where the insertion
190         *  of a new element would make the queue size greater than the initial size
191         *  given in this.
192         *
193         *  @param behavior A string representing the behavior.
194         */
195        public void setArrivalTimeQueueOverflowBehavior(String behavior) {
196            arrivalTimeQueueOverflowBehavior = new String(behavior);
197        }
198    
199        /** Set the initial number of elements the arrival time queue can hold
200         *  without lengthening the queue.
201         *
202         *  @param initial The initial length of the queue.
203         */
204        public void setInitialArrivalTimeQueueLength(int initial) {
205            initialArrivalTimeQueueLength = initial;
206        }
207    
208        /** Set the minimum interarrival time.
209         *
210         *  @param minInterarrival The release times of the schedulable object will
211         *                         occur no closer than this interval. Must be greater
212         *                         than zero when entering feasibility analysis.
213         */
214        public void setMinimumInterarrival(RelativeTime minInterarrival) {
215            minInterarrival.set(minInterarrival);
216        }
217    
218        /** Set the behavior of the arrival time queue in the case where the new
219         *  arrival time is closer to the previous arrival time than the minimum
220         *  interarrival time given in this.
221         *
222         *  @param behavior A string representing the behavior.
223         */
224        public void setMitViolationBehavior(String behavior) {
225            mitViolationBehavior = new String(behavior);
226        }
227    
228        /** This method appears in many classes in the RTSJ and with varous parameters.
229         *  The parameters are either new scheduling characteristics for an instance
230         *  <code>Schedulable</code> or an instance of <code>Schedulable</code>. The
231         *  method first performs a feasibility analysis using the new scheduling
232         *  characteristics of either <code>this</code> or the given instance of
233         *  <code>Schedulable</code>. If the resulting system is feasible the method
234         *  replaces the current scheduling characteristics, of either <code>this</code>
235         *  or the given instance of <code>Schedulable</code> as appropriate, with the
236         *  new scheduling characteristics.
237         *
238         *  @param interarrival The proposed interarrival time.
239         *  @param cost The proposed cost.
240         *  @param deadline The proposed deadline.
241         *  @return True, if the resulting system is feasible and the changes are made.
242         *          False, if the resulting system is not feasible and no changes are made.
243         */
244        public boolean setIfFeasible(RelativeTime interarrival,
245                                     RelativeTime cost,
246                                     RelativeTime deadline) {
247            boolean b = true;
248            Iterator it = schList.iterator();
249            RelativeTime old_interarrival = this.minInterarrival;
250            RelativeTime old_cost = this.cost;
251            RelativeTime old_deadline = this.deadline;
252            setMinimumInterarrival(interarrival);
253            setCost(cost);
254            setDeadline(deadline);
255            while (b && it.hasNext())
256                b = ((Schedulable)it.next()).setReleaseParametersIfFeasible(this);
257            if (!b) {
258                setMinimumInterarrival(old_interarrival);
259                setCost(old_cost);
260                setDeadline(old_deadline);
261            }
262            return b;
263        }
264    
265        public boolean bindSchedulable(Schedulable sch) {
266            return schList.add(sch);
267        }
268    
269        public boolean unbindSchedulable(Schedulable sch) {
270            return schList.remove(sch);
271        }
272    }