

Public Member Functions | |
| RealTimeScheduler () | |
| virtual void | run () |
| double | start () const |
| virtual void | reset () |
| void | cancel (Event *) |
| void | insert (Event *) |
| Event * | lookup (scheduler_uid_t uid) |
| Event * | deque () |
| const Event * | head () |
| void | schedule (Handler *, Event *, double delay) |
| double | clock () const |
| virtual double | start () |
Static Public Member Functions | |
| Scheduler & | instance () |
Protected Member Functions | |
| void | sync () |
| double | tod () |
| virtual void | reinit (int nbuck, double bwidth, double start) |
| virtual void | resize (int newsize, double start) |
| virtual double | newwidth (int newsize) |
| void | dumpq () |
| void | dispatch (Event *) |
| void | dispatch (Event *, double) |
| int | command (int argc, const char *const *argv) |
Protected Attributes | |
| double | slop_ |
| double | start_ |
| double | width_ |
| double | diff0_ |
| double | diff1_ |
| double | diff2_ |
| int | stat_qsize_ |
| int | nbuckets_ |
| int | lastbucket_ |
| int | top_threshold_ |
| int | bot_threshold_ |
| CalendarScheduler::Bucket * | buckets_ |
| int | qsize_ |
| double | clock_ |
| int | halted_ |
Static Protected Attributes | |
| Scheduler * | instance_ |
| scheduler_uid_t | uid_ = 1 |
|
|
Definition at line 974 of file scheduler.cc. References slop_.
00974 : start_(0.0) 00975 { 00976 bind("maxslop_", &slop_); 00977 } |
|
|
Implements Scheduler. Definition at line 892 of file scheduler.cc. References CalendarScheduler::buckets_, CALENDAR_HASH, CalendarScheduler::Bucket::count_, CalendarScheduler::Bucket::list_, Event::next_, Event::prev_, CalendarScheduler::qsize_, CalendarScheduler::stat_qsize_, Event::time_, and Event::uid_.
00893 {
00894 if (e->uid_ <= 0) // event not in queue
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 }
|
|
|
||||||||||||
|
Definition at line 188 of file scheduler.cc. References at_handler, Scheduler::cancel(), Scheduler::clock(), MemTrace::diff(), Scheduler::dumpq(), Scheduler::halted_, Scheduler::instance_, Scheduler::lookup(), AtEvent::proc_, Scheduler::reset(), Scheduler::run(), Scheduler::schedule(), STRTOUID, Event::uid_, and UID_PRINTF_FORMAT.
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 /* set global to 0 before calling object reset methods */
00196 reset(); // sets clock to zero
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 /*XXX make sure it really is an atevent*/
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 // "at [$ns now]" may not work because of tcl's
00244 // string number resolution
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 /* t < 0 means relative time: delay = -t */
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 }
|
Here is the call graph for this function:

