mirror of
https://github.com/wheremyfoodat/Panda3DS.git
synced 2025-04-07 22:55:40 +12:00
[Kernel] Implement GetThreadID, stub DuplicateHandle
This commit is contained in:
parent
0b2e22ca6d
commit
aef1520f17
5 changed files with 46 additions and 6 deletions
|
@ -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();
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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";
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
Loading…
Add table
Reference in a new issue