#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 (kThread *thread): thread->schedule_next = first_scheduled if thread->schedule_next: thread->schedule_next->schedule_prev = thread thread->schedule_prev = NULL first_scheduled = thread static void unrun_thread (kThread *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 kThread::run (): if flags & Kernel::Thread::RUNNING: return flags |= Kernel::Thread::RUNNING if is_waiting (): return run_thread (this) void kThread::unrun (): if !(flags & Kernel::Thread::RUNNING): return flags &= ~Kernel::Thread::RUNNING if is_waiting (): return unrun_thread (this) void kThread::unwait (): flags &= ~Kernel::Thread::WAITING if flags & Kernel::Thread::RUNNING: run_thread (this) static void alarm_tick (kReceiver *recv): if !recv->alarm_count: // Send message and stop counting. kCapability::Context c for unsigned i = 0; i < 2; ++i: c.data[i] = 0 recv->send_message (~0, &c) if recv->prev_alarm: recv->prev_alarm->next_alarm = recv->next_alarm else: first_alarm = recv->next_alarm if recv->next_alarm: recv->next_alarm->prev_alarm = recv->prev_alarm // Fall through to let alarm_count be ~0. This is required, because it is the indicator for no running alarm. --recv->alarm_count void kThread::wait (): if flags & Kernel::Thread::RUNNING: unrun_thread (this) flags |= Kernel::Thread::WAITING // Try to receive a message from a kReceiver immediately. for kReceiver *r = receivers; r; r = r->next_owned: if r->try_deliver (): return void schedule (): if current: current = current->schedule_next if !current: current = first_scheduled void timer_interrupt (): kReceiver *recv, *next for recv = first_alarm; recv; recv = next: next = (kReceiver *)recv->next_alarm alarm_tick (recv) //schedule ()