#pypp 0 // Iris: micro-kernel for a capability-based operating system. // schedule.ccp: Thread scheduling. // Copyright 2009 Bas Wijnen // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program. If not, see . #include "kernel.hh" static void run_thread (Thread *thread): thread->schedule_next = first_scheduled if thread->schedule_next: thread->schedule_next->schedule_prev = thread first_scheduled = thread static void unrun_thread (Thread *thread): if current == thread: current = thread->schedule_next if thread->schedule_prev: thread->schedule_prev->schedule_next = thread->schedule_next else: first_scheduled = thread->schedule_next if thread->schedule_next: thread->schedule_next->schedule_prev = thread->schedule_prev void Thread::sleep (): schedule_next = first_sleeper if schedule_next: schedule_next->schedule_prev = this schedule_prev = NULL first_sleeper = this void Thread::unsleep (): if schedule_next: schedule_next->schedule_prev = schedule_prev if schedule_prev: schedule_prev->schedule_next = schedule_next else: first_sleeper = schedule_next void Thread::run (): if flags & THREAD_FLAG_RUNNING: return flags |= THREAD_FLAG_RUNNING if flags & THREAD_FLAG_WAITING: if sleep_count != ~0: sleep () return run_thread (this) void Thread::unrun (): if !(flags & THREAD_FLAG_RUNNING): return flags &= ~THREAD_FLAG_RUNNING if flags & THREAD_FLAG_WAITING: if sleep_count != ~0: unsleep () return unrun_thread (this) void Thread::unwait (): if !(flags & THREAD_FLAG_WAITING): return flags &= ~THREAD_FLAG_WAITING if sleep_count != ~0: unsleep () if flags & THREAD_FLAG_RUNNING: run_thread (this) static void sleep_tick (Thread *thread): if !thread->sleep_count: thread->unwait () // Time-out: let the thread know with a special message. Capability::Context c for unsigned i = 0; i < 4; ++i: c.data[i] = 0 c.cap[i] = NULL c.copy[i] = false Thread_arch_receive (thread, ~0, &c) // Fall through to let sleep be set to ~0, so the next wait will be infinitely long again. --thread->sleep_count void Thread::wait (): if flags & THREAD_FLAG_WAITING: return if flags & THREAD_FLAG_RUNNING: unrun_thread (this) flags |= THREAD_FLAG_WAITING if sleep_count != ~0: sleep () // Try to receive a message from a Receiver immediately. for Receiver *r = receivers; r; r = r->next_owned: if r->try_deliver (): return if sleep_count != ~0: sleep_tick (this) void schedule (): Thread *old = current if current: current = current->schedule_next if !current: current = first_scheduled if !current: current = &idle void timer_interrupt (): //panic (0x88877744, "Timer interrupt") Thread *thread, *next for thread = first_sleeper; thread; thread = next: next = thread->next sleep_tick (thread) schedule () //#ifndef NDEBUG //static bool ledstate = false //dbg_led (false, false, ledstate = !ledstate) //#endif