|
|
Implements Scheduler. Definition at line 763 of file scheduler.cc. References CalendarScheduler::bot_threshold_, CalendarScheduler::buckets_, CalendarScheduler::cal_clock_, CalendarScheduler::Bucket::count_, CalendarScheduler::head(), CalendarScheduler::lastbucket_, CalendarScheduler::Bucket::list_, CalendarScheduler::nbuckets_, Event::next_, Event::prev_, CalendarScheduler::qsize_, CalendarScheduler::resize(), CalendarScheduler::stat_qsize_, and Event::time_. Referenced by run().
00764 {
00765 Event *e = const_cast<Event *>(head());
00766
00767 if (!e)
00768 return 0;
00769
00770 int l = lastbucket_;
00771
00772 // update stats and unlink
00773 if (e->next_ == e || e->next_->time_ != e->time_) {
00774 --stat_qsize_;
00775 //assert(stat_qsize_ >= 0);
00776 --buckets_[l].count_;
00777 //assert(buckets_[l].count_ >= 0);
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 //if (buckets_[l].count_ == 0)
00794 // assert(buckets_[l].list_ == 0);
00795
00796 if (stat_qsize_ < bot_threshold_) {
00797 resize(nbuckets_ >> 1, cal_clock_);
00798 }
00799
00800 return e;
00801 }
|
Here is the call graph for this function:

|
||||||||||||
|
Definition at line 140 of file scheduler.cc. References abort(), Scheduler::clock_, Handler::handle(), Event::handler_, and Event::uid_.
|
Here is the call graph for this function:

|
|
Definition at line 153 of file scheduler.cc. References Event::time_. Referenced by run(), and Scheduler::run().
|
|
|
Definition at line 279 of file scheduler.cc. References Scheduler::clock(), Scheduler::deque(), Event::handler_, Event::time_, Event::uid_, and UID_PRINTF_FORMAT. Referenced by Scheduler::command().
|
Here is the call graph for this function:

|
|
Implements Scheduler. Definition at line 701 of file scheduler.cc. References CalendarScheduler::buckets_, CalendarScheduler::cal_clock_, CalendarScheduler::lastbucket_, CalendarScheduler::Bucket::list_, CalendarScheduler::nbuckets_, CalendarScheduler::qsize_, and Event::time_. Referenced by CalendarScheduler::deque(), CalendarScheduler::insert(), CalendarScheduler::insert2(), CalendarScheduler::lookup(), and run().
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 // CAL_DEQUEUE applied successively will find the event to
00727 // dequeue (within one year) and keep track of the
00728 // minimum-priority event seen so far; the argument controls
00729 // the criteria used to decide whether the event should be
00730 // considered `within one year'. Importantly, the number of
00731 // buckets should not be less than 4.
00732 CAL_DEQUEUE(0);
00733 CAL_DEQUEUE(1);
00734 for (; i != lastbucket_dec; ) {
00735 CAL_DEQUEUE(2);
00736 }
00737 // one last bucket is left unchecked - take the minimum
00738 // [could have done CAL_DEQUEUE(3) with diff3_ = bwidth*(nbuck*3/2-1)]
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 //assert(e);
00745 l = i;
00746 }
00747 found_l:
00748 //assert(buckets_[l].count_ >= 0);
00749 //assert(buckets_[l].list_ == e);
00750
00751 /* l is the index of the bucket to dequeue, e is the event */
00752 /*
00753 * still want to advance lastbucket_ and cal_clock_ to save
00754 * time when deque() follows.
00755 */
00756 lastbucket_ = l;
00757 cal_clock_ = e->time_;
00758
00759 return e;
00760 }
|
|
|
Implements Scheduler. Definition at line 594 of file scheduler.cc. References CalendarScheduler::buckets_, CalendarScheduler::cal_clock_, CALENDAR_HASH, CalendarScheduler::head(), CalendarScheduler::lastbucket_, CalendarScheduler::Bucket::list_, CalendarScheduler::nbuckets_, Event::next_, Event::prev_, CalendarScheduler::qsize_, CalendarScheduler::resize(), CalendarScheduler::stat_qsize_, Event::time_, and CalendarScheduler::top_threshold_.
00595 {
00596 int i;
00597 if (cal_clock_ > e->time_) {
00598 // may happen in RT scheduler
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 // insert at the tail
00616 before = head;
00617 newhead = false;
00618 } else {
00619 // insert event in time sorted order, FIFO for sim-time events
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 //assert(e->time_ <= e->next_->time_);
00632 }
00633 //assert(e->prev_ != e);
00634 if (e->prev_->time_ != e->time_) {
00635 // unique timing
00636 ++stat_qsize_;
00637 ++buckets_[i].count_;
00638 }
00639 }
00640 ++qsize_;
00641 //assert(e == buckets_[i].list_ || e->prev_->time_ <= e->time_);
00642 //assert(e == buckets_[i].list_->prev_ || e->next_->time_ >= e->time_);
00643
00644 if (stat_qsize_ > top_threshold_) {
00645 resize(nbuckets_ << 1, cal_clock_);
00646 return;
00647 }
00648 }
|
Here is the call graph for this function:

|
|
|
Implements Scheduler. Definition at line 933 of file scheduler.cc. References CalendarScheduler::buckets_, CalendarScheduler::head(), CalendarScheduler::Bucket::list_, CalendarScheduler::nbuckets_, Event::next_, and Event::uid_.
|
Here is the call graph for this function:

|
|
Definition at line 862 of file scheduler.cc. References CalendarScheduler::buckets_, CalendarScheduler::Bucket::count_, CalendarScheduler::nbuckets_, and CalendarScheduler::width_. Referenced by CalendarScheduler::resize().
00863 {
00864 int i;
00865 short max_bucket = 0; // index of the fullest bucket
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); // min (newsize, nsamples)
00879 nw *= 4.0;
00880
00881 return nw;
00882 }
|
|
||||||||||||||||
|
Definition at line 804 of file scheduler.cc. References CalendarScheduler::bot_threshold_, CalendarScheduler::buckets_, CALENDAR_HASH, CalendarScheduler::diff0_, CalendarScheduler::diff1_, CalendarScheduler::diff2_, CalendarScheduler::lastbucket_, CalendarScheduler::nbuckets_, CalendarScheduler::qsize_, CalendarScheduler::stat_qsize_, CalendarScheduler::top_threshold_, and CalendarScheduler::width_. Referenced by CalendarScheduler::CalendarScheduler(), and CalendarScheduler::resize().
00805 {
00806 buckets_ = new Bucket[nbuck];
00807
00808 memset(buckets_, 0, sizeof(Bucket)*nbuck); //faster than ctor
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 //diff3_ = bwidth*(nbuck*3/2-1);
00821
00822 bot_threshold_ = (nbuck >> 1) - 2;
00823 top_threshold_ = (nbuck << 1);
00824 }
|
|
|
Reimplemented from Scheduler. Definition at line 990 of file scheduler.cc. References Scheduler::clock_, SCHED_START, start_, and tod().
00991 {
00992 clock_ = SCHED_START;
00993 start_ = tod();
00994 }
|
Here is the call graph for this function:

|
||||||||||||
|
Definition at line 827 of file scheduler.cc. References CalendarScheduler::buckets_, CalendarScheduler::insert2(), CalendarScheduler::Bucket::list_, CalendarScheduler::nbuckets_, CalendarScheduler::newwidth(), Event::next_, Event::prev_, and CalendarScheduler::reinit(). Referenced by CalendarScheduler::deque(), and CalendarScheduler::insert().
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 // copy events to new buckets
00840 int i;
00841
00842 for (i = 0; i < oldn; ++i) {
00843 // we can do inserts faster, if we use insert2, but to
00844 // preserve FIFO, we have to start from the end of
00845 // each bucket and use insert2
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 }
|
Here is the call graph for this function:

|
|
Reimplemented from Scheduler. Definition at line 997 of file scheduler.cc. References Scheduler::clock_, CalendarScheduler::deque(), Scheduler::dispatch(), Scheduler::halted_, CalendarScheduler::head(), Scheduler::instance_, slop_, Event::time_, and tod().
00998 {
00999 static const double RTSCHEDULER_MINWAIT = 1.0e-3; // don't wait for less
01000 const Event *p;
01001
01002 /*XXX*/
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 // handle "old events"
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 // blocking wait for TCL events
01026 Tcl_WaitForEvent(0); // no sim events, wait forever
01027 clock_ = tod();
01028 } else {
01029 double diff = p->time_ - clock_;
01030 // blocking wait only if there is enough time
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); // block
01036 clock_ = tod();
01037 }
01038 }
01039 Tcl_DoOneEvent(TCL_DONT_WAIT);
01040 }
01041 // we reach here only if halted
01042 }
|
Here is the call graph for this function:

|
||||||||||||||||
Here is the call graph for this function:

|
|
Definition at line 94 of file scheduler.h. References SCHED_START.
00094 { // start time
00095 return SCHED_START;
00096 }
|
|
|
Definition at line 957 of file scheduler.cc. References start_.
00957 { return start_; }
|
|
|
Reimplemented from Scheduler. Definition at line 960 of file scheduler.cc. References Scheduler::clock_, and tod().
|
Here is the call graph for this function:

|
|
Definition at line 980 of file scheduler.cc. References start_. Referenced by reset(), run(), and sync().
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 }
|
|
|
Definition at line 163 of file scheduler.h. Referenced by CalendarScheduler::deque(), and CalendarScheduler::reinit(). |
|
|
|
Definition at line 105 of file scheduler.h. Referenced by Scheduler::clock(), Scheduler::dispatch(), reset(), Scheduler::reset(), run(), Scheduler::schedule(), and sync(). |
|
|
Definition at line 157 of file scheduler.h. Referenced by CalendarScheduler::reinit(). |
|
|
Definition at line 157 of file scheduler.h. Referenced by CalendarScheduler::reinit(). |
|
|
Definition at line 157 of file scheduler.h. Referenced by CalendarScheduler::reinit(). |
|
|
Definition at line 106 of file scheduler.h. Referenced by Scheduler::command(), run(), and Scheduler::run(). |
|
|
Definition at line 55 of file scheduler.cc. Referenced by Scheduler::command(), run(), Scheduler::run(), and Scheduler::~Scheduler(). |
|
|
Definition at line 161 of file scheduler.h. Referenced by CalendarScheduler::deque(), CalendarScheduler::head(), CalendarScheduler::insert(), and CalendarScheduler::reinit(). |
|
|
Definition at line 160 of file scheduler.h. Referenced by CalendarScheduler::deque(), CalendarScheduler::head(), CalendarScheduler::insert(), CalendarScheduler::lookup(), CalendarScheduler::newwidth(), CalendarScheduler::reinit(), and CalendarScheduler::resize(). |
|
|
Definition at line 170 of file scheduler.h. Referenced by CalendarScheduler::cancel(), CalendarScheduler::deque(), CalendarScheduler::head(), CalendarScheduler::insert(), CalendarScheduler::insert2(), CalendarScheduler::reinit(), and CalendarScheduler::~CalendarScheduler(). |
|
|
Definition at line 962 of file scheduler.cc. Referenced by RealTimeScheduler(), and run(). |
|
|
Definition at line 963 of file scheduler.cc. |
|
|
Definition at line 159 of file scheduler.h. Referenced by CalendarScheduler::cancel(), CalendarScheduler::deque(), CalendarScheduler::insert(), CalendarScheduler::insert2(), CalendarScheduler::reinit(), and CalendarScheduler::~CalendarScheduler(). |
|
|
Definition at line 162 of file scheduler.h. Referenced by CalendarScheduler::insert(), and CalendarScheduler::reinit(). |
|
|
Definition at line 56 of file scheduler.cc. Referenced by Scheduler::schedule(). |
|
|
Definition at line 156 of file scheduler.h. Referenced by CalendarScheduler::newwidth(), and CalendarScheduler::reinit(). |
1.3.3