mirror of
https://github.com/wheremyfoodat/Panda3DS.git
synced 2025-04-21 21:05:50 +12:00
revert formatting
This commit is contained in:
parent
124622cf18
commit
863edac152
7 changed files with 338 additions and 331 deletions
|
@ -5,19 +5,19 @@ using HandleType = u32;
|
|||
|
||||
namespace KernelHandles {
|
||||
enum : u32 {
|
||||
Max = 0xFFFF7FFF, // Max handle the kernel can automagically allocate
|
||||
Max = 0xFFFF7FFF, // Max handle the kernel can automagically allocate
|
||||
|
||||
// Hardcoded handles
|
||||
CurrentThread = 0xFFFF8000, // Used by the original kernel
|
||||
CurrentProcess = 0xFFFF8001, // Used by the original kernel
|
||||
AC, // Something network related
|
||||
ACT, // Handles NNID accounts
|
||||
AM, // Application manager
|
||||
APT, // App Title something service?
|
||||
BOSS, // Streetpass stuff?
|
||||
CAM, // Camera service
|
||||
CECD, // More Streetpass stuff?
|
||||
CFG_U, // CFG service (Console & region info)
|
||||
CurrentThread = 0xFFFF8000, // Used by the original kernel
|
||||
CurrentProcess = 0xFFFF8001, // Used by the original kernel
|
||||
AC, // Something network related
|
||||
ACT, // Handles NNID accounts
|
||||
AM, // Application manager
|
||||
APT, // App Title something service?
|
||||
BOSS, // Streetpass stuff?
|
||||
CAM, // Camera service
|
||||
CECD, // More Streetpass stuff?
|
||||
CFG_U, // CFG service (Console & region info)
|
||||
CFG_I,
|
||||
CFG_S, // Used by most system apps in lieu of cfg:u
|
||||
CSND, // Plays audio directly from PCM samples
|
||||
|
@ -50,10 +50,10 @@ namespace KernelHandles {
|
|||
MinServiceHandle = AC,
|
||||
MaxServiceHandle = Y2R,
|
||||
|
||||
GSPSharedMemHandle = MaxServiceHandle + 1, // HandleType for the GSP shared memory
|
||||
GSPSharedMemHandle = MaxServiceHandle + 1, // Handle for the GSP shared memory
|
||||
FontSharedMemHandle,
|
||||
CSNDSharedMemHandle,
|
||||
APTCaptureSharedMemHandle, // Shared memory for display capture info,
|
||||
APTCaptureSharedMemHandle, // Shared memory for display capture info,
|
||||
HIDSharedMemHandle,
|
||||
|
||||
MinSharedMemHandle = GSPSharedMemHandle,
|
||||
|
@ -61,10 +61,14 @@ namespace KernelHandles {
|
|||
};
|
||||
|
||||
// Returns whether "handle" belongs to one of the OS services
|
||||
static constexpr bool isServiceHandle(HandleType handle) { return handle >= MinServiceHandle && handle <= MaxServiceHandle; }
|
||||
static constexpr bool isServiceHandle(HandleType handle) {
|
||||
return handle >= MinServiceHandle && handle <= MaxServiceHandle;
|
||||
}
|
||||
|
||||
// Returns whether "handle" belongs to one of the OS services' shared memory areas
|
||||
static constexpr bool isSharedMemHandle(HandleType handle) { return handle >= MinSharedMemHandle && handle <= MaxSharedMemHandle; }
|
||||
static constexpr bool isSharedMemHandle(HandleType handle) {
|
||||
return handle >= MinSharedMemHandle && handle <= MaxSharedMemHandle;
|
||||
}
|
||||
|
||||
// Returns the name of a handle as a string based on the given handle
|
||||
static const char* getServiceName(HandleType handle) {
|
||||
|
@ -106,4 +110,4 @@ namespace KernelHandles {
|
|||
default: return "Unknown";
|
||||
}
|
||||
}
|
||||
} // namespace KernelHandles
|
||||
}
|
||||
|
|
|
@ -45,12 +45,12 @@ class Kernel {
|
|||
HandleType currentProcess;
|
||||
HandleType mainThread;
|
||||
int currentThreadIndex;
|
||||
HandleType srvHandle; // HandleType for the special service manager port "srv:"
|
||||
HandleType errorPortHandle; // HandleType for the err:f port used for displaying errors
|
||||
HandleType srvHandle; // Handle for the special service manager port "srv:"
|
||||
HandleType errorPortHandle; // Handle for the err:f port used for displaying errors
|
||||
|
||||
u32 arbiterCount;
|
||||
u32 threadCount; // How many threads in our thread pool have been used as of now (Up to 32)
|
||||
u32 aliveThreadCount; // How many of these threads are actually alive?
|
||||
u32 threadCount; // How many threads in our thread pool have been used as of now (Up to 32)
|
||||
u32 aliveThreadCount; // How many of these threads are actually alive?
|
||||
ServiceManager serviceManager;
|
||||
|
||||
// Top 8 bits are the major version, bottom 8 are the minor version
|
||||
|
@ -66,7 +66,7 @@ class Kernel {
|
|||
HandleType makeThread(u32 entrypoint, u32 initialSP, u32 priority, ProcessorID id, u32 arg, ThreadStatus status = ThreadStatus::Dormant);
|
||||
HandleType makeMemoryBlock(u32 addr, u32 size, u32 myPermission, u32 otherPermission);
|
||||
|
||||
public:
|
||||
public:
|
||||
// Needs to be public to be accessible to the APT/HID services
|
||||
HandleType makeEvent(ResetType resetType, Event::CallbackType callback = Event::CallbackType::None);
|
||||
// Needs to be public to be accessible to the APT/DSP services
|
||||
|
@ -88,7 +88,7 @@ class Kernel {
|
|||
}
|
||||
}
|
||||
|
||||
private:
|
||||
private:
|
||||
void signalArbiter(u32 waitingAddress, s32 threadCount);
|
||||
void sleepThread(s64 ns);
|
||||
void sleepThreadOnArbiter(u32 waitingAddress);
|
||||
|
@ -194,7 +194,7 @@ class Kernel {
|
|||
void closeDirectory(u32 messagePointer, HandleType directory);
|
||||
void readDirectory(u32 messagePointer, HandleType directory);
|
||||
|
||||
public:
|
||||
public:
|
||||
Kernel(CPU& cpu, Memory& mem, GPU& gpu, const EmulatorConfig& config);
|
||||
void initializeFS() { return serviceManager.initializeFS(); }
|
||||
void setVersion(u8 major, u8 minor);
|
||||
|
|
|
@ -1,102 +1,99 @@
|
|||
#pragma once
|
||||
#include <array>
|
||||
#include <cstring>
|
||||
|
||||
#include "fs/archive_base.hpp"
|
||||
#include "handles.hpp"
|
||||
#include "helpers.hpp"
|
||||
#include "result/result.hpp"
|
||||
|
||||
enum class KernelObjectType : u8 {
|
||||
AddressArbiter,
|
||||
Archive,
|
||||
Directory,
|
||||
File,
|
||||
MemoryBlock,
|
||||
Process,
|
||||
ResourceLimit,
|
||||
Session,
|
||||
Dummy,
|
||||
AddressArbiter, Archive, Directory, File, MemoryBlock, Process, ResourceLimit, Session, Dummy,
|
||||
// Bundle waitable objects together in the enum to let the compiler optimize certain checks better
|
||||
Event,
|
||||
Mutex,
|
||||
Port,
|
||||
Semaphore,
|
||||
Timer,
|
||||
Thread
|
||||
Event, Mutex, Port, Semaphore, Timer, Thread
|
||||
};
|
||||
|
||||
enum class ResourceLimitCategory : int { Application = 0, SystemApplet = 1, LibraryApplet = 2, Misc = 3 };
|
||||
enum class ResourceLimitCategory : int {
|
||||
Application = 0,
|
||||
SystemApplet = 1,
|
||||
LibraryApplet = 2,
|
||||
Misc = 3
|
||||
};
|
||||
|
||||
// Reset types (for use with events and timers)
|
||||
enum class ResetType {
|
||||
OneShot = 0, // When the primitive is signaled, it will wake up exactly one thread and will clear itself automatically.
|
||||
Sticky = 1, // When the primitive is signaled, it will wake up all threads and it won't clear itself automatically.
|
||||
Pulse = 2, // Only meaningful for timers: same as ONESHOT but it will periodically signal the timer instead of just once.
|
||||
OneShot = 0, // When the primitive is signaled, it will wake up exactly one thread and will clear itself automatically.
|
||||
Sticky = 1, // When the primitive is signaled, it will wake up all threads and it won't clear itself automatically.
|
||||
Pulse = 2, // Only meaningful for timers: same as ONESHOT but it will periodically signal the timer instead of just once.
|
||||
};
|
||||
|
||||
enum class ArbitrationType { Signal = 0, WaitIfLess = 1, DecrementAndWaitIfLess = 2, WaitIfLessTimeout = 3, DecrementAndWaitIfLessTimeout = 4 };
|
||||
enum class ArbitrationType {
|
||||
Signal = 0,
|
||||
WaitIfLess = 1,
|
||||
DecrementAndWaitIfLess = 2,
|
||||
WaitIfLessTimeout = 3,
|
||||
DecrementAndWaitIfLessTimeout = 4
|
||||
};
|
||||
|
||||
enum class ProcessorID : s32 {
|
||||
AllCPUs = -1,
|
||||
Default = -2,
|
||||
AllCPUs = -1,
|
||||
Default = -2,
|
||||
|
||||
AppCore = 0,
|
||||
Syscore = 1,
|
||||
New3DSExtra1 = 2,
|
||||
New3DSExtra2 = 3
|
||||
AppCore = 0,
|
||||
Syscore = 1,
|
||||
New3DSExtra1 = 2,
|
||||
New3DSExtra2 = 3
|
||||
};
|
||||
|
||||
struct AddressArbiter {};
|
||||
|
||||
struct ResourceLimits {
|
||||
HandleType handle;
|
||||
HandleType handle;
|
||||
|
||||
s32 currentCommit = 0;
|
||||
s32 currentCommit = 0;
|
||||
};
|
||||
|
||||
struct Process {
|
||||
// Resource limits for this process
|
||||
ResourceLimits limits;
|
||||
// Process ID
|
||||
u32 id;
|
||||
// Resource limits for this process
|
||||
ResourceLimits limits;
|
||||
// Process ID
|
||||
u32 id;
|
||||
|
||||
Process(u32 id) : id(id) {}
|
||||
Process(u32 id) : id(id) {}
|
||||
};
|
||||
|
||||
struct Event {
|
||||
// Some events (for now, only the DSP semaphore events) need to execute a callback when signalled
|
||||
// This enum stores what kind of callback they should execute
|
||||
enum class CallbackType : u32 {
|
||||
None,
|
||||
DSPSemaphore,
|
||||
};
|
||||
// Some events (for now, only the DSP semaphore events) need to execute a callback when signalled
|
||||
// This enum stores what kind of callback they should execute
|
||||
enum class CallbackType : u32 {
|
||||
None,
|
||||
DSPSemaphore,
|
||||
};
|
||||
|
||||
u64 waitlist; // A bitfield where each bit symbolizes if the thread with thread with the corresponding index is waiting on the event
|
||||
ResetType resetType = ResetType::OneShot;
|
||||
CallbackType callback = CallbackType::None;
|
||||
bool fired = false;
|
||||
u64 waitlist; // A bitfield where each bit symbolizes if the thread with thread with the corresponding index is waiting on the event
|
||||
ResetType resetType = ResetType::OneShot;
|
||||
CallbackType callback = CallbackType::None;
|
||||
bool fired = false;
|
||||
|
||||
Event(ResetType resetType) : resetType(resetType), waitlist(0) {}
|
||||
Event(ResetType resetType, CallbackType cb) : resetType(resetType), waitlist(0), callback(cb) {}
|
||||
Event(ResetType resetType) : resetType(resetType), waitlist(0) {}
|
||||
Event(ResetType resetType, CallbackType cb) : resetType(resetType), waitlist(0), callback(cb) {}
|
||||
};
|
||||
|
||||
struct Port {
|
||||
static constexpr u32 maxNameLen = 11;
|
||||
static constexpr u32 maxNameLen = 11;
|
||||
|
||||
char name[maxNameLen + 1] = {};
|
||||
bool isPublic = false; // Setting name=NULL creates a private port not accessible from svcConnectToPort.
|
||||
char name[maxNameLen + 1] = {};
|
||||
bool isPublic = false; // Setting name=NULL creates a private port not accessible from svcConnectToPort.
|
||||
|
||||
Port(const char* name) {
|
||||
// If the name is empty (ie the first char is the null terminator) then the port is private
|
||||
isPublic = name[0] != '\0';
|
||||
std::strncpy(this->name, name, maxNameLen);
|
||||
}
|
||||
Port(const char* name) {
|
||||
// If the name is empty (ie the first char is the null terminator) then the port is private
|
||||
isPublic = name[0] != '\0';
|
||||
std::strncpy(this->name, name, maxNameLen);
|
||||
}
|
||||
};
|
||||
|
||||
struct Session {
|
||||
HandleType portHandle; // The port this session is subscribed to
|
||||
Session(HandleType portHandle) : portHandle(portHandle) {}
|
||||
HandleType portHandle; // The port this session is subscribed to
|
||||
Session(HandleType portHandle) : portHandle(portHandle) {}
|
||||
};
|
||||
|
||||
enum class ThreadStatus {
|
||||
|
@ -145,102 +142,101 @@ struct Thread {
|
|||
};
|
||||
|
||||
static const char* kernelObjectTypeToString(KernelObjectType t) {
|
||||
switch (t) {
|
||||
case KernelObjectType::AddressArbiter: return "address arbiter";
|
||||
case KernelObjectType::Archive: return "archive";
|
||||
case KernelObjectType::Directory: return "directory";
|
||||
case KernelObjectType::Event: return "event";
|
||||
case KernelObjectType::File: return "file";
|
||||
case KernelObjectType::MemoryBlock: return "memory block";
|
||||
case KernelObjectType::Port: return "port";
|
||||
case KernelObjectType::Process: return "process";
|
||||
case KernelObjectType::ResourceLimit: return "resource limit";
|
||||
case KernelObjectType::Session: return "session";
|
||||
case KernelObjectType::Mutex: return "mutex";
|
||||
case KernelObjectType::Semaphore: return "semaphore";
|
||||
case KernelObjectType::Thread: return "thread";
|
||||
case KernelObjectType::Dummy: return "dummy";
|
||||
default: return "unknown";
|
||||
}
|
||||
switch (t) {
|
||||
case KernelObjectType::AddressArbiter: return "address arbiter";
|
||||
case KernelObjectType::Archive: return "archive";
|
||||
case KernelObjectType::Directory: return "directory";
|
||||
case KernelObjectType::Event: return "event";
|
||||
case KernelObjectType::File: return "file";
|
||||
case KernelObjectType::MemoryBlock: return "memory block";
|
||||
case KernelObjectType::Port: return "port";
|
||||
case KernelObjectType::Process: return "process";
|
||||
case KernelObjectType::ResourceLimit: return "resource limit";
|
||||
case KernelObjectType::Session: return "session";
|
||||
case KernelObjectType::Mutex: return "mutex";
|
||||
case KernelObjectType::Semaphore: return "semaphore";
|
||||
case KernelObjectType::Thread: return "thread";
|
||||
case KernelObjectType::Dummy: return "dummy";
|
||||
default: return "unknown";
|
||||
}
|
||||
}
|
||||
|
||||
struct Mutex {
|
||||
u64 waitlist; // Refer to the getWaitlist function below for documentation
|
||||
HandleType ownerThread = 0; // Index of the thread that holds the mutex if it's locked
|
||||
HandleType handle; // HandleType of the mutex itself
|
||||
u32 lockCount; // Number of times this mutex has been locked by its daddy. 0 = not locked
|
||||
bool locked;
|
||||
u64 waitlist; // Refer to the getWaitlist function below for documentation
|
||||
HandleType ownerThread = 0; // Index of the thread that holds the mutex if it's locked
|
||||
HandleType handle; // HandleType of the mutex itself
|
||||
u32 lockCount; // Number of times this mutex has been locked by its daddy. 0 = not locked
|
||||
bool locked;
|
||||
|
||||
Mutex(bool lock, HandleType handle) : locked(lock), waitlist(0), lockCount(lock ? 1 : 0), handle(handle) {}
|
||||
Mutex(bool lock, HandleType handle) : locked(lock), waitlist(0), lockCount(lock ? 1 : 0), handle(handle) {}
|
||||
};
|
||||
|
||||
struct Semaphore {
|
||||
u64 waitlist; // Refer to the getWaitlist function below for documentation
|
||||
s32 availableCount;
|
||||
s32 maximumCount;
|
||||
u64 waitlist; // Refer to the getWaitlist function below for documentation
|
||||
s32 availableCount;
|
||||
s32 maximumCount;
|
||||
|
||||
Semaphore(s32 initialCount, s32 maximumCount) : availableCount(initialCount), maximumCount(maximumCount), waitlist(0) {}
|
||||
Semaphore(s32 initialCount, s32 maximumCount) : availableCount(initialCount), maximumCount(maximumCount), waitlist(0) {}
|
||||
};
|
||||
|
||||
struct Timer {
|
||||
u64 waitlist; // Refer to the getWaitlist function below for documentation
|
||||
ResetType resetType = ResetType::OneShot;
|
||||
u64 waitlist; // Refer to the getWaitlist function below for documentation
|
||||
ResetType resetType = ResetType::OneShot;
|
||||
|
||||
u64 fireTick; // CPU tick the timer will be fired
|
||||
u64 interval; // Number of ns until the timer fires for the second and future times
|
||||
bool fired; // Has this timer been signalled?
|
||||
bool running; // Is this timer running or stopped?
|
||||
u64 fireTick; // CPU tick the timer will be fired
|
||||
u64 interval; // Number of ns until the timer fires for the second and future times
|
||||
bool fired; // Has this timer been signalled?
|
||||
bool running; // Is this timer running or stopped?
|
||||
|
||||
Timer(ResetType type) : resetType(type), fireTick(0), interval(0), waitlist(0), fired(false), running(false) {}
|
||||
Timer(ResetType type) : resetType(type), fireTick(0), interval(0), waitlist(0), fired(false), running(false) {}
|
||||
};
|
||||
|
||||
struct MemoryBlock {
|
||||
u32 addr = 0;
|
||||
u32 size = 0;
|
||||
u32 myPermission = 0;
|
||||
u32 otherPermission = 0;
|
||||
bool mapped = false;
|
||||
u32 addr = 0;
|
||||
u32 size = 0;
|
||||
u32 myPermission = 0;
|
||||
u32 otherPermission = 0;
|
||||
bool mapped = false;
|
||||
|
||||
MemoryBlock(u32 addr, u32 size, u32 myPerm, u32 otherPerm)
|
||||
: addr(addr), size(size), myPermission(myPerm), otherPermission(otherPerm), mapped(false) {}
|
||||
MemoryBlock(u32 addr, u32 size, u32 myPerm, u32 otherPerm) : addr(addr), size(size), myPermission(myPerm), otherPermission(otherPerm), mapped(false) {}
|
||||
};
|
||||
|
||||
// Generic kernel object class
|
||||
struct KernelObject {
|
||||
HandleType handle = 0; // A u32 the OS will use to identify objects
|
||||
void* data = nullptr;
|
||||
KernelObjectType type;
|
||||
HandleType handle = 0; // A u32 the OS will use to identify objects
|
||||
void* data = nullptr;
|
||||
KernelObjectType type;
|
||||
|
||||
KernelObject(HandleType handle, KernelObjectType type) : handle(handle), type(type) {}
|
||||
KernelObject(HandleType handle, KernelObjectType type) : handle(handle), type(type) {}
|
||||
|
||||
// Our destructor does not free the data in order to avoid it being freed when our std::vector is expanded
|
||||
// Thus, the kernel needs to delete it when appropriate
|
||||
~KernelObject() {}
|
||||
// Our destructor does not free the data in order to avoid it being freed when our std::vector is expanded
|
||||
// Thus, the kernel needs to delete it when appropriate
|
||||
~KernelObject() {}
|
||||
|
||||
template <typename T>
|
||||
T* getData() {
|
||||
return static_cast<T*>(data);
|
||||
}
|
||||
template <typename T>
|
||||
T* getData() {
|
||||
return static_cast<T*>(data);
|
||||
}
|
||||
|
||||
const char* getTypeName() const { return kernelObjectTypeToString(type); }
|
||||
const char* getTypeName() const { return kernelObjectTypeToString(type); }
|
||||
|
||||
// Retrieves a reference to the waitlist for a specified object
|
||||
// We return a reference because this function is only called in the kernel threading internals
|
||||
// We want the kernel to be able to easily manage waitlists, by reading/parsing them or setting/clearing bits.
|
||||
// As we mention in the definition of the "Event" struct, the format for wailists is very simple and made to be efficient.
|
||||
// Each bit corresponds to a thread index and denotes whether the corresponding thread is waiting on this object
|
||||
// For example if bit 0 of the wait list is set, then the thread with index 0 is waiting on our object
|
||||
u64& getWaitlist() {
|
||||
// This code is actually kinda trash but eh good enough
|
||||
switch (type) {
|
||||
case KernelObjectType::Event: return getData<Event>()->waitlist;
|
||||
case KernelObjectType::Mutex: return getData<Mutex>()->waitlist;
|
||||
case KernelObjectType::Semaphore: return getData<Mutex>()->waitlist;
|
||||
case KernelObjectType::Thread: return getData<Thread>()->threadsWaitingForTermination;
|
||||
case KernelObjectType::Timer: return getData<Timer>()->waitlist;
|
||||
// Retrieves a reference to the waitlist for a specified object
|
||||
// We return a reference because this function is only called in the kernel threading internals
|
||||
// We want the kernel to be able to easily manage waitlists, by reading/parsing them or setting/clearing bits.
|
||||
// As we mention in the definition of the "Event" struct, the format for wailists is very simple and made to be efficient.
|
||||
// Each bit corresponds to a thread index and denotes whether the corresponding thread is waiting on this object
|
||||
// For example if bit 0 of the wait list is set, then the thread with index 0 is waiting on our object
|
||||
u64& getWaitlist() {
|
||||
// This code is actually kinda trash but eh good enough
|
||||
switch (type) {
|
||||
case KernelObjectType::Event: return getData<Event>()->waitlist;
|
||||
case KernelObjectType::Mutex: return getData<Mutex>()->waitlist;
|
||||
case KernelObjectType::Semaphore: return getData<Mutex>()->waitlist;
|
||||
case KernelObjectType::Thread: return getData<Thread>()->threadsWaitingForTermination;
|
||||
case KernelObjectType::Timer: return getData<Timer>()->waitlist;
|
||||
|
||||
// This should be unreachable once we fully implement sync objects
|
||||
default: [[unlikely]] Helpers::panic("Called GetWaitList on kernel object without a waitlist (Type: %s)", getTypeName());
|
||||
}
|
||||
}
|
||||
// This should be unreachable once we fully implement sync objects
|
||||
default: [[unlikely]] Helpers::panic("Called GetWaitList on kernel object without a waitlist (Type: %s)", getTypeName());
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue