/* * random.sched * * A very simple, random-order scheduler. */ scheduler random { thread { int state; int index; /* where in the array are you? */ } data { const int RLSIZE = 100; threadref current; /* current thread */ threadref next; /* next thread (named yield) */ threadref RL[RLSIZE]; /* ready list */ queue WQ; /* waiting for event */ queue SQ; /* suspended */ int numready; const int NEW = 1; const int READY = 2; const int WAITING = 3; const int DEAD = 4; const int SUSPENDED = 5; } event init { numready = 0; {* srand(time(NULL)); fprintf(stderr, "Initializing 'random' scheduler.\n"); *} } event newthread(t) { t.state = NEW; t.index = numready; t => RL[numready]; numready++; } event schedule { int idx; threadref tmp; /* Find next thread to run */ if (|next| == 1) { next => current; } else { idx = (* rand() % numready *); // {* fprintf(stderr, "Scheduling thread #%d\n", idx); *} RL[idx].index = -1; RL[idx] => current; numready--; /* If we made a hole, plug it by moving up the last element */ if (numready != idx) { RL[numready] => RL[idx]; RL[idx].index = idx; } } dispatch current; } event switch_out { /* Did the last thread end? */ if (current.state == DEAD) destroy current; else if (current.state == WAITING) current => WQ; else { current.index = numready; current => RL[numready]; numready++; } } event event_raised(t) { t.index = numready; t => RL[numready]; numready++; } event set_next_thread(t) { int idx = t.index; t.index = -1; t => next; numready--; /* If we created a hole, plug it by moving up the last element */ if (idx != numready) { RL[numready] => RL[idx]; RL[idx].index = idx; } } query threads_new { return 0; } query threads_ready { return numready; } query threads_waiting { return |WQ|; } query threads_suspended { return |SQ|; } query threads_total { return numready + |next| + |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) { if (tid.state == READY || tid.state == NEW) { numready--; /* If we made a hole, move the last element up to plug it */ if (numready != tid.index) { RL[numready] => RL[tid.index]; RL[tid.index].index = tid.index; } } tid.index = -1; tid.state = SUSPENDED; tid => SQ; } event resume_thread(tid) { tid.state = READY; tid.index = numready; tid => RL[numready]; numready++; } } /* * vim: filetype=c */