mirror of
https://github.com/wheremyfoodat/Panda3DS.git
synced 2025-06-10 04:52:13 +12:00
hle: Add proper type for result code
This should clean up all HLE errorcode in the codebase. I didn't removed Rust::Result as this should be a cleanup for another iteration.
This commit is contained in:
parent
c6f5d19983
commit
122b1b2727
73 changed files with 540 additions and 419 deletions
|
@ -26,7 +26,7 @@ Handle Kernel::makeArbiter() {
|
|||
// Result CreateAddressArbiter(Handle* arbiter)
|
||||
void Kernel::createAddressArbiter() {
|
||||
logSVC("CreateAddressArbiter\n");
|
||||
regs[0] = SVCResult::Success;
|
||||
regs[0] = Result::Success;
|
||||
regs[1] = makeArbiter();
|
||||
}
|
||||
|
||||
|
@ -43,7 +43,7 @@ void Kernel::arbitrateAddress() {
|
|||
|
||||
const auto arbiter = getObject(handle, KernelObjectType::AddressArbiter);
|
||||
if (arbiter == nullptr) [[unlikely]] {
|
||||
regs[0] = SVCResult::BadHandle;
|
||||
regs[0] = Result::Kernel::InvalidHandle;
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -52,16 +52,16 @@ void Kernel::arbitrateAddress() {
|
|||
}
|
||||
|
||||
if (type > 4) [[unlikely]] {
|
||||
regs[0] = SVCResult::InvalidEnumValueAlt;
|
||||
regs[0] = Result::FND::InvalidEnumValue;
|
||||
return;
|
||||
}
|
||||
// This needs to put the error code in r0 before we change threads
|
||||
regs[0] = SVCResult::Success;
|
||||
regs[0] = Result::Success;
|
||||
|
||||
switch (static_cast<ArbitrationType>(type)) {
|
||||
// Puts this thread to sleep if word < value until another thread arbitrates the address using SIGNAL
|
||||
case ArbitrationType::WaitIfLess: {
|
||||
s32 word = static_cast<s32>(mem.read32(address)); // Yes this is meant to be signed
|
||||
s32 word = static_cast<s32>(mem.read32(address)); // Yes this is meant to be signed
|
||||
if (word < value) {
|
||||
sleepThreadOnArbiter(address);
|
||||
}
|
||||
|
@ -71,7 +71,7 @@ void Kernel::arbitrateAddress() {
|
|||
// Puts this thread to sleep if word < value until another thread arbitrates the address using SIGNAL
|
||||
// If the thread is put to sleep, the arbiter address is decremented
|
||||
case ArbitrationType::DecrementAndWaitIfLess: {
|
||||
s32 word = static_cast<s32>(mem.read32(address)); // Yes this is meant to be signed
|
||||
s32 word = static_cast<s32>(mem.read32(address)); // Yes this is meant to be signed
|
||||
if (word < value) {
|
||||
mem.write32(address, word - 1);
|
||||
sleepThreadOnArbiter(address);
|
||||
|
|
|
@ -7,12 +7,6 @@ namespace DirectoryOps {
|
|||
};
|
||||
}
|
||||
|
||||
namespace Result {
|
||||
enum : u32 {
|
||||
Success = 0
|
||||
};
|
||||
}
|
||||
|
||||
void Kernel::handleDirectoryOperation(u32 messagePointer, Handle directory) {
|
||||
const u32 cmd = mem.read32(messagePointer);
|
||||
switch (cmd) {
|
||||
|
|
|
@ -38,7 +38,7 @@ bool Kernel::signalEvent(Handle handle) {
|
|||
// One-shot events get cleared once they are acquired by some thread and only wake up 1 thread at a time
|
||||
if (event->resetType == ResetType::OneShot) {
|
||||
int index = wakeupOneThread(event->waitlist, handle); // Wake up one thread with the highest priority
|
||||
event->waitlist ^= (1ull << index); // Remove thread from waitlist
|
||||
event->waitlist ^= (1ull << index); // Remove thread from waitlist
|
||||
event->fired = false;
|
||||
} else {
|
||||
wakeupAllThreads(event->waitlist, handle);
|
||||
|
@ -64,11 +64,11 @@ void Kernel::svcCreateEvent() {
|
|||
|
||||
logSVC("CreateEvent(handle pointer = %08X, resetType = %s)\n", outPointer, resetTypeToString(resetType));
|
||||
|
||||
regs[0] = SVCResult::Success;
|
||||
regs[0] = Result::Success;
|
||||
regs[1] = makeEvent(static_cast<ResetType>(resetType));
|
||||
}
|
||||
|
||||
// Result ClearEvent(Handle event)
|
||||
// Result ClearEvent(Handle event)
|
||||
void Kernel::svcClearEvent() {
|
||||
const Handle handle = regs[0];
|
||||
const auto event = getObject(handle, KernelObjectType::Event);
|
||||
|
@ -76,15 +76,15 @@ void Kernel::svcClearEvent() {
|
|||
|
||||
if (event == nullptr) [[unlikely]] {
|
||||
Helpers::panic("Tried to clear non-existent event (handle = %X)", handle);
|
||||
regs[0] = SVCResult::BadHandle;
|
||||
regs[0] = Result::Kernel::InvalidHandle;
|
||||
return;
|
||||
}
|
||||
|
||||
event->getData<Event>()->fired = false;
|
||||
regs[0] = SVCResult::Success;
|
||||
regs[0] = Result::Success;
|
||||
}
|
||||
|
||||
// Result SignalEvent(Handle event)
|
||||
// Result SignalEvent(Handle event)
|
||||
void Kernel::svcSignalEvent() {
|
||||
const Handle handle = regs[0];
|
||||
logSVC("SignalEvent(event handle = %X)\n", handle);
|
||||
|
@ -92,15 +92,15 @@ void Kernel::svcSignalEvent() {
|
|||
|
||||
if (object == nullptr) {
|
||||
Helpers::panic("Signalled non-existent event: %X\n", handle);
|
||||
regs[0] = SVCResult::BadHandle;
|
||||
regs[0] = Result::Kernel::InvalidHandle;
|
||||
} else {
|
||||
// We must signalEvent after setting r0, otherwise the r0 of the new thread will ne corrupted
|
||||
regs[0] = SVCResult::Success;
|
||||
regs[0] = Result::Success;
|
||||
signalEvent(handle);
|
||||
}
|
||||
}
|
||||
|
||||
// Result WaitSynchronization1(Handle handle, s64 timeout_nanoseconds)
|
||||
// Result WaitSynchronization1(Handle handle, s64 timeout_nanoseconds)
|
||||
void Kernel::waitSynchronization1() {
|
||||
const Handle handle = regs[0];
|
||||
const s64 ns = s64(u64(regs[1]) | (u64(regs[2]) << 32));
|
||||
|
@ -110,7 +110,7 @@ void Kernel::waitSynchronization1() {
|
|||
|
||||
if (object == nullptr) [[unlikely]] {
|
||||
Helpers::panic("WaitSynchronization1: Bad event handle %X\n", handle);
|
||||
regs[0] = SVCResult::BadHandle;
|
||||
regs[0] = Result::Kernel::InvalidHandle;
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -120,16 +120,16 @@ void Kernel::waitSynchronization1() {
|
|||
|
||||
if (!shouldWaitOnObject(object)) {
|
||||
acquireSyncObject(object, threads[currentThreadIndex]); // Acquire the object since it's ready
|
||||
regs[0] = SVCResult::Success;
|
||||
regs[0] = Result::Success;
|
||||
rescheduleThreads();
|
||||
} else {
|
||||
// Timeout is 0, don't bother waiting, instantly timeout
|
||||
if (ns == 0) {
|
||||
regs[0] = SVCResult::Timeout;
|
||||
regs[0] = Result::OS::Timeout;
|
||||
return;
|
||||
}
|
||||
|
||||
regs[0] = SVCResult::Timeout; // This will be overwritten with success if we don't timeout
|
||||
regs[0] = Result::OS::Timeout; // This will be overwritten with success if we don't timeout
|
||||
|
||||
auto& t = threads[currentThreadIndex];
|
||||
t.waitList.resize(1);
|
||||
|
@ -180,7 +180,7 @@ void Kernel::waitSynchronizationN() {
|
|||
// Panic if one of the objects is not even an object
|
||||
if (object == nullptr) [[unlikely]] {
|
||||
Helpers::panic("WaitSynchronizationN: Bad object handle %X\n", handle);
|
||||
regs[0] = SVCResult::BadHandle;
|
||||
regs[0] = Result::Kernel::InvalidHandle;
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -206,16 +206,16 @@ void Kernel::waitSynchronizationN() {
|
|||
|
||||
// We only need to wait on one object. Easy...?!
|
||||
if (!waitAll) {
|
||||
// If there's ready objects, acquire the first one and return
|
||||
// If there's ready objects, acquire the first one and return
|
||||
if (oneObjectReady) {
|
||||
regs[0] = SVCResult::Success;
|
||||
regs[0] = Result::Success;
|
||||
regs[1] = firstReadyObjectIndex; // Return index of the acquired object
|
||||
acquireSyncObject(waitObjects[firstReadyObjectIndex].second, t); // Acquire object
|
||||
rescheduleThreads();
|
||||
return;
|
||||
}
|
||||
|
||||
regs[0] = SVCResult::Timeout; // This will be overwritten with success if we don't timeout
|
||||
regs[0] = Result::OS::Timeout; // This will be overwritten with success if we don't timeout
|
||||
// If the thread wakes up without timeout, this will be adjusted to the index of the handle that woke us up
|
||||
regs[1] = 0xFFFFFFFF;
|
||||
t.waitList.resize(handleCount);
|
||||
|
@ -223,7 +223,7 @@ void Kernel::waitSynchronizationN() {
|
|||
t.outPointer = outPointer;
|
||||
t.waitingNanoseconds = ns;
|
||||
t.sleepTick = cpu.getTicks();
|
||||
|
||||
|
||||
for (s32 i = 0; i < handleCount; i++) {
|
||||
t.waitList[i] = waitObjects[i].first; // Add object to this thread's waitlist
|
||||
waitObjects[i].second->getWaitlist() |= (1ull << currentThreadIndex); // And add the thread to the object's waitlist
|
||||
|
|
|
@ -14,12 +14,6 @@ namespace FileOps {
|
|||
};
|
||||
}
|
||||
|
||||
namespace Result {
|
||||
enum : u32 {
|
||||
Success = 0
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
void Kernel::handleFileOperation(u32 messagePointer, Handle file) {
|
||||
const u32 cmd = mem.read32(messagePointer);
|
||||
|
@ -90,7 +84,7 @@ void Kernel::readFile(u32 messagePointer, Handle fileHandle) {
|
|||
if (!file->isOpen) {
|
||||
Helpers::panic("Tried to read closed file");
|
||||
}
|
||||
|
||||
|
||||
// Handle files with their own file descriptors by just fread'ing the data
|
||||
if (file->fd) {
|
||||
std::unique_ptr<u8[]> data(new u8[size]);
|
||||
|
|
|
@ -149,7 +149,7 @@ u32 Kernel::getTLSPointer() {
|
|||
// Result CloseHandle(Handle handle)
|
||||
void Kernel::svcCloseHandle() {
|
||||
logSVC("CloseHandle(handle = %d) (Unimplemented)\n", regs[0]);
|
||||
regs[0] = SVCResult::Success;
|
||||
regs[0] = Result::Success;
|
||||
}
|
||||
|
||||
// u64 GetSystemTick()
|
||||
|
@ -169,7 +169,7 @@ void Kernel::outputDebugString() {
|
|||
|
||||
std::string message = mem.readString(pointer, size);
|
||||
logDebugString("[OutputDebugString] %s\n", message.c_str());
|
||||
regs[0] = SVCResult::Success;
|
||||
regs[0] = Result::Success;
|
||||
}
|
||||
|
||||
void Kernel::getProcessID() {
|
||||
|
@ -178,11 +178,11 @@ void Kernel::getProcessID() {
|
|||
logSVC("GetProcessID(process: %s)\n", getProcessName(pid).c_str());
|
||||
|
||||
if (process == nullptr) [[unlikely]] {
|
||||
regs[0] = SVCResult::BadHandle;
|
||||
regs[0] = Result::Kernel::InvalidHandle;
|
||||
return;
|
||||
}
|
||||
|
||||
regs[0] = SVCResult::Success;
|
||||
regs[0] = Result::Success;
|
||||
regs[1] = process->getData<Process>()->id;
|
||||
}
|
||||
|
||||
|
@ -194,7 +194,7 @@ void Kernel::getProcessInfo() {
|
|||
logSVC("GetProcessInfo(process: %s, type = %d)\n", getProcessName(pid).c_str(), type);
|
||||
|
||||
if (process == nullptr) [[unlikely]] {
|
||||
regs[0] = SVCResult::BadHandle;
|
||||
regs[0] = Result::Kernel::InvalidHandle;
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -215,7 +215,7 @@ void Kernel::getProcessInfo() {
|
|||
Helpers::panic("GetProcessInfo: unimplemented type %d", type);
|
||||
}
|
||||
|
||||
regs[0] = SVCResult::Success;
|
||||
regs[0] = Result::Success;
|
||||
}
|
||||
|
||||
// Result DuplicateHandle(Handle* out, Handle original)
|
||||
|
@ -224,7 +224,7 @@ void Kernel::duplicateHandle() {
|
|||
logSVC("DuplicateHandle(handle = %X)\n", original);
|
||||
|
||||
if (original == KernelHandles::CurrentThread) {
|
||||
regs[0] = SVCResult::Success;
|
||||
regs[0] = Result::Success;
|
||||
Handle ret = makeObject(KernelObjectType::Thread);
|
||||
objects[ret].data = &threads[currentThreadIndex];
|
||||
|
||||
|
|
|
@ -36,7 +36,7 @@ static constexpr bool isAligned(u32 value) {
|
|||
return (value & 0xFFF) == 0;
|
||||
}
|
||||
|
||||
// Result ControlMemory(u32* outaddr, u32 addr0, u32 addr1, u32 size,
|
||||
// Result ControlMemory(u32* outaddr, u32 addr0, u32 addr1, u32 size,
|
||||
// MemoryOperation operation, MemoryPermission permissions)
|
||||
// This has a weird ABI documented here https://www.3dbrew.org/wiki/Kernel_ABI
|
||||
// TODO: Does this need to write to outaddr?
|
||||
|
@ -64,7 +64,7 @@ void Kernel::controlMemory() {
|
|||
if (!isAligned(addr0) || !isAligned(addr1) || !isAligned(size)) {
|
||||
Helpers::panic("ControlMemory: Unaligned parameters\nAddr0: %08X\nAddr1: %08X\nSize: %08X", addr0, addr1, size);
|
||||
}
|
||||
|
||||
|
||||
logSVC("ControlMemory(addr0 = %08X, addr1 = %08X, size = %08X, operation = %X (%c%c%c)%s\n",
|
||||
addr0, addr1, size, operation, r ? 'r' : '-', w ? 'w' : '-', x ? 'x' : '-', linear ? ", linear" : ""
|
||||
);
|
||||
|
@ -90,7 +90,7 @@ void Kernel::controlMemory() {
|
|||
default: Helpers::panic("ControlMemory: unknown operation %X\n", operation);
|
||||
}
|
||||
|
||||
regs[0] = SVCResult::Success;
|
||||
regs[0] = Result::Success;
|
||||
}
|
||||
|
||||
// Result QueryMemory(MemoryInfo* memInfo, PageInfo* pageInfo, u32 addr)
|
||||
|
@ -102,7 +102,7 @@ void Kernel::queryMemory() {
|
|||
logSVC("QueryMemory(mem info pointer = %08X, page info pointer = %08X, addr = %08X)\n", memInfo, pageInfo, addr);
|
||||
|
||||
const auto info = mem.queryMemory(addr);
|
||||
regs[0] = SVCResult::Success;
|
||||
regs[0] = Result::Success;
|
||||
regs[1] = info.baseAddr;
|
||||
regs[2] = info.size;
|
||||
regs[3] = info.perms;
|
||||
|
@ -110,7 +110,7 @@ void Kernel::queryMemory() {
|
|||
regs[5] = 0; // page flags
|
||||
}
|
||||
|
||||
// Result MapMemoryBlock(Handle memblock, u32 addr, MemoryPermission myPermissions, MemoryPermission otherPermission)
|
||||
// Result MapMemoryBlock(Handle memblock, u32 addr, MemoryPermission myPermissions, MemoryPermission otherPermission)
|
||||
void Kernel::mapMemoryBlock() {
|
||||
const Handle block = regs[0];
|
||||
u32 addr = regs[1];
|
||||
|
@ -146,7 +146,7 @@ void Kernel::mapMemoryBlock() {
|
|||
Helpers::panic("MapMemoryBlock where the handle does not refer to a known piece of kernel shared mem");
|
||||
}
|
||||
|
||||
regs[0] = SVCResult::Success;
|
||||
regs[0] = Result::Success;
|
||||
}
|
||||
|
||||
Handle Kernel::makeMemoryBlock(u32 addr, u32 size, u32 myPermission, u32 otherPermission) {
|
||||
|
@ -180,13 +180,13 @@ void Kernel::createMemoryBlock() {
|
|||
|
||||
// Throw error if the size of the shared memory block is not aligned to page boundary
|
||||
if (!isAligned(size)) {
|
||||
regs[0] = SVCResult::UnalignedSize;
|
||||
regs[0] = Result::OS::MisalignedSize;
|
||||
return;
|
||||
}
|
||||
|
||||
// Throw error if one of the permissions is not valid
|
||||
if (!isPermValid(myPermission) || !isPermValid(otherPermission)) {
|
||||
regs[0] = SVCResult::InvalidCombination;
|
||||
regs[0] = Result::OS::InvalidCombination;
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -199,6 +199,6 @@ void Kernel::createMemoryBlock() {
|
|||
if (myPermission == MemoryPermissions::DontCare) myPermission = MemoryPermissions::ReadWrite;
|
||||
if (otherPermission == MemoryPermissions::DontCare) otherPermission = MemoryPermissions::ReadWrite;
|
||||
|
||||
regs[0] = SVCResult::Success;
|
||||
regs[0] = Result::Success;
|
||||
regs[1] = makeMemoryBlock(addr, size, myPermission, otherPermission);
|
||||
}
|
|
@ -43,7 +43,7 @@ void Kernel::connectToPort() {
|
|||
|
||||
if (port.size() > Port::maxNameLen) {
|
||||
Helpers::panic("ConnectToPort: Port name too long\n");
|
||||
regs[0] = SVCResult::PortNameTooLong;
|
||||
regs[0] = Result::OS::PortNameTooLong;
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -51,7 +51,7 @@ void Kernel::connectToPort() {
|
|||
std::optional<Handle> optionalHandle = getPortHandle(port.c_str());
|
||||
if (!optionalHandle.has_value()) [[unlikely]] {
|
||||
Helpers::panic("ConnectToPort: Port doesn't exist\n");
|
||||
regs[0] = SVCResult::ObjectNotFound;
|
||||
regs[0] = Result::Kernel::NotFound;
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -65,7 +65,7 @@ void Kernel::connectToPort() {
|
|||
// TODO: Actually create session
|
||||
Handle sessionHandle = makeSession(portHandle);
|
||||
|
||||
regs[0] = SVCResult::Success;
|
||||
regs[0] = Result::Success;
|
||||
regs[1] = sessionHandle;
|
||||
}
|
||||
|
||||
|
@ -80,7 +80,7 @@ void Kernel::sendSyncRequest() {
|
|||
if (KernelHandles::isServiceHandle(handle)) {
|
||||
// The service call might cause a reschedule and change threads. Hence, set r0 before executing the service call
|
||||
// Because if the service call goes first, we might corrupt the new thread's r0!!
|
||||
regs[0] = SVCResult::Success;
|
||||
regs[0] = Result::Success;
|
||||
serviceManager.sendCommandToService(messagePointer, handle);
|
||||
return;
|
||||
}
|
||||
|
@ -88,7 +88,7 @@ void Kernel::sendSyncRequest() {
|
|||
// Check if our sync request is targetting a file instead of a service
|
||||
bool isFileOperation = getObject(handle, KernelObjectType::File) != nullptr;
|
||||
if (isFileOperation) {
|
||||
regs[0] = SVCResult::Success; // r0 goes first here too
|
||||
regs[0] = Result::Success; // r0 goes first here too
|
||||
handleFileOperation(messagePointer, handle);
|
||||
return;
|
||||
}
|
||||
|
@ -96,7 +96,7 @@ void Kernel::sendSyncRequest() {
|
|||
// Check if our sync request is targetting a directory instead of a service
|
||||
bool isDirectoryOperation = getObject(handle, KernelObjectType::Directory) != nullptr;
|
||||
if (isDirectoryOperation) {
|
||||
regs[0] = SVCResult::Success; // r0 goes first here too
|
||||
regs[0] = Result::Success; // r0 goes first here too
|
||||
handleDirectoryOperation(messagePointer, handle);
|
||||
return;
|
||||
}
|
||||
|
@ -105,7 +105,7 @@ void Kernel::sendSyncRequest() {
|
|||
const auto session = getObject(handle, KernelObjectType::Session);
|
||||
if (session == nullptr) [[unlikely]] {
|
||||
Helpers::panic("SendSyncRequest: Invalid handle");
|
||||
regs[0] = SVCResult::BadHandle;
|
||||
regs[0] = Result::Kernel::InvalidHandle;
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -113,10 +113,10 @@ void Kernel::sendSyncRequest() {
|
|||
const Handle portHandle = sessionData->portHandle;
|
||||
|
||||
if (portHandle == srvHandle) { // Special-case SendSyncRequest targetting the "srv: port"
|
||||
regs[0] = SVCResult::Success;
|
||||
regs[0] = Result::Success;
|
||||
serviceManager.handleSyncRequest(messagePointer);
|
||||
} else if (portHandle == errorPortHandle) { // Special-case "err:f" for juicy logs too
|
||||
regs[0] = SVCResult::Success;
|
||||
regs[0] = Result::Success;
|
||||
handleErrorSyncRequest(messagePointer);
|
||||
} else {
|
||||
const auto portData = objects[portHandle].getData<Port>();
|
||||
|
|
|
@ -10,13 +10,13 @@ void Kernel::getResourceLimit() {
|
|||
logSVC("GetResourceLimit (handle pointer = %08X, process: %s)\n", handlePointer, getProcessName(pid).c_str());
|
||||
|
||||
if (process == nullptr) [[unlikely]] {
|
||||
regs[0] = SVCResult::BadHandle;
|
||||
regs[0] = Result::Kernel::InvalidHandle;
|
||||
return;
|
||||
}
|
||||
|
||||
const auto processData = static_cast<Process*>(process->data);
|
||||
|
||||
regs[0] = SVCResult::Success;
|
||||
regs[0] = Result::Success;
|
||||
regs[1] = processData->limits.handle;
|
||||
}
|
||||
|
||||
|
@ -29,7 +29,7 @@ void Kernel::getResourceLimitLimitValues() {
|
|||
|
||||
const KernelObject* limit = getObject(resourceLimit, KernelObjectType::ResourceLimit);
|
||||
if (limit == nullptr) [[unlikely]] {
|
||||
regs[0] = SVCResult::BadHandle;
|
||||
regs[0] = Result::Kernel::InvalidHandle;
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -46,7 +46,7 @@ void Kernel::getResourceLimitLimitValues() {
|
|||
count--;
|
||||
}
|
||||
|
||||
regs[0] = SVCResult::Success;
|
||||
regs[0] = Result::Success;
|
||||
}
|
||||
|
||||
// Result GetResourceLimitCurrentValues(s64* values, Handle resourceLimit, LimitableResource* names, s32 nameCount)
|
||||
|
@ -59,7 +59,7 @@ void Kernel::getResourceLimitCurrentValues() {
|
|||
|
||||
const KernelObject* limit = getObject(resourceLimit, KernelObjectType::ResourceLimit);
|
||||
if (limit == nullptr) [[unlikely]] {
|
||||
regs[0] = SVCResult::BadHandle;
|
||||
regs[0] = Result::Kernel::InvalidHandle;
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -75,7 +75,7 @@ void Kernel::getResourceLimitCurrentValues() {
|
|||
count--;
|
||||
}
|
||||
|
||||
regs[0] = SVCResult::Success;
|
||||
regs[0] = Result::Success;
|
||||
}
|
||||
|
||||
s32 Kernel::getCurrentResourceValue(const KernelObject* limit, u32 resourceName) {
|
||||
|
|
|
@ -47,7 +47,7 @@ void Kernel::sortThreads() {
|
|||
bool Kernel::canThreadRun(const Thread& t) {
|
||||
if (t.status == ThreadStatus::Ready) {
|
||||
return true;
|
||||
} else if (t.status == ThreadStatus::WaitSleep || t.status == ThreadStatus::WaitSync1
|
||||
} else if (t.status == ThreadStatus::WaitSleep || t.status == ThreadStatus::WaitSync1
|
||||
|| t.status == ThreadStatus::WaitSyncAny || t.status == ThreadStatus::WaitSyncAll) {
|
||||
const u64 elapsedTicks = cpu.getTicks() - t.sleepTick;
|
||||
|
||||
|
@ -81,7 +81,7 @@ std::optional<int> Kernel::getNextThread() {
|
|||
|
||||
void Kernel::switchToNextThread() {
|
||||
std::optional<int> newThreadIndex = getNextThread();
|
||||
|
||||
|
||||
if (!newThreadIndex.has_value()) {
|
||||
log("Kernel tried to switch to the next thread but none found. Switching to random thread\n");
|
||||
assert(aliveThreadCount != 0);
|
||||
|
@ -101,7 +101,7 @@ void Kernel::switchToNextThread() {
|
|||
// See if there;s a higher priority, ready thread and switch to that
|
||||
void Kernel::rescheduleThreads() {
|
||||
std::optional<int> newThreadIndex = getNextThread();
|
||||
|
||||
|
||||
if (newThreadIndex.has_value() && newThreadIndex.value() != currentThreadIndex) {
|
||||
threads[currentThreadIndex].status = ThreadStatus::Ready;
|
||||
switchThread(newThreadIndex.value());
|
||||
|
@ -273,12 +273,12 @@ int Kernel::wakeupOneThread(u64 waitlist, Handle handle) {
|
|||
switch (t.status) {
|
||||
case ThreadStatus::WaitSync1:
|
||||
t.status = ThreadStatus::Ready;
|
||||
t.gprs[0] = SVCResult::Success; // The thread did not timeout, so write success to r0
|
||||
t.gprs[0] = Result::Success; // The thread did not timeout, so write success to r0
|
||||
break;
|
||||
|
||||
case ThreadStatus::WaitSyncAny:
|
||||
t.status = ThreadStatus::Ready;
|
||||
t.gprs[0] = SVCResult::Success; // The thread did not timeout, so write success to r0
|
||||
t.gprs[0] = Result::Success; // The thread did not timeout, so write success to r0
|
||||
|
||||
// Get the index of the event in the object's waitlist, write it to r1
|
||||
for (size_t i = 0; i < t.waitList.size(); i++) {
|
||||
|
@ -308,12 +308,12 @@ void Kernel::wakeupAllThreads(u64 waitlist, Handle handle) {
|
|||
switch (t.status) {
|
||||
case ThreadStatus::WaitSync1:
|
||||
t.status = ThreadStatus::Ready;
|
||||
t.gprs[0] = SVCResult::Success; // The thread did not timeout, so write success to r0
|
||||
t.gprs[0] = Result::Success; // The thread did not timeout, so write success to r0
|
||||
break;
|
||||
|
||||
case ThreadStatus::WaitSyncAny:
|
||||
t.status = ThreadStatus::Ready;
|
||||
t.gprs[0] = SVCResult::Success; // The thread did not timeout, so write success to r0
|
||||
t.gprs[0] = Result::Success; // The thread did not timeout, so write success to r0
|
||||
|
||||
// Get the index of the event in the object's waitlist, write it to r1
|
||||
for (size_t i = 0; i < t.waitList.size(); i++) {
|
||||
|
@ -352,7 +352,7 @@ void Kernel::sleepThread(s64 ns) {
|
|||
}
|
||||
}
|
||||
|
||||
// Result CreateThread(s32 priority, ThreadFunc entrypoint, u32 arg, u32 stacktop, s32 threadPriority, s32 processorID)
|
||||
// Result CreateThread(s32 priority, ThreadFunc entrypoint, u32 arg, u32 stacktop, s32 threadPriority, s32 processorID)
|
||||
void Kernel::createThread() {
|
||||
u32 priority = regs[0];
|
||||
u32 entrypoint = regs[1];
|
||||
|
@ -365,11 +365,11 @@ void Kernel::createThread() {
|
|||
|
||||
if (priority > 0x3F) [[unlikely]] {
|
||||
Helpers::panic("Created thread with bad priority value %X", priority);
|
||||
regs[0] = SVCResult::BadThreadPriority;
|
||||
regs[0] = Result::OS::OutOfRange;
|
||||
return;
|
||||
}
|
||||
|
||||
regs[0] = SVCResult::Success;
|
||||
regs[0] = Result::Success;
|
||||
regs[1] = makeThread(entrypoint, initialSP, priority, id, arg, ThreadStatus::Ready);
|
||||
rescheduleThreads();
|
||||
}
|
||||
|
@ -379,7 +379,7 @@ void Kernel::svcSleepThread() {
|
|||
const s64 ns = s64(u64(regs[0]) | (u64(regs[1]) << 32));
|
||||
//logSVC("SleepThread(ns = %lld)\n", ns);
|
||||
|
||||
regs[0] = SVCResult::Success;
|
||||
regs[0] = Result::Success;
|
||||
sleepThread(ns);
|
||||
}
|
||||
|
||||
|
@ -388,18 +388,18 @@ void Kernel::getThreadID() {
|
|||
logSVC("GetThreadID(handle = %X)\n", handle);
|
||||
|
||||
if (handle == KernelHandles::CurrentThread) {
|
||||
regs[0] = SVCResult::Success;
|
||||
regs[0] = Result::Success;
|
||||
regs[1] = currentThreadIndex;
|
||||
return;
|
||||
}
|
||||
|
||||
const auto thread = getObject(handle, KernelObjectType::Thread);
|
||||
if (thread == nullptr) [[unlikely]] {
|
||||
regs[0] = SVCResult::BadHandle;
|
||||
regs[0] = Result::Kernel::InvalidHandle;
|
||||
return;
|
||||
}
|
||||
|
||||
regs[0] = SVCResult::Success;
|
||||
regs[0] = Result::Success;
|
||||
regs[1] = thread->getData<Thread>()->index;
|
||||
}
|
||||
|
||||
|
@ -408,14 +408,14 @@ void Kernel::getThreadPriority() {
|
|||
logSVC("GetThreadPriority (handle = %X)\n", handle);
|
||||
|
||||
if (handle == KernelHandles::CurrentThread) {
|
||||
regs[0] = SVCResult::Success;
|
||||
regs[0] = Result::Success;
|
||||
regs[1] = threads[currentThreadIndex].priority;
|
||||
} else {
|
||||
auto object = getObject(handle, KernelObjectType::Thread);
|
||||
if (object == nullptr) [[unlikely]] {
|
||||
regs[0] = SVCResult::BadHandle;
|
||||
regs[0] = Result::Kernel::InvalidHandle;
|
||||
} else {
|
||||
regs[0] = SVCResult::Success;
|
||||
regs[0] = Result::Success;
|
||||
regs[1] = object->getData<Thread>()->priority;
|
||||
}
|
||||
}
|
||||
|
@ -427,20 +427,20 @@ void Kernel::setThreadPriority() {
|
|||
logSVC("SetThreadPriority (handle = %X, priority = %X)\n", handle, priority);
|
||||
|
||||
if (priority > 0x3F) {
|
||||
regs[0] = SVCResult::BadThreadPriority;
|
||||
regs[0] = Result::OS::OutOfRange;
|
||||
return;
|
||||
}
|
||||
|
||||
if (handle == KernelHandles::CurrentThread) {
|
||||
regs[0] = SVCResult::Success;
|
||||
regs[0] = Result::Success;
|
||||
threads[currentThreadIndex].priority = priority;
|
||||
} else {
|
||||
auto object = getObject(handle, KernelObjectType::Thread);
|
||||
if (object == nullptr) [[unlikely]] {
|
||||
regs[0] = SVCResult::BadHandle;
|
||||
regs[0] = Result::Kernel::InvalidHandle;
|
||||
return;
|
||||
} else {
|
||||
regs[0] = SVCResult::Success;
|
||||
regs[0] = Result::Success;
|
||||
object->getData<Thread>()->priority = priority;
|
||||
}
|
||||
}
|
||||
|
@ -476,7 +476,7 @@ void Kernel::svcCreateMutex() {
|
|||
bool locked = regs[1] != 0;
|
||||
logSVC("CreateMutex (locked = %s)\n", locked ? "yes" : "no");
|
||||
|
||||
regs[0] = SVCResult::Success;
|
||||
regs[0] = Result::Success;
|
||||
regs[1] = makeMutex(locked);
|
||||
}
|
||||
|
||||
|
@ -487,18 +487,18 @@ void Kernel::svcReleaseMutex() {
|
|||
const auto object = getObject(handle, KernelObjectType::Mutex);
|
||||
if (object == nullptr) [[unlikely]] {
|
||||
Helpers::panic("Tried to release non-existent mutex");
|
||||
regs[0] = SVCResult::BadHandle;
|
||||
regs[0] = Result::Kernel::InvalidHandle;
|
||||
return;
|
||||
}
|
||||
|
||||
Mutex* moo = object->getData<Mutex>();
|
||||
// A thread can't release a mutex it does not own
|
||||
if (!moo->locked || moo->ownerThread != currentThreadIndex) {
|
||||
regs[0] = SVCResult::InvalidMutexRelease;
|
||||
regs[0] = Result::Kernel::InvalidMutexRelease;
|
||||
return;
|
||||
}
|
||||
|
||||
regs[0] = SVCResult::Success;
|
||||
regs[0] = Result::Success;
|
||||
releaseMutex(moo);
|
||||
}
|
||||
|
||||
|
@ -513,7 +513,7 @@ void Kernel::svcCreateSemaphore() {
|
|||
if (initialCount < 0 || maxCount < 0)
|
||||
Helpers::panic("CreateSemaphore: Negative count value");
|
||||
|
||||
regs[0] = SVCResult::Success;
|
||||
regs[0] = Result::Success;
|
||||
regs[1] = makeSemaphore(initialCount, maxCount);
|
||||
}
|
||||
|
||||
|
@ -525,7 +525,7 @@ void Kernel::svcReleaseSemaphore() {
|
|||
const auto object = getObject(handle, KernelObjectType::Semaphore);
|
||||
if (object == nullptr) [[unlikely]] {
|
||||
Helpers::panic("Tried to release non-existent semaphore");
|
||||
regs[0] = SVCResult::BadHandle;
|
||||
regs[0] = Result::Kernel::InvalidHandle;
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -537,7 +537,7 @@ void Kernel::svcReleaseSemaphore() {
|
|||
Helpers::panic("ReleaseSemaphore: Release count too high");
|
||||
|
||||
// Write success and old available count to r0 and r1 respectively
|
||||
regs[0] = SVCResult::Success;
|
||||
regs[0] = Result::Success;
|
||||
regs[1] = s->availableCount;
|
||||
// Bump available count
|
||||
s->availableCount += releaseCount;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue