mirror of
https://github.com/wheremyfoodat/Panda3DS.git
synced 2025-04-17 19:21:30 +12:00
[Kernel & APT] Mutexes v0.1
This commit is contained in:
parent
41e01bbdd4
commit
3c55d88fab
7 changed files with 51 additions and 8 deletions
|
@ -46,6 +46,10 @@ class Kernel {
|
||||||
Handle makeSession(Handle port);
|
Handle makeSession(Handle port);
|
||||||
Handle makeThread(u32 entrypoint, u32 initialSP, u32 priority, s32 id, u32 arg,ThreadStatus status = ThreadStatus::Dormant);
|
Handle makeThread(u32 entrypoint, u32 initialSP, u32 priority, s32 id, u32 arg,ThreadStatus status = ThreadStatus::Dormant);
|
||||||
|
|
||||||
|
public:
|
||||||
|
Handle makeMutex(bool locked = false); // Needs to be public to be accessible to the APT/DSP services
|
||||||
|
|
||||||
|
private:
|
||||||
void signalArbiter(u32 waitingAddress, s32 threadCount);
|
void signalArbiter(u32 waitingAddress, s32 threadCount);
|
||||||
void sleepThread(s64 ns);
|
void sleepThread(s64 ns);
|
||||||
void sleepThreadOnArbiter(u32 waitingAddress);
|
void sleepThreadOnArbiter(u32 waitingAddress);
|
||||||
|
|
|
@ -150,6 +150,13 @@ static const char* kernelObjectTypeToString(KernelObjectType t) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct Mutex {
|
||||||
|
Handle ownerThread = 0; // Index of the thread that holds the mutex if it's locked
|
||||||
|
bool locked;
|
||||||
|
|
||||||
|
Mutex(bool lock = false) : locked(lock) {}
|
||||||
|
};
|
||||||
|
|
||||||
// Generic kernel object class
|
// Generic kernel object class
|
||||||
struct KernelObject {
|
struct KernelObject {
|
||||||
Handle handle = 0; // A u32 the OS will use to identify objects
|
Handle handle = 0; // A u32 the OS will use to identify objects
|
||||||
|
@ -166,4 +173,8 @@ struct KernelObject {
|
||||||
T* getData() {
|
T* getData() {
|
||||||
return static_cast<T*>(data);
|
return static_cast<T*>(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const char* getTypeName() {
|
||||||
|
return kernelObjectTypeToString(type);
|
||||||
|
}
|
||||||
};
|
};
|
|
@ -1,12 +1,20 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
#include <optional>
|
||||||
#include "helpers.hpp"
|
#include "helpers.hpp"
|
||||||
#include "kernel_types.hpp"
|
#include "kernel_types.hpp"
|
||||||
#include "logger.hpp"
|
#include "logger.hpp"
|
||||||
#include "memory.hpp"
|
#include "memory.hpp"
|
||||||
|
|
||||||
|
// Yay, more circular dependencies
|
||||||
|
class Kernel;
|
||||||
|
|
||||||
class APTService {
|
class APTService {
|
||||||
Handle handle = KernelHandles::APT;
|
Handle handle = KernelHandles::APT;
|
||||||
Memory& mem;
|
Memory& mem;
|
||||||
|
Kernel& kernel;
|
||||||
|
|
||||||
|
std::optional<Handle> lockHandle = std::nullopt;
|
||||||
|
|
||||||
MAKE_LOG_FUNCTION(log, aptLogger)
|
MAKE_LOG_FUNCTION(log, aptLogger)
|
||||||
|
|
||||||
// Service commands
|
// Service commands
|
||||||
|
@ -25,7 +33,7 @@ class APTService {
|
||||||
u32 cpuTimeLimit;
|
u32 cpuTimeLimit;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
APTService(Memory& mem) : mem(mem) {}
|
APTService(Memory& mem, Kernel& kernel) : mem(mem), kernel(kernel) {}
|
||||||
void reset();
|
void reset();
|
||||||
void handleSyncRequest(u32 messagePointer);
|
void handleSyncRequest(u32 messagePointer);
|
||||||
};
|
};
|
|
@ -79,7 +79,7 @@ void Kernel::waitSynchronization1() {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!isWaitable(object)) [[unlikely]] {
|
if (!isWaitable(object)) [[unlikely]] {
|
||||||
Helpers::panic("Tried to wait on a non waitable object. Type: %s, handle: %X\n", kernelObjectTypeToString(object->type), handle);
|
Helpers::panic("Tried to wait on a non waitable object. Type: %s, handle: %X\n", object->getTypeName(), handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
regs[0] = SVCResult::Success;
|
regs[0] = SVCResult::Success;
|
||||||
|
@ -124,7 +124,7 @@ void Kernel::waitSynchronizationN() {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!isWaitable(object)) [[unlikely]] {
|
if (!isWaitable(object)) [[unlikely]] {
|
||||||
Helpers::panic("Tried to wait on a non waitable object. Type: %s, handle: %X\n", kernelObjectTypeToString(object->type), handle);
|
Helpers::panic("Tried to wait on a non waitable object. Type: %s, handle: %X\n", object->getTypeName(), handle);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -137,6 +137,18 @@ Handle Kernel::makeThread(u32 entrypoint, u32 initialSP, u32 priority, s32 id, u
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Handle Kernel::makeMutex(bool locked) {
|
||||||
|
Handle ret = makeObject(KernelObjectType::Mutex);
|
||||||
|
objects[ret].data = new Mutex(locked);
|
||||||
|
|
||||||
|
// If the mutex is initially locked, store the index of the thread that owns it
|
||||||
|
if (locked) {
|
||||||
|
objects[ret].getData<Mutex>()->ownerThread = currentThreadIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
void Kernel::sleepThreadOnArbiter(u32 waitingAddress) {
|
void Kernel::sleepThreadOnArbiter(u32 waitingAddress) {
|
||||||
Thread& t = threads[currentThreadIndex];
|
Thread& t = threads[currentThreadIndex];
|
||||||
t.status = ThreadStatus::WaitArbiter;
|
t.status = ThreadStatus::WaitArbiter;
|
||||||
|
@ -260,10 +272,9 @@ void Kernel::setThreadPriority() {
|
||||||
|
|
||||||
void Kernel::createMutex() {
|
void Kernel::createMutex() {
|
||||||
bool locked = regs[1] != 0;
|
bool locked = regs[1] != 0;
|
||||||
// Helpers::panic("CreateMutex (initially locked: %s)\n", locked ? "yes" : "no");
|
|
||||||
|
|
||||||
regs[0] = SVCResult::Success;
|
regs[0] = SVCResult::Success;
|
||||||
regs[1] = makeObject(KernelObjectType::Mutex);
|
regs[1] = makeMutex(locked);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Kernel::releaseMutex() {
|
void Kernel::releaseMutex() {
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
#include "services/apt.hpp"
|
#include "services/apt.hpp"
|
||||||
|
#include "kernel.hpp"
|
||||||
|
|
||||||
namespace APTCommands {
|
namespace APTCommands {
|
||||||
enum : u32 {
|
enum : u32 {
|
||||||
|
@ -32,6 +33,8 @@ namespace Result {
|
||||||
void APTService::reset() {
|
void APTService::reset() {
|
||||||
// Set the default CPU time limit to 30%. Seems safe, as this is what Metroid 2 uses by default
|
// Set the default CPU time limit to 30%. Seems safe, as this is what Metroid 2 uses by default
|
||||||
cpuTimeLimit = 30;
|
cpuTimeLimit = 30;
|
||||||
|
|
||||||
|
lockHandle = std::nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
void APTService::handleSyncRequest(u32 messagePointer) {
|
void APTService::handleSyncRequest(u32 messagePointer) {
|
||||||
|
@ -80,12 +83,18 @@ void APTService::enable(u32 messagePointer) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void APTService::getLockHandle(u32 messagePointer) {
|
void APTService::getLockHandle(u32 messagePointer) {
|
||||||
log("APT::GetLockHandle");
|
log("APT::GetLockHandle\n");
|
||||||
|
|
||||||
|
// Create a lock handle if none exists
|
||||||
|
if (!lockHandle.has_value() || kernel.getObject(lockHandle.value(), KernelObjectType::Mutex) == nullptr) {
|
||||||
|
lockHandle = kernel.makeMutex();
|
||||||
|
}
|
||||||
|
|
||||||
mem.write32(messagePointer + 4, Result::Success); // Result code
|
mem.write32(messagePointer + 4, Result::Success); // Result code
|
||||||
mem.write32(messagePointer + 8, 0); // AppletAttr
|
mem.write32(messagePointer + 8, 0); // AppletAttr
|
||||||
mem.write32(messagePointer + 12, 0); // APT State (bit0 = Power Button State, bit1 = Order To Close State)
|
mem.write32(messagePointer + 12, 0); // APT State (bit0 = Power Button State, bit1 = Order To Close State)
|
||||||
mem.write32(messagePointer + 16, 0); // Translation descriptor
|
mem.write32(messagePointer + 16, 0); // Translation descriptor
|
||||||
mem.write32(messagePointer + 20, 0x34563456); // Lock handle
|
mem.write32(messagePointer + 20, lockHandle.value()); // Lock handle
|
||||||
}
|
}
|
||||||
|
|
||||||
// This apparently does nothing on the original kernel either?
|
// This apparently does nothing on the original kernel either?
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
#include "services/service_manager.hpp"
|
#include "services/service_manager.hpp"
|
||||||
|
|
||||||
ServiceManager::ServiceManager(std::array<u32, 16>& regs, Memory& mem, GPU& gpu, u32& currentPID, Kernel& kernel)
|
ServiceManager::ServiceManager(std::array<u32, 16>& regs, Memory& mem, GPU& gpu, u32& currentPID, Kernel& kernel)
|
||||||
: regs(regs), mem(mem), apt(mem), cecd(mem), cfg(mem), dsp(mem), hid(mem), fs(mem, kernel), gsp_gpu(mem, gpu, currentPID),
|
: regs(regs), mem(mem), apt(mem, kernel), cecd(mem), cfg(mem), dsp(mem), hid(mem), fs(mem, kernel), gsp_gpu(mem, gpu, currentPID),
|
||||||
gsp_lcd(mem), mic(mem), ndm(mem), ptm(mem) {}
|
gsp_lcd(mem), mic(mem), ndm(mem), ptm(mem) {}
|
||||||
|
|
||||||
void ServiceManager::reset() {
|
void ServiceManager::reset() {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue