From 499efede478ea26ae0ccfe751ad478c47643e258 Mon Sep 17 00:00:00 2001 From: ChUrl Date: Sat, 16 Jul 2022 01:03:00 +0200 Subject: [PATCH] update scheduler to arraylist --- c_os/kernel/threads/Scheduler.cc | 58 +++++++++----------------------- c_os/kernel/threads/Scheduler.h | 31 +++++++++++------ 2 files changed, 36 insertions(+), 53 deletions(-) diff --git a/c_os/kernel/threads/Scheduler.cc b/c_os/kernel/threads/Scheduler.cc index 8807b9e..b45d6f6 100644 --- a/c_os/kernel/threads/Scheduler.cc +++ b/c_os/kernel/threads/Scheduler.cc @@ -54,10 +54,9 @@ void Scheduler::ready(Thread* that) { // Thread-Wechsel durch PIT verhindern cpu.disable_int(); - - this->readyQueue.enqueue(that); - - // Thread-Wechsel durch PIT jetzt wieder erlauben + this->ready_queue.insert(that); + kout << "Scheduler :: Adding to ready_queue" << endl; + this->ready_queue.print(); cpu.enable_int(); } @@ -75,8 +74,9 @@ void Scheduler::exit() { // Thread-Wechsel durch PIT verhindern cpu.disable_int(); - - Thread& next = *(Thread*)this->readyQueue.dequeue(); + Thread& next = *(Thread*)this->ready_queue.remove_first(); + kout << "Scheduler :: Exiting thread" << endl; + this->ready_queue.print(); this->dispatch(next); // Interrupts werden in Thread_switch in Thread.asm wieder zugelassen @@ -100,10 +100,9 @@ void Scheduler::kill(Thread* that) { // Thread-Wechsel durch PIT verhindern cpu.disable_int(); - - this->readyQueue.remove(that); - - // Thread-Wechsel durch PIT jetzt wieder erlauben + this->ready_queue.remove(that); + kout << "Scheduler :: Killing thread" << endl; + this->ready_queue.print(); cpu.enable_int(); } @@ -122,18 +121,12 @@ void Scheduler::yield() { /* hier muss Code eingefuegt werden */ - // When only one thread exists (IdleThread) it can't yield as the readyqueue becomes empty - // and this is not handled anywhere else - if (this->readyQueue.isEmpty()) { - // Idle thread running - return; - } - // Thread-Wechsel durch PIT verhindern cpu.disable_int(); - - Thread& next = *(Thread*)this->readyQueue.dequeue(); - this->readyQueue.enqueue(this->get_active()); + this->ready_queue.insert(this->get_active()); + Thread& next = *(Thread*)this->ready_queue.remove_first(); + kout << "Scheduler :: Yield" << endl; + this->ready_queue.print(); this->dispatch(next); } @@ -148,17 +141,7 @@ void Scheduler::preempt() { /* Hier muss Code eingefuegt werden */ - if (this->readyQueue.isEmpty()) { - // Idle thread running - return; - } - - // Thread-Wechsel durch PIT verhindern - cpu.disable_int(); - - Thread& next = *(Thread*)this->readyQueue.dequeue(); - this->readyQueue.enqueue(this->get_active()); - this->dispatch(next); + this->yield(); // We already have that } /***************************************************************************** @@ -175,15 +158,7 @@ void Scheduler::block() { /* hier muss Code eingefuegt werden */ - if (this->readyQueue.isEmpty()) { - // Something went seriously wrong - return; - } - - cpu.disable_int(); - Thread& next = *(Thread*)this->readyQueue.dequeue(); - // Current thread is not added to readyQueue, gets managed by semaphore - this->dispatch(next); + this->exit(); // If I'm not mistaken block/deblock is the same functionality we already have } /***************************************************************************** @@ -201,8 +176,5 @@ void Scheduler::deblock(Thread* that) { /* hier muss Code eingefuegt werden */ - // NOTE: I wanted to prefer the deblocked thread but did something wrong - // which fucked the queue and didn't continue blocked threads so I - // left it at ready(that). this->ready(that); } diff --git a/c_os/kernel/threads/Scheduler.h b/c_os/kernel/threads/Scheduler.h index 7cd5772..c857a10 100644 --- a/c_os/kernel/threads/Scheduler.h +++ b/c_os/kernel/threads/Scheduler.h @@ -12,31 +12,46 @@ #ifndef __Scheduler_include__ #define __Scheduler_include__ +#include "devices/CGA_Stream.h" #include "kernel/threads/Dispatch.h" #include "kernel/threads/Thread.h" #include "lib/Queue.h" +#include "lib/SpinLock.h" +#include "user/lib/ArrayList.h" class Scheduler : public Dispatcher { private: Scheduler(const Scheduler& copy) = delete; // Verhindere Kopieren - Queue readyQueue; // auf die CPU wartende Threads - Queue blockQueue; + // Queue readyQueue; // auf die CPU wartende Threads // Scheduler wird evt. von einer Unterbrechung vom Zeitgeber gerufen, // bevor er initialisiert wurde - bool initialized; + bool has_idle_thread; + + // NOTE: I would have to release the lock when switching threads but I don't know exactly how to do this + // in the assembly function + // SpinLock lock; // Use spinlock instead of cpu.disable_int() because it still allows preemption + // // for threads that don't use the scheduler + + // NOTE: Using this instead of the Queue is a side effect, I added the ArrayList for different reasons + // but my Queue was shit so I replaced it (and didn't fix the Queue) + ArrayList ready_queue; public: - Scheduler() : initialized(false) {} + Scheduler() : has_idle_thread(false) {} + + void init() { + this->ready_queue.init(); + } // Scheduler initialisiert? // Zeitgeber-Unterbrechung kommt evt. bevor der Scheduler fertig // intiialisiert wurde! - bool isInitialized() const { return initialized; } + bool preemption_enabled() const { return has_idle_thread; } // ruft nur der Idle-Thread (erster Thread der vom Scheduler gestartet wird) - void setInitialized() { initialized = true; } + void enable_preemption() { has_idle_thread = true; } // Scheduler starten void schedule(); @@ -56,12 +71,8 @@ public: // Thread umschalten; wird aus der ISR des PITs gerufen void preempt(); - // TODO: Merge this with usual block/deblock void block(); void deblock(Thread* that); - - // void block(); - // void deblock(Thread* that); }; #endif