diff --git a/src/kernel/exception/Bluescreen.h b/src/kernel/exception/Bluescreen.h index a53671a..9d77ceb 100644 --- a/src/kernel/exception/Bluescreen.h +++ b/src/kernel/exception/Bluescreen.h @@ -18,5 +18,4 @@ // dump blue screen (will not return) void bs_dump(uint8_t exceptionNr); - #endif diff --git a/src/lib/async/Semaphore.cc b/src/lib/async/Semaphore.cc index edd6816..98c1452 100644 --- a/src/lib/async/Semaphore.cc +++ b/src/lib/async/Semaphore.cc @@ -5,7 +5,9 @@ namespace Async { -void Semaphore::p() { +Semaphore::Semaphore(uint32_t c) : counter(c) {} + +void Semaphore::acquire() { // Lock to allow deterministic operations on counter/queue lock.acquire(); @@ -15,7 +17,7 @@ void Semaphore::p() { lock.release(); } else { // Block and manage thread in semaphore queue until it's woken up by v() again - if (!wait_queue.initialized()) { // TODO: I will replace this suboptimal datastructure in the future + if (!wait_queue.initialized()) { wait_queue.reserve(); } auto &schedulerService = Kernel::System::getService(); @@ -27,7 +29,7 @@ void Semaphore::p() { } } -void Semaphore::v() { +void Semaphore::release() { lock.acquire(); if (!wait_queue.empty()) { diff --git a/src/lib/async/Semaphore.h b/src/lib/async/Semaphore.h index 8a86fb3..93eec8b 100755 --- a/src/lib/async/Semaphore.h +++ b/src/lib/async/Semaphore.h @@ -1,41 +1,43 @@ -/***************************************************************************** - * * - * S E M A P H O R E * - * * - *---------------------------------------------------------------------------* - * Beschreibung: Implementierung von Sempahor-Objekten. * - * * - * Autor: Michael Schoettner, 2.9.2016 * - *****************************************************************************/ - #ifndef Semaphore_include__ #define Semaphore_include__ -#include "kernel/process/Thread.h" #include "SpinLock.h" -#include "lib/container//Vector.h" +#include "kernel/process/Thread.h" +#include "lib/container/Vector.h" +#include "lib/util/RestrictedConstructors.h" namespace Async { class Semaphore { -private: - // Queue fuer wartende Threads. - Container::Vector wait_queue; - SpinLock lock; - - int counter; - public: - Semaphore(const Semaphore ©) = delete; // Verhindere Kopieren + /** + * Initialize the semaphore and it's counter. + * + * @param c The semaphore counter + */ + explicit Semaphore(uint32_t c); - // Konstruktor: Initialisieren des Semaphorzaehlers - explicit Semaphore(int c) : counter(c) {} + MakeUncopyable(Semaphore) - // 'Passieren': Warten auf das Freiwerden eines kritischen Abschnitts. - void p(); + MakeUnmovable(Semaphore) - // 'Vreigeben': Freigeben des kritischen Abschnitts. - void v(); + ~Semaphore() = default; + + /** + * Wait in queue until the semaphore can be acquired. + */ + void acquire(); + + /** + * Release the semaphore. + */ + void release(); + +private: + SpinLock lock; + Container::Vector wait_queue; // TODO: Replace with a queue (linked list) + + uint32_t counter; }; } diff --git a/src/lib/async/SpinLock.cc b/src/lib/async/SpinLock.cc index 54b6525..3e324b5 100644 --- a/src/lib/async/SpinLock.cc +++ b/src/lib/async/SpinLock.cc @@ -1,66 +1,28 @@ -/***************************************************************************** - * * - * S P I N L O C K * - * * - *---------------------------------------------------------------------------* - * Beschreibung: Implementierung eines Spinlocks mithilfe der cmpxchg * - * Instruktion. * - * * - * Autor: Michael Schoettner, 2.2.2018 * - *****************************************************************************/ - #include "SpinLock.h" namespace Async { -/***************************************************************************** - * Methode: CAS * - *---------------------------------------------------------------------------* - * Parameter: *ptr Adresse der Variable des Locks * - * old Wert gegen den verglichen wird * - * _new Wert der gesetzt werden soll * - * * - * Beschreibung: Semantik der Funktion CAS = Cmompare & Swap: * - * if old == *ptr then * - * *ptr := _new * - * return prev * - *****************************************************************************/ +// TODO: Outsource to Atomic lib static inline uint32_t CAS(const uint32_t *ptr) { uint32_t prev; - /* - AT&T/UNIX assembly syntax + asm volatile("lock;" // prevent race conditions with other cores + "cmpxchg %1, %2;" // %1 = _new; %2 = *ptr + : "=a"(prev) // output: =a: RAX -> prev (%0)) + : "r"(1), "m"(*ptr), "a"(0) // input = %1, %2, %3 (r=register, m=memory, a=accumlator = eax + : "memory"); // ensures assembly block will not be moved by gcc - The 'volatile' keyword after 'asm' indicates that the instruction - has important side-effects. GCC will not delete a volatile asm if - sit is reachable. - */ - asm volatile("lock;" // prevent race conditions with other cores - "cmpxchg %1, %2;" // %1 = _new; %2 = *ptr - // constraints - : "=a"(prev) // output: =a: RAX -> prev (%0)) - : "r"(1), "m"(*ptr), "a"(0) // input = %1, %2, %3 (r=register, m=memory, a=accumlator = eax - : "memory"); // ensures assembly block will not be moved by gcc - - return prev; // return pointer instead of prev to prevent unnecessary second call + return prev; // return pointer instead of prev to prevent unnecessary second call } -/***************************************************************************** - * Methode: SpinLock::acquire * - *---------------------------------------------------------------------------* - * Beschreibung: Lock belegen. * - *****************************************************************************/ +SpinLock::SpinLock() : lock(0), ptr(&lock) {} + 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) {} } -/***************************************************************************** - * Methode: SpinLock::release * - *---------------------------------------------------------------------------* - * Beschreibung: Lock freigeben. * - *****************************************************************************/ void SpinLock::release() { lock = 0; } diff --git a/src/lib/async/SpinLock.h b/src/lib/async/SpinLock.h index be5532e..15af7fa 100644 --- a/src/lib/async/SpinLock.h +++ b/src/lib/async/SpinLock.h @@ -13,22 +13,33 @@ #define SpinLock_include__ #include +#include "lib/util/RestrictedConstructors.h" namespace Async { class SpinLock { +public: + SpinLock(); + + MakeUncopyable(SpinLock) + + MakeUnmovable(SpinLock) + + ~SpinLock() = default; + + /** + * Acquire the spin lock. + */ + void acquire(); + + /** + * Release the spin lock. + */ + void release(); + private: uint32_t lock; uint32_t *ptr; - -public: - SpinLock(const SpinLock ©) = delete; // Verhindere Kopieren - - SpinLock() : lock(0), ptr(&lock) {} - - void acquire(); - - void release(); }; } diff --git a/src/lib/stream/CGA_Stream.h b/src/lib/stream/CGA_Stream.h index 986f021..81fa44e 100755 --- a/src/lib/stream/CGA_Stream.h +++ b/src/lib/stream/CGA_Stream.h @@ -62,9 +62,9 @@ public: // ~CGA_Stream() override = default; - void lock() { sem.p(); } + void lock() { sem.acquire(); } - void unlock() { sem.v(); } + void unlock() { sem.release(); } // Methode zur Ausgabe des Pufferinhalts der Basisklasse StringBuffer. void flush() override;