From 012f68838bac7e69e54df9d0d2f13d90dcdce329 Mon Sep 17 00:00:00 2001 From: ChUrl Date: Mon, 11 Jul 2022 15:00:05 +0200 Subject: [PATCH] implement semaphore --- c_os/kernel/threads/Scheduler.cc | 1 - c_os/lib/Semaphore.cc | 32 ++++++++++++++++++++++++++++++++ c_os/lib/SpinLock.cc | 2 ++ c_os/main.cc | 5 +++++ 4 files changed, 39 insertions(+), 1 deletion(-) create mode 100644 c_os/lib/Semaphore.cc diff --git a/c_os/kernel/threads/Scheduler.cc b/c_os/kernel/threads/Scheduler.cc index 8765496..ee3cd49 100644 --- a/c_os/kernel/threads/Scheduler.cc +++ b/c_os/kernel/threads/Scheduler.cc @@ -181,7 +181,6 @@ void Scheduler::block() { } cpu.disable_int(); - Thread& next = *(Thread*)this->readyQueue.dequeue(); this->dispatch(next); } diff --git a/c_os/lib/Semaphore.cc b/c_os/lib/Semaphore.cc new file mode 100644 index 0000000..9d1bb7a --- /dev/null +++ b/c_os/lib/Semaphore.cc @@ -0,0 +1,32 @@ +#include "Semaphore.h" +#include "kernel/Globals.h" + +void Semaphore::p() { + // Lock to allow deterministic operations on counter + this->lock.acquire(); + + if (this->counter > 0) { + // Semaphore can be acquired + this->counter = this->counter - 1; + } else { + // Block and manage thread in semaphore queue until it's woken up by v() + this->waitQueue.enqueue(scheduler.get_active()); + scheduler.block(); + } + + this->lock.release(); +} + +void Semaphore::v() { + this->lock.acquire(); + + if (!this->waitQueue.isEmpty()) { + // Semaphore stays busy and unblocks next thread to work in critical section + scheduler.deblock((Thread*)this->waitQueue.dequeue()); + } else { + // No more threads want to work so free semaphore + this->counter = this->counter + 1; + } + + this->lock.release(); +} diff --git a/c_os/lib/SpinLock.cc b/c_os/lib/SpinLock.cc index 6f2d5f5..cfcf279 100644 --- a/c_os/lib/SpinLock.cc +++ b/c_os/lib/SpinLock.cc @@ -50,6 +50,8 @@ static inline unsigned long CAS(unsigned long* ptr, unsigned long old, unsigned * Beschreibung: Lock belegen. * *****************************************************************************/ void SpinLock::acquire() { + // If lock == 0 the SpinLock can be aquired without waiting + // If lock == 1 the while loop blocks until aquired while (CAS(ptr, 0, 1) != 0) {} } diff --git a/c_os/main.cc b/c_os/main.cc index 21428e6..08f2e2c 100755 --- a/c_os/main.cc +++ b/c_os/main.cc @@ -84,6 +84,11 @@ int main() { scheduler.schedule(); // TODO: Use templates for queue so threads don't have to be casted down from chain + // TODO: Change scheduler to only use references instead of pointers + // TODO: Rewrite all demos to threads + // TODO: Make menu for demos + // TODO: Unify debug output format + // TODO: Serial output // Scheduler doesn't return return 0;