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