00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037 #ifndef lint
00038 static const char rcsid[] =
00039 "@(#) $Header: /nfs/jade/vint/CVSROOT/ns-2/common/scheduler.cc,v 1.70 2002/08/02 01:35:20 yuri Exp $ (LBL)";
00040 #endif
00041
00042 #include <stdlib.h>
00043 #include <limits.h>
00044 #include <math.h>
00045
00046 #include "config.h"
00047 #include "scheduler.h"
00048 #include "packet.h"
00049
00050
00051 #ifdef MEMDEBUG_SIMULATIONS
00052 #include "mem-trace.h"
00053 #endif
00054
00055 Scheduler* Scheduler::instance_;
00056 scheduler_uid_t Scheduler::uid_ = 1;
00057
00058
00059
00060
00061
00062
00063 Scheduler::Scheduler() : clock_(SCHED_START), halted_(0)
00064 {
00065 }
00066
00067 Scheduler::~Scheduler(){
00068 instance_ = NULL ;
00069 }
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082 void
00083 Scheduler::schedule(Handler* h, Event* e, double delay)
00084 {
00085
00086 if (!h) {
00087 fprintf(stderr,
00088 "Scheduler: attempt to schedule an event with a NULL handler."
00089 " Don't DO that.\n");
00090 abort();
00091 };
00092 if (e->uid_ > 0) {
00093 printf("Scheduler: Event UID not valid!\n\n");
00094 abort();
00095 }
00096
00097 if (delay < 0) {
00098
00099
00100 fprintf(stderr,
00101 "warning: ns Scheduler::schedule: scheduling event\n\t"
00102 "with negative delay (%f) at time %f.\n", delay, clock_);
00103 }
00104
00105 if (uid_ < 0) {
00106 fprintf(stderr, "Scheduler: UID space exhausted!\n");
00107 abort();
00108 }
00109 e->uid_ = uid_++;
00110 e->handler_ = h;
00111 double t = clock_ + delay;
00112
00113 e->time_ = t;
00114 insert(e);
00115 }
00116
00117 void
00118 Scheduler::run()
00119 {
00120 instance_ = this;
00121 Event *p;
00122
00123
00124
00125
00126
00127 while (!halted_ && (p = deque())) {
00128 dispatch(p, p->time_);
00129 }
00130 }
00131
00132
00133
00134
00135
00136
00137
00138
00139 void
00140 Scheduler::dispatch(Event* p, double t)
00141 {
00142 if (t < clock_) {
00143 fprintf(stderr, "ns: scheduler going backwards in time from %f to %f.\n", clock_, t);
00144 abort();
00145 }
00146
00147 clock_ = t;
00148 p->uid_ = -p->uid_;
00149 p->handler_->handle(p);
00150 }
00151
00152 void
00153 Scheduler::dispatch(Event* p)
00154 {
00155 dispatch(p, p->time_);
00156 }
00157
00158 class AtEvent : public Event {
00159 public:
00160 AtEvent() : proc_(0) {
00161 }
00162 ~AtEvent() {
00163 if (proc_) delete [] proc_;
00164 }
00165 char* proc_;
00166 };
00167
00168 class AtHandler : public Handler {
00169 public:
00170 void handle(Event* event);
00171 } at_handler;
00172
00173 void
00174 AtHandler::handle(Event* e)
00175 {
00176 AtEvent* at = (AtEvent*)e;
00177 Tcl::instance().eval(at->proc_);
00178 delete at;
00179 }
00180
00181 void
00182 Scheduler::reset()
00183 {
00184 clock_ = SCHED_START;
00185 }
00186
00187 int
00188 Scheduler::command(int argc, const char*const* argv)
00189 {
00190 Tcl& tcl = Tcl::instance();
00191 if (instance_ == 0)
00192 instance_ = this;
00193 if (argc == 2) {
00194 if (strcmp(argv[1], "run") == 0) {
00195
00196 reset();
00197 run();
00198 return (TCL_OK);
00199 } else if (strcmp(argv[1], "now") == 0) {
00200 sprintf(tcl.buffer(), "%.17g", clock());
00201 tcl.result(tcl.buffer());
00202 return (TCL_OK);
00203 } else if (strcmp(argv[1], "resume") == 0) {
00204 halted_ = 0;
00205 run();
00206 return (TCL_OK);
00207 } else if (strcmp(argv[1], "halt") == 0) {
00208 halted_ = 1;
00209 return (TCL_OK);
00210
00211 } else if (strcmp(argv[1], "clearMemTrace") == 0) {
00212 #ifdef MEMDEBUG_SIMULATIONS
00213 extern MemTrace *globalMemTrace;
00214 if (globalMemTrace)
00215 globalMemTrace->diff("Sim.");
00216 #endif
00217 return (TCL_OK);
00218 } else if (strcmp(argv[1], "is-running") == 0) {
00219 sprintf(tcl.buffer(), "%d", !halted_);
00220 return (TCL_OK);
00221 } else if (strcmp(argv[1], "dumpq") == 0) {
00222 if (!halted_) {
00223 fprintf(stderr, "Scheduler: dumpq only allowed while halted\n");
00224 tcl.result("0");
00225 return (TCL_ERROR);
00226 }
00227 dumpq();
00228 return (TCL_OK);
00229 }
00230 } else if (argc == 3) {
00231 if (strcmp(argv[1], "at") == 0 ||
00232 strcmp(argv[1], "cancel") == 0) {
00233 Event* p = lookup(STRTOUID(argv[2]));
00234 if (p != 0) {
00235
00236 cancel(p);
00237 AtEvent* ae = (AtEvent*)p;
00238 delete ae;
00239 }
00240 } else if (strcmp(argv[1], "at-now") == 0) {
00241 const char* proc = argv[2];
00242
00243
00244
00245 AtEvent* e = new AtEvent;
00246 int n = strlen(proc);
00247 e->proc_ = new char[n + 1];
00248 strcpy(e->proc_, proc);
00249 schedule(&at_handler, e, 0);
00250 sprintf(tcl.buffer(), UID_PRINTF_FORMAT, e->uid_);
00251 tcl.result(tcl.buffer());
00252 }
00253 return (TCL_OK);
00254 } else if (argc == 4) {
00255 if (strcmp(argv[1], "at") == 0) {
00256
00257 double delay, t = atof(argv[2]);
00258 const char* proc = argv[3];
00259
00260 AtEvent* e = new AtEvent;
00261 int n = strlen(proc);
00262 e->proc_ = new char[n + 1];
00263 strcpy(e->proc_, proc);
00264 delay = (t < 0) ? -t : t - clock();
00265 if (delay < 0) {
00266 tcl.result("can't schedule command in past");
00267 return (TCL_ERROR);
00268 }
00269 schedule(&at_handler, e, delay);
00270 sprintf(tcl.buffer(), UID_PRINTF_FORMAT, e->uid_);
00271 tcl.result(tcl.buffer());
00272 return (TCL_OK);
00273 }
00274 }
00275 return (TclObject::command(argc, argv));
00276 }
00277
00278 void
00279 Scheduler::dumpq()
00280 {
00281 Event *p;
00282
00283 printf("Contents of scheduler queue (events) [cur time: %f]---\n",
00284 clock());
00285 while ((p = deque()) != NULL) {
00286 printf("t:%f uid: ", p->time_);
00287 printf(UID_PRINTF_FORMAT, p->uid_);
00288 printf(" handler: %p\n", p->handler_);
00289 }
00290 }
00291
00292 static class ListSchedulerClass : public TclClass {
00293 public:
00294 ListSchedulerClass() : TclClass("Scheduler/List") {}
00295 TclObject* create(int , const char*const* ) {
00296 return (new ListScheduler);
00297 }
00298 } class_list_sched;
00299
00300 void
00301 ListScheduler::insert(Event* e)
00302 {
00303 double t = e->time_;
00304 Event** p;
00305 for (p = &queue_; *p != 0; p = &(*p)->next_)
00306 if (t < (*p)->time_)
00307 break;
00308 e->next_ = *p;
00309 *p = e;
00310 }
00311
00312
00313
00314
00315
00316
00317
00318 void
00319 ListScheduler::cancel(Event* e)
00320 {
00321 Event** p;
00322 if (e->uid_ <= 0)
00323 return;
00324 for (p = &queue_; *p != e; p = &(*p)->next_)
00325 if (*p == 0)
00326 abort();
00327
00328 *p = (*p)->next_;
00329 e->uid_ = - e->uid_;
00330 }
00331
00332 Event*
00333 ListScheduler::lookup(scheduler_uid_t uid)
00334 {
00335 Event* e;
00336 for (e = queue_; e != 0; e = e->next_)
00337 if (e->uid_ == uid)
00338 break;
00339 return (e);
00340 }
00341
00342
00343 Event*
00344 ListScheduler::deque()
00345 {
00346 Event* e = queue_;
00347 if (e)
00348 queue_ = e->next_;
00349 return (e);
00350 }
00351
00352 #include "heap.h"
00353
00354 Heap::Heap(int size)
00355 : h_s_key(0), h_size(0), h_maxsize(size), h_iter(0)
00356 {
00357 h_elems = new Heap_elem[h_maxsize];
00358 memset(h_elems, 0, h_maxsize*sizeof(Heap_elem));
00359
00360
00361 }
00362
00363 Heap::~Heap()
00364 {
00365 delete [] h_elems;
00366 }
00367
00368
00369
00370
00371
00372
00373
00374
00375
00376
00377 int
00378 Heap::heap_member(void* elem)
00379 {
00380 unsigned int i;
00381 Heap::Heap_elem* he;
00382 for (i = 0, he = h_elems; i < h_size; i++, he++)
00383 if (he->he_elem == elem)
00384 return ++i;
00385 return 0;
00386 }
00387
00388
00389
00390
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401
00402
00403
00404
00405
00406
00407
00408
00409
00410 int
00411 Heap::heap_delete(void* elem)
00412 {
00413 int i;
00414 if ((i = heap_member(elem)) == 0)
00415 return 0;
00416 for (--i; i; i = parent(i)) {
00417 swap(i, parent(i));
00418 }
00419 (void) heap_extract_min();
00420 return 1;
00421 }
00422
00423
00424
00425
00426
00427
00428
00429
00430
00431
00432
00433
00434
00435
00436 void
00437 Heap::heap_insert(heap_key_t key, void* elem)
00438 {
00439 unsigned int i, par;
00440 if (h_maxsize == h_size) {
00441 unsigned int osize = h_maxsize;
00442 Heap::Heap_elem *he_old = h_elems;
00443 h_maxsize *= 2;
00444 h_elems = new Heap::Heap_elem[h_maxsize];
00445 memcpy(h_elems, he_old, osize*sizeof(Heap::Heap_elem));
00446 delete []he_old;
00447 }
00448
00449 i = h_size++;
00450 par = parent(i);
00451 while ((i > 0) &&
00452 (KEY_LESS_THAN(key, h_s_key,
00453 h_elems[par].he_key, h_elems[par].he_s_key))) {
00454 h_elems[i] = h_elems[par];
00455 i = par;
00456 par = parent(i);
00457 }
00458 h_elems[i].he_key = key;
00459 h_elems[i].he_s_key= h_s_key++;
00460 h_elems[i].he_elem = elem;
00461 return;
00462 };
00463
00464
00465
00466
00467
00468
00469
00470
00471
00472
00473
00474
00475
00476
00477
00478
00479
00480
00481
00482
00483
00484
00485
00486
00487
00488
00489
00490
00491
00492
00493
00494
00495
00496 void*
00497 Heap::heap_extract_min()
00498 {
00499 void* min;
00500 unsigned int i;
00501 unsigned int l, r, x;
00502
00503 if (h_size == 0)
00504 return 0;
00505 min = h_elems[0].he_elem;
00506 h_elems[0] = h_elems[--h_size];
00507
00508 i = 0;
00509 while (i < h_size) {
00510 l = left(i);
00511 r = right(i);
00512 if (r < h_size) {
00513 if (KEY_LESS_THAN(h_elems[l].he_key, h_elems[l].he_s_key,
00514 h_elems[r].he_key, h_elems[r].he_s_key))
00515 x= l;
00516 else
00517 x= r;
00518 } else
00519 x = (l < h_size ? l : i);
00520 if ((x != i) &&
00521 (KEY_LESS_THAN(h_elems[x].he_key, h_elems[x].he_s_key,
00522 h_elems[i].he_key, h_elems[i].he_s_key))) {
00523 swap(i, x);
00524 i = x;
00525 } else {
00526 break;
00527 }
00528 }
00529 return min;
00530 }
00531
00532
00533 static class HeapSchedulerClass : public TclClass {
00534 public:
00535 HeapSchedulerClass() : TclClass("Scheduler/Heap") {}
00536 TclObject* create(int , const char*const* ) {
00537 return (new HeapScheduler);
00538 }
00539 } class_heap_sched;
00540
00541 Event*
00542 HeapScheduler::lookup(scheduler_uid_t uid)
00543 {
00544 Event* e;
00545
00546 for (e = (Event*) hp_->heap_iter_init(); e;
00547 e = (Event*) hp_->heap_iter())
00548 if (e->uid_ == uid)
00549 break;
00550 return e;
00551 }
00552
00553 Event*
00554 HeapScheduler::deque()
00555 {
00556 return ((Event*) hp_->heap_extract_min());
00557 }
00558
00559
00560
00561
00562
00563
00564
00565
00566
00567
00568
00569
00570
00571
00572 #define CALENDAR_HASH(t) ((int)fmod((t)/width_, nbuckets_))
00573
00574 static class CalendarSchedulerClass : public TclClass {
00575 public:
00576 CalendarSchedulerClass() : TclClass("Scheduler/Calendar") {}
00577 TclObject* create(int , const char*const* ) {
00578 return (new CalendarScheduler);
00579 }
00580 } class_calendar_sched;
00581
00582 CalendarScheduler::CalendarScheduler() : cal_clock_(clock_) {
00583 reinit(4, 1.0, cal_clock_);
00584 }
00585
00586 CalendarScheduler::~CalendarScheduler() {
00587
00588 delete [] buckets_;
00589 qsize_ = 0;
00590 stat_qsize_ = 0;
00591 }
00592
00593 void
00594 CalendarScheduler::insert(Event* e)
00595 {
00596 int i;
00597 if (cal_clock_ > e->time_) {
00598
00599 cal_clock_ = e->time_;
00600 i = lastbucket_ = CALENDAR_HASH(cal_clock_);
00601 } else
00602 i = CALENDAR_HASH(e->time_);
00603
00604 Event *head = buckets_[i].list_;
00605 Event *before=0;
00606
00607 if (!head) {
00608 buckets_[i].list_ = e;
00609 e->next_ = e->prev_ = e;
00610 ++stat_qsize_;
00611 ++buckets_[i].count_;
00612 } else {
00613 bool newhead;
00614 if (e->time_ >= head->prev_->time_) {
00615
00616 before = head;
00617 newhead = false;
00618 } else {
00619
00620 for (before = head; e->time_ >= before->time_; before = before->next_)
00621 ;
00622 newhead = (before == head);
00623 }
00624
00625 e->next_ = before;
00626 e->prev_ = before->prev_;
00627 before->prev_ = e;
00628 e->prev_->next_ = e;
00629 if (newhead) {
00630 buckets_[i].list_ = e;
00631
00632 }
00633
00634 if (e->prev_->time_ != e->time_) {
00635
00636 ++stat_qsize_;
00637 ++buckets_[i].count_;
00638 }
00639 }
00640 ++qsize_;
00641
00642
00643
00644 if (stat_qsize_ > top_threshold_) {
00645 resize(nbuckets_ << 1, cal_clock_);
00646 return;
00647 }
00648 }
00649
00650 void
00651 CalendarScheduler::insert2(Event* e)
00652 {
00653
00654
00655
00656
00657 int i = CALENDAR_HASH(e->time_);
00658 Event *head = buckets_[i].list_;
00659 Event *before=0;
00660 if (!head) {
00661 buckets_[i].list_ = e;
00662 e->next_ = e->prev_ = e;
00663 ++stat_qsize_;
00664 ++buckets_[i].count_;
00665 } else {
00666 bool newhead;
00667 if (e->time_ > head->prev_->time_) {
00668
00669 before = head;
00670 newhead = false;
00671 } else {
00672
00673 for (before = head; e->time_ > before->time_; before = before->next_)
00674 ;
00675 newhead = (before == head);
00676 }
00677
00678 e->next_ = before;
00679 e->prev_ = before->prev_;
00680 before->prev_ = e;
00681 e->prev_->next_ = e;
00682 if (newhead) {
00683 buckets_[i].list_ = e;
00684
00685 }
00686
00687 if (e != e->next_ && e->next_->time_ != e->time_) {
00688
00689 ++stat_qsize_;
00690 ++buckets_[i].count_;
00691 }
00692 }
00693
00694
00695
00696 ++qsize_;
00697
00698 }
00699
00700 const Event*
00701 CalendarScheduler::head()
00702 {
00703 if (qsize_ == 0)
00704 return NULL;
00705
00706 int l, i = lastbucket_;
00707 int lastbucket_dec = (lastbucket_) ? lastbucket_ - 1 : nbuckets_ - 1;
00708 double diff;
00709 Event *e, *min_e = NULL;
00710 #define CAL_DEQUEUE(x) \
00711 do { \
00712 if ((e = buckets_[i].list_) != NULL) { \
00713 diff = e->time_ - cal_clock_; \
00714 if (diff < diff##x##_) { \
00715 l = i; \
00716 goto found_l; \
00717 } \
00718 if (min_e == NULL || min_e->time_ > e->time_) { \
00719 min_e = e; \
00720 l = i; \
00721 } \
00722 } \
00723 if (++i == nbuckets_) i = 0; \
00724 } while (0)
00725
00726
00727
00728
00729
00730
00731
00732 CAL_DEQUEUE(0);
00733 CAL_DEQUEUE(1);
00734 for (; i != lastbucket_dec; ) {
00735 CAL_DEQUEUE(2);
00736 }
00737
00738
00739 e = buckets_[i].list_;
00740 if (min_e != NULL &&
00741 (e == NULL || min_e->time_ < e->time_))
00742 e = min_e;
00743 else {
00744
00745 l = i;
00746 }
00747 found_l:
00748
00749
00750
00751
00752
00753
00754
00755
00756 lastbucket_ = l;
00757 cal_clock_ = e->time_;
00758
00759 return e;
00760 }
00761
00762 Event*
00763 CalendarScheduler::deque()
00764 {
00765 Event *e = const_cast<Event *>(head());
00766
00767 if (!e)
00768 return 0;
00769
00770 int l = lastbucket_;
00771
00772
00773 if (e->next_ == e || e->next_->time_ != e->time_) {
00774 --stat_qsize_;
00775
00776 --buckets_[l].count_;
00777
00778
00779 }
00780 --qsize_;
00781
00782 if (e->next_ == e)
00783 buckets_[l].list_ = 0;
00784 else {
00785 e->next_->prev_ = e->prev_;
00786 e->prev_->next_ = e->next_;
00787 buckets_[l].list_ = e->next_;
00788 }
00789
00790 e->next_ = e->prev_ = NULL;
00791
00792
00793
00794
00795
00796 if (stat_qsize_ < bot_threshold_) {
00797 resize(nbuckets_ >> 1, cal_clock_);
00798 }
00799
00800 return e;
00801 }
00802
00803 void
00804 CalendarScheduler::reinit(int nbuck, double bwidth, double start)
00805 {
00806 buckets_ = new Bucket[nbuck];
00807
00808 memset(buckets_, 0, sizeof(Bucket)*nbuck);
00809
00810 width_ = bwidth;
00811 nbuckets_ = nbuck;
00812 qsize_ = 0;
00813 stat_qsize_ = 0;
00814
00815 lastbucket_ = CALENDAR_HASH(start);
00816
00817 diff0_ = bwidth*nbuck/2;
00818 diff1_ = diff0_ + bwidth;
00819 diff2_ = bwidth*nbuck;
00820
00821
00822 bot_threshold_ = (nbuck >> 1) - 2;
00823 top_threshold_ = (nbuck << 1);
00824 }
00825
00826 void
00827 CalendarScheduler::resize(int newsize, double start)
00828 {
00829 double bwidth = newwidth(newsize);
00830
00831 if (newsize < 4)
00832 newsize = 4;
00833
00834 Bucket *oldb = buckets_;
00835 int oldn = nbuckets_;
00836
00837 reinit(newsize, bwidth, start);
00838
00839
00840 int i;
00841
00842 for (i = 0; i < oldn; ++i) {
00843
00844
00845
00846 if (oldb[i].list_) {
00847 Event *tail = oldb[i].list_->prev_;
00848 Event *e = tail;
00849 do {
00850 Event* ep = e->prev_;
00851 e->next_ = e->prev_ = 0;
00852 insert2(e);
00853 e = ep;
00854 } while (e != tail);
00855 }
00856 }
00857 delete [] oldb;
00858 }
00859
00860
00861 double
00862 CalendarScheduler::newwidth(int newsize)
00863 {
00864 int i;
00865 short max_bucket = 0;
00866 for (i = 1; i < nbuckets_; ++i) {
00867 if (buckets_[i].count_ > buckets_[max_bucket].count_)
00868 max_bucket = i;
00869 }
00870 int nsamples = buckets_[max_bucket].count_;
00871
00872 if (nsamples <= 4) return width_;
00873
00874 double nw = buckets_[max_bucket].list_->prev_->time_
00875 - buckets_[max_bucket].list_->time_;
00876 assert(nw > 0);
00877
00878 nw /= ((newsize < nsamples) ? newsize : nsamples);
00879 nw *= 4.0;
00880
00881 return nw;
00882 }
00883
00884
00885
00886
00887
00888
00889
00890
00891 void
00892 CalendarScheduler::cancel(Event* e)
00893 {
00894 if (e->uid_ <= 0)
00895 return;
00896
00897 int i = CALENDAR_HASH(e->time_);
00898
00899 assert(e->prev_->next_ == e);
00900 assert(e->next_->prev_ == e);
00901
00902 if (e->next_ == e ||
00903 (e->next_->time_ != e->time_ &&
00904 (e->prev_->time_ != e->time_))) {
00905 --stat_qsize_;
00906 assert(stat_qsize_ >= 0);
00907 --buckets_[i].count_;
00908 assert(buckets_[i].count_ >= 0);
00909 }
00910
00911 if (e->next_ == e) {
00912 assert(buckets_[i].list_ == e);
00913 buckets_[i].list_ = 0;
00914 } else {
00915 e->next_->prev_ = e->prev_;
00916 e->prev_->next_ = e->next_;
00917 if (buckets_[i].list_ == e)
00918 buckets_[i].list_ = e->next_;
00919 }
00920
00921 if (buckets_[i].count_ == 0)
00922 assert(buckets_[i].list_ == 0);
00923
00924 e->uid_ = -e->uid_;
00925 e->next_ = e->prev_ = NULL;
00926
00927 --qsize_;
00928
00929 return;
00930 }
00931
00932 Event *
00933 CalendarScheduler::lookup(scheduler_uid_t uid)
00934 {
00935 for (int i = 0; i < nbuckets_; i++) {
00936 Event* head = buckets_[i].list_;
00937 Event* p = head;
00938 if (p) {
00939 do {
00940 if (p->uid_== uid)
00941 return p;
00942 p = p->next_;
00943 } while (p != head);
00944 }
00945 }
00946 return NULL;
00947 }
00948
00949 #ifndef WIN32
00950 #include <sys/time.h>
00951 #endif
00952
00953 class RealTimeScheduler : public CalendarScheduler {
00954 public:
00955 RealTimeScheduler();
00956 virtual void run();
00957 double start() const { return start_; }
00958 virtual void reset();
00959 protected:
00960 void sync() { clock_ = tod(); }
00961 double tod();
00962 double slop_;
00963 double start_;
00964 };
00965
00966 static class RealTimeSchedulerClass : public TclClass {
00967 public:
00968 RealTimeSchedulerClass() : TclClass("Scheduler/RealTime") {}
00969 TclObject* create(int , const char*const* ) {
00970 return (new RealTimeScheduler);
00971 }
00972 } class_realtime_sched;
00973
00974 RealTimeScheduler::RealTimeScheduler() : start_(0.0)
00975 {
00976 bind("maxslop_", &slop_);
00977 }
00978
00979 double
00980 RealTimeScheduler::tod()
00981 {
00982 timeval tv;
00983 gettimeofday(&tv, 0);
00984 double s = tv.tv_sec;
00985 s += (1e-6 * tv.tv_usec);
00986 return (s - start_);
00987 }
00988
00989 void
00990 RealTimeScheduler::reset()
00991 {
00992 clock_ = SCHED_START;
00993 start_ = tod();
00994 }
00995
00996 void
00997 RealTimeScheduler::run()
00998 {
00999 static const double RTSCHEDULER_MINWAIT = 1.0e-3;
01000 const Event *p;
01001
01002
01003 instance_ = this;
01004
01005 while (!halted_) {
01006 clock_ = tod();
01007 p = head();
01008 if (p && (clock_ - p->time_) > slop_) {
01009 fprintf(stderr,
01010 "RealTimeScheduler: warning: slop "
01011 "%f exceeded limit %f [clock_:%f, p->time_:%f]\n",
01012 clock_ - p->time_, slop_, clock_, p->time_);
01013 }
01014
01015 while (p && p->time_ <= clock_) {
01016
01017 dispatch(deque(), clock_);
01018 if (halted_)
01019 return;
01020 p = head();
01021 clock_ = tod();
01022 }
01023
01024 if (!p) {
01025
01026 Tcl_WaitForEvent(0);
01027 clock_ = tod();
01028 } else {
01029 double diff = p->time_ - clock_;
01030
01031 if (diff > RTSCHEDULER_MINWAIT) {
01032 Tcl_Time to;
01033 to.sec = long(diff);
01034 to.usec = long(1e6*(diff - to.sec));
01035 Tcl_WaitForEvent(&to);
01036 clock_ = tod();
01037 }
01038 }
01039 Tcl_DoOneEvent(TCL_DONT_WAIT);
01040 }
01041
01042 }