diff --git a/include/kernel/kernel.hpp b/include/kernel/kernel.hpp index a2e22803..3333923d 100644 --- a/include/kernel/kernel.hpp +++ b/include/kernel/kernel.hpp @@ -83,6 +83,7 @@ private: u32 getTLSPointer(); void setupIdleThread(); + void acquireSyncObject(KernelObject* object, const Thread& thread); bool isWaitable(const KernelObject* object); // Functions for the err:f port diff --git a/include/kernel/kernel_types.hpp b/include/kernel/kernel_types.hpp index 8db4903a..cd93a2c7 100644 --- a/include/kernel/kernel_types.hpp +++ b/include/kernel/kernel_types.hpp @@ -211,7 +211,7 @@ struct KernelObject { return static_cast(data); } - const char* getTypeName() { + const char* getTypeName() const { return kernelObjectTypeToString(type); } diff --git a/src/core/kernel/events.cpp b/src/core/kernel/events.cpp index dad80a47..409e5747 100644 --- a/src/core/kernel/events.cpp +++ b/src/core/kernel/events.cpp @@ -101,6 +101,7 @@ void Kernel::waitSynchronization1() { } if (!shouldWaitOnObject(object)) { + acquireSyncObject(object, threads[currentThreadIndex]); // Acquire the object since it's ready regs[0] = SVCResult::Success; } else { // Timeout is 0, don't bother waiting, instantly timeout diff --git a/src/core/kernel/threads.cpp b/src/core/kernel/threads.cpp index 7da1d8da..59b3df77 100644 --- a/src/core/kernel/threads.cpp +++ b/src/core/kernel/threads.cpp @@ -186,6 +186,19 @@ void Kernel::sleepThreadOnArbiter(u32 waitingAddress) { switchToNextThread(); } +void Kernel::acquireSyncObject(KernelObject* object, const Thread& thread) { + switch (object->type) { + case KernelObjectType::Mutex: { + Mutex* moo = object->getData(); + moo->locked = true; + moo->ownerThread = thread.index; + break; + } + + default: Helpers::panic("Acquiring unimplemented sync object %s", object->getTypeName()); + } +} + // Make a thread sleep for a certain amount of nanoseconds at minimum void Kernel::sleepThread(s64 ns) { if (ns < 0) { @@ -353,8 +366,19 @@ bool Kernel::shouldWaitOnObject(KernelObject* object) { case KernelObjectType::Event: // We should wait on an event only if it has not been signalled return !object->getData()->fired; + case KernelObjectType::Mutex: { + Mutex* moo = object->getData(); // mooooooooooo + return moo->locked && moo->ownerThread != currentThreadIndex; // If the current thread owns the moo then no reason to wait + } + + case KernelObjectType::Thread: // Waiting on a thread waits until it's dead. If it's dead then no need to wait + return object->getData()->status != ThreadStatus::Dead; + + case KernelObjectType::Semaphore: + Helpers::panic("No semaphore :("); + default: - logThread("Not sure whether to wait on object (type: %s)", object->getTypeName()); + Helpers::panic("Not sure whether to wait on object (type: %s)", object->getTypeName()); return true; } } \ No newline at end of file