[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 createEvent();
void createThread(); void createThread();
void controlMemory(); void controlMemory();
void duplicateHandle();
void mapMemoryBlock(); void mapMemoryBlock();
void queryMemory(); void queryMemory();
void getProcessInfo(); void getProcessInfo();
@ -97,6 +98,7 @@ class Kernel {
void getResourceLimitLimitValues(); void getResourceLimitLimitValues();
void getResourceLimitCurrentValues(); void getResourceLimitCurrentValues();
void getSystemTick(); void getSystemTick();
void getThreadID();
void sendSyncRequest(); void sendSyncRequest();
void svcCloseHandle(); void svcCloseHandle();
void connectToPort(); void connectToPort();

View file

@ -102,9 +102,11 @@ struct Thread {
u32 initialSP; // Initial r13 value u32 initialSP; // Initial r13 value
u32 entrypoint; // Initial r15 value u32 entrypoint; // Initial r15 value
u32 priority; u32 priority;
u32 arg;
s32 processorID; s32 processorID;
ThreadStatus status; ThreadStatus status;
Handle handle; // OS handle for this thread 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 // The waiting address for threads that are waiting on an AddressArbiter
u32 waitingAddress; u32 waitingAddress;

View file

@ -9,6 +9,7 @@ Kernel::Kernel(CPU& cpu, Memory& mem, GPU& gpu)
portHandles.reserve(32); portHandles.reserve(32);
for (int i = 0; i < threads.size(); i++) { for (int i = 0; i < threads.size(); 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;
} }
@ -28,10 +29,12 @@ void Kernel::serviceSVC(u32 svc) {
case 0x22: arbitrateAddress(); break; case 0x22: arbitrateAddress(); break;
case 0x23: svcCloseHandle(); break; case 0x23: svcCloseHandle(); break;
case 0x24: waitSynchronization1(); break; case 0x24: waitSynchronization1(); break;
case 0x27: duplicateHandle(); break;
case 0x28: getSystemTick(); break; case 0x28: getSystemTick(); break;
case 0x2B: getProcessInfo(); break; case 0x2B: getProcessInfo(); break;
case 0x2D: connectToPort(); break; case 0x2D: connectToPort(); break;
case 0x32: sendSyncRequest(); break; case 0x32: sendSyncRequest(); break;
case 0x37: getThreadID(); break;
case 0x38: getResourceLimit(); break; case 0x38: getResourceLimit(); break;
case 0x39: getResourceLimitLimitValues(); break; case 0x39: getResourceLimitLimitValues(); break;
case 0x3A: getResourceLimitCurrentValues(); 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. // 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, // 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 // 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; currentThreadIndex = 0;
// Create global service manager port // Create global service manager port
@ -139,6 +142,7 @@ void Kernel::outputDebugString() {
regs[0] = SVCResult::Success; regs[0] = SVCResult::Success;
} }
// Result GetProcessInfo(s64* out, Handle process, ProcessInfoType type)
void Kernel::getProcessInfo() { void Kernel::getProcessInfo() {
const auto pid = regs[1]; const auto pid = regs[1];
const auto type = regs[2]; const auto type = regs[2];
@ -163,6 +167,21 @@ void Kernel::getProcessInfo() {
regs[0] = SVCResult::Success; 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) { std::string Kernel::getProcessName(u32 pid) {
if (pid == KernelHandles::CurrentProcess) { if (pid == KernelHandles::CurrentProcess) {
return "current"; return "current";

View file

@ -70,16 +70,11 @@ void Kernel::controlMemory() {
} }
// Result QueryMemory(MemoryInfo* memInfo, PageInfo* pageInfo, u32 addr) // Result QueryMemory(MemoryInfo* memInfo, PageInfo* pageInfo, u32 addr)
// TODO: Is this SVC supposed to write to memory or...?
void Kernel::queryMemory() { void Kernel::queryMemory() {
const u32 memInfo = regs[0]; const u32 memInfo = regs[0];
const u32 pageInfo = regs[1]; const u32 pageInfo = regs[1];
const u32 addr = regs[2]; 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); printf("QueryMemory(mem info pointer = %08X, page info pointer = %08X, addr = %08X)\n", memInfo, pageInfo, addr);
const auto info = mem.queryMemory(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.gprs.fill(0);
t.fprs.fill(0); t.fprs.fill(0);
t.arg = arg;
t.initialSP = initialSP; t.initialSP = initialSP;
t.entrypoint = entrypoint; t.entrypoint = entrypoint;
@ -93,4 +94,25 @@ void Kernel::sleepThreadOnArbiter(u32 waitingAddress) {
t.status = ThreadStatus::WaitArbiter; t.status = ThreadStatus::WaitArbiter;
t.waitingAddress = waitingAddress; t.waitingAddress = waitingAddress;
switchThread(1); // TODO: Properly change threads 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;
} }