mirror of
https://github.com/wheremyfoodat/Panda3DS.git
synced 2025-04-08 07:05:40 +12:00
Sync objects 0.1
This commit is contained in:
parent
182132cbb1
commit
41e01bbdd4
6 changed files with 66 additions and 21 deletions
|
@ -64,6 +64,8 @@ class Kernel {
|
||||||
u32 getMaxForResource(const KernelObject* limit, u32 resourceName);
|
u32 getMaxForResource(const KernelObject* limit, u32 resourceName);
|
||||||
u32 getTLSPointer();
|
u32 getTLSPointer();
|
||||||
|
|
||||||
|
bool isWaitable(const KernelObject* object);
|
||||||
|
|
||||||
// Functions for the err:f port
|
// Functions for the err:f port
|
||||||
void handleErrorSyncRequest(u32 messagePointer);
|
void handleErrorSyncRequest(u32 messagePointer);
|
||||||
void throwError(u32 messagePointer);
|
void throwError(u32 messagePointer);
|
||||||
|
|
|
@ -23,9 +23,9 @@ namespace SVCResult {
|
||||||
}
|
}
|
||||||
|
|
||||||
enum class KernelObjectType : u8 {
|
enum class KernelObjectType : u8 {
|
||||||
AddressArbiter, Archive, File, Port, Process, ResourceLimit, Session, Dummy,
|
AddressArbiter, Archive, File, Process, ResourceLimit, Session, Dummy,
|
||||||
// Bundle waitable objects together in the enum to let the compiler optimize certain checks better
|
// Bundle waitable objects together in the enum to let the compiler optimize certain checks better
|
||||||
Event, Mutex, Semaphore, Thread
|
Event, Mutex, Port, Semaphore, Timer, Thread
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class ResourceLimitCategory : int {
|
enum class ResourceLimitCategory : int {
|
||||||
|
@ -121,6 +121,8 @@ struct Thread {
|
||||||
s64 waitingNanoseconds;
|
s64 waitingNanoseconds;
|
||||||
// The tick this thread went to sleep on
|
// The tick this thread went to sleep on
|
||||||
u64 sleepTick;
|
u64 sleepTick;
|
||||||
|
// For WaitSynchronization: A vector of objects this thread is waiting for
|
||||||
|
std::vector<Handle> waitList;
|
||||||
|
|
||||||
// Thread context used for switching between threads
|
// Thread context used for switching between threads
|
||||||
std::array<u32, 16> gprs;
|
std::array<u32, 16> gprs;
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
#include "kernel.hpp"
|
#include "kernel.hpp"
|
||||||
|
#include "cpu.hpp"
|
||||||
|
|
||||||
const char* Kernel::resetTypeToString(u32 type) {
|
const char* Kernel::resetTypeToString(u32 type) {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
|
@ -67,41 +68,68 @@ void Kernel::signalEvent() {
|
||||||
void Kernel::waitSynchronization1() {
|
void Kernel::waitSynchronization1() {
|
||||||
const Handle handle = regs[0];
|
const Handle handle = regs[0];
|
||||||
const s64 ns = s64(u64(regs[1]) | (u64(regs[2]) << 32));
|
const s64 ns = s64(u64(regs[1]) | (u64(regs[2]) << 32));
|
||||||
const auto event = getObject(handle, KernelObjectType::Event);
|
logSVC("WaitSynchronization1(handle = %X, ns = %lld)\n", handle, ns);
|
||||||
|
|
||||||
if (event == nullptr) [[unlikely]] {
|
const auto object = getObject(handle);
|
||||||
|
|
||||||
|
if (object == nullptr) [[unlikely]] {
|
||||||
Helpers::panic("WaitSynchronization1: Bad event handle");
|
Helpers::panic("WaitSynchronization1: Bad event handle");
|
||||||
regs[0] = SVCResult::BadHandle;
|
regs[0] = SVCResult::BadHandle;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
logSVC("WaitSynchronization1(handle = %X, ns = %lld) (STUBBED)\n", handle, ns);
|
if (!isWaitable(object)) [[unlikely]] {
|
||||||
|
Helpers::panic("Tried to wait on a non waitable object. Type: %s, handle: %X\n", kernelObjectTypeToString(object->type), handle);
|
||||||
|
}
|
||||||
|
|
||||||
regs[0] = SVCResult::Success;
|
regs[0] = SVCResult::Success;
|
||||||
|
|
||||||
|
auto& t = threads[currentThreadIndex];
|
||||||
|
t.waitList.resize(1);
|
||||||
|
t.status = ThreadStatus::WaitSync1;
|
||||||
|
t.sleepTick = cpu.getTicks();
|
||||||
|
t.waitingNanoseconds = ns;
|
||||||
|
t.waitList[0] = handle;
|
||||||
|
switchToNextThread();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Result WaitSynchronizationN(s32* out, Handle* handles, s32 handlecount, bool waitAll, s64 timeout_nanoseconds)
|
// Result WaitSynchronizationN(s32* out, Handle* handles, s32 handlecount, bool waitAll, s64 timeout_nanoseconds)
|
||||||
void Kernel::waitSynchronizationN() {
|
void Kernel::waitSynchronizationN() {
|
||||||
// TODO: Are these arguments even correct?
|
// TODO: Are these arguments even correct?
|
||||||
u32 ns1 = regs[0];
|
s32 ns1 = regs[0];
|
||||||
u32 handles = regs[1];
|
u32 handles = regs[1];
|
||||||
u32 handleCount = regs[2];
|
u32 handleCount = regs[2];
|
||||||
bool waitAll = regs[3] != 0;
|
bool waitAll = regs[3] != 0;
|
||||||
u32 ns2 = regs[4];
|
u32 ns2 = regs[4];
|
||||||
u32 out = regs[5];
|
s32 pointer = regs[5];
|
||||||
|
s64 ns = s64(ns1) | (s64(ns2) << 32);
|
||||||
|
|
||||||
logSVC("WaitSynchronizationN (STUBBED)\n");
|
logSVC("WaitSynchronizationN (handle pointer: %08X, count: %d)\n", handles, handleCount);
|
||||||
regs[0] = SVCResult::Success;
|
ThreadStatus newStatus = waitAll ? ThreadStatus::WaitSyncAll : ThreadStatus::WaitSync1;
|
||||||
|
|
||||||
printf("Hacky WaitSync stuff for OoT triggered!!!\n");
|
auto& t = threads[currentThreadIndex];
|
||||||
threads[currentThreadIndex].status = ThreadStatus::Ready;
|
t.waitList.resize(handleCount);
|
||||||
|
|
||||||
while (1) {
|
for (uint i = 0; i < handleCount; i++) {
|
||||||
auto index = rand() % threadCount;
|
Handle handle = mem.read32(handles);
|
||||||
auto& thread = threads[index];
|
handles += sizeof(Handle);
|
||||||
|
|
||||||
if (canThreadRun(thread)) {
|
t.waitList[i] = handle;
|
||||||
switchThread(rand() % threadCount);
|
|
||||||
break;
|
auto object = getObject(handle);
|
||||||
|
if (object == nullptr) [[unlikely]] {
|
||||||
|
Helpers::panic("WaitSynchronizationN: Bad object handle");
|
||||||
|
regs[0] = SVCResult::BadHandle;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isWaitable(object)) [[unlikely]] {
|
||||||
|
Helpers::panic("Tried to wait on a non waitable object. Type: %s, handle: %X\n", kernelObjectTypeToString(object->type), handle);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
regs[0] = SVCResult::Success;
|
||||||
|
t.status = newStatus;
|
||||||
|
t.waitingNanoseconds = ns;
|
||||||
|
switchToNextThread();
|
||||||
}
|
}
|
|
@ -13,6 +13,7 @@ Kernel::Kernel(CPU& cpu, Memory& mem, GPU& gpu)
|
||||||
threads[i].index = i;
|
threads[i].index = i;
|
||||||
threads[i].tlsBase = VirtualAddrs::TLSBase + i * VirtualAddrs::TLSSize;
|
threads[i].tlsBase = VirtualAddrs::TLSBase + i * VirtualAddrs::TLSSize;
|
||||||
threads[i].status = ThreadStatus::Dead;
|
threads[i].status = ThreadStatus::Dead;
|
||||||
|
threads[i].waitList.reserve(10); // Reserve some space for the wait list to avoid further memory allocs later
|
||||||
}
|
}
|
||||||
|
|
||||||
setVersion(1, 69);
|
setVersion(1, 69);
|
||||||
|
@ -101,6 +102,7 @@ void Kernel::reset() {
|
||||||
|
|
||||||
for (auto& t : threads) {
|
for (auto& t : threads) {
|
||||||
t.status = ThreadStatus::Dead;
|
t.status = ThreadStatus::Dead;
|
||||||
|
t.waitList.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto& object : objects) {
|
for (auto& object : objects) {
|
||||||
|
|
|
@ -46,7 +46,7 @@ void Kernel::sortThreads() {
|
||||||
bool Kernel::canThreadRun(const Thread& t) {
|
bool Kernel::canThreadRun(const Thread& t) {
|
||||||
if (t.status == ThreadStatus::Ready) {
|
if (t.status == ThreadStatus::Ready) {
|
||||||
return true;
|
return true;
|
||||||
} else if (t.status == ThreadStatus::WaitSleep) {
|
} else if (t.status == ThreadStatus::WaitSleep || t.status == ThreadStatus::WaitSync1 || t.status == ThreadStatus::WaitSyncAll) {
|
||||||
const u64 elapsedTicks = cpu.getTicks() - t.sleepTick;
|
const u64 elapsedTicks = cpu.getTicks() - t.sleepTick;
|
||||||
|
|
||||||
constexpr double ticksPerSec = double(CPU::ticksPerSec);
|
constexpr double ticksPerSec = double(CPU::ticksPerSec);
|
||||||
|
@ -260,9 +260,10 @@ 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");
|
// Helpers::panic("CreateMutex (initially locked: %s)\n", locked ? "yes" : "no");
|
||||||
|
|
||||||
regs[0] = SVCResult::Success;
|
regs[0] = SVCResult::Success;
|
||||||
|
regs[1] = makeObject(KernelObjectType::Mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Kernel::releaseMutex() {
|
void Kernel::releaseMutex() {
|
||||||
|
@ -271,3 +272,13 @@ void Kernel::releaseMutex() {
|
||||||
logSVC("ReleaseMutex (handle = %x) (STUBBED)\n", handle);
|
logSVC("ReleaseMutex (handle = %x) (STUBBED)\n", handle);
|
||||||
regs[0] = SVCResult::Success;
|
regs[0] = SVCResult::Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Returns whether an object is waitable or not
|
||||||
|
// The KernelObject type enum is arranged in a specific order in kernel_types.hpp so this
|
||||||
|
// can simply compile to a fast sub+cmp+set despite looking slow
|
||||||
|
bool Kernel::isWaitable(const KernelObject* object) {
|
||||||
|
auto type = object->type;
|
||||||
|
using enum KernelObjectType;
|
||||||
|
|
||||||
|
return type == Event || type == Mutex || type == Port || type == Semaphore || type == Timer || type == Thread;
|
||||||
|
}
|
|
@ -80,8 +80,8 @@ void APTService::enable(u32 messagePointer) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void APTService::getLockHandle(u32 messagePointer) {
|
void APTService::getLockHandle(u32 messagePointer) {
|
||||||
log("APT::GetLockHandle (Failure)\n");
|
log("APT::GetLockHandle");
|
||||||
mem.write32(messagePointer + 4, Result::Failure); // 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
|
||||||
|
|
Loading…
Add table
Reference in a new issue