[Kernel] Implement GetThreadID, stub DuplicateHandle

This commit is contained in:
wheremyfoodat 2022-09-22 00:02:50 +03:00
parent 0b2e22ca6d
commit aef1520f17
5 changed files with 46 additions and 6 deletions

View file

@ -90,6 +90,7 @@ class Kernel {
void createEvent();
void createThread();
void controlMemory();
void duplicateHandle();
void mapMemoryBlock();
void queryMemory();
void getProcessInfo();
@ -97,6 +98,7 @@ class Kernel {
void getResourceLimitLimitValues();
void getResourceLimitCurrentValues();
void getSystemTick();
void getThreadID();
void sendSyncRequest();
void svcCloseHandle();
void connectToPort();

View file

@ -102,9 +102,11 @@ struct Thread {
u32 initialSP; // Initial r13 value
u32 entrypoint; // Initial r15 value
u32 priority;
u32 arg;
s32 processorID;
ThreadStatus status;
Handle handle; // OS handle for this thread
int index; // Index of the thread. 0 for the first thread, 1 for the second, and so on
// The waiting address for threads that are waiting on an AddressArbiter
u32 waitingAddress;

View file

@ -9,6 +9,7 @@ Kernel::Kernel(CPU& cpu, Memory& mem, GPU& gpu)
portHandles.reserve(32);
for (int i = 0; i < threads.size(); i++) {
threads[i].index = i;
threads[i].tlsBase = VirtualAddrs::TLSBase + i * VirtualAddrs::TLSSize;
threads[i].status = ThreadStatus::Dead;
}
@ -28,10 +29,12 @@ void Kernel::serviceSVC(u32 svc) {
case 0x22: arbitrateAddress(); break;
case 0x23: svcCloseHandle(); break;
case 0x24: waitSynchronization1(); break;
case 0x27: duplicateHandle(); break;
case 0x28: getSystemTick(); break;
case 0x2B: getProcessInfo(); break;
case 0x2D: connectToPort(); break;
case 0x32: sendSyncRequest(); break;
case 0x37: getThreadID(); break;
case 0x38: getResourceLimit(); break;
case 0x39: getResourceLimitLimitValues(); break;
case 0x3A: getResourceLimitCurrentValues(); break;
@ -101,7 +104,7 @@ void Kernel::reset() {
// Make main thread object. We do not have to set the entrypoint and SP for it as the ROM loader does.
// Main thread seems to have a priority of 0x30. TODO: This creates a dummy context for thread 0,
// which is thankfully not used. Maybe we should prevent this
mainThread = makeThread(0, 0, 0x30, -2, 0, ThreadStatus::Running);
mainThread = makeThread(0, VirtualAddrs::StackTop, 0x30, -2, 0, ThreadStatus::Running);
currentThreadIndex = 0;
// Create global service manager port
@ -139,6 +142,7 @@ void Kernel::outputDebugString() {
regs[0] = SVCResult::Success;
}
// Result GetProcessInfo(s64* out, Handle process, ProcessInfoType type)
void Kernel::getProcessInfo() {
const auto pid = regs[1];
const auto type = regs[2];
@ -163,6 +167,21 @@ void Kernel::getProcessInfo() {
regs[0] = SVCResult::Success;
}
// Result GetThreadId(u32* threadId, Handle thread)
void Kernel::duplicateHandle() {
Handle original = regs[1];
printf("DuplicateHandle(handle = %X)\n", original);
if (original == KernelHandles::CurrentThread) {
printf("[Warning] Duplicated current thread. This might be horribly broken!\n");
const auto& t = threads[currentThreadIndex];
regs[0] = SVCResult::Success;
regs[1] = makeThread(t.entrypoint, t.initialSP, t.priority, t.processorID, t.arg, t.status);
} else {
Helpers::panic("DuplicateHandle: unimplemented handle type");
}
}
std::string Kernel::getProcessName(u32 pid) {
if (pid == KernelHandles::CurrentProcess) {
return "current";

View file

@ -70,16 +70,11 @@ void Kernel::controlMemory() {
}
// Result QueryMemory(MemoryInfo* memInfo, PageInfo* pageInfo, u32 addr)
// TODO: Is this SVC supposed to write to memory or...?
void Kernel::queryMemory() {
const u32 memInfo = regs[0];
const u32 pageInfo = regs[1];
const u32 addr = regs[2];
if (!isAligned(addr)) [[unlikely]] {
Helpers::panic("QueryMemory: Address not page aligned\n");
}
printf("QueryMemory(mem info pointer = %08X, page info pointer = %08X, addr = %08X)\n", memInfo, pageInfo, addr);
const auto info = mem.queryMemory(addr);

View file

@ -46,6 +46,7 @@ Handle Kernel::makeThread(u32 entrypoint, u32 initialSP, u32 priority, s32 id, u
t.gprs.fill(0);
t.fprs.fill(0);
t.arg = arg;
t.initialSP = initialSP;
t.entrypoint = entrypoint;
@ -93,4 +94,25 @@ void Kernel::sleepThreadOnArbiter(u32 waitingAddress) {
t.status = ThreadStatus::WaitArbiter;
t.waitingAddress = waitingAddress;
switchThread(1); // TODO: Properly change threads
}
void Kernel::getThreadID() {
Handle handle = regs[1];
printf("GetThreadID(handle = %X)\n", handle);
if (handle == KernelHandles::CurrentThread) {
regs[0] = SVCResult::Success;
regs[1] = currentThreadIndex;
return;
}
const auto thread = getObject(handle, KernelObjectType::Thread);
if (thread == nullptr) [[unlikely]] {
regs[0] = SVCResult::BadHandle;
return;
}
regs[0] = SVCResult::Success;
regs[1] = thread->getData<Thread>()->index;
}