Files
P3DS-test/src/core/kernel/address_arbiter.cpp
2022-09-20 01:50:32 +03:00

73 lines
2.1 KiB
C++

#include "kernel.hpp"
#include "resource_limits.hpp"
static const char* arbitrationTypeToString(u32 type) {
switch (type) {
case 0: return "Signal";
case 1: return "Wait if less";
case 2: return "Decrement and wait if less";
case 3: return "Wait if less with timeout";
case 4: return "Decrement and wait if less with timeout";
default: return "Unknown arbitration type";
}
}
Handle Kernel::makeArbiter() {
if (arbiterCount >= appResourceLimits.maxAddressArbiters) {
Helpers::panic("Overflowed the number of address arbiters");
}
arbiterCount++;
Handle ret = makeObject(KernelObjectType::AddressArbiter);
objects[ret].data = new AddressArbiter();
return ret;
}
// Result CreateAddressArbiter(Handle* arbiter)
void Kernel::createAddressArbiter() {
regs[0] = SVCResult::Success;
regs[1] = makeArbiter();
}
// Result ArbitrateAddress(Handle arbiter, u32 addr, ArbitrationType type, s32 value, s64 nanoseconds)
void Kernel::arbitrateAddress() {
const Handle handle = regs[0];
const u32 address = regs[1];
const u32 type = regs[2];
const s32 value = regs[3];
const s64 ns = s64(u64(regs[4]) | (u64(regs[5]) << 32));
printf("ArbitrateAddress(Handle = %X, address = %08X, type = %s, value = %d, ns = %lld)\n", handle, address,
arbitrationTypeToString(type), value, ns);
const auto arbiter = getObject(handle, KernelObjectType::AddressArbiter);
if (arbiter == nullptr) [[unlikely]] {
regs[0] = SVCResult::BadHandle;
return;
}
if (address & 3) {
Helpers::panic("ArbitrateAddres:: Unaligned address");
}
if (value > 4) [[unlikely]] {
regs[0] = SVCResult::InvalidEnumValueAlt;
return;
}
switch (static_cast<ArbitrationType>(type)) {
// Puts this thread to sleep if word < value until another thread signals the address with the type SIGNAL
case ArbitrationType::WaitIfLess: {
s32 word = static_cast<s32>(mem.read32(address)); // Yes this is meant to be signed
if (word < value) {
Helpers::panic("Needa sleep");
}
break;
}
default:
Helpers::panic("ArbitrateAddress: Unimplemented type %s", arbitrationTypeToString(type));
}
regs[0] = SVCResult::Success;
}