/* * pth.sched * * A reimplementation of the Pth scheduler in CATAPULTS */ scheduler pth { thread { int priority; int dispatches; int state; } data { threadref current; /* current thread */ threadref next; /* next thread (named yield) */ queue NQ; /* new threads */ pqueue RQ sortable on priority; /* ready threads */ queue WQ; /* waiting for event */ queue SQ; /* suspended */ float loadval; /* scheduler load */ int loadticknext; int loadtickgap; int now = 10; int NEW = 1; int READY = 2; int WAITING = 3; int DEAD = 4; int SUSPENDED = 5; } event init { loadval = 1.0; loadtickgap = 1; loadticknext = now; } event newthread(t) { t.state = NEW; t.priority = 0; t.dispatches = 0; t => NQ; } event schedule { /* Move all new threads to ready queue */ while (|NQ| > 0) NQ => RQ; /* * Update scheduler load; I don't really use this, but Pth tracks * it so I will too. */ if (now - loadticknext >= 0) { float numready; int ttmp; numready = |RQ|; ttmp = now; while(ttmp - loadticknext >= 0) { loadval = numready*0.25 + loadval*0.75; ttmp -= loadtickgap; } } /* Find next thread to run */ if (|next| == 1) next => current; else RQ => current; current.dispatches++; dispatch current; } event switch_out { /* Increase priority of each ready thread */ foreach thr in RQ { thr.priority++; } /* This thread no longer has any priority */ current.priority = 0; /* Did the last thread end? */ if (current.state == DEAD) destroy current; else if (current.state == WAITING) current => WQ; else current => RQ; } event event_raised(t) { t => RQ; } event set_next_thread(t) { t => next; } query threads_new { return |NQ|; } query threads_ready { return |RQ|; } query threads_waiting { return |WQ|; } query threads_suspended { return |SQ|; } query threads_total { return |RQ| + |NQ| + |WQ| + |SQ| + 1; } event set_waiting(fixed tid) { tid.state = WAITING; } event set_dead(fixed tid) { tid.state = DEAD; } query is_new(tid) { return tid.state == NEW; } query is_ready(tid) { return tid.state == READY; } query is_waiting(tid) { return tid.state == WAITING; } query first_waiting { return *WQ; } query can_switch_to(tid) { return (tid.state == NEW || tid.state == READY); } event suspend_thread(tid) { tid.state = SUSPENDED; tid => SQ; } event resume_thread(tid) { tid.state = READY; tid => RQ; } } // vim: filetype=c