001    // RealtimeThread.java, created by wbeebee
002    // Copyright (C) 2001 Wes Beebee <wbeebee@mit.edu>
003    // Licensed under the terms of the GNU GPL; see COPYING for details.
004    package javax.realtime; 
005    
006    /**
007     * @author Wes Beebee <<a href="mailto:wbeebee@mit.edu">wbeebee@mit.edu</a>>
008     */
009    
010    /** Class <code>RealtimeThread</code> extends <code>java.lang.Thread</code>
011     *  and includes classes and methods to get and set parameterer objects,
012     *  manage the execution of those threads with a
013     *  <code>ReleaseParameters</code> type of <code>PeriodicParameters</code>,
014     *  and manage waiting.
015     *  <p>
016     *  A <code>RealtimeThread</code> object must be placed in a memory area
017     *  such that thread logic may unexceptionally access instance variables
018     *  and such that Java methods on <code>java.lang.Thread</code> (e.g.,
019     *  enumerate and join) complete normally except where such execution
020     *  would cause access violations.
021     *  <p>
022     *  Parameters for constructors may be <code>null</code>. In such cases
023     *  the default value will be the default value set for the particular
024     *  type by the associated instance of <code>Scheduler</code>.
025     */
026    public class RealtimeThread extends Thread implements Schedulable {
027    
028        public Scheduler currentScheduler = null;
029    
030        /** Contains the cactus stack of previous memoryAreas... */
031        MemAreaStack memAreaStack;
032    
033        /** The top of the stack for this RealtimeThread. */
034        int heapMemCount;
035    
036        MemAreaStack topStack;
037    
038        /** Specifies whether this RealtimeThread has access to the heap. */
039        boolean noHeap;
040    
041        private boolean blocked = false;
042    
043        /** Contains the memoryArea associated with this mem. */
044        MemoryArea mem, original;
045    
046        /** Realtime parameters for this thread */
047        ReleaseParameters releaseParameters = null;
048        MemoryParameters memoryParameters = null;
049        SchedulingParameters schedulingParameters = null;
050        ProcessingGroupParameters processingGroupParameters = null;
051    
052        /** Specifies whether the initialization code has finished setting up RTJ. */
053        static boolean RTJ_init_in_progress;
054    
055        /** The target to run. */
056        
057        private Runnable target;
058    
059        private static long nextThreadID;
060        private long threadID; 
061    
062        long checkDepth = 0;
063    
064        public long getUID() {
065            return threadID;
066        }
067    
068        static void checkInit() {
069            if (RTJ_init_in_progress) {
070                System.out.println("Cannot use any MemoryArea except heap until" +
071                                   "RTJ initialization has completed!");
072                System.exit(-1);
073            }
074        }
075    
076        /** Create a real-time thread. All parameter values are null. */
077        public RealtimeThread() {
078            this((MemoryArea)null);
079        }
080    
081        /** Create a real-time thread with the given <code>SchedulingParameters</code>.
082         *
083         *  @param scheduling The <code>SchedulingParameters</code> associated with
084         *                    <code>this</code> (and possibly other instances of
085         *                    <code>Schedulable</code>).
086         */
087        public RealtimeThread(SchedulingParameters scheduling) {
088            this();
089            schedulingParameters = scheduling;
090        }
091    
092        /** Create a real-time thread with the given <code>SchedulingParameters</code>
093         *  and <code>ReleaseParameters</code>.
094         *
095         *  @param scheduling The <code>SchedulingParameters</code> associated with
096         *                    <code>this</code> (and possibly other instances of
097         *                    <code>Schedulable</code>).
098         *  @param release The <code>ReleaseParameters</code> associated with
099         *                 <code>this</code> (and possibly other instances of
100         *                 <code>Schedulable</code>).
101         */
102        public RealtimeThread(SchedulingParameters scheduling,
103                              ReleaseParameters release) {
104            this();
105            schedulingParameters = scheduling;
106            releaseParameters = release;
107        }
108    
109        /** Create a real-time thread with the given characteristics and a 
110         *  <code>java.lang.Runnable</code>.
111         *
112         *  @param scheduling The <code>SchedulingParameters</code> associated with
113         *                    <code>this</code> (and possibly other instances of
114         *                    <code>Schedulable</code>).
115         *  @param release The <code>ReleaseParameters</code> associated with
116         *                 <code>this</code> (and possibly other instances of
117         *                 <code>Schedulable</code>).
118         *  @param memory The <code>MemoryParameters</code> associated with
119         *                <code>this</code> (and possibly other instances of
120         *                <code>Schedulable</code>).
121         *  @param area The <code>MemoryArea</code> associated with <code>this</code>.
122         *  @param group The <code>ProcessingGroupParameters</code> associated with
123         *               <code>this</code> (and possibly other instances of
124         *               <code>Schedulable</code>).
125         *  @param logic A <code>Runnable</code> whose <code>run()</code> method will
126         *               be executed for <code>this</code>.
127         */
128        public RealtimeThread(SchedulingParameters scheduling,
129                              ReleaseParameters release, MemoryParameters memory,
130                              MemoryArea area, ProcessingGroupParameters group,
131                              Runnable logic) {
132            this(area, logic);
133            schedulingParameters = scheduling;
134            releaseParameters = release;
135            memoryParameters = memory;
136            processingGroupParameters = group;
137        }
138    
139        public RealtimeThread(ThreadGroup group, Runnable target) {
140            super(group, (Runnable)null);
141            this.target = target;
142            mem = null;
143            setup();
144        }
145        
146        public RealtimeThread(MemoryArea memory) {
147            super();
148            target = null;
149            mem = ((original=memory)==null)?null:(memory.shadow);
150            setup();
151        }
152        
153        public RealtimeThread(MemoryParameters mp, Runnable target) {
154            this(mp.getMemoryArea(), target);
155        }
156    
157        public RealtimeThread(Runnable target) {
158            this((MemoryArea)null, target);
159        }
160        
161        public RealtimeThread(String name) {
162            this((Runnable)null, name);
163        }
164        
165        public RealtimeThread(ThreadGroup group, Runnable target, String name) {
166            this(group, target, name, null);
167        }
168    
169        public RealtimeThread(ThreadGroup group, String name) {
170            this(group, null, name);
171        }
172        
173        public RealtimeThread(Runnable target, String name) {
174            super(name);
175            this.target = target;
176            mem = null;
177            setup();
178        }
179        
180        public RealtimeThread(MemoryArea memory, Runnable target) {
181            super(target);
182            mem = memory;
183            setup();
184        }
185    
186        public RealtimeThread(ThreadGroup group, Runnable target,
187                              String name, MemoryArea memory) {
188            super(group, target, name);
189            this.target = target;
190            mem = ((original=memory)==null)?null:(memory.shadow);
191            setup();
192        }
193    
194        /** This sets up the unspecified local variables for the constructor. */
195        private void setup() {
196            memAreaStack = null;
197            noHeap = false;
198            heapMemCount = 0;
199            topStack = null;
200            initScheduler();
201            threadID = ++nextThreadID;
202        }
203    
204        void initScheduler() {
205            if (!RTJ_init_in_progress) {
206                currentScheduler = Scheduler.getDefaultScheduler();
207            }
208        }
209    
210        /** Add the scheduling and release characteristics of <code>this</code>
211         *  to the sed of such characteristics already being considered, if the
212         *  addition would result in the new, larger set being feasible.
213         *
214         *  @return True, if the addition would result in the set of considered
215         *          characteristics being feasible. False, if the addition would
216         *          result in the set of considered characteristics being
217         *          infeasible or there is no assigned instance of <code>Scheduler</code>.
218         */
219        public boolean addIfFeasible() {
220            if ((currentScheduler == null) ||
221                (!currentScheduler.isFeasible(this, getReleaseParameters()))) return false;
222            else return addToFeasibility();
223        }
224    
225        /** Inform the scheduler and cooperating facilities that scheduling and
226         *  release characteristics of this instance of <code>Schedulable</code>
227         *  should be considered in feasibility analysis until further notified.
228         *
229         *  @return True, if the addition was successful. False, if not.
230         */
231        public boolean addToFeasibility() {
232            if(currentScheduler != null) {
233                currentScheduler.addToFeasibility(this);
234                return currentScheduler.isFeasible();
235            } else return false;
236        }
237        
238        /** Gets a reference to the current instance of <code>RealtimeThread</code>.
239         *  
240         *  @return A reference to the current instance of <code>RealtimeThread</code>.
241         *  @throws java.lang.ClassCastException If the current thread is not a
242         *                                       <code>RealtimeThread</code>.
243         */
244        public static RealtimeThread currentRealtimeThread()
245            throws ClassCastException {
246            return (RealtimeThread)currentThread();
247        }
248    
249        /** Stop unblocking <code>waitForNextPeriod()</code> for <code>this</code> if
250         *  the type of the associated instance of <code>ReleaseParameters</code> is
251         *  <code>PeriodicParameters</code>. If <code>this</code> does not have a type
252         *  of <code>PeriodicParameters</code>, nothing happens.
253         */
254        public void deschedulePeriodic() {
255            if (releaseParameters instanceof PeriodicParameters) blocked = true;
256        }
257        
258        /** Gets the current memory area of <code>this</code>.
259         *
260         *  @return A reference to the current <code>MemoryArea</code> object.
261         */
262        public MemoryArea getCurrentMemoryArea() {
263            return mem;
264        }
265    
266        /** Memory area stacks include inherited stacks from parent threads. The initial
267         *  memory area for the current <code>RealtimeThread</code> is the memory area
268         *  given as a parameter to the constructor. This method returns the position in
269         *  the memory area stack of that initial memory area.
270         *
271         *  @return The index into the memory area stack of the initial memory area of
272         *          the current <code>RealtimeThread</code>.
273         */
274        public /* spec says it should be static */ int getInitialMemoryAreaIndex() {
275            MemAreaStack temp = memAreaStack;
276            int index = 0;
277            while (temp != null) {
278                if (temp.entry == mem) return index;
279                else {
280                    index++;
281                    temp = temp.next;
282                }
283            }
284    
285            return -1;
286        }
287        
288        /** Gets a reference to the current <code>MemoryArea</code>.
289         *
290         *  @return A reference to the current memory area in which allocations occur.
291         */
292        public MemoryArea getMemoryArea() {
293            if (mem == null) {
294                mem = (original = HeapMemory.instance()).shadow;
295            }
296            return original;
297        }
298    
299        /** Get the size of the stack of <code>MemoryArea</code> instances to which
300         *  this <code>RealtimeThread</code> has access.
301         *
302         *  @return The size of the stack of <code>MemoryArea</code> instances.
303         */
304        public /* spec says it should be static */ int getMemoryAreaStackDepth() {
305            MemAreaStack temp = memAreaStack;
306            int count = 0;
307            while (temp != null) {
308                count++;
309                temp = temp.next;
310            }
311            return count;
312        }
313    
314        /** Gets a reference to the <code>MemoryParameters</code> object.
315         *
316         *  @return A reference to the current <code>MemoryParameters</code> object.
317         */
318        public MemoryParameters getMemoryParameters() {
319            return memoryParameters;
320        }
321        
322        /** Gets the instance of <code>MemoryArea</code> in the memory area stack
323         *  at the index given. If the given index does not exist in the memory
324         *  area scope stack then null is returned.
325         *
326         *  @param index The offset into the memory area stack.
327         *  @return The instance of <code>MemoryArea</code> at index or <code>null</code>
328         *          if the given value does not correspond to a position in the stack.
329         */
330        public /* specs says it should be static */ MemoryArea getOuterMemoryArea(int index) {
331            MemAreaStack temp = memAreaStack;
332            for (int i = 0; i < index; i++)
333                if (temp != null) temp = temp.next;
334                else return null;
335            if (temp != null) return temp.entry;
336            else return null;
337        }
338    
339        /** Gets a reference to the <code>ProcessingGroupParameters</code> object.
340         *
341         *  @return A reference to the current <code>ProcessingGroupParameters</code> object.
342         */
343        public ProcessingGroupParameters getProcessingGroupParameters() {
344            return processingGroupParameters;
345        }
346    
347        /** Gets a reference to the <code>ReleaseParameters</code> object.
348         *
349         *  @return A reference to the current <code>ReleaseParameters</code> object.
350         */
351        public ReleaseParameters getReleaseParameters() {
352            return releaseParameters;
353        }
354    
355        /** Get a reference to the <code>Scheduler</code> object.
356         *
357         *  @return A reference to the current <code>Scheduler</code> object.
358         */
359        public Scheduler getScheduler() {
360            return currentScheduler;
361        }
362    
363        /** Gets a reference to the <code>SchedulingParameters</code> object.
364         *
365         *  @return A reference to the current <code>SchedulingParameters</code> object.
366         */
367        public SchedulingParameters getSchedulingParameters() {
368            return schedulingParameters;
369        }
370    
371        /** Sets the state of the generic <code>AsynchronouslyInterruptedException<code>
372         *  to pending.
373         */
374        public void interrupt() {
375            // TODO
376    
377            super.interrupt();
378        }
379    
380        /** Inform the scheduler and cooperating facilities that the scheduling and
381         *  release characteristics of this instance of <code>Schedulable</code>
382         *  should <i>not</i> be considered in feasibility analyses until further
383         *  notified.
384         *
385         *  @return True, if the removal was successful. False, if the removal was
386         *          unsuccessful.
387         */
388        public void removeFromFeasibility() {
389            if (currentScheduler != null)
390                currentScheduler.removeFromFeasibility(this);
391        }
392    
393        /** Begin unblocking <code>waitForNextPeriod()</code> for a periodic thread.
394         *  Typically used when a periodic schedulable object is in an overrun condition.
395         *  The scheduler should recompute the schedule and perform admission control.
396         *  If this does not have a type of <code>PeriodicParameters</code> as its
397         *  <code>ReleaseParameters</code>, nothing happens.
398         */
399        public void schedulePeriodic() {
400            blocked = false;
401        }
402    
403        /** This method appears in many classes in the RTSJ and with various parameters.
404         *  The parameters are either new scheduling characteristics for an instance
405         *  <code>Schedulable</code> or an instance of <code>Schedulable</code>. The
406         *  method first performs a feasibility analysis using the new scheduling
407         *  characteristics as replacements for the matching scheduling characteristics
408         *  of either <code>this</code> or the given instance of <code>Schedulable</code>.
409         *  If the resulting system is feasible the method replaces the current scheduling
410         *  characteristics, of either <code>this</code> or the given instance of
411         *  <code>Schedulable</code> as appropriate, with the new scheduling characteristics.
412         *
413         *  @param release The proposed release parameters.
414         *  @param memory The proposed memory parameters.
415         *  @return True, if the resulting system is feasible and the changes are made.
416         *          False, if the resulting system is not feasible and no changes are made.
417         */
418        public boolean setIfFeasible(ReleaseParameters release, MemoryParameters memory) {
419            return setIfFeasible(release, memory, processingGroupParameters);
420        }
421    
422        /** This method appears in many classes in the RTSJ and with various parameters.
423         *  The parameters are either new scheduling characteristics for an instance
424         *  <code>Schedulable</code> or an instance of <code>Schedulable</code>. The
425         *  method first performs a feasibility analysis using the new scheduling
426         *  characteristics as replacements for the matching scheduling characteristics
427         *  of either <code>this</code> or the given instance of <code>Schedulable</code>.
428         *  If the resulting system is feasible the method replaces the current scheduling
429         *  characteristics, of either <code>this</code> or the given instance of
430         *  <code>Schedulable</code> as appropriate, with the new scheduling characteristics.
431         *
432         *  @param release The proposed release parameters.
433         *  @param memory The proposed memory parameters.
434         *  @param group The proposed processing group parameters.
435         *  @return True, if the resulting system is feasible and the changes are made.
436         *          False, if the resulting system is not feasible and no changes are made.
437         */
438        public boolean setIfFeasible(ReleaseParameters release, MemoryParameters memory,
439                                     ProcessingGroupParameters group) {
440            if (currentScheduler == null) return false;
441            else return currentScheduler.setIfFeasible(this, release, memory, group);
442        }
443    
444        /** This method appears in many classes in the RTSJ and with various parameters.
445         *  The parameters are either new scheduling characteristics for an instance
446         *  <code>Schedulable</code> or an instance of <code>Schedulable</code>. The
447         *  method first performs a feasibility analysis using the new scheduling
448         *  characteristics as replacements for the matching scheduling characteristics
449         *  of either <code>this</code> or the given instance of <code>Schedulable</code>.
450         *  If the resulting system is feasible the method replaces the current scheduling
451         *  characteristics, of either <code>this</code> or the given instance of
452         *  <code>Schedulable</code> as appropriate, with the new scheduling characteristics.
453         *
454         *  @param release The proposed release parameters.
455         *  @param group The proposed processing group parameters.
456         *  @return True, if the resulting system is feasible and the changes are made.
457         *          False, if the resulting system is not feasible and no changes are made.
458         */
459        public boolean setIfFeasible(ReleaseParameters release, ProcessingGroupParameters group) {
460            return setIfFeasible(release, memoryParameters, group);
461        }
462    
463        /** Sets the memory parameters associated with this instance of <code>Schedulable</code>.
464         *
465         *  @param memory A <code>MemoryParameters</code> object which will become the memory
466         *                parameters associated with <code>this</code> after the method call.
467         *  @throws java.lang.IllegalThreadStateException
468         */
469        public void setMemoryParameters(MemoryParameters memory)
470            throws IllegalThreadStateException {
471            this.memoryParameters = memory;
472        }
473        
474        /** The method first performs a feasibility analysis using the ginve memory parameters
475         *  as replacements for the memory parameters of <code>this</code>. If the resulting
476         *  system is feasible the method replaces the current memory parameters of
477         *  <code>this</code> with the new memory parameters.
478         *
479         *  @param memory The proposed memory parameters. If <code>null</code>, nothing happens.
480         *  @return True, if the resulting system is fesible and the changes are made. False,
481         *          if the resulting system is not feasible and no changes are made.
482         */
483        public boolean setMemoryParametersIfFeasible(MemoryParameters memParam) {
484            return setIfFeasible(releaseParameters, memParam, processingGroupParameters);
485        }
486    
487        /** Sets the reference to the <code>ProcessingGroupParameters</code> object.
488         *
489         *  @param parameters A reference to the <code>ProcessingGroupParameters</code> object.
490         */
491        public void setProcessingGroupParameters(ProcessingGroupParameters parameters) {
492            this.processingGroupParameters = parameters;
493        }
494    
495        /** Sets the <code>ProcessingGroupParameters</code> of <code>this</code> only if the
496         *  resulting set of scheduling and release characteristics is feasible.
497         *
498         *  @param groupParameters The <code>ProcessingGroupParameters</code> object. If
499         *                         <code>null</code>, nothing happens.
500         *  @return True, if the resulting system is feasible and the changes are made.
501         *          False, if the resulting system is not feasible and no changes are made.
502         */
503        public boolean setProcessingGroupParametersIfFeasible(ProcessingGroupParameters groupParameters) {
504            return setIfFeasible(releaseParameters, memoryParameters, groupParameters);
505        }
506    
507        /** Since this affects the constraints expressed in the release parameters of the
508         *  existing schedulable objects, this may change the feasibility of the current
509         *  schedule.
510         *
511         *  @param release A <code>ReleaseParameters</code> object which will become the
512         *                 release parameters associated with <code>this</code> afther the
513         *                 method call.
514         *  @throws java.lang.IllegalThreadStateException Thrown if the state of this instance
515         *                                                of <code>Schedulable</code> is not
516         *                                                appropriate to changing the release
517         *                                                parameters.
518         */
519        public void setReleaseParameters(ReleaseParameters release)
520            throws IllegalThreadStateException {
521            this.releaseParameters = releaseParameters;
522        }
523        
524        /** Set the <code>ReleaseParameters</code> for this schedulable object only if
525         *  the resulting set of scheduling and release characteristics is feasible.
526         *
527         *  @param release The <code>ReleaseParameters</code> object. If <code>null</code>
528         *                 nothing happens.
529         *  @return True, if the resulting system is feasible and the changes are made.
530         *          False, if the resulting system is not feasible and no changes are made.
531         */
532        public boolean setReleaseParametersIfFeasible(ReleaseParameters release) {
533            return setIfFeasible(release, memoryParameters, processingGroupParameters);
534        }
535    
536        /** Sets the reference to the <code>Scheduler</code> object.
537         *
538         *  @param scheduler A reference to the <code>Scheduler</code> object.
539         *  @throws java.lang.IllegalThreadStateException Thrown when:
540         *                                                <code>((Thread.isAlive() &&
541         *                                                Not Blocked) == true)</code>.
542         *                                                (Where blocked means waiting in
543         *                                                <code>Thread.wait(), Thread.join()</code>
544         *                                                or <code>Thread.sleep()</code>).
545         */
546        public void setScheduler(Scheduler scheduler)
547            throws IllegalThreadStateException {
548            if (currentScheduler != null) currentScheduler.removeFromFeasibility(this);
549            currentScheduler = scheduler;
550        }
551        
552        /** Sets the scheduler and associated parameter objects.
553         *
554         *  @param scheduler A reference to the scheduler that will manage the execution
555         *                   of this thread. If <code>null</code>, no change to current
556         *                   value of this parameter is made.
557         *  @param scheduling A reference to the <code>SchedulingParameters</code> which
558         *                    will be associated with <code>this</code>. If null, no
559         *                    change to current value of this parameter is made.
560         *  @param release A reference to the <code>ReleasePrameters</code> which will
561         *                 be associated with <code>this</code>. If null, no change to
562         *                 current value of this parameter is made.
563         *  @param memory A reference to the <code>MemoryParameters</code> which will be
564         *                associated with <code>this</code>. If null, no change to
565         *                current value of this parameter is made.
566         *  @param group A reference to the <code>ProcessingGroupParameters</code> which
567         *               will be associated with <code>this</code>. If null, no change
568         *               to current value of this parameter is made.
569         *  @throws java.lang.IllegalThreadStateException Thrown when:
570         *                                                <code>((Thread.isAlive() &&
571         *                                                Not Blocked) == true).</code>
572         *                                                (Where blocked means waiting
573         *                                                in <code>Thread.wait(),
574         *                                                Thread.join()</code> or
575         *                                                <code>Thread.sleep()</code>).
576         */
577        public void setScheduler(Scheduler scheduler,
578                                 SchedulingParameters scheduling,
579                                 ReleaseParameters release,
580                                 MemoryParameters memParameters,
581                                 ProcessingGroupParameters processingGroup)
582            throws IllegalThreadStateException {
583    
584            currentScheduler = scheduler;
585            schedulingParameters = scheduling;
586            releaseParameters = release;
587            memoryParameters = memParameters;
588            processingGroupParameters = processingGroup;
589        }
590    
591        /** Sets the reference to the <code>SchedulingParameters</code> object.
592         *
593         *  @param scheduling A reference to the <code>SchedulingParameters</code> in
594         *                    interface <code>Schedulable</code>.
595         *  @throws java.lang.IllegalThreadStateException Thrown when:
596         *                                                <code>((Thread.isAlive() &&
597         *                                                Not Blocked) == true).</code>
598         *                                                (Where blocked means waiting
599         *                                                in <code>Thread.wait(),
600         *                                                Thread.join()</code> or
601         *                                                <code>Thread.sleep()</code>).
602         */
603        public void setSchedulingParameters(SchedulingParameters scheduling)
604            throws IllegalThreadStateException {
605            this.schedulingParameters = scheduling;
606        }
607        
608        /** The method first performs a feasiblity analysis using the given scheduling
609         *  parameters as replacements for the scheduling parameters of <code>this</code>.
610         *  If the resulting system is feasible the method replaces the current scheduling
611         *  parameters of <code>this</code> with the new scheduling parameters.
612         *
613         *  @param scheduling The proposed scheduling parameters. If null, nothing happens.
614         *  @return True, if the resulting system is feasible and the changes are made.
615         *          False, if the resulting system is not feasible and no changes are made.
616         */
617        public boolean setSchedulingParametersIfFeasible(SchedulingParameters scheduling) {
618            //How do scheduling parameters affect the feasibility of the task set?
619            this.schedulingParameters = scheduling;
620            return true;
621    //      if (currentScheduler == null) return false;
622    //      SchedulingParameters oldSchedulingParameters = schedulingParameters;
623    //      schedulingParameters = scheduling;
624    //      if (currentScheduler.isFeasible()) return true;
625    //      else {
626    //          schedulingParameters = oldSchedulingParameters;
627    //          return false;
628    //      }
629        }
630    
631        /** An accurate timer with nanoseconds granularity. The actual resolution
632         *  available for the clock must be queried form somewhere else. The time
633         *  base is the given <code>Clock</code>. The sleep time may be relative
634         *  of absolute. If relative, then the calling thread is blocked for the
635         *  amount of time given by the parameter. If absolute, then the calling
636         *  thread is blocked until the indicated point in time. If the given
637         *  absolute time is before the current time, the call to sleep returns
638         *  immediately.
639         *
640         *  @param clock The instance of <code>Clock</code> used as the base.
641         *  @param time The amount of time to sleep or the point in time at
642         *              which to awaken.
643         *  @throws java.lang.InterruptedException If interrupted.
644         */
645        public static void sleep(Clock clock, HighResolutionTime time)
646            throws InterruptedException {
647            if (time instanceof AbsoluteTime) {
648                RelativeTime temp = ((AbsoluteTime)time).subtract(clock.getTime());
649                Thread.sleep(temp.getMilliseconds(), temp.getNanoseconds());
650            }
651            else 
652                Thread.sleep(time.getMilliseconds(), time.getNanoseconds());
653        }
654    
655        /** An accurate timer with nanoseconds granularity. The actual resolution
656         *  available for the clock must be queried form somewhere else. The time
657         *  base is the given <code>Clock</code>. The sleep time may be relative
658         *  of absolute. If relative, then the calling thread is blocked for the
659         *  amount of time given by the parameter. If absolute, then the calling
660         *  thread is blocked until the indicated point in time. If the given
661         *  absolute time is before the current time, the call to sleep returns
662         *  immediately.
663         *
664         *  @param time The amount of time to sleep or the point in time at
665         *              which to awaken.
666         *  @throws java.lang.InterruptedException If interrupted.
667         */
668        public static void sleep(HighResolutionTime time)
669            throws InterruptedException {
670            sleep(Clock.getRealtimeClock(), time);
671        }
672    
673        /** Starts the thread. */
674        public void start() {
675            if ((mem != null)&&(!mem.heap)) {
676                checkInit();
677            }
678            RealtimeThread previousThread = currentRealtimeThread();
679            memAreaStack = previousThread.memAreaStack;
680            MemoryArea newMem = previousThread.getMemoryArea();
681            if (mem == null) {
682                enter(newMem, previousThread.getMemoryArea());
683            } else {
684                enter(mem, original);
685            }
686            mem = getMemoryArea();
687            super.start(); // Setup thread
688        }
689    
690        /** Used by threads that have a reference to a <code>ReleaseParameters</code>
691         *  type of <code>PeriodicParameters</code> to block until the start of each
692         *  period. Periods start at either the start time in <code>PeriodicParameters</code>
693         *  of when <cod>this.start()</code> is called. This method will block until
694         *  the start of the next period unless the thread is in either an overrun or
695         *  deadline miss condition. If both overrun and miss handlers are null and
696         *  the thread has overrun its cost of missed a deadline <code>waitForNextPeriod</code>
697         *  will immediately return false once per overrun or deadline miss. It will
698         *  then again block until the start of the next period (unless, of course,
699         *  the thread has overrun of missed again). If either the overrun of deadline
700         *  miss handlers are not null and the thread is in either an overrun or
701         *  deadline miss condition <code>waitForNextObject()</code> will block until
702         *  handler corrects the situation (possibly by calling <code>schedulePeriodic</code>).
703         *  <code>waitForNextPeriod()</code> throws <code>IllegalThreadStateException</code>
704         *  if this does not have a reference to a <code>ReleaseParameters</code>
705         *  type of <code>PeriodicParameters</code>.
706         *
707         *  @return True when the thread is not in an overrun or deadline miss
708         *          condition and unblocks at the start of the next period.
709         *  @throws java.lang.IllegalThreadStateException If <code>this</code> does not
710         *                                                have a reference to a
711         *                                                <code>ReleaseParameters</code>
712         *                                                type of <code>PeriodicParameters</code>.
713         */
714        public boolean waitForNextPeriod() throws IllegalThreadStateException {
715            if ((releaseParameters instanceof PeriodicParameters) && (!blocked))
716                currentScheduler.waitForNextPeriod(this);
717            return false;
718        }
719    
720        /** Informs <code>ReleaseParameters, ProcessingGroupParameters</code> and
721         *  <code>MemoryParameters</code> that <code>this</code> has them as its parameters.
722         */
723        public void bindSchedulable() {
724            releaseParameters.bindSchedulable(this);
725            processingGroupParameters.bindSchedulable(this);
726            memoryParameters.bindSchedulable(this);
727        }
728    
729        /** Informs <code>ReleaseParameters, ProcessingGroupParameters</code> and
730         *  <code>MemoryParameters</code> that <code>this</code> does not have them
731         *  any longer as its parameters.
732         */
733        public void unbindSchedulable() {
734            releaseParameters.unbindSchedulable(this);
735            processingGroupParameters.unbindSchedulable(this);
736            memoryParameters.unbindSchedulable(this);
737        }
738    
739        public static int activeCount() {
740            return Thread.activeCount();
741        }
742    
743        /** Returns the current running thread. */    
744    
745        public static Thread currentThread() {
746            return Thread.currentThread();
747        }
748    
749        /** Same as <code>java.lang.Thread.enumerate()</code>. */
750        
751        public static int enumerate(Thread tarray[]) {
752            return Thread.enumerate(tarray);
753        }
754        
755        /** Same as <code>java.lang.Thread.interrupted()</code>. */
756        
757        public static boolean interrupted() {
758            return Thread.interrupted();
759        }
760        
761        /** Same as <code>java.lang.Thread.yield()</code>. */
762    
763        public static void yield() {
764            Thread.yield();
765        }
766        
767        /** Same as <code>java.lang.Thread.sleep(long)</code>. */
768    
769        public static void sleep(long millis) throws InterruptedException {
770            Thread.sleep(millis);
771        }
772        
773        /** Same as <code>java.lang.Thread.sleep(long, int)</code>. */
774    
775        public static void sleep(long millis, int nanos) 
776            throws InterruptedException {
777            Thread.sleep(millis, nanos);
778        }
779        
780        /** */
781    
782        public static void dumpStack() {
783            //              System.out.println("MemoryArea stack:");
784            System.out.println(currentRealtimeThread().memAreaStack.toString());
785            Thread.dumpStack();
786        }
787        
788        /** Override the Thread.run() method, because Thread.run() doesn't work. */
789        public void run() {
790            if (target != null) {
791                target.run();
792            }
793        }
794    
795        /** For internal use only. */
796        public MemoryArea memoryArea() {
797            if (mem == null) { // Bypass static initializer problem.
798                mem = (original = HeapMemory.instance()).shadow;
799            }
800            return mem;
801        }  
802    
803        void enter(MemoryArea mem, MemoryArea original) {
804            memAreaStack = MemAreaStack.PUSH(this.mem, this.original, memAreaStack);
805            this.original = original;
806            /* Think about whether this should be original or mem... */
807            (this.mem = mem).enterMemBlock(this, memAreaStack);
808        }
809    
810        /** */
811        void exitMem() {
812            mem.exitMemBlock(this, memAreaStack);
813            mem = memAreaStack.entry;
814            original = memAreaStack.original;
815            memAreaStack = MemAreaStack.POP(memAreaStack);
816        }
817        
818        /** */
819        void cleanup() {
820            NoHeapRealtimeThread.print("MemAreaStack: "+memAreaStack+", topStack: "+topStack+"\n");
821            while (memAreaStack != topStack) {
822                NoHeapRealtimeThread.print("Exiting mem: "+mem+"\n");
823                exitMem();
824            }
825        }
826    
827        /** Get the outerScope of a given MemoryArea for the current 
828         *  RealtimeThread. 
829         */
830        
831        MemoryArea outerScope(MemoryArea child) {
832            MemAreaStack current = memAreaStack.first(child.shadow);
833            if (current != null) {
834                current = current.next;
835            }
836            while ((current != null) && (!current.entry.scoped)) {
837                current = current.next;
838            }
839            if (current == null) {
840                return getMemoryArea();
841            } else {
842                return current.original;
843            }
844        }
845        
846        /** */
847        boolean checkAccess(MemoryArea source, MemoryArea target) {
848            MemAreaStack sourceStack = (source == memoryArea()) ? 
849                memAreaStack : memAreaStack.first(source);
850            return (sourceStack != null) && (sourceStack.first(target) != null);
851        }
852        
853        public void checkNoHeapWrite(Object obj) {}
854        
855        public void checkNoHeapRead(Object obj) {}
856        
857        public String toString() {
858            return "RealtimeThread";
859        }
860    
861        /** Schedule this on the thread lists */
862        final void schedule() {
863            if (currentScheduler != null) {
864                currentScheduler.addThreadToLists(this);
865            }
866        }
867    
868        /** Deschedule this from the thread lists */
869        final void unschedule() {
870            if (currentScheduler != null) {
871                currentScheduler.removeThreadFromLists(this);
872            }
873        }
874    }