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 }