001    // NoHeapRealtimeThread.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    /** A <code>NoHeapRealtimeThread</code> is a specialized form of
011     *  <code>RealtimeThread</code>. Because an instance of
012     *  <code>NoHeapRealtimeThread</code> may immediately preempt any
013     *  implemented garbage collector logic contained in its <code>run()</code>
014     *  is never allowed to allocated or reference any object allocated
015     *  in the heap nor is it even allowed to manipulate any reference
016     *  to any object in the heap. For example, if <code>a</code> and
017     *  <code>b</code> are objects in immortal memory, <code>b.p</code>
018     *  is reference to an object on the heap, and <code>a.p</code> is
019     *  type complatible with <code>b.p</code>, then a
020     *  <code>NoHeapRealtimeThread</code> is <i>not</i> allowed to
021     *  execute anything like the following:
022     *  <p>
023     *  <code>a.p = b.p; b.p = null;</code>
024     *  <p>
025     *  Thus, it is always safe for a <code>NoHeapRealtimeThread</code>
026     *  to interrupt the garbage collector at any time, without waiting
027     *  for the end of the garbage collection cycle or a defined preemption
028     *  point. Due to these restrictions, a <code>NoHeapRealtimeThread</code>
029     *  object must be placed in a memory area such that thread logic
030     *  may unexceptionally access instance variables and such that
031     *  Java methods on <code>java.lang.Thread</code> (e.g., enumerate
032     *  and join) complete normally except where the execution would
033     *  cause access violations. The constructors of
034     *  <code>NoHeapRealtimeThread</code> require a reference to
035     *  <code>ScopedMemory</code> or <code>ImmortalMemory</code>.
036     *  <p>
037     *  When the thread is started, all execution occurs in the scope
038     *  of the given memory area. Thus, all memory allocation performed
039     *  with the "new" operator is taken from this given area.
040     *  <p>
041     *  Parameters for constructors may be <code>null</code>. In such
042     *  cases the default value will be the default value set for the
043     *  particular type by the associated instance of <code>Scheduler</code>.
044     */
045    public class NoHeapRealtimeThread extends RealtimeThread {
046    
047        /** Create a <code>NoHeapRealtimeThread</code>.
048         *
049         *  @param sp A <code>SchedulingParameters</code> object that will be
050         *            associated with <code>this</code>. A null value means
051         *            this will not have an associated
052         *            <code>SchedulingParameters</code> object.
053         *  @param ma A <code>MemoryArea</code> object. Must be a
054         *            <code>ScopedMemory</code> or <code>ImmortalMemory</code>
055         *            type. A null value causes an <code>IllegalArgumentException<code>
056         *            to be thrown.
057         *  @throws java.lang.IllegalArgumentException If the memory area
058         *                                             parameter is null.
059         */
060        public NoHeapRealtimeThread(SchedulingParameters sp, MemoryArea ma)
061            throws IllegalArgumentException {
062            schedulingParameters = sp;
063            memoryArea = ma;
064            noHeap = true;
065        }
066    
067        /** Create a <code>NoHeapRealtimeThread</code>.
068         *
069         *  @param sp A <code>SchedulingParameters</code> object that will be
070         *            associated with <code>this</code>. A null value means
071         *            this will not have an associated
072         *            <code>SchedulingParameters</code> object.
073         *  @param rp A <code>ReleaseParameters</code> object that will be
074         *            associated with <code>this</code>. A null value means
075         *            this will not have an associated <code>ReleaseParameters</code>
076         *            object.
077         *  @param ma A <code>MemoryArea</code> object. Must be a
078         *            <code>ScopedMemory</code> or <code>ImmortalMemory</code>
079         *            type. A null value causes an <code>IllegalArgumentException<code>
080         *            to be thrown.
081         *  @throws java.lang.IllegalArgumentException If the memory area
082         *                                             parameter is null.
083         */
084        public NoHeapRealtimeThread(SchedulingParameters sp, ReleaseParameters rp,
085                                   MemoryArea ma) throws IllegalArgumentException {
086            this(sp, ma);
087            releaseParameters = rp;
088        }
089    
090        /** Create a <code>NoHeapRealtimeThread</code>.
091         *
092         *  @param sp A <code>SchedulingParameters</code> object that will be
093         *            associated with <code>this</code>. A null value means
094         *            this will not have an associated
095         *            <code>SchedulingParameters</code> object.
096         *  @param rp A <code>ReleaseParameters</code> object that will be
097         *            associated with <code>this</code>. A null value means
098         *            this will not have an associated <code>ReleaseParameters</code>
099         *            object.
100         *  @param mp A <code>MemoryParameters</code> object that will be
101         *            associated with <code>this</code>. A null value means
102         *            this will not have a <code>MemoryParameters</code> object.
103         *  @param ma A <code>MemoryArea</code> object. Must be a
104         *            <code>ScopedMemory</code> or <code>ImmortalMemory</code>
105         *            type. A null value causes an <code>IllegalArgumentException<code>
106         *            to be thrown.
107         *  @param group A <code>ProcessingGroupParameters</code> object that will
108         *               be associated with <code>this</code> A null value means this
109         *               will not have an associated <code>ProcessingGroupParameters</code>
110         *               object.
111         *  @param logic A <code>Runnable</code> whose <code>run()</code> method will
112         *               be executed for <code>this</code>.
113         *  @throws java.lang.IllegalArgumentException If the memory area
114         *                                             parameter is null.
115         */
116        public NoHeapRealtimeThread(SchedulingParameters sp, ReleaseParameters rp,
117                                    MemoryParameters mp, MemoryArea ma,
118                                    ProcessingGroupParameters group, Runnable logic)
119            throws IllegalArgumentException {
120            super(sp, rp, mp, ma, group, logic);
121        }
122    
123        /** Construct a <code>NoHeapRealtimeThread</code> which will execute in the
124         *  given <code>MemoryArea</code>
125         */
126        public NoHeapRealtimeThread(MemoryArea area) 
127            throws IllegalArgumentException 
128        {
129            super(area);
130            setup(area);
131        }
132        
133        /** Construct a <code>NoHeapRealtimeThread</code> which will execute 
134         *  <code>logic</code> in the given <code>MemoryArea</code> 
135         */
136        public NoHeapRealtimeThread(MemoryArea area, Runnable logic) 
137            throws IllegalArgumentException 
138        {
139            super(area, logic);
140            setup(area);
141        }
142        
143        /** Setup some state for the constructors */
144        private void setup(MemoryArea area) throws IllegalArgumentException {
145            if ((area == null) || area.heap) {
146                throw new IllegalArgumentException("invalid MemoryArea");
147            } else {
148                mem = area;
149            }
150            noHeap = true;
151        }
152        
153        /** Construct a new <code>NoHeapRealtimeThread</code> that will inherit
154         *  the properties described in <code>MemoryParameters</code> and will
155         *  run <code>logic</code>.
156         */
157        public NoHeapRealtimeThread(MemoryParameters mp, Runnable logic) {
158            this(mp.getMemoryArea(), logic);
159        }
160        
161        /** Check to see if a write is possible to the given object. 
162         *  Warning: this method can only be used when we're not really running
163         *  <code>NoHeapRealtimeThreads</code> for real, because you can't access
164         *  the object at all in a real <code>NoHeapRealtimeThread</code>. 
165         */
166        
167        public NoHeapRealtimeThread(SchedulingParameters scheduling,
168                                    ReleaseParameters release) {
169            super(scheduling, release);
170        }
171    
172        /** Checks if the <code>NoHeapRealtimeThread</code> is startable and starts
173         *  it if it is. Checks that the parameters associated with this
174         *  <code>NoHeapRealtimeThread</code> object are not allocated in heap. Also,
175         *  checks if <code>this</code> object is allocated in heap. If any of them
176         *  are allocated, <code>start()</code> throws a <code>MemoryAccessError</code>.
177         *
178         *  @throws MemoryAccessError If any of the parameters of <code>this</code>
179         *                            is allocated on heap.
180         */
181        public void start() {
182            HeapMemory heap = HeapMemory.instance();
183            if (heap.equals(getMemoryArea()))
184                throw new MemoryAccessError("NoHeapRealtimeThread cannot be allocated in heap.");
185            SchedulingParameters scheduling = getSchedulingParameters();
186            if ((scheduling != null) && (heap.equals(MemoryArea.getMemoryArea(scheduling))))
187                throw new MemoryAccessError("SchedulingParameters of a NoHeapRealtimeThread cannot be allocated in heap.");
188            ReleaseParameters release = getReleaseParameters();
189            if ((release != null) && (heap.equals(MemoryArea.getMemoryArea(release))))
190                throw new MemoryAccessError("ReleaseParameters of a NoHeapRealtimeThread cannot be allocated in heap.");
191            MemoryParameters memParams = getMemoryParameters();
192            if ((memParams != null) && (heap.equals(MemoryArea.getMemoryArea(memParams))))
193                throw new MemoryAccessError("MemoryParameters of a NoHeapRealtimeThread cannot be allocated in heap.");
194            ProcessingGroupParameters group = getProcessingGroupParameters();
195            if ((group != null) && (heap.equals(MemoryArea.getMemoryArea(group))))
196                throw new MemoryAccessError("ProcessingGroupParameters of a NoHeapRealtimeThread cannot be allocated in heap.");
197    
198            super.start();
199        }
200    
201        public void checkNoHeapWrite(Object obj) {
202            if ((obj != null) && (obj.memoryArea != null) && obj.memoryArea.heap) {
203                throw new IllegalAssignmentError("Cannot assign " +
204                                                 obj.memoryArea.toString() +
205                                                 " from " + toString());
206            }
207        }
208        
209        /** Check to see if a read is possible from the given object.
210         *  Warning: this method can only be used when we're not really running
211         *  <code>NoHeapRealtimeThreads</code> for real, because you can't access
212         *  the object at all in a real <code>NoHeapRealtimeThread</code>.
213         */
214        public void checkNoHeapRead(Object obj) {
215            if ((obj != null) && (obj.memoryArea != null) && obj.memoryArea.heap) {
216                throw new MemoryAccessError("Cannot read " + 
217                                            obj.memoryArea.toString() +
218                                            " from " + toString());
219            }
220        }
221        
222        /** Return a String describing this thread. */
223        public String toString() {
224            return "NoHeapRealtimeThread";
225        }
226        
227        /** A print method that's safe to call from a NoHeapRealtimeThread. */
228        public native static void print(String s);
229        public native static void print(double d);
230        public native static void print(int n);
231        public native static void print(long l);
232    }