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 }