Merge branch 'master' into timerz

This commit is contained in:
wheremyfoodat 2023-08-21 18:57:18 +03:00
commit 1d601e41ba
63 changed files with 871 additions and 262282 deletions

View file

@ -3,8 +3,8 @@
#include "kernel_types.hpp"
#include "cpu.hpp"
Kernel::Kernel(CPU& cpu, Memory& mem, GPU& gpu)
: cpu(cpu), regs(cpu.regs()), mem(mem), handleCounter(0), serviceManager(regs, mem, gpu, currentProcess, *this) {
Kernel::Kernel(CPU& cpu, Memory& mem, GPU& gpu, const EmulatorConfig& config)
: cpu(cpu), regs(cpu.regs()), mem(mem), handleCounter(0), serviceManager(regs, mem, gpu, currentProcess, *this, config) {
objects.reserve(512); // Make room for a few objects to avoid further memory allocs later
mutexHandles.reserve(8);
timerHandles.reserve(8);
@ -36,6 +36,8 @@ void Kernel::serviceSVC(u32 svc) {
case 0x0A: svcSleepThread(); break;
case 0x0B: getThreadPriority(); break;
case 0x0C: setThreadPriority(); break;
case 0x0F: getThreadIdealProcessor(); break;
case 0x11: getCurrentProcessorNumber(); break;
case 0x13: svcCreateMutex(); break;
case 0x14: svcReleaseMutex(); break;
case 0x15: svcCreateSemaphore(); break;
@ -161,7 +163,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, VirtualAddrs::StackTop, 0x30, -2, 0, ThreadStatus::Running);
mainThread = makeThread(0, VirtualAddrs::StackTop, 0x30, ProcessorID::Default, 0, ThreadStatus::Running);
currentThreadIndex = 0;
setupIdleThread();

View file

@ -1,5 +1,4 @@
#include "kernel.hpp"
#include "services/shared_font.hpp"
namespace Operation {
enum : u32 {
@ -137,7 +136,7 @@ void Kernel::mapMemoryBlock() {
break;
case KernelHandles::FontSharedMemHandle:
std::memcpy(ptr, _shared_font_bin, _shared_font_len);
mem.copySharedFont(ptr);
break;
default: Helpers::panic("Mapping unknown shared memory block: %X", block);

View file

@ -109,7 +109,7 @@ void Kernel::sendSyncRequest() {
// If we're actually communicating with a port
const auto session = getObject(handle, KernelObjectType::Session);
if (session == nullptr) [[unlikely]] {
Helpers::panic("SendSyncRequest: Invalid handle");
Helpers::warn("SendSyncRequest: Invalid handle");
regs[0] = Result::Kernel::InvalidHandle;
return;
}
@ -127,4 +127,4 @@ void Kernel::sendSyncRequest() {
const auto portData = objects[portHandle].getData<Port>();
Helpers::panic("SendSyncRequest targetting port %s\n", portData->name);
}
}
}

View file

@ -89,6 +89,7 @@ s32 Kernel::getCurrentResourceValue(const KernelObject* limit, u32 resourceName)
u32 Kernel::getMaxForResource(const KernelObject* limit, u32 resourceName) {
switch (resourceName) {
case ResourceType::Commit: return appResourceLimits.maxCommit;
case ResourceType::Thread: return appResourceLimits.maxThreads;
default: Helpers::panic("Attempted to get the max of unknown kernel resource: %d\n", resourceName);
}
}
}

View file

@ -106,7 +106,7 @@ void Kernel::rescheduleThreads() {
}
// Internal OS function to spawn a thread
Handle Kernel::makeThread(u32 entrypoint, u32 initialSP, u32 priority, s32 id, u32 arg, ThreadStatus status) {
Handle Kernel::makeThread(u32 entrypoint, u32 initialSP, u32 priority, ProcessorID id, u32 arg, ThreadStatus status) {
int index; // Index of the created thread in the threads array
if (threadCount < appResourceLimits.maxThreads) [[likely]] { // If we have not yet created over too many threads
@ -397,8 +397,12 @@ void Kernel::createThread() {
return;
}
if (id < -2 || id > 3) {
Helpers::panic("Invalid processor ID in CreateThread");
}
regs[0] = Result::Success;
regs[1] = makeThread(entrypoint, initialSP, priority, id, arg, ThreadStatus::Ready);
regs[1] = makeThread(entrypoint, initialSP, priority, static_cast<ProcessorID>(id), arg, ThreadStatus::Ready);
requireReschedule();
}
@ -449,6 +453,15 @@ void Kernel::getThreadPriority() {
}
}
void Kernel::getThreadIdealProcessor() {
const Handle handle = regs[1]; // Thread handle
logSVC("GetThreadIdealProcessor (handle = %X)\n", handle);
// TODO: Not documented what this is or what it does. Citra doesn't implement it at all. Return AppCore as the ideal processor for now
regs[0] = Result::Success;
regs[1] = static_cast<u32>(ProcessorID::AppCore);
}
void Kernel::setThreadPriority() {
const Handle handle = regs[0];
const u32 priority = regs[1];
@ -476,6 +489,33 @@ void Kernel::setThreadPriority() {
requireReschedule();
}
void Kernel::getCurrentProcessorNumber() {
logSVC("GetCurrentProcessorNumber()\n");
const ProcessorID id = threads[currentThreadIndex].processorID;
s32 ret;
// Until we properly implement per-core schedulers, return whatever processor ID passed to svcCreateThread
switch (id) {
// TODO: This is picked from exheader
case ProcessorID::Default:
ret = static_cast<s32>(ProcessorID::AppCore);
break;
case ProcessorID::AllCPUs:
ret = static_cast<s32>(ProcessorID::AppCore);
Helpers::warn("GetCurrentProcessorNumber on thread created to run on all CPUs...?\n");
break;
default: ret = static_cast<s32>(id); break;
}
if (ret != static_cast<s32>(ProcessorID::AppCore)) {
Helpers::warn("GetCurrentProcessorNumber: Thread not running on appcore\n");
}
regs[0] = static_cast<u32>(ret);
}
void Kernel::exitThread() {
logSVC("ExitThread\n");
@ -630,4 +670,4 @@ bool Kernel::shouldWaitOnObject(KernelObject* object) {
Helpers::panic("Not sure whether to wait on object (type: %s)", object->getTypeName());
return true;
}
}
}