001 // Scheduler.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 import java.util.HashSet; 007 008 /** An instance of <code>Scheduler</code> manages the execution of 009 * schedulable objects and may implement a feasibility algorithm. The 010 * feasibility algorithm may determine if the known set of schedulable 011 * objects, given their particular exection ordering (or priority 012 * assignment), is a feasible schedule. Subclasses of <code>Scheduler</code> 013 * are used for alternative scheduling policies and should define an 014 * <code>instance()</code> class method to return the default 015 * instance of the subclass. The name of the subclass should be 016 * descriptive of the policy, allowing applications to deduce the 017 * policy available for the scheduler obtained via 018 * <code>getDefaultScheduler()</code> (e.g., <code>EDFScheduler</code>). 019 */ 020 public abstract class Scheduler { 021 protected static Scheduler defaultScheduler = null; 022 private static VTMemory vt = null; 023 024 /** Create an instance of <code>Scheduler</code>. */ 025 protected Scheduler() { 026 addToRootSet(); 027 if (vt == null) { 028 vt = new VTMemory(); 029 } 030 } 031 032 /** Inform the scheduler and cooperating facilities that the resource 033 * demands (as expressed in the associated instances of 034 * <code>SchedulingParameters, ReleaseParameters, MemoryParameters</code> 035 * and <code>ProcessingGroupParameters</code>) of this instance of 036 * <code>Schedulable</code> will be considered in the feasibility analysis 037 * of the associated <code>Scheduler</code> until further notice. Whether 038 * the resulting system is feasible or not, the addition is completed. 039 * 040 * @param schedulable A reference to the given instance of <code>Schedulable</code>. 041 * @return True, if the addition was successful. False, if not. 042 */ 043 protected abstract void addToFeasibility(Schedulable schedulable); 044 045 /** Trigger the execution of a schedulable object (like an 046 * <code>AsyncEventHandler</code>. 047 * 048 * @param schedulable The Schedulable object to make active. 049 */ 050 public abstract void fireSchedulable(Schedulable schedulable); 051 052 /** Gets a reference to the default scheduler. 053 * In the RTJ spec, this is the PriorityScheduler, but we'll set it to whatever 054 * we wish to focus on at the moment, since this is a hot research target. 055 * 056 * Currently, there's a PriorityScheduler (for compliance), and a 057 * RoundRobinScheduler (for debugging). Conceivably, one can put Schedulers 058 * in a containment hierarchy, and getDefaultScheduler() would 059 * return the root. 060 * 061 * @return A reference to the default scheduler. 062 */ 063 public static Scheduler getDefaultScheduler() { 064 if (defaultScheduler == null) { 065 setDefaultScheduler(DebugScheduler.instance()); 066 return getDefaultScheduler(); 067 } 068 return defaultScheduler; 069 } 070 071 /** Gets a string representing the policy of <code>this</code>. 072 * 073 * @return A <code>java.lang.String</code> object which is the name 074 * of the scheduling polixy used by <code>this</code>. 075 */ 076 public abstract String getPolicyName(); 077 078 /** Queries the system about the feasibility of the set of scheduling 079 * and release characteristics currently being considered. 080 */ 081 public abstract boolean isFeasible(); 082 protected abstract boolean isFeasible(Schedulable s, ReleaseParameters rp); 083 084 /** Inform the scheduler and cooperating facilities that the resource 085 * demands (as expressed in the associated instances of 086 * <code>SchedulingParameters, ReleaseParameters, MemoryParameters</code> 087 * and <code>ProcessingGroupParameters</code>) of this instance of 088 * <code>Schedulable</code> should no longer be considered in the 089 * feasibility analysis of the associated <code>Scheduler</code> 090 * until further notice. Whether the resulting system is feasible 091 * or not, the subtraction is completed. 092 * 093 * @return True, if the removal was successful. False, if the removal 094 * was unsuccessful. 095 */ 096 protected abstract void removeFromFeasibility(Schedulable schedulable); 097 098 /** Set the default scheduler. This is the scheduler given to instances 099 * of <code>RealtimeThread</code> when they are constructed. The default 100 * scheduler is set to the required <code>PriorityScheduler</code> at 101 * startup. 102 * 103 * @param scheduler The <code>Scheduler</code> that becomes the default 104 * scheduler assigned to new threads. If null nothing happens. 105 */ 106 public static void setDefaultScheduler(Scheduler scheduler) { 107 defaultScheduler = scheduler; 108 } 109 110 /** This method appears in many classes in the RTSJ and with various parameters. 111 * The parameters are either new scheduling characteristics for an instance of 112 * <code>Schedulable</code> or an instance of <code>Schedulable</code>. The 113 * method first performs a feasibility analysis using the new scheduling 114 * characteristics of either <code>this</code> or the given instance of 115 * <code>Schedulable</code>. If the resulting system is feasible the method 116 * replaces the current sheduling characteristics, of either <code>this</code> 117 * or the given instance of <code>Schedulable</code> as appropriate, with the 118 * new scheduling characteristics. 119 * 120 * @param schedulable The instance of <code>Schedulable</code> to which the 121 * parameters will be assigned. 122 * @param release The proposed release parameters. 123 * @param memory The proposed memory parameters. 124 * @return True, if the resulting system is feasible and the changes are made. 125 * False, if the resulting system is not feasible and no changes are made. 126 */ 127 public abstract boolean setIfFeasible(Schedulable schedulable, 128 ReleaseParameters release, 129 MemoryParameters memory); 130 131 /** This method appears in many classes in the RTSJ and with various parameters. 132 * The parameters are either new scheduling characteristics for an instance of 133 * <code>Schedulable</code> or an instance of <code>Schedulable</code>. The 134 * method first performs a feasibility analysis using the new scheduling 135 * characteristics of either <code>this</code> or the given instance of 136 * <code>Schedulable</code>. If the resulting system is feasible the method 137 * replaces the current sheduling characteristics, of either <code>this</code> 138 * or the given instance of <code>Schedulable</code> as appropriate, with the 139 * new scheduling characteristics. 140 * 141 * @param schedulable The instance of <code>Schedulable</code> to which the 142 * parameters will be assigned. 143 * @param release The proposed release parameters. 144 * @param memory The proposed memory parameters. 145 * @param group The proposed processing group parameters. 146 * @return True, if the resulting system is feasible and the changes are made. 147 * False, if the resulting system is not feasible and no changes are made. 148 */ 149 150 public abstract boolean setIfFeasible(Schedulable schedulable, 151 ReleaseParameters release, 152 MemoryParameters memory, 153 ProcessingGroupParameters group); 154 155 /** Chooses a thread to run */ 156 protected abstract long chooseThread(long currentTime); 157 158 /** Adds a thread to the thread list */ 159 protected abstract void addThread(RealtimeThread thread); 160 161 /** Removes a thread from the thread list */ 162 protected abstract void removeThread(RealtimeThread thread); 163 164 /** Used for adding a C thread that doesn't have any Java counterpart. 165 * The convention is that the threadID for C threads is negative. 166 */ 167 protected abstract void addThread(long threadID); 168 169 /** Used for removing a C thread that doesn't have any Java counterpart. 170 * The convention is that the threadID for C threads is negative. 171 */ 172 protected abstract void removeThread(long threadID); 173 174 /** Stop running <code>threadID</code> until enableThread - 175 * used in the lock implementation to wait on a lock. 176 */ 177 protected abstract void disableThread(long threadID); 178 179 /** Enable <code>threadID</code>, allowing it run again - used in notify */ 180 protected abstract void enableThread(long threadID); 181 182 /** Cause the thread to block until the next period */ 183 protected abstract void waitForNextPeriod(RealtimeThread rt); 184 185 /** Switch every <code>microsecs</code> microseconds */ 186 protected final native void setQuanta(long microsecs); 187 188 /** Print out the status of the scheduler */ 189 public final static void print() { 190 Scheduler sched = RealtimeThread.currentRealtimeThread().getScheduler(); 191 if (sched == null) { 192 sched = Scheduler.getDefaultScheduler(); 193 } 194 MemoryArea.startMem(vt); 195 NoHeapRealtimeThread.print("\n"+sched.getPolicyName()+": "+sched); 196 MemoryArea.stopMem(); 197 } 198 199 /** Run the runnable in an atomic section */ 200 public final static void atomic(Runnable run) { 201 int state = beginAtomic(); 202 run.run(); 203 endAtomic(state); 204 } 205 206 private final void addToRootSet() { 207 if (Math.sqrt(4)==0) { 208 jDisableThread(null, 0); 209 jEnableThread(null, 0); 210 jChooseThread(0); 211 jRemoveCThread(0); 212 jAddCThread(0); 213 jNumThreads(); 214 (new RealtimeThread()).schedule(); 215 (new RealtimeThread()).unschedule(); 216 new NoSuchMethodException(); 217 new NoSuchMethodException(""); 218 print(); 219 } 220 } 221 222 final void addThreadToLists(final RealtimeThread thread) { 223 totalThreads++; 224 MemoryArea.startMem(vt); 225 int state = beginAtomic(); 226 addToFeasibility(thread); 227 addThreadInC(thread, thread.getUID()); 228 addThread(thread); 229 endAtomic(state); 230 MemoryArea.stopMem(); 231 } 232 233 final void removeThreadFromLists(final RealtimeThread thread) { 234 totalThreads--; 235 MemoryArea.startMem(vt); 236 int state = beginAtomic(); 237 removeThread(thread); 238 removeThreadInC(thread); 239 removeFromFeasibility(thread); 240 endAtomic(state); 241 MemoryArea.stopMem(); 242 } 243 244 private final native void addThreadInC(Schedulable t, long threadID); 245 private final native long removeThreadInC(Schedulable t); 246 private final native static int beginAtomic(); 247 private final native static void endAtomic(int state); 248 249 final static void jDisableThread(final RealtimeThread rt, 250 final long threadID) { 251 NoHeapRealtimeThread.print("\njDisableThread("+threadID+")"); 252 disabledThreads++; 253 MemoryArea.startMem(vt); 254 Scheduler sched; 255 if (rt != null) { 256 sched = rt.getScheduler(); 257 } else { 258 sched = getDefaultScheduler(); 259 } 260 if (sched != null) { 261 sched.disableThread(threadID); 262 } else { 263 throw new RuntimeException("\nNo scheduler!!!"); 264 } 265 MemoryArea.stopMem(); 266 } 267 268 final static void jEnableThread(final RealtimeThread rt, 269 final long threadID) { 270 NoHeapRealtimeThread.print("\njEnableThread("+threadID+")"); 271 disabledThreads--; 272 MemoryArea.startMem(vt); 273 Scheduler sched; 274 if (rt != null) { 275 sched = rt.getScheduler(); 276 } else { 277 sched = getDefaultScheduler(); 278 } 279 if (sched != null) { 280 sched.enableThread(threadID); 281 } else { 282 throw new RuntimeException("\nNo scheduler!!!"); 283 } 284 MemoryArea.stopMem(); 285 } 286 287 final static void jAddCThread(final long threadID) { 288 totalThreads++; 289 getDefaultScheduler().addThread(threadID); 290 } 291 292 final static void jRemoveCThread(final long threadID) { 293 totalThreads--; 294 getDefaultScheduler().removeThread(threadID); 295 } 296 297 private static long totalThreads = 0; 298 private static long disabledThreads = 0; 299 300 /** Return the total number of active threads in the system. */ 301 final static long jNumThreads() { 302 NoHeapRealtimeThread.print("\nActive threads: "+(totalThreads-disabledThreads)); 303 return totalThreads-disabledThreads; 304 } 305 306 final protected long jChooseThread(final long currentTime) { 307 MemoryArea.startMem(vt); 308 long temp = chooseThread(currentTime); 309 MemoryArea.stopMem(); 310 return temp; 311 } 312 313 }