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:
Mary 2023-06-16 19:42:02 +02:00
parent c6f5d19983
commit 122b1b2727
73 changed files with 540 additions and 419 deletions

View file

@ -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);

View file

@ -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) {

View file

@ -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

View file

@ -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]);

View file

@ -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];

View file

@ -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);
}

View file

@ -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>();

View file

@ -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) {

View file

@ -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;