diff --git a/src/Cafe/CafeSystem.cpp b/src/Cafe/CafeSystem.cpp index 6e6504a5..33491108 100644 --- a/src/Cafe/CafeSystem.cpp +++ b/src/Cafe/CafeSystem.cpp @@ -1,6 +1,5 @@ #include "Cafe/OS/common/OSCommon.h" #include "WindowSystem.h" -#include "Cafe/OS/libs/gx2/GX2.h" #include "Cafe/GameProfile/GameProfile.h" #include "Cafe/HW/Espresso/Interpreter/PPCInterpreterInternal.h" #include "Cafe/HW/Espresso/Recompiler/PPCRecompiler.h" @@ -27,6 +26,7 @@ #include "GamePatch.h" #include "HW/Espresso/Debugger/GDBStub.h" +#include "Common/CafeStaticVar.h" #include "Cafe/IOSU/legacy/iosu_ioctl.h" #include "Cafe/IOSU/legacy/iosu_act.h" #include "Cafe/IOSU/legacy/iosu_fpd.h" @@ -624,9 +624,6 @@ namespace CafeSystem cemuLog_log(LogType::Force, "Used CPU extensions: {}", g_CPUFeatures.GetCommaSeparatedExtensionList()); // misc systems rplSymbolStorage_init(); - // allocate memory for all SysAllocators - // must happen before COS module init, but also before iosu::kernel::Initialize() - SysAllocatorContainer::GetInstance().Initialize(); // init IOSU modules for(auto& module : s_iosuModules) module->SystemLaunch(); @@ -664,6 +661,7 @@ namespace CafeSystem // shutdown IOSU modules for(auto it = s_iosuModules.rbegin(); it != s_iosuModules.rend(); ++it) (*it)->SystemExit(); + cemu_assert_debug(!IOSUStaticData::HasAnyAllocations()); // check for leak s_initialized = false; } diff --git a/src/Cafe/HW/Espresso/Debugger/Debugger.cpp b/src/Cafe/HW/Espresso/Debugger/Debugger.cpp index 2a9e546e..f0e82e27 100644 --- a/src/Cafe/HW/Espresso/Debugger/Debugger.cpp +++ b/src/Cafe/HW/Espresso/Debugger/Debugger.cpp @@ -5,7 +5,7 @@ #include "Cafe/HW/Espresso/Recompiler/PPCRecompiler.h" #include "Cemu/ExpressionParser/ExpressionParser.h" -#include "Cafe/OS/libs/coreinit/coreinit.h" +#include "Cafe/OS/libs/coreinit/coreinit_Thread.h" #include "OS/RPL/rpl.h" #include "util/helpers/helpers.h" @@ -792,3 +792,4 @@ bool debugger_getOptionLogOnlyMemoryBreakpoints() { return s_debuggerState.logOnlyMemoryBreakpoints; } + diff --git a/src/Cafe/HW/Espresso/PPCScheduler.cpp b/src/Cafe/HW/Espresso/PPCScheduler.cpp index a4c04aaa..33bc697a 100644 --- a/src/Cafe/HW/Espresso/PPCScheduler.cpp +++ b/src/Cafe/HW/Espresso/PPCScheduler.cpp @@ -60,6 +60,7 @@ void _PPCCore_callbackExit(PPCInterpreter_t* hCPU) PPCInterpreter_t* PPCCore_executeCallbackInternal(uint32 functionMPTR) { + cemu_assert_debug(PPCInterpreter_getCurrentInstance()); // PPC callbacks can be only called from the dedicated PPC scheduler threads cemu_assert_debug(functionMPTR != 0); PPCInterpreter_t* hCPU = PPCInterpreter_getCurrentInstance(); // remember LR and instruction pointer diff --git a/src/Cafe/HW/MMU/MMU.cpp b/src/Cafe/HW/MMU/MMU.cpp index 2a3c7bbf..11df031b 100644 --- a/src/Cafe/HW/MMU/MMU.cpp +++ b/src/Cafe/HW/MMU/MMU.cpp @@ -112,7 +112,8 @@ MMURange mmuRange_LOW0 { 0x00010000, 0x000F0000, MMU_MEM_AREA_ID::CODE_LOW0, MMURange mmuRange_TRAMPOLINE_AREA { 0x00E00000, 0x00200000, MMU_MEM_AREA_ID::CODE_TRAMPOLINE, "TRAMPOLINE_AREA" }; // code area for trampolines and imports MMURange mmuRange_CODECAVE { 0x01800000, 0x00400000, MMU_MEM_AREA_ID::CODE_CAVE, "CODECAVE" }; // code cave area (4MiB) MMURange mmuRange_TEXT_AREA { 0x02000000, 0x0C000000, MMU_MEM_AREA_ID::CODE_MAIN, "TEXT_AREA" }; // module text sections go here (0x02000000 to 0x10000000, 224MiB) -MMURange mmuRange_CEMU_AREA { 0x0E000000, 0x02000000, MMU_MEM_AREA_ID::CEMU_PRIVATE, "CEMU_AREA", MMURange::MFLAG::FLAG_MAP_EARLY }; // Cemu-only, 32MiB. Should be allocated early for SysAllocator +MMURange mmuRange_CEMU_AREA { 0x0E000000, 0x01C00000, MMU_MEM_AREA_ID::CEMU_PRIVATE, "CEMU_AREA", MMURange::MFLAG::FLAG_MAP_EARLY }; // Cemu-only, 28MiB +MMURange mmuRange_IOSU_AREA { 0x0FC00000, 0x00400000, MMU_MEM_AREA_ID::IOSU_PRIVATE, "IOSU_AREA", MMURange::MFLAG::FLAG_MAP_EARLY }; // Cemu-only, 4MiB MMURange mmuRange_MEM2 { 0x10000000, 0x40000000, MMU_MEM_AREA_ID::MEM2_DATA, "MEM2" }; // main memory area (1GB) MMURange mmuRange_OVERLAY_AREA { 0xA0000000, 0x1C000000, MMU_MEM_AREA_ID::OVERLAY, "OVERLAY_AREA", MMURange::MFLAG::FLAG_OPTIONAL }; // has to be requested, 448MiB MMURange mmuRange_FGBUCKET { 0xE0000000, 0x04000000, MMU_MEM_AREA_ID::FGBUCKET, "FGBUCKET" }; // foreground bucket (64MiB) @@ -139,7 +140,7 @@ void memory_init() } for (auto& itr : g_mmuRanges) { - if (itr->isMappedEarly()) + if (itr->isMappedEarly() && !itr->isMapped()) itr->mapMem(); } } diff --git a/src/Cafe/HW/MMU/MMU.h b/src/Cafe/HW/MMU/MMU.h index 6e3bee70..8a685686 100644 --- a/src/Cafe/HW/MMU/MMU.h +++ b/src/Cafe/HW/MMU/MMU.h @@ -39,6 +39,7 @@ enum class MMU_MEM_AREA_ID CPU_PER_CORE, CEMU_PRIVATE, + IOSU_PRIVATE, }; struct MMURange @@ -125,6 +126,7 @@ extern MMURange mmuRange_CODECAVE; extern MMURange mmuRange_TEXT_AREA; extern MMURange mmuRange_MEM2; extern MMURange mmuRange_CEMU_AREA; +extern MMURange mmuRange_IOSU_AREA; extern MMURange mmuRange_OVERLAY_AREA; extern MMURange mmuRange_FGBUCKET; extern MMURange mmuRange_TILINGAPERTURE; diff --git a/src/Cafe/IOSU/ODM/iosu_odm.cpp b/src/Cafe/IOSU/ODM/iosu_odm.cpp index aae3c503..14ba4f55 100644 --- a/src/Cafe/IOSU/ODM/iosu_odm.cpp +++ b/src/Cafe/IOSU/ODM/iosu_odm.cpp @@ -1,9 +1,10 @@ -#include +#include "util/helpers/helpers.h" #include "iosu_odm.h" #include "config/ActiveSettings.h" #include "Common/FileStream.h" #include "util/helpers/Semaphore.h" #include "../kernel/iosu_kernel.h" +#include "Common/CafeStaticVar.h" namespace iosu { @@ -18,7 +19,8 @@ namespace iosu std::atomic_bool s_threadInitialized{ false }; IOSMsgQueueId s_msgQueueId; - SysAllocator _s_msgBuffer; + constinit IOSUStaticData s_odmStaticData; + CafeStaticVar _s_msgBuffer{s_odmStaticData}; enum class ODM_CMD_OPERATION_TYPE { @@ -139,6 +141,7 @@ namespace iosu { if (s_isRunning.exchange(true)) return; + s_odmStaticData.Allocate(); s_threadInitialized = false; s_requestStop = false; s_serviceThread = std::thread(&ODMServiceThread); @@ -152,6 +155,8 @@ namespace iosu s_requestStop = true; IOS_SendMessage(s_msgQueueId, 0, 0); s_serviceThread.join(); + IOS_DestroyMessageQueue(s_msgQueueId); + s_odmStaticData.Deallocate(); } } } diff --git a/src/Cafe/IOSU/ccr_nfc/iosu_ccr_nfc.cpp b/src/Cafe/IOSU/ccr_nfc/iosu_ccr_nfc.cpp index 1ceb16dc..53f66663 100644 --- a/src/Cafe/IOSU/ccr_nfc/iosu_ccr_nfc.cpp +++ b/src/Cafe/IOSU/ccr_nfc/iosu_ccr_nfc.cpp @@ -1,3 +1,4 @@ +#include "Common/CafeStaticVar.h" #include "iosu_ccr_nfc.h" #include "Cafe/IOSU/kernel/iosu_kernel.h" #include "util/crypto/aes128.h" @@ -9,7 +10,8 @@ namespace iosu namespace ccr_nfc { IOSMsgQueueId sCCRNFCMsgQueue; - SysAllocator sCCRNFCMsgQueueMsgBuffer; + constinit IOSUStaticData s_ccrNfcStaticData; + CafeStaticVar sCCRNFCMsgQueueMsgBuffer{s_ccrNfcStaticData}; std::thread sCCRNFCThread; constexpr uint8 sNfcKey[] = { 0xC1, 0x2B, 0x07, 0x10, 0xD7, 0x2C, 0xEB, 0x5D, 0x43, 0x49, 0xB7, 0x43, 0xE3, 0xCA, 0xD2, 0x24 }; @@ -374,6 +376,8 @@ namespace iosu { void SystemLaunch() override { + s_ccrNfcStaticData.Allocate(); + sCCRNFCMsgQueue = iosu::kernel::IOS_CreateMessageQueue(sCCRNFCMsgQueueMsgBuffer.GetPtr(), sCCRNFCMsgQueueMsgBuffer.GetCount()); cemu_assert(!IOS_ResultIsError(static_cast(sCCRNFCMsgQueue))); @@ -395,6 +399,8 @@ namespace iosu iosu::kernel::IOS_DestroyMessageQueue(sCCRNFCMsgQueue); sCCRNFCMsgQueue = -1; + + s_ccrNfcStaticData.Deallocate(); } } sIOSUModuleCCRNFC; diff --git a/src/Cafe/IOSU/fsa/iosu_fsa.cpp b/src/Cafe/IOSU/fsa/iosu_fsa.cpp index 1429d083..bba8b872 100644 --- a/src/Cafe/IOSU/fsa/iosu_fsa.cpp +++ b/src/Cafe/IOSU/fsa/iosu_fsa.cpp @@ -1,3 +1,4 @@ +#include "Common/CafeStaticVar.h" #include "fsa_types.h" #include "iosu_fsa.h" #include "Cafe/IOSU/kernel/iosu_kernel.h" @@ -7,8 +8,6 @@ #include "Cafe/OS/libs/coreinit/coreinit_FS.h" // get rid of this dependency, requires reworking some of the IPC stuff. See locations where we use coreinit::FSCmdBlockBody_t #include "Cafe/HW/Latte/Core/LatteBufferCache.h" // also remove this dependency -#include "Cafe/HW/MMU/MMU.h" - using namespace iosu::kernel; namespace iosu @@ -16,7 +15,8 @@ namespace iosu namespace fsa { IOSMsgQueueId sFSAIoMsgQueue; - SysAllocator _m_sFSAIoMsgQueueMsgBuffer; + constinit IOSUStaticData s_fsaStaticData; + CafeStaticVar _m_sFSAIoMsgQueueMsgBuffer{s_fsaStaticData}; std::thread sFSAIoThread; struct FSAClient // IOSU's counterpart to the coreinit FSClient struct @@ -888,6 +888,7 @@ namespace iosu void Initialize() { + s_fsaStaticData.Allocate(); for (auto& it : sFSAClientArray) it.ReleaseAndCleanup(); sFSAIoMsgQueue = (IOSMsgQueueId)IOS_CreateMessageQueue(_m_sFSAIoMsgQueueMsgBuffer.GetPtr(), _m_sFSAIoMsgQueueMsgBuffer.GetCount()); @@ -901,6 +902,8 @@ namespace iosu { IOS_SendMessage(sFSAIoMsgQueue, 0, 0); sFSAIoThread.join(); + IOS_DestroyMessageQueue(sFSAIoMsgQueue); + s_fsaStaticData.Deallocate(); } } // namespace fsa } // namespace iosu diff --git a/src/Cafe/IOSU/kernel/iosu_kernel.cpp b/src/Cafe/IOSU/kernel/iosu_kernel.cpp index 3ea6d7da..e8281643 100644 --- a/src/Cafe/IOSU/kernel/iosu_kernel.cpp +++ b/src/Cafe/IOSU/kernel/iosu_kernel.cpp @@ -3,12 +3,14 @@ #include "util/helpers/helpers.h" #include "Cafe/OS/libs/coreinit/coreinit_IPC.h" #include "util/highresolutiontimer/HighResolutionTimer.h" +#include "Common/CafeStaticVar.h" namespace iosu { namespace kernel { std::mutex sInternalMutex; + constinit IOSUStaticData s_kernelStaticData; void IOS_DestroyResourceManagerForQueueId(IOSMsgQueueId msgQueueId); void _IPCDestroyAllHandlesForMsgQueue(IOSMsgQueueId msgQueueId); @@ -66,6 +68,7 @@ namespace iosu { std::unique_lock _l(sInternalMutex); cemu_assert(messageCount != 0); + cemu_assert_debug(messageArray); auto it = std::find_if(sMsgQueuePool.begin(), sMsgQueuePool.end(), [](const IOSMessageQueue& q) { return q.msgArraySize == 0; }); if (it == sMsgQueuePool.end()) { @@ -390,12 +393,13 @@ namespace iosu bool isAllocated{false}; }; - SysAllocator sIPCDispatchableCommandPool; + CafeStaticVar sIPCDispatchableCommandPool{s_kernelStaticData}; std::queue sIPCFreeDispatchableCommands; FSpinlock sIPCDispatchableCommandPoolLock; void _IPCInitDispatchablePool() { + cemu_assert_debug(sIPCDispatchableCommandPool.IsAllocated()); sIPCDispatchableCommandPoolLock.lock(); while (!sIPCFreeDispatchableCommands.empty()) sIPCFreeDispatchableCommands.pop(); @@ -754,6 +758,7 @@ namespace iosu { void SystemLaunch() override { + s_kernelStaticData.Allocate(); _IPCInitDispatchablePool(); // start timer thread sTimerThreadStop = false; @@ -768,6 +773,7 @@ namespace iosu m_timerThread.join(); // reset resources // todo + s_kernelStaticData.Deallocate(); } std::thread m_timerThread; diff --git a/src/Cafe/IOSU/legacy/iosu_acp.cpp b/src/Cafe/IOSU/legacy/iosu_acp.cpp index 871cc495..06f9da6e 100644 --- a/src/Cafe/IOSU/legacy/iosu_acp.cpp +++ b/src/Cafe/IOSU/legacy/iosu_acp.cpp @@ -581,6 +581,8 @@ namespace iosu namespace acp { + constinit IOSUStaticData s_staticData; + iosu::nn::IPCService::WorkArea s_ipcServiceWorkArea(s_staticData); uint64 _ACPGetTimestamp() { @@ -780,7 +782,7 @@ namespace iosu class AcpMainService : public iosu::nn::IPCService { public: - AcpMainService() : iosu::nn::IPCService("/dev/acp_main") {} + AcpMainService() : iosu::nn::IPCService("/dev/acp_main", s_ipcServiceWorkArea) {} nnResult ServiceCall(IPCServiceCall& serviceCall) override { @@ -796,12 +798,14 @@ namespace iosu { void TitleStart() override { + s_staticData.Allocate(); gACPMainService.Start(); // gACPMainService.SetTimerUpdate(1000); // call TimerUpdate() once a second } void TitleStop() override { gACPMainService.Stop(); + s_staticData.Deallocate(); } }sIOSUModuleNNACP; diff --git a/src/Cafe/IOSU/legacy/iosu_act.cpp b/src/Cafe/IOSU/legacy/iosu_act.cpp index 11e613ac..dc4b2cc0 100644 --- a/src/Cafe/IOSU/legacy/iosu_act.cpp +++ b/src/Cafe/IOSU/legacy/iosu_act.cpp @@ -384,6 +384,9 @@ namespace iosu { namespace act { + constinit IOSUStaticData s_staticData; + nn::IPCService::WorkArea s_workArea(s_staticData); + uint8 getCurrentAccountSlot() { return 1; @@ -605,7 +608,7 @@ namespace iosu class ActService : public iosu::nn::IPCService { public: - ActService() : iosu::nn::IPCService("/dev/act") {} + ActService() : iosu::nn::IPCService("/dev/act", s_workArea) {} nnResult ServiceCall(IPCServiceCall& serviceCall) override { @@ -619,12 +622,14 @@ namespace iosu void Initialize() { + s_staticData.Allocate(); gActService.Start(); } void Stop() { gActService.Stop(); + s_staticData.Deallocate(); } } } diff --git a/src/Cafe/IOSU/legacy/iosu_fpd.cpp b/src/Cafe/IOSU/legacy/iosu_fpd.cpp index b3f7e5d9..754b6c26 100644 --- a/src/Cafe/IOSU/legacy/iosu_fpd.cpp +++ b/src/Cafe/IOSU/legacy/iosu_fpd.cpp @@ -20,6 +20,9 @@ namespace iosu { namespace fpd { + constinit IOSUStaticData s_staticData; + nn::IPCSimpleService::WorkArea s_workArea(s_staticData); + using NotificationRunningId = uint64; struct NotificationEntry @@ -362,7 +365,7 @@ namespace iosu std::vector m_clients; public: - FPDService() : iosu::nn::IPCSimpleService("/dev/fpd") {} + FPDService() : iosu::nn::IPCSimpleService("/dev/fpd", s_workArea) {} std::string GetThreadName() override { @@ -1510,6 +1513,7 @@ namespace iosu { void TitleStart() override { + s_staticData.Allocate(); gFPDService.Start(); gFPDService.SetTimerUpdate(1000); // call TimerUpdate() once a second } @@ -1517,6 +1521,7 @@ namespace iosu { gFPDService.StopFriendSession(); gFPDService.Stop(); + s_staticData.Deallocate(); } }sIOSUModuleNNFPD; diff --git a/src/Cafe/IOSU/legacy/iosu_mcp.cpp b/src/Cafe/IOSU/legacy/iosu_mcp.cpp index 3108e1f2..94cd69cb 100644 --- a/src/Cafe/IOSU/legacy/iosu_mcp.cpp +++ b/src/Cafe/IOSU/legacy/iosu_mcp.cpp @@ -1,7 +1,6 @@ #include "iosu_ioctl.h" #include "iosu_mcp.h" #include "Cafe/OS/libs/nn_common.h" -#include "util/tinyxml2/tinyxml2.h" #include "config/CemuConfig.h" #include "Cafe/TitleList/GameInfo.h" @@ -10,6 +9,7 @@ #include "Cafe/CafeSystem.h" #include "Cafe/IOSU/iosu_ipc_common.h" #include "Cafe/IOSU/kernel/iosu_kernel.h" +#include "Common/CafeStaticVar.h" using namespace iosu::kernel; @@ -21,6 +21,7 @@ namespace iosu }iosuMcp = { 0 }; std::recursive_mutex sTitleInfoMutex; + constinit IOSUStaticData s_mcpStaticData; bool sHasAllTitlesMounted = false; @@ -159,7 +160,7 @@ namespace iosu namespace mcp { IOSMsgQueueId sMCPIoMsgQueue; - SysAllocator _m_sMCPIoMsgQueueMsgBuffer; + CafeStaticVar _m_sMCPIoMsgQueueMsgBuffer{s_mcpStaticData}; std::thread sMCPIoThread; struct MCPClient @@ -253,6 +254,7 @@ namespace iosu void Init() { + s_mcpStaticData.Allocate(); for (auto& it : sMCPClientArray) it.ReleaseAndCleanup(); sMCPIoMsgQueue = (IOSMsgQueueId)IOS_CreateMessageQueue(_m_sMCPIoMsgQueueMsgBuffer.GetPtr(), _m_sMCPIoMsgQueueMsgBuffer.GetCount()); @@ -266,6 +268,8 @@ namespace iosu { IOS_SendMessage(sMCPIoMsgQueue, 0, 0); sMCPIoThread.join(); + IOS_DestroyMessageQueue(sMCPIoMsgQueue); + s_mcpStaticData.Deallocate(); } }; } diff --git a/src/Cafe/IOSU/nn/boss/boss_common.h b/src/Cafe/IOSU/nn/boss/boss_common.h index fcc66ebb..35a5e750 100644 --- a/src/Cafe/IOSU/nn/boss/boss_common.h +++ b/src/Cafe/IOSU/nn/boss/boss_common.h @@ -1,6 +1,8 @@ #pragma once #include "Common/CafeString.h" +template class RPLStaticVar; + namespace nn::boss { typedef uint32 BossResult; @@ -54,7 +56,7 @@ namespace nn::boss VTableEntry rtti; VTableEntry dtor; }; - static inline SysAllocator s_titleVTable; + static CafeStaticVar s_titleVTable; static Title* ctor(Title* _this); static void dtor(Title* _this, uint32 options); @@ -78,7 +80,7 @@ namespace nn::boss VTableEntry rtti; VTableEntry dtor; }; - static inline SysAllocator s_VTable; + static CafeStaticVar s_VTable; uint32be accountId; MEMPTR vTablePtr; @@ -232,7 +234,7 @@ namespace nn::boss VTableEntry RegisterPreprocess; // todo - double check the offset VTableEntry unk1; }; - static inline SysAllocator s_VTable; + static CafeStaticVar s_VTable; static TaskSetting* ctor(TaskSetting* _thisptr); static void dtor(TaskSetting* _this, uint32 options); @@ -280,7 +282,7 @@ namespace nn::boss { struct VTableNetTaskSetting : public VTableTaskSetting { }; - static inline SysAllocator s_VTable; + static CafeStaticVar s_VTable; static NetTaskSetting* ctor(NetTaskSetting* _thisptr); static BossResult AddCaCert(NetTaskSetting* _thisptr, const char* name); @@ -300,7 +302,7 @@ namespace nn::boss VTableEntry rttiNetTaskSetting; // unknown }; static_assert(sizeof(VTableNbdlTaskSetting) == 8*5); - static inline SysAllocator s_VTable; + static CafeStaticVar s_VTable; static NbdlTaskSetting* ctor(NbdlTaskSetting* _thisptr); static BossResult Initialize(NbdlTaskSetting* _thisptr, const char* bossCode, uint64 directorySizeLimit, const char* bossDirectory); @@ -323,7 +325,7 @@ namespace nn::boss VTableEntry rttiNetTaskSetting; // unknown }; static_assert(sizeof(VTableRawUlTaskSetting) == 8*5); - static inline SysAllocator s_VTable; + static CafeStaticVar s_VTable; static RawUlTaskSetting* ctor(RawUlTaskSetting* _thisptr); static void dtor(RawUlTaskSetting* _this, uint32 options); @@ -339,7 +341,7 @@ namespace nn::boss VTableEntry rttiNetTaskSetting; // unknown }; static_assert(sizeof(VTableRawDlTaskSetting) == 8*5); - static inline SysAllocator s_VTable; + static CafeStaticVar s_VTable; static RawDlTaskSetting* ctor(RawDlTaskSetting* _thisptr); static BossResult Initialize(RawDlTaskSetting* _thisptr, const char* url, bool newArrival, bool led, const char* fileName, const char* bossDirectory); @@ -360,7 +362,7 @@ namespace nn::boss struct VTablePlayReportSetting : public VTableRawUlTaskSetting {}; static_assert(sizeof(VTablePlayReportSetting) == 8*5); - static inline SysAllocator s_VTable; + static CafeStaticVar s_VTable; static PlayReportSetting* ctor(PlayReportSetting* _this); static void dtor(PlayReportSetting* _this, uint32 options); diff --git a/src/Cafe/IOSU/nn/boss/boss_service.cpp b/src/Cafe/IOSU/nn/boss/boss_service.cpp index 3f710c40..f6ab764d 100644 --- a/src/Cafe/IOSU/nn/boss/boss_service.cpp +++ b/src/Cafe/IOSU/nn/boss/boss_service.cpp @@ -25,6 +25,9 @@ namespace iosu::boss { + constinit IOSUStaticData s_staticData; + nn::IPCService::WorkArea s_workArea(s_staticData); + using namespace ::nn::boss; static constexpr nnResult RESULT_SUCCESS = 0x200080; @@ -975,7 +978,7 @@ namespace iosu::boss class BossMainService : public iosu::nn::IPCService { public: - BossMainService() : iosu::nn::IPCService("/dev/boss") {} + BossMainService() : iosu::nn::IPCService("/dev/boss", s_workArea) {} nnResult ServiceCall(IPCServiceCall& serviceCall) override { @@ -1412,6 +1415,18 @@ namespace iosu::boss class : public ::IOSUModule { + void SystemLaunch() override + { + s_staticData.Allocate(); + } + + void SystemExit() override + { + s_bossService.Stop(); + s_bossDaemon.Stop(); + s_staticData.Deallocate(); + } + void TitleStart() override { s_bossService.Start(); diff --git a/src/Cafe/IOSU/nn/iosu_nn_service.cpp b/src/Cafe/IOSU/nn/iosu_nn_service.cpp index 53468950..526da7f0 100644 --- a/src/Cafe/IOSU/nn/iosu_nn_service.cpp +++ b/src/Cafe/IOSU/nn/iosu_nn_service.cpp @@ -37,7 +37,7 @@ namespace iosu { if(!GetThreadName().empty()) SetThreadName(GetThreadName().c_str()); - m_msgQueueId = IOS_CreateMessageQueue(_m_msgBuffer.GetPtr(), _m_msgBuffer.GetCount()); + m_msgQueueId = IOS_CreateMessageQueue( m_workArea._m_msgBuffer.GetPtr(), m_workArea._m_msgBuffer.GetCount()); cemu_assert(!IOS_ResultIsError((IOS_ERROR)m_msgQueueId)); IOS_ERROR r = IOS_RegisterResourceManager(m_devicePath.c_str(), m_msgQueueId); cemu_assert(!IOS_ResultIsError(r)); @@ -158,7 +158,7 @@ namespace iosu std::string serviceName = m_devicePath.substr(m_devicePath.find_last_of('/') == std::string::npos ? 0 : m_devicePath.find_last_of('/') + 1); serviceName.insert(0, "NNsvc_"); SetThreadName(serviceName.c_str()); - m_msgQueueId = IOS_CreateMessageQueue(_m_msgBuffer.GetPtr(), _m_msgBuffer.GetCount()); + m_msgQueueId = IOS_CreateMessageQueue(m_workArea._m_msgBuffer.GetPtr(), m_workArea._m_msgBuffer.GetCount()); cemu_assert(!IOS_ResultIsError((IOS_ERROR)m_msgQueueId)); IOS_ERROR r = IOS_RegisterResourceManager(m_devicePath.c_str(), m_msgQueueId); cemu_assert(!IOS_ResultIsError(r)); diff --git a/src/Cafe/IOSU/nn/iosu_nn_service.h b/src/Cafe/IOSU/nn/iosu_nn_service.h index 32d17c8c..48f66bbe 100644 --- a/src/Cafe/IOSU/nn/iosu_nn_service.h +++ b/src/Cafe/IOSU/nn/iosu_nn_service.h @@ -3,6 +3,7 @@ #include "Cafe/IOSU/iosu_ipc_common.h" #include "Cafe/IOSU/iosu_types_common.h" #include "Cafe/OS/libs/nn_common.h" +#include "Common/CafeStaticVar.h" namespace iosu { @@ -12,7 +13,14 @@ namespace iosu class IPCSimpleService { public: - IPCSimpleService(std::string_view devicePath) : m_devicePath(devicePath) {}; + struct WorkArea // must be in guest memory. Provided by caller + { + WorkArea(IOSUStaticData& staticData) : _m_msgBuffer(staticData) + {} + CafeStaticVar _m_msgBuffer; + }; + + IPCSimpleService(std::string_view devicePath, WorkArea& workArea) : m_devicePath(devicePath), m_workArea(workArea) {}; virtual ~IPCSimpleService() {}; virtual void StartService() {}; @@ -70,7 +78,7 @@ namespace iosu bool m_delayResponse{false}; IOSMsgQueueId m_msgQueueId; - SysAllocator _m_msgBuffer; + WorkArea& m_workArea; }; // a complex service interface which wraps Ioctlv and adds an additional service channel, used by /dev/act, /dev/acp_main, /dev/boss and most nn services @@ -91,6 +99,13 @@ namespace iosu uint32be nnResultCode; }; public: + struct WorkArea // must be in guest memory. Provided by caller + { + WorkArea(IOSUStaticData& staticData) : _m_msgBuffer(staticData) + {} + CafeStaticVar _m_msgBuffer; + }; + class IPCParameterStream // input stream for parameters { public: @@ -308,7 +323,7 @@ namespace iosu sint8 m_outputBufferIndex{1}; }; - IPCService(std::string_view devicePath) : m_devicePath(devicePath) {}; + IPCService(std::string_view devicePath, WorkArea& workArea) : m_devicePath(devicePath), m_workArea(workArea) {}; virtual ~IPCService() {}; virtual IOSDevHandle CreateClientHandle() @@ -340,7 +355,7 @@ namespace iosu std::atomic_bool m_threadInitialized{ false }; IOSMsgQueueId m_msgQueueId; - SysAllocator _m_msgBuffer; + WorkArea& m_workArea; }; }; diff --git a/src/Cafe/OS/RPL/rpl.cpp b/src/Cafe/OS/RPL/rpl.cpp index 4d33e5f0..c4d7bc84 100644 --- a/src/Cafe/OS/RPL/rpl.cpp +++ b/src/Cafe/OS/RPL/rpl.cpp @@ -287,7 +287,7 @@ bool RPLLoader_ProcessHeaders(std::string_view moduleName, uint8* rplData, uint3 fileName.append(rplLoaderContext->IsRPX() ? ".rpx" : ".rpl"); // allocate modulename in PPC memory - rplLoaderContext->ppcName = coreinit_allocFromSysArea(fileName.size() + 1, 4); + rplLoaderContext->ppcName = OSAllocFromSystem(fileName.size() + 1, 4); memcpy(rplLoaderContext->ppcName.GetPtr(), fileName.data(), fileName.size() + 1); // load CRC section diff --git a/src/Cafe/OS/common/OSCommon.h b/src/Cafe/OS/common/OSCommon.h index d35ff893..4aab1872 100644 --- a/src/Cafe/OS/common/OSCommon.h +++ b/src/Cafe/OS/common/OSCommon.h @@ -29,8 +29,9 @@ namespace coreinit }; } -// utility functions +// utilities #include "Cafe/OS/common/OSUtil.h" +#include "Common/CafeStaticVar.h" // va_list struct ppc_va_list @@ -113,4 +114,4 @@ static void* _ppc_va_arg(ppc_va_list* vargs, ppc_va_type argType) vargs->overflow_arg_area += 8; return r; } -} \ No newline at end of file +} diff --git a/src/Cafe/OS/libs/TCL/TCL.cpp b/src/Cafe/OS/libs/TCL/TCL.cpp index b697ceca..3905bbd5 100644 --- a/src/Cafe/OS/libs/TCL/TCL.cpp +++ b/src/Cafe/OS/libs/TCL/TCL.cpp @@ -1,12 +1,14 @@ #include "Cafe/OS/common/OSCommon.h" #include "Cafe/OS/libs/TCL/TCL.h" - #include "HW/Latte/Core/LattePM4.h" #include "OS/libs/coreinit/coreinit_Time.h" +#include "Common/CafeStaticVar.h" namespace TCL { - SysAllocator s_updateRetirementEvent; + constinit COSStaticData s_rplData; + + CafeStaticVar s_updateRetirementEvent{s_rplData}; uint64 s_currentRetireMarker = 0; struct TCLStatePPC // mapped into PPC space @@ -14,11 +16,13 @@ namespace TCL uint64be gpuRetireMarker; // written by GPU }; - SysAllocator s_tclStatePPC; + CafeStaticVar s_tclStatePPC{s_rplData}; // called from GPU for timestamp EOP event void TCLGPUNotifyNewRetirementTimestamp() { + if (!s_updateRetirementEvent.IsAllocated()) + return; // gpuRetireMarker is updated via event eop command __OSLockScheduler(); coreinit::OSSignalEventAllInternal(s_updateRetirementEvent.GetPtr()); @@ -165,8 +169,14 @@ namespace TCL return "tcl"; } + void RPLUnmapped() override + { + s_rplData.Deallocate(); + } + void RPLMapped() override { + s_rplData.Allocate(); cafeExportRegister("TCL", TCLSubmitToRing, LogType::Placeholder); cafeExportRegister("TCL", TCLTimestamp, LogType::Placeholder); cafeExportRegister("TCL", TCLWaitTimestamp, LogType::Placeholder); diff --git a/src/Cafe/OS/libs/camera/camera.cpp b/src/Cafe/OS/libs/camera/camera.cpp index 6812de7b..b95d19c7 100644 --- a/src/Cafe/OS/libs/camera/camera.cpp +++ b/src/Cafe/OS/libs/camera/camera.cpp @@ -5,9 +5,11 @@ #include "Cafe/OS/libs/coreinit/coreinit_Alarm.h" #include "Cafe/OS/libs/coreinit/coreinit_Time.h" #include "Cafe/HW/Espresso/PPCCallback.h" +#include "Common/CafeStaticVar.h" namespace camera { + constinit COSStaticData s_camStaticData; struct CAMInitInfo_t { @@ -58,8 +60,8 @@ namespace camera std::vector g_activeCameraInstances; std::recursive_mutex g_mutex_camera; std::atomic_int g_cameraCounter{ 0 }; - SysAllocator g_alarm_camera; - SysAllocator g_cameraHandlerParam; + CafeStaticVar g_alarm_camera{s_camStaticData}; + CafeStaticVar g_cameraHandlerParam{s_camStaticData}; CameraInstance* GetCameraInstanceByHandle(sint32 camHandle) { @@ -250,8 +252,15 @@ namespace camera return "camera"; } + void RPLUnmapped() override + { + coreinit::OSCancelAlarm(g_alarm_camera.GetPtr()); + s_camStaticData.Deallocate(); + } + void RPLMapped() override { + s_camStaticData.Allocate(); cafeExportRegister("camera", CAMGetMemReq, LogType::Placeholder); cafeExportRegister("camera", CAMCheckMemSegmentation, LogType::Placeholder); cafeExportRegister("camera", CAMInit, LogType::Placeholder); diff --git a/src/Cafe/OS/libs/coreinit/coreinit.cpp b/src/Cafe/OS/libs/coreinit/coreinit.cpp index 4d454e0e..6c1eb245 100644 --- a/src/Cafe/OS/libs/coreinit/coreinit.cpp +++ b/src/Cafe/OS/libs/coreinit/coreinit.cpp @@ -184,6 +184,8 @@ void coreinitExport_OSGetSharedData(PPCInterpreter_t* hCPU) namespace coreinit { + COSStaticData g_coreinitStaticData; + sint32 OSGetCoreId() { return PPCInterpreter_getCoreIndex(PPCInterpreter_getCurrentInstance()); @@ -297,6 +299,7 @@ namespace coreinit void RPLMapped() override { + g_coreinitStaticData.Allocate(); coreinit::InitializeCore(); coreinit::InitializeSchedulerLock(); coreinit::InitializeSysHeap(); @@ -360,6 +363,11 @@ namespace coreinit osLib_addFunction("coreinit", "UCReadSysConfig", coreinitExport_UCReadSysConfig); }; + void RPLUnmapped() override + { + g_coreinitStaticData.Deallocate(); + } + void rpl_entry(uint32 moduleHandle, coreinit::RplEntryReason reason) override { if (reason == coreinit::RplEntryReason::Loaded) diff --git a/src/Cafe/OS/libs/coreinit/coreinit.h b/src/Cafe/OS/libs/coreinit/coreinit.h index e7b88821..12d4c77c 100644 --- a/src/Cafe/OS/libs/coreinit/coreinit.h +++ b/src/Cafe/OS/libs/coreinit/coreinit.h @@ -1,11 +1,10 @@ #pragma once #include "Cafe/HW/Espresso/Const.h" #include "Cafe/OS/RPL/COSModule.h" +class COSStaticData; #define PPC_CORE_COUNT (Espresso::CORE_COUNT) -#include "Cafe/OS/libs/coreinit/coreinit_MessageQueue.h" - // async callback helper void InitializeAsyncCallback(); @@ -36,9 +35,11 @@ void OSFreeToSystem(MPTR mem); namespace coreinit { + extern COSStaticData g_coreinitStaticData; + sint32 OSGetCoreId(); uint32 OSGetCoreCount(); uint32 OSGetStackPointer(); COSModule* GetModule(); -}; \ No newline at end of file +}; diff --git a/src/Cafe/OS/libs/coreinit/coreinit_Alarm.cpp b/src/Cafe/OS/libs/coreinit/coreinit_Alarm.cpp index 42229c7a..568db971 100644 --- a/src/Cafe/OS/libs/coreinit/coreinit_Alarm.cpp +++ b/src/Cafe/OS/libs/coreinit/coreinit_Alarm.cpp @@ -10,12 +10,11 @@ namespace coreinit { - SysAllocator g_alarmEvent; - - SysAllocator g_alarmThread; - SysAllocator _g_alarmThreadStack; - SysAllocator _g_alarmThreadName; + CafeStaticVar g_alarmEvent{coreinit::g_coreinitStaticData}; + CafeStaticVar g_alarmThread{coreinit::g_coreinitStaticData}; + CafeStaticVar _g_alarmThreadStack{coreinit::g_coreinitStaticData}; + CafeStaticVar _g_alarmThreadName{coreinit::g_coreinitStaticData}; class OSHostAlarm { diff --git a/src/Cafe/OS/libs/coreinit/coreinit_Callbacks.cpp b/src/Cafe/OS/libs/coreinit/coreinit_Callbacks.cpp index aef7e5aa..790dd3cb 100644 --- a/src/Cafe/OS/libs/coreinit/coreinit_Callbacks.cpp +++ b/src/Cafe/OS/libs/coreinit/coreinit_Callbacks.cpp @@ -1,5 +1,7 @@ +#include "Cafe/OS/libs/coreinit/coreinit.h" #include "Cafe/OS/libs/coreinit/coreinit_Thread.h" #include "util/helpers/fspinlock.h" +#include "Common/CafeStaticVar.h" struct CoreinitAsyncCallback { @@ -71,10 +73,10 @@ std::vector CoreinitAsyncCallback::s_asyncCallbac std::vector CoreinitAsyncCallback::s_asyncCallbackQueue; FSpinlock CoreinitAsyncCallback::s_asyncCallbackSpinlock; -SysAllocator g_coreinitCallbackThread; -SysAllocator _g_coreinitCallbackThreadStack; -SysAllocator g_asyncCallbackAsync; -SysAllocator _g_coreinitCBThreadName; +CafeStaticVar g_coreinitCallbackThread{coreinit::g_coreinitStaticData}; +CafeStaticVar _g_coreinitCallbackThreadStack{coreinit::g_coreinitStaticData}; +CafeStaticVar g_asyncCallbackAsync{coreinit::g_coreinitStaticData}; +CafeStaticVar _g_coreinitCBThreadName{coreinit::g_coreinitStaticData}; void _coreinitCallbackThread(PPCInterpreter_t* hCPU) { @@ -113,4 +115,4 @@ void InitializeAsyncCallback() strcpy(_g_coreinitCBThreadName.GetPtr(), "Callback Thread"); coreinit::OSSetThreadName(g_coreinitCallbackThread.GetPtr(), _g_coreinitCBThreadName.GetPtr()); -} \ No newline at end of file +} diff --git a/src/Cafe/OS/libs/coreinit/coreinit_FS.cpp b/src/Cafe/OS/libs/coreinit/coreinit_FS.cpp index 12ddb8df..7cf03978 100644 --- a/src/Cafe/OS/libs/coreinit/coreinit_FS.cpp +++ b/src/Cafe/OS/libs/coreinit/coreinit_FS.cpp @@ -44,7 +44,7 @@ bool strcpy_whole(char* dst, size_t dstLength, const char* src) namespace coreinit { - SysAllocator s_fsGlobalMutex; + CafeStaticVar s_fsGlobalMutex{coreinit::g_coreinitStaticData}; inline void FSLockMutex() { @@ -1056,7 +1056,7 @@ namespace coreinit return FSA_RESULT::OK; } - SysAllocator _tempFSSpace; + CafeStaticVar _tempFSSpace{coreinit::g_coreinitStaticData}; sint32 __FSReadFileAsyncEx(FSClient_t* fsClient, FSCmdBlock_t* fsCmdBlock, void* dest, uint32 size, uint32 count, bool usePos, uint32 filePos, uint32 fileHandle, uint32 flag, uint32 errorMask, FSAsyncParams* fsAsyncParams) { @@ -2019,9 +2019,9 @@ namespace coreinit return FSA_RESULT::OK; } - SysAllocator s_fsaIpcPool; - SysAllocator s_fsaIpcPoolBuffer; - SysAllocator s_fsaIpcPoolBufferNumItems; + CafeStaticVar s_fsaIpcPool{coreinit::g_coreinitStaticData}; + CafeStaticVar s_fsaIpcPoolBuffer{coreinit::g_coreinitStaticData}; + CafeStaticVar s_fsaIpcPoolBufferNumItems{coreinit::g_coreinitStaticData}; std::mutex sFSAIPCBufferLock; bool s_fsaInitDone = false; @@ -2508,27 +2508,27 @@ namespace coreinit return FSAGetInfoByQuery(client, path, FSA_QUERY_TYPE_FREESPACE, outSize); } - SysAllocator s_fsaStr_OK("FSA_STATUS_OK"); - SysAllocator s_fsaStr_NOT_INIT("FSA_STATUS_NOT_INIT"); - SysAllocator s_fsaStr_END_OF_DIRECTORY("FSA_STATUS_END_OF_DIRECTORY"); - SysAllocator s_fsaStr_END_OF_FILE("FSA_STATUS_END_OF_FILE"); - SysAllocator s_fsaStr_MAX_CLIENTS("FSA_STATUS_MAX_CLIENTS"); - SysAllocator s_fsaStr_MAX_FILES("FSA_STATUS_MAX_FILES"); - SysAllocator s_fsaStr_MAX_DIRS("FSA_STATUS_MAX_DIRS"); - SysAllocator s_fsaStr_ALREADY_EXISTS("FSA_STATUS_ALREADY_EXISTS"); - SysAllocator s_fsaStr_NOT_FOUND("FSA_STATUS_NOT_FOUND"); - SysAllocator s_fsaStr_PERMISSION_ERROR("FSA_STATUS_PERMISSION_ERROR"); - SysAllocator s_fsaStr_INVALID_PARAM("FSA_STATUS_INVALID_PARAM"); - SysAllocator s_fsaStr_INVALID_PATH("FSA_STATUS_INVALID_PATH"); - SysAllocator s_fsaStr_INVALID_BUFFER("FSA_STATUS_INVALID_BUFFER"); - SysAllocator s_fsaStr_INVALID_ALIGNMENT("FSA_STATUS_INVALID_ALIGNMENT"); - SysAllocator s_fsaStr_INVALID_CLIENT_HANDLE("FSA_STATUS_INVALID_CLIENT_HANDLE"); - SysAllocator s_fsaStr_INVALID_FILE_HANDLE("FSA_STATUS_INVALID_FILE_HANDLE"); - SysAllocator s_fsaStr_INVALID_DIR_HANDLE("FSA_STATUS_INVALID_DIR_HANDLE"); - SysAllocator s_fsaStr_NOT_FILE("FSA_STATUS_NOT_FILE"); - SysAllocator s_fsaStr_NOT_DIR("FSA_STATUS_NOT_DIR"); - SysAllocator s_fsaStr_OUT_OF_RESOURCES("FSA_STATUS_OUT_OF_RESOURCES"); - SysAllocator s_fsaStr_UNKNOWN("FSA_STATUS_???"); + CafeStaticVar s_fsaStr_OK(g_coreinitStaticData, "FSA_STATUS_OK"); + CafeStaticVar s_fsaStr_NOT_INIT(g_coreinitStaticData, "FSA_STATUS_NOT_INIT"); + CafeStaticVar s_fsaStr_END_OF_DIRECTORY(g_coreinitStaticData, "FSA_STATUS_END_OF_DIRECTORY"); + CafeStaticVar s_fsaStr_END_OF_FILE(g_coreinitStaticData, "FSA_STATUS_END_OF_FILE"); + CafeStaticVar s_fsaStr_MAX_CLIENTS(g_coreinitStaticData, "FSA_STATUS_MAX_CLIENTS"); + CafeStaticVar s_fsaStr_MAX_FILES(g_coreinitStaticData, "FSA_STATUS_MAX_FILES"); + CafeStaticVar s_fsaStr_MAX_DIRS(g_coreinitStaticData, "FSA_STATUS_MAX_DIRS"); + CafeStaticVar s_fsaStr_ALREADY_EXISTS(g_coreinitStaticData, "FSA_STATUS_ALREADY_EXISTS"); + CafeStaticVar s_fsaStr_NOT_FOUND(g_coreinitStaticData, "FSA_STATUS_NOT_FOUND"); + CafeStaticVar s_fsaStr_PERMISSION_ERROR(g_coreinitStaticData, "FSA_STATUS_PERMISSION_ERROR"); + CafeStaticVar s_fsaStr_INVALID_PARAM(g_coreinitStaticData, "FSA_STATUS_INVALID_PARAM"); + CafeStaticVar s_fsaStr_INVALID_PATH(g_coreinitStaticData, "FSA_STATUS_INVALID_PATH"); + CafeStaticVar s_fsaStr_INVALID_BUFFER(g_coreinitStaticData, "FSA_STATUS_INVALID_BUFFER"); + CafeStaticVar s_fsaStr_INVALID_ALIGNMENT(g_coreinitStaticData, "FSA_STATUS_INVALID_ALIGNMENT"); + CafeStaticVar s_fsaStr_INVALID_CLIENT_HANDLE(g_coreinitStaticData, "FSA_STATUS_INVALID_CLIENT_HANDLE"); + CafeStaticVar s_fsaStr_INVALID_FILE_HANDLE(g_coreinitStaticData, "FSA_STATUS_INVALID_FILE_HANDLE"); + CafeStaticVar s_fsaStr_INVALID_DIR_HANDLE(g_coreinitStaticData, "FSA_STATUS_INVALID_DIR_HANDLE"); + CafeStaticVar s_fsaStr_NOT_FILE(g_coreinitStaticData, "FSA_STATUS_NOT_FILE"); + CafeStaticVar s_fsaStr_NOT_DIR(g_coreinitStaticData, "FSA_STATUS_NOT_DIR"); + CafeStaticVar s_fsaStr_OUT_OF_RESOURCES(g_coreinitStaticData, "FSA_STATUS_OUT_OF_RESOURCES"); + CafeStaticVar s_fsaStr_UNKNOWN(g_coreinitStaticData, "FSA_STATUS_???"); const char* FSAGetStatusStr(FSA_RESULT status) { diff --git a/src/Cafe/OS/libs/coreinit/coreinit_GHS.cpp b/src/Cafe/OS/libs/coreinit/coreinit_GHS.cpp index 33c8eedc..83d1ff41 100644 --- a/src/Cafe/OS/libs/coreinit/coreinit_GHS.cpp +++ b/src/Cafe/OS/libs/coreinit/coreinit_GHS.cpp @@ -25,7 +25,7 @@ namespace coreinit uint32 ghs_Errno; // exposed as 'errno' data export }; - SysAllocator g_ghs_data; + CafeStaticVar g_ghs_data{coreinit::g_coreinitStaticData}; struct ghs_flock { @@ -38,7 +38,7 @@ namespace coreinit std::recursive_mutex g_ghsLock; std::recursive_mutex g_ghsLockFlock; - SysAllocator _flockMutexArray; + CafeStaticVar _flockMutexArray{coreinit::g_coreinitStaticData}; bool _flockMutexMask[GHS_FOPEN_MAX]; // if set, mutex in _flockMutexArray is reserved #define IOB_FLAG_IN (0x1) diff --git a/src/Cafe/OS/libs/coreinit/coreinit_IPC.cpp b/src/Cafe/OS/libs/coreinit/coreinit_IPC.cpp index 19a3b69c..bb3b3c40 100644 --- a/src/Cafe/OS/libs/coreinit/coreinit_IPC.cpp +++ b/src/Cafe/OS/libs/coreinit/coreinit_IPC.cpp @@ -102,8 +102,8 @@ namespace coreinit //static_assert(sizeof(IPCDriverInstance) == 0x1740); - SysAllocator s_ipcResourceBuffers; - SysAllocator s_ipcDriver; + CafeStaticVar s_ipcResourceBuffers{coreinit::g_coreinitStaticData}; + CafeStaticVar s_ipcDriver{coreinit::g_coreinitStaticData}; IPCDriver& IPCDriver_GetByCore(uint32 coreIndex) { @@ -176,11 +176,11 @@ namespace coreinit /* IPC threads */ - SysAllocator gIPCThread; - SysAllocator _gIPCThreadStack; - SysAllocator _gIPCThreadNameStorage; - SysAllocator gIPCThreadMsgQueue; - SysAllocator _gIPCThreadSemaphoreStorage; + CafeStaticVar gIPCThread{coreinit::g_coreinitStaticData}; + CafeStaticVar _gIPCThreadStack{coreinit::g_coreinitStaticData}; + CafeStaticVar _gIPCThreadNameStorage{coreinit::g_coreinitStaticData}; + CafeStaticVar gIPCThreadMsgQueue{coreinit::g_coreinitStaticData}; + CafeStaticVar _gIPCThreadSemaphoreStorage{coreinit::g_coreinitStaticData}; // handler thread for asynchronous callbacks for IPC responses void __IPCDriverThreadFunc(PPCInterpreter_t* hCPU) diff --git a/src/Cafe/OS/libs/coreinit/coreinit_Init.cpp b/src/Cafe/OS/libs/coreinit/coreinit_Init.cpp index 04e7d07d..e7abcda6 100644 --- a/src/Cafe/OS/libs/coreinit/coreinit_Init.cpp +++ b/src/Cafe/OS/libs/coreinit/coreinit_Init.cpp @@ -2,10 +2,8 @@ #include "Cafe/HW/Espresso/PPCCallback.h" #include "Cafe/OS/libs/coreinit/coreinit.h" #include "Cafe/OS/RPL/rpl.h" -#include "Cafe/OS/libs/padscore/padscore.h" #include "Cafe/OS/libs/coreinit/coreinit_SysHeap.h" #include "Cafe/OS/libs/coreinit/coreinit_Alarm.h" -#include "Cafe/OS/libs/vpad/vpad.h" #include "Cafe/OS/libs/coreinit/coreinit_GHS.h" #include "Cafe/OS/libs/coreinit/coreinit_DynLoad.h" #include "Cafe/OS/libs/coreinit/coreinit_MEM.h" @@ -159,7 +157,7 @@ struct PreinitUserHeapStruct MEMPTR heapTempMEM2; }; -SysAllocator g_preinitUserParam; +CafeStaticVar g_preinitUserParam{coreinit::g_coreinitStaticData}; void InitCafeHeaps() { @@ -208,10 +206,6 @@ void coreinit_start(PPCInterpreter_t* hCPU) RPLLoader_CallEntrypoints(); - // init vpadbase (todo - simulate entrypoints for HLE modules) - padscore::start(); - vpad::start(); - // call entry-type callbacks in graphic packs for (const auto gp : GraphicPack2::GetActiveGraphicPacks()) { diff --git a/src/Cafe/OS/libs/coreinit/coreinit_MEM.cpp b/src/Cafe/OS/libs/coreinit/coreinit_MEM.cpp index 83658f3c..9241df2e 100644 --- a/src/Cafe/OS/libs/coreinit/coreinit_MEM.cpp +++ b/src/Cafe/OS/libs/coreinit/coreinit_MEM.cpp @@ -6,33 +6,33 @@ #include "Cafe/OS/RPL/rpl.h" #include "Cafe/OS/libs/coreinit/coreinit_MEM_FrmHeap.h" #include "coreinit_DynLoad.h" +#include "util/ChunkedHeap/ChunkedHeap.h" // the system area is a block of memory that exists only in the emulator. It is used to simplify dynamic memory allocation for system data -// this partially overlaps with the system heap from coreinit_SysHeap.cpp -> Use SysHeap for everything -MPTR sysAreaAllocatorOffset = 0; +// it's deprecated -> Use SysHeap/CafeStaticVar for everything +static std::unique_ptr s_cosSysHeap; +static std::mutex s_allocatorMtx; + +// deprecated MPTR coreinit_allocFromSysArea(uint32 size, uint32 alignment) { + std::unique_lock _(s_allocatorMtx); cemu_assert_debug(mmuRange_CEMU_AREA.isMapped()); - // deprecated, use OSAllocFromSystem instead (for everything but SysAllocator which probably should use its own allocator?) - static std::mutex s_allocator_mutex; - s_allocator_mutex.lock(); - sysAreaAllocatorOffset = (sysAreaAllocatorOffset+alignment-1); - sysAreaAllocatorOffset -= (sysAreaAllocatorOffset%alignment); - uint32 newMemOffset = mmuRange_CEMU_AREA.getBase() + sysAreaAllocatorOffset; - sysAreaAllocatorOffset += (size+3)&~3; - if( sysAreaAllocatorOffset >= mmuRange_CEMU_AREA.getSize() ) - { + if (!s_cosSysHeap) + s_cosSysHeap = std::make_unique(mmuRange_CEMU_AREA.getPtr(), mmuRange_CEMU_AREA.getSize()); + MEMPTR r = s_cosSysHeap->alloc(size, alignment); + if (!r) cemuLog_log(LogType::Force, "Ran out of system memory"); - cemu_assert(false); // out of bounds - } - s_allocator_mutex.unlock(); - return newMemOffset; + cemu_assert(r); + return r.GetMPTR(); } void coreinit_freeToSysArea(MPTR mem) { - // todo + cemu_assert(mem != MPTR_NULL); + std::unique_lock _(s_allocatorMtx); + s_cosSysHeap->free(MEMPTR(mem).GetPtr()); } namespace coreinit @@ -50,7 +50,7 @@ namespace coreinit MEMList g_list3; std::array gHeapFillValues{ 0xC3C3C3C3, 0xF3F3F3F3, 0xD3D3D3D3 }; - SysAllocator gHeapGlobalLock; + CafeStaticVar gHeapGlobalLock{coreinit::g_coreinitStaticData}; MEMHeapBase* gDefaultHeap; bool MEMHeapTable_Add(MEMHeapBase* heap) @@ -562,7 +562,7 @@ namespace coreinit hCPU->instructionPointer = gCoreinitData->MEMFreeToDefaultHeap.GetMPTR(); } - SysAllocator gDefaultHeapAllocator; + CafeStaticVar gDefaultHeapAllocator{coreinit::g_coreinitStaticData}; void coreinitExport_MEMInitAllocatorForDefaultHeap(PPCInterpreter_t* hCPU) { diff --git a/src/Cafe/OS/libs/coreinit/coreinit_MEM_ExpHeap.cpp b/src/Cafe/OS/libs/coreinit/coreinit_MEM_ExpHeap.cpp index 04cc5d84..fa98349f 100644 --- a/src/Cafe/OS/libs/coreinit/coreinit_MEM_ExpHeap.cpp +++ b/src/Cafe/OS/libs/coreinit/coreinit_MEM_ExpHeap.cpp @@ -828,7 +828,7 @@ void _DefaultAllocatorForExpHeap_Free(PPCInterpreter_t* hCPU) osLib_returnFromFunction(hCPU, 0); } -SysAllocator gExpHeapDefaultAllocator; +CafeStaticVar gExpHeapDefaultAllocator{coreinit::g_coreinitStaticData}; void MEMInitAllocatorForExpHeap(MEMAllocator* allocator, MEMHeapHandle heap, sint32 alignment) { diff --git a/src/Cafe/OS/libs/coreinit/coreinit_MessageQueue.cpp b/src/Cafe/OS/libs/coreinit/coreinit_MessageQueue.cpp index cbcfa4d1..dcca09c4 100644 --- a/src/Cafe/OS/libs/coreinit/coreinit_MessageQueue.cpp +++ b/src/Cafe/OS/libs/coreinit/coreinit_MessageQueue.cpp @@ -6,8 +6,8 @@ namespace coreinit void UpdateSystemMessageQueue(); void HandleReceivedSystemMessage(OSMessage* msg); - SysAllocator g_systemMessageQueue; - SysAllocator _systemMessageQueueArray; + CafeStaticVar g_systemMessageQueue{coreinit::g_coreinitStaticData}; + CafeStaticVar _systemMessageQueueArray{coreinit::g_coreinitStaticData}; void OSInitMessageQueueEx(OSMessageQueue* msgQueue, OSMessage* msgArray, uint32 msgCount, void* userData) { diff --git a/src/Cafe/OS/libs/coreinit/coreinit_Synchronization.cpp b/src/Cafe/OS/libs/coreinit/coreinit_Synchronization.cpp index 4f85537b..ca03b0e3 100644 --- a/src/Cafe/OS/libs/coreinit/coreinit_Synchronization.cpp +++ b/src/Cafe/OS/libs/coreinit/coreinit_Synchronization.cpp @@ -174,7 +174,7 @@ namespace coreinit /************* OSRendezvous ************/ - SysAllocator g_rendezvousEvent; + CafeStaticVar g_rendezvousEvent{coreinit::g_coreinitStaticData}; void OSInitRendezvous(OSRendezvous* rendezvous) { diff --git a/src/Cafe/OS/libs/coreinit/coreinit_SystemInfo.cpp b/src/Cafe/OS/libs/coreinit/coreinit_SystemInfo.cpp index 83925acd..bb76ffe2 100644 --- a/src/Cafe/OS/libs/coreinit/coreinit_SystemInfo.cpp +++ b/src/Cafe/OS/libs/coreinit/coreinit_SystemInfo.cpp @@ -3,7 +3,7 @@ namespace coreinit { - SysAllocator g_system_info; + CafeStaticVar g_system_info{coreinit::g_coreinitStaticData}; const OSSystemInfo& OSGetSystemInfo() { diff --git a/src/Cafe/OS/libs/coreinit/coreinit_Thread.cpp b/src/Cafe/OS/libs/coreinit/coreinit_Thread.cpp index 8968720b..ef25c5d1 100644 --- a/src/Cafe/OS/libs/coreinit/coreinit_Thread.cpp +++ b/src/Cafe/OS/libs/coreinit/coreinit_Thread.cpp @@ -65,9 +65,9 @@ namespace coreinit std::vector sSchedulerThreads; std::mutex sSchedulerStateMtx; - SysAllocator g_activeThreadQueue; // list of all threads (can include non-detached inactive threads) + CafeStaticVar g_activeThreadQueue{coreinit::g_coreinitStaticData}; // list of all threads (can include non-detached inactive threads) - SysAllocator g_coreRunQueue; + CafeStaticVar g_coreRunQueue{coreinit::g_coreinitStaticData}; CounterSemaphore g_coreRunQueueThreadCount[3]; bool g_isMulticoreMode; @@ -1485,8 +1485,8 @@ namespace coreinit return sSchedulerActive; } - SysAllocator s_defaultThreads; - SysAllocator s_stack; + CafeStaticVar s_defaultThreads{coreinit::g_coreinitStaticData}; + CafeStaticVar s_stack{coreinit::g_coreinitStaticData}; OSThread_t* OSGetDefaultThread(sint32 coreIndex) { @@ -1532,10 +1532,10 @@ namespace coreinit MEMPTR deallocatorFunc; }; - SysAllocator terminatorThread; - SysAllocator threadStack; - SysAllocator threadName; - SysAllocator semaphoreQueuedDeallocators; + CafeStaticVar terminatorThread{coreinit::g_coreinitStaticData}; + CafeStaticVar threadStack{coreinit::g_coreinitStaticData}; + CafeStaticVar threadName{coreinit::g_coreinitStaticData}; + CafeStaticVar semaphoreQueuedDeallocators{coreinit::g_coreinitStaticData}; ConcurrentQueue queueDeallocators; }; @@ -1575,18 +1575,18 @@ namespace coreinit } } - SysAllocator _defaultThreadName[PPC_CORE_COUNT]; + CafeStaticVar, PPC_CORE_COUNT> _defaultThreadName{coreinit::g_coreinitStaticData}; void __OSInitDefaultThreads() { for (sint32 i = 0; i < PPC_CORE_COUNT; i++) { - sprintf(_defaultThreadName[i].GetPtr(), "Default Core %d", i); + sprintf(_defaultThreadName[i].data(), "Default Core %d", i); OSThread_t* coreDefaultThread = coreinit::OSGetDefaultThread(i); uint32 stackSize; void* stackBase = coreinit::OSGetDefaultThreadStack(i, stackSize); coreinit::OSCreateThreadType(coreDefaultThread, MPTR_NULL, 0, nullptr, (uint8*)stackBase + stackSize, stackSize, 16, 1 << i, OSThread_t::THREAD_TYPE::TYPE_APP); - coreinit::OSSetThreadName(coreDefaultThread, _defaultThreadName[i].GetPtr()); + coreinit::OSSetThreadName(coreDefaultThread, _defaultThreadName[i].data()); } } diff --git a/src/Cafe/OS/libs/erreula/erreula.cpp b/src/Cafe/OS/libs/erreula/erreula.cpp index d9b4d49f..a2ca1264 100644 --- a/src/Cafe/OS/libs/erreula/erreula.cpp +++ b/src/Cafe/OS/libs/erreula/erreula.cpp @@ -1,4 +1,4 @@ -#include "Cafe/OS/common/OSCommon.h" +#include "Cafe/OS/common/OSCommon.h" #include "erreula.h" #include "Cafe/HW/Latte/Renderer/Renderer.h" #include "util/helpers/helpers.h" @@ -15,6 +15,7 @@ namespace nn { namespace erreula { + constinit COSStaticData s_erreulaStaticData; enum class ErrorDialogType : uint32 { @@ -222,7 +223,7 @@ namespace erreula struct ErrEula_t { - SysAllocator mutex; + CafeStaticVar mutex{s_erreulaStaticData}; uint32 regionType{0}; uint32 langType{0}; MEMPTR fsClient; @@ -494,8 +495,14 @@ namespace erreula return "erreula"; } + void RPLUnmapped() override + { + s_erreulaStaticData.Deallocate(); + } + void RPLMapped() override { + s_erreulaStaticData.Allocate(); cafeExportRegisterFunc(ErrEulaCreate, "erreula", "ErrEulaCreate__3RplFPUcQ3_2nn7erreula10RegionTypeQ3_2nn7erreula8LangTypeP8FSClient", LogType::Placeholder); cafeExportRegisterFunc(ErrEulaDestroy, "erreula", "ErrEulaDestroy__3RplFv", LogType::Placeholder); diff --git a/src/Cafe/OS/libs/gx2/GX2.cpp b/src/Cafe/OS/libs/gx2/GX2.cpp index cc07dc5b..d5dcfe2e 100644 --- a/src/Cafe/OS/libs/gx2/GX2.cpp +++ b/src/Cafe/OS/libs/gx2/GX2.cpp @@ -313,6 +313,8 @@ void gx2Export_GX2SetSemaphore(PPCInterpreter_t* hCPU) namespace GX2 { + constinit COSStaticData s_gx2StaticData; + class : public COSModule { public: @@ -326,8 +328,14 @@ namespace GX2 return "gx2"; } + void RPLUnmapped() override + { + s_gx2StaticData.Deallocate(); + } + void RPLMapped() override { + s_gx2StaticData.Allocate(); osLib_addFunction("gx2", "GX2GetContextStateDisplayList", gx2Export_GX2GetContextStateDisplayList); // swap, vsync & timing diff --git a/src/Cafe/OS/libs/gx2/GX2.h b/src/Cafe/OS/libs/gx2/GX2.h index b722fca6..62a2b44f 100644 --- a/src/Cafe/OS/libs/gx2/GX2.h +++ b/src/Cafe/OS/libs/gx2/GX2.h @@ -12,8 +12,11 @@ // general +class COSStaticData; + namespace GX2 { + extern COSStaticData s_gx2StaticData; COSModule* GetModule(); } diff --git a/src/Cafe/OS/libs/gx2/GX2_Command.cpp b/src/Cafe/OS/libs/gx2/GX2_Command.cpp index 3edefacb..c66694bd 100644 --- a/src/Cafe/OS/libs/gx2/GX2_Command.cpp +++ b/src/Cafe/OS/libs/gx2/GX2_Command.cpp @@ -60,7 +60,7 @@ namespace GX2 uint64be lastSubmissionTime; }; - SysAllocator s_commandState; + CafeStaticVar s_commandState{s_gx2StaticData}; GX2PerCoreCBState s_mainCoreLastCommandState; bool s_cbBufferIsInternallyAllocated; @@ -529,6 +529,8 @@ namespace GX2 void GX2CommandResetToDefaultState() { + if (!s_commandState.IsAllocated()) + return; s_commandState->commandPoolBase = nullptr; s_commandState->commandPoolSizeInU32s = 0; s_commandState->gpuCommandReadPtr = nullptr; diff --git a/src/Cafe/OS/libs/gx2/GX2_Event.cpp b/src/Cafe/OS/libs/gx2/GX2_Event.cpp index 338b7d79..ea88b37e 100644 --- a/src/Cafe/OS/libs/gx2/GX2_Event.cpp +++ b/src/Cafe/OS/libs/gx2/GX2_Event.cpp @@ -12,9 +12,8 @@ namespace GX2 { - - SysAllocator g_vsyncThreadQueue; - SysAllocator g_flipThreadQueue; + CafeStaticVar g_vsyncThreadQueue{s_gx2StaticData}; + CafeStaticVar g_flipThreadQueue{s_gx2StaticData}; void GX2SetGPUFence(uint32be* fencePtr, uint32 mask, uint32 compareOp, uint32 compareValue) { @@ -143,9 +142,9 @@ namespace GX2 // event callback thread bool s_callbackThreadLaunched{}; - SysAllocator s_eventCallbackThread; - SysAllocator s_eventCallbackThreadStack; - SysAllocator s_eventCallbackThreadName; + CafeStaticVar s_eventCallbackThread{s_gx2StaticData}; + CafeStaticVar s_eventCallbackThreadStack{s_gx2StaticData}; + CafeStaticVar s_eventCallbackThreadName{s_gx2StaticData}; // event callback queue struct GX2EventQueueEntry { @@ -154,11 +153,13 @@ namespace GX2 GX2CallbackEventType eventType{(GX2CallbackEventType)-1}; }; - SysAllocator s_eventCbQueueSemaphore; + CafeStaticVar s_eventCbQueueSemaphore{s_gx2StaticData}; ConcurrentQueue s_eventCbQueue; void __GX2NotifyEvent(GX2CallbackEventType eventType) { + if (!g_vsyncThreadQueue.IsAllocated()) + return; if ((size_t)eventType >= GX2CallbackEventTypeCount) { cemu_assert_debug(false); diff --git a/src/Cafe/OS/libs/gx2/GX2_Misc.cpp b/src/Cafe/OS/libs/gx2/GX2_Misc.cpp index 83209514..a3144b1a 100644 --- a/src/Cafe/OS/libs/gx2/GX2_Misc.cpp +++ b/src/Cafe/OS/libs/gx2/GX2_Misc.cpp @@ -78,7 +78,7 @@ void gx2Export_GX2SampleBottomGPUCycle(PPCInterpreter_t* hCPU) namespace GX2 { - SysAllocator _lastFrame; + CafeStaticVar _lastFrame{s_gx2StaticData}; uint32 sGX2MainCoreIndex = 0; void _test_AddrLib(); diff --git a/src/Cafe/OS/libs/nfc/nfc.cpp b/src/Cafe/OS/libs/nfc/nfc.cpp index b1c9a2cc..e85d7e5a 100644 --- a/src/Cafe/OS/libs/nfc/nfc.cpp +++ b/src/Cafe/OS/libs/nfc/nfc.cpp @@ -29,6 +29,8 @@ namespace nfc { + constinit COSStaticData s_nfcStaticData; + struct NFCContext { bool isInitialized; @@ -56,7 +58,7 @@ namespace nfc void* writeContext; MPTR getTagInfoCallback; - SysAllocator tagInfo; + CafeStaticVar tagInfo{s_nfcStaticData}; fs::path tagPath; std::shared_ptr tag; @@ -646,8 +648,14 @@ namespace nfc return "nfc"; } + void RPLUnmapped() override + { + s_nfcStaticData.Deallocate(); + } + void RPLMapped() override { + s_nfcStaticData.Allocate(); cafeExportRegister("nfc", NFCInit, LogType::NFC); cafeExportRegister("nfc", NFCInitEx, LogType::NFC); cafeExportRegister("nfc", NFCShutdown, LogType::NFC); diff --git a/src/Cafe/OS/libs/nn_boss/nn_boss.cpp b/src/Cafe/OS/libs/nn_boss/nn_boss.cpp index 66c89fee..abecd036 100644 --- a/src/Cafe/OS/libs/nn_boss/nn_boss.cpp +++ b/src/Cafe/OS/libs/nn_boss/nn_boss.cpp @@ -15,19 +15,30 @@ namespace nn { namespace boss { + constinit COSStaticData s_rplData; + + CafeStaticVar Title::s_titleVTable{s_rplData}; + CafeStaticVar BossAccount::s_VTable{s_rplData}; + CafeStaticVar TaskSetting::s_VTable{s_rplData}; + CafeStaticVar NetTaskSetting::s_VTable{s_rplData}; + CafeStaticVar NbdlTaskSetting::s_VTable{s_rplData}; + CafeStaticVar RawUlTaskSetting::s_VTable{s_rplData}; + CafeStaticVar RawDlTaskSetting::s_VTable{s_rplData}; + CafeStaticVar PlayReportSetting::s_VTable{s_rplData}; + IPCServiceClient s_ipcClient; static constexpr BossResult resultSuccess = BUILD_NN_RESULT(NN_RESULT_LEVEL_SUCCESS, NN_RESULT_MODULE_NN_BOSS, 0x80); static constexpr BossResult resultInvalidParam = BUILD_NN_RESULT(NN_RESULT_LEVEL_LVL6, NN_RESULT_MODULE_NN_BOSS, 0x3780); static constexpr BossResult resultUknA0220300 = BUILD_NN_RESULT(NN_RESULT_LEVEL_STATUS, NN_RESULT_MODULE_NN_BOSS, 0x20300); - SysAllocator g_mutex; + CafeStaticVar g_mutex{s_rplData}; sint32 g_initCounter = 0; bool g_isInitialized = false; #define DTOR_WRAPPER(__TYPE) RPLLoader_MakePPCCallable([](PPCInterpreter_t* hCPU) { dtor(MEMPTR<__TYPE>(hCPU->gpr[3]), hCPU->gpr[4]); osLib_returnFromFunction(hCPU, 0); }) - SysAllocator s_ipcBuffer; + CafeStaticVar s_ipcBuffer{s_rplData}; constexpr uint32 BOSS_MEM_MAGIC = 0xCAFE4321; @@ -492,7 +503,7 @@ namespace boss VTableEntry rtti; VTableEntry dtor; }; - static inline SysAllocator s_vTable; + static inline CafeStaticVar s_vTable{s_rplData}; uint32be persistentId; // 0x00 uint32be uk2; // 0x04 @@ -744,7 +755,7 @@ namespace boss VTableEntry rttiTask; }; static_assert(sizeof(VTablePrivilegedTask) == 8*3); - static inline SysAllocator s_VTable; + static inline CafeStaticVar s_VTable{s_rplData}; static PrivilegedTask* ctor(PrivilegedTask* _thisptr) { @@ -778,7 +789,7 @@ namespace boss struct VTableAlmightyTask : public VTablePrivilegedTask {}; static_assert(sizeof(VTableAlmightyTask) == 8*3); - static inline SysAllocator s_VTable; + static inline CafeStaticVar s_VTable{s_rplData}; static AlmightyTask* ctor(AlmightyTask* _thisptr) { @@ -850,7 +861,7 @@ namespace boss VTableEntry rtti; VTableEntry dtor; }; - static inline SysAllocator s_vTable; + static inline CafeStaticVar s_vTable{s_rplData}; enum StorageKind { @@ -958,7 +969,7 @@ namespace boss VTableEntry rttiStorage; }; static_assert(sizeof(VTableAlmightyStorage) == 8*3); - static inline SysAllocator s_VTable; + static inline CafeStaticVar s_VTable{s_rplData}; static AlmightyStorage* ctor(AlmightyStorage* _thisptr) { @@ -1001,7 +1012,7 @@ namespace boss VTableEntry rtti; VTableEntry dtor; }; - static inline SysAllocator s_vTable; + static inline CafeStaticVar s_vTable{s_rplData}; /* +0x00 */ DataName name; /* +0x20 */ Storage storage; @@ -1202,8 +1213,14 @@ namespace nn::boss return "nn_boss"; } + void RPLUnmapped() override + { + s_rplData.Deallocate(); + } + void RPLMapped() override { + s_rplData.Allocate(); cafeExportRegisterFunc(nn::boss::GetBossState, "nn_boss", "GetBossState__Q2_2nn4bossFv", LogType::NN_BOSS); // boss lib diff --git a/src/Cafe/OS/libs/nn_fp/nn_fp.cpp b/src/Cafe/OS/libs/nn_fp/nn_fp.cpp index 3c3321fc..5b56e7b0 100644 --- a/src/Cafe/OS/libs/nn_fp/nn_fp.cpp +++ b/src/Cafe/OS/libs/nn_fp/nn_fp.cpp @@ -13,6 +13,8 @@ namespace nn { namespace fp { + constinit constinit COSStaticData s_nnfpStaticData; + static const auto FPResult_OkZero = 0; static const auto FPResult_Ok = BUILD_NN_RESULT(NN_RESULT_LEVEL_SUCCESS, NN_RESULT_MODULE_NN_FP, 0); static const auto FPResult_InvalidIPCParam = BUILD_NN_RESULT(NN_RESULT_LEVEL_LVL6, NN_RESULT_MODULE_NN_FP, 0x680); @@ -24,12 +26,12 @@ namespace nn bool isAdminMode; bool isLoggedIn; IOSDevHandle fpdHandle; - SysAllocator fpMutex; - SysAllocator g_fpdAllocatorSpace; + CafeStaticVar fpMutex{s_nnfpStaticData}; + CafeStaticVar g_fpdAllocatorSpace{s_nnfpStaticData}; VHeap* fpBufferHeap{nullptr}; // PPC buffers for async notification query - SysAllocator notificationCount; - SysAllocator notificationBuffer; + CafeStaticVar notificationCount{s_nnfpStaticData}; + CafeStaticVar notificationBuffer{s_nnfpStaticData}; bool getNotificationCalled{false}; // notification handler MEMPTR notificationHandler{nullptr}; @@ -49,6 +51,7 @@ namespace nn { std::unique_lock _l(m_mtx); delete g_fp.fpBufferHeap; + g_fp.fpBufferHeap = nullptr; } void* Allocate(uint32 size, uint32 alignment) @@ -766,8 +769,15 @@ namespace nn return "nn_fp"; } + void RPLUnmapped() override + { + FPIpcBufferAllocator.Destroy(); + s_nnfpStaticData.Deallocate(); + } + void RPLMapped() override { + s_nnfpStaticData.Allocate(); g_fp.initCounter = 0; g_fp.isAdminMode = false; g_fp.isLoggedIn = false; diff --git a/src/Cafe/OS/libs/nn_olv/nn_olv.cpp b/src/Cafe/OS/libs/nn_olv/nn_olv.cpp index 34b4b599..9d3a876e 100644 --- a/src/Cafe/OS/libs/nn_olv/nn_olv.cpp +++ b/src/Cafe/OS/libs/nn_olv/nn_olv.cpp @@ -11,13 +11,16 @@ #include "Cafe/OS/libs/coreinit/coreinit_Time.h" #include "Cafe/OS/libs/coreinit/coreinit_Misc.h" + namespace nn { namespace olv { - static SysAllocator s_OlvReleaseBgThread; - SysAllocator s_OlvReleaseBgThreadStack; - SysAllocator s_OlvReleaseBgThreadName; + constinit COSStaticData s_nnolvStaticData; + + CafeStaticVar s_OlvReleaseBgThread{s_nnolvStaticData}; + CafeStaticVar s_OlvReleaseBgThreadStack{s_nnolvStaticData}; + CafeStaticVar s_OlvReleaseBgThreadName{s_nnolvStaticData}; void StubPostAppReleaseBackground(PPCInterpreter_t* hCPU) { @@ -103,8 +106,14 @@ namespace nn return "nn_olv"; } + void RPLUnmapped() override + { + s_nnolvStaticData.Deallocate(); + } + void RPLMapped() override { + s_nnolvStaticData.Allocate(); loadOliveInitializeTypes(); loadOliveUploadCommunityTypes(); loadOliveDownloadCommunityTypes(); diff --git a/src/Cafe/OS/libs/nn_save/nn_save.cpp b/src/Cafe/OS/libs/nn_save/nn_save.cpp index 2c608482..d0227b84 100644 --- a/src/Cafe/OS/libs/nn_save/nn_save.cpp +++ b/src/Cafe/OS/libs/nn_save/nn_save.cpp @@ -4,14 +4,13 @@ #include "Cafe/OS/libs/nn_acp/nn_acp.h" #include "Cafe/OS/libs/nn_act/nn_act.h" -#include -#include #include "config/ActiveSettings.h" #include "Cafe/OS/libs/coreinit/coreinit_Thread.h" #include "Cafe/OS/libs/coreinit/coreinit_FS.h" #include "Cafe/CafeSystem.h" #include "Cafe/Filesystem/fsc.h" + #define SAVE_STATUS_OK ((FSStatus)FS_RESULT::SUCCESS) #define SAVE_MAX_PATH_SIZE (FSA_CMD_PATH_MAX_LENGTH) @@ -27,6 +26,8 @@ namespace nn { namespace save { + constinit COSStaticData s_rplData; + typedef FSStatus SAVEStatus; typedef struct @@ -38,7 +39,7 @@ namespace save uint32 persistentIdCache[0xC]; }nn_save_t; - SysAllocator g_nn_save; + CafeStaticVar g_nn_save{s_rplData}; uint32 GetPersistentIdFromLocalCache(uint8 accountSlot) { @@ -767,7 +768,7 @@ namespace save void ResetToDefaultState() { - if(g_nn_save->initialized) + if(g_nn_save.IsAllocated() && g_nn_save->initialized) { SAVEUnmountSaveDir(); g_nn_save->initialized = false; @@ -782,8 +783,14 @@ namespace save return "nn_save"; } + void RPLUnmapped() override + { + s_rplData.Deallocate(); + } + void RPLMapped() override { + s_rplData.Allocate(); cafeExportRegister("nn_save", SAVEInit, LogType::Save); cafeExportRegister("nn_save", SAVEInitSaveDir, LogType::Save); diff --git a/src/Cafe/OS/libs/nn_sl/nn_sl.cpp b/src/Cafe/OS/libs/nn_sl/nn_sl.cpp index a1e663cc..d2d464e3 100644 --- a/src/Cafe/OS/libs/nn_sl/nn_sl.cpp +++ b/src/Cafe/OS/libs/nn_sl/nn_sl.cpp @@ -4,11 +4,14 @@ #include "config/ActiveSettings.h" #include "Cafe/CafeSystem.h" + namespace nn { typedef uint32 Result; namespace sl { + constinit COSStaticData s_nnslStaticData; + struct VTableEntry { uint16be offsetA{0}; @@ -66,7 +69,7 @@ namespace nn VTableEntry dtor; VTableEntry get; }; - static inline SysAllocator s_titleVTable; + static inline CafeStaticVar s_titleVTable{s_nnslStaticData}; static WhiteListAccessor* ctor(WhiteListAccessor* _this) { @@ -97,7 +100,7 @@ namespace nn }; static_assert(sizeof(WhiteListAccessor) == 0x04); - SysAllocator s_defaultWhiteListAccessor; + CafeStaticVar s_defaultWhiteListAccessor{s_nnslStaticData}; WhiteListAccessor* GetDefaultWhiteListAccessor() { @@ -112,8 +115,14 @@ namespace nn return "nn_sl"; } + void RPLUnmapped() override + { + s_nnslStaticData.Deallocate(); + } + void RPLMapped() override { + s_nnslStaticData.Allocate(); cafeExportRegisterFunc(nn::sl::GetDefaultWhiteListAccessor, "nn_sl", "GetDefaultWhiteListAccessor__Q2_2nn2slFv", LogType::NN_SL); }; diff --git a/src/Cafe/OS/libs/nsyshid/nsyshid.cpp b/src/Cafe/OS/libs/nsyshid/nsyshid.cpp index a26aef61..288a8d08 100644 --- a/src/Cafe/OS/libs/nsyshid/nsyshid.cpp +++ b/src/Cafe/OS/libs/nsyshid/nsyshid.cpp @@ -1,17 +1,16 @@ #include "Cafe/OS/common/OSCommon.h" #include "Cafe/HW/Espresso/PPCCallback.h" -#include -#include #include "nsyshid.h" #include "Cafe/OS/libs/coreinit/coreinit_Thread.h" #include "Backend.h" #include "Whitelist.h" + namespace nsyshid { + constinit COSStaticData s_nsyshidStaticData; std::list> backendList; - std::list> deviceList; typedef struct _HIDClient_t @@ -75,7 +74,7 @@ namespace nsyshid const int HID_MAX_NUM_DEVICES = 128; - SysAllocator HIDPool; + CafeStaticVar HIDPool{s_nsyshidStaticData}; std::queue HIDPoolIndexQueue; void InitHIDPoolIndexQueue() @@ -96,6 +95,9 @@ namespace nsyshid HID_t* GetFreeHID() { std::lock_guard lock(hidMutex); + cemu_assert_debug(HIDPool.IsAllocated()); + if (!HIDPool.IsAllocated()) + return nullptr; InitHIDPoolIndexQueue(); if (HIDPoolIndexQueue.empty()) { @@ -952,8 +954,28 @@ namespace nsyshid return "nsyshid"; } + void RPLUnmapped() override + { + // Stop backends and drop callbacks before their guest descriptors go away. + { + std::lock_guard lock(hidMutex); + HIDClientList.clear(); + } + DetachAllBackends(); + std::list> remainingDevices; + { + std::lock_guard lock(hidMutex); + remainingDevices = deviceList; + } + for (const auto& device : remainingDevices) + DetachDevice(device); + std::lock_guard lock(hidMutex); + s_nsyshidStaticData.Deallocate(); + } + void RPLMapped() override { + s_nsyshidStaticData.Allocate(); osLib_addFunction("nsyshid", "HIDAddClient", export_HIDAddClient); osLib_addFunction("nsyshid", "HIDDelClient", export_HIDDelClient); osLib_addFunction("nsyshid", "HIDGetDescriptor", export_HIDGetDescriptor); diff --git a/src/Cafe/OS/libs/nsysnet/nsysnet.cpp b/src/Cafe/OS/libs/nsysnet/nsysnet.cpp index a68bade4..53a2e91d 100644 --- a/src/Cafe/OS/libs/nsysnet/nsysnet.cpp +++ b/src/Cafe/OS/libs/nsysnet/nsysnet.cpp @@ -79,6 +79,7 @@ #define WU_SO_ESHUTDOWN 0x000F +constinit COSStaticData s_nsysnetData; typedef signed int WUSOCKET; @@ -1385,10 +1386,10 @@ void nsysnetExport_gethostbyname(PPCInterpreter_t* hCPU) return; } -SysAllocator _staticHostent; -SysAllocator _staticHostentName; -SysAllocator _staticHostentPtrList; -SysAllocator _staticHostentEntries; +CafeStaticVar _staticHostent{s_nsysnetData}; +CafeStaticVar _staticHostentName{s_nsysnetData}; +CafeStaticVar _staticHostentPtrList{s_nsysnetData}; +CafeStaticVar _staticHostentEntries{s_nsysnetData}; void nsysnetExport_gethostbyaddr(PPCInterpreter_t* hCPU) { @@ -2211,8 +2212,14 @@ namespace nsysnet return "nsysnet"; } + void RPLUnmapped() override + { + s_nsysnetData.Deallocate(); + } + void RPLMapped() override { + s_nsysnetData.Allocate(); cafeExportRegister("nsysnet", inet_ntop, LogType::Socket); // the below code is the old way of registering API which is deprecated diff --git a/src/Cafe/OS/libs/padscore/padscore.cpp b/src/Cafe/OS/libs/padscore/padscore.cpp index 3faa5fba..c9e4195d 100644 --- a/src/Cafe/OS/libs/padscore/padscore.cpp +++ b/src/Cafe/OS/libs/padscore/padscore.cpp @@ -7,6 +7,8 @@ #include "WindowSystem.h" #include "input/InputManager.h" +constinit COSStaticData s_padscoreStaticData; + // KPAD enum class KPAD_ERROR : sint32 @@ -55,7 +57,7 @@ namespace padscore WPADState_t g_wpad_state = kWPADStateMaster; struct { - SysAllocator alarm; + CafeStaticVar alarm{s_padscoreStaticData}; bool kpad_initialized = false; struct WPADData @@ -774,8 +776,21 @@ namespace padscore return "padscore"; } + void RPLUnmapped() override + { + coreinit::OSCancelAlarm(g_padscore.alarm.GetPtr()); + s_padscoreStaticData.Deallocate(); + } + + void rpl_entry(uint32 moduleHandle, coreinit::RplEntryReason reason) override + { + if (reason == coreinit::RplEntryReason::Loaded) + start(); + } + void RPLMapped() override { + s_padscoreStaticData.Allocate(); cafeExportRegister("padscore", WPADIsMplsAttached, LogType::InputAPI); cafeExportRegister("padscore", WPADGetAccGravityUnit, LogType::InputAPI); diff --git a/src/Cafe/OS/libs/proc_ui/proc_ui.cpp b/src/Cafe/OS/libs/proc_ui/proc_ui.cpp index 653a0f7d..942b3e2a 100644 --- a/src/Cafe/OS/libs/proc_ui/proc_ui.cpp +++ b/src/Cafe/OS/libs/proc_ui/proc_ui.cpp @@ -20,6 +20,8 @@ using namespace coreinit; namespace proc_ui { + constinit COSStaticData s_procuiStaticData; + enum class ProcUICoreThreadCommand { AcquireForeground = 0x0, @@ -58,26 +60,26 @@ namespace proc_ui MEMPTR s_saveCallbackEx; // with custom param and return value, set by ProcUIInitEx() MEMPTR s_saveCallbackExUserParam; MEMPTR s_systemMessageQueuePtr; - SysAllocator s_eventStateMessageReceived; - SysAllocator s_eventWaitingBeforeReleaseForeground; - SysAllocator s_eventBackgroundThreadGotMessage; + CafeStaticVar s_eventStateMessageReceived{s_procuiStaticData}; + CafeStaticVar s_eventWaitingBeforeReleaseForeground{s_procuiStaticData}; + CafeStaticVar s_eventBackgroundThreadGotMessage{s_procuiStaticData}; // procUI core threads uint32 s_coreThreadStackSize; bool s_coreThreadsCreated; std::atomic s_commandForCoreThread; - SysAllocator s_coreThreadArray[Espresso::CORE_COUNT]; + CafeStaticVar s_coreThreadArray{s_procuiStaticData}; MEMPTR s_coreThreadStackPerCore[Espresso::CORE_COUNT]; - SysAllocator> s_coreThread0NameBuffer; - SysAllocator> s_coreThread1NameBuffer; - SysAllocator> s_coreThread2NameBuffer; - SysAllocator s_eventCoreThreadsNewCommandReady; - SysAllocator s_eventCoreThreadsCommandDone; - SysAllocator s_coreThreadRendezvousA; - SysAllocator s_coreThreadRendezvousB; - SysAllocator s_coreThreadRendezvousC; + CafeStaticVar> s_coreThread0NameBuffer{s_procuiStaticData}; + CafeStaticVar> s_coreThread1NameBuffer{s_procuiStaticData}; + CafeStaticVar> s_coreThread2NameBuffer{s_procuiStaticData}; + CafeStaticVar s_eventCoreThreadsNewCommandReady{s_procuiStaticData}; + CafeStaticVar s_eventCoreThreadsCommandDone{s_procuiStaticData}; + CafeStaticVar s_coreThreadRendezvousA{s_procuiStaticData}; + CafeStaticVar s_coreThreadRendezvousB{s_procuiStaticData}; + CafeStaticVar s_coreThreadRendezvousC{s_procuiStaticData}; // background thread MEMPTR s_backgroundThreadStack; - SysAllocator s_backgroundThread; + CafeStaticVar s_backgroundThread{s_procuiStaticData}; // user defined heap MEMPTR s_memoryPoolHeapPtr; MEMPTR s_memAllocPtr; @@ -102,8 +104,8 @@ namespace proc_ui uint32be s_driverArgUkn1; uint32be s_driverArgUkn2; bool s_driverInBackground; - SysAllocator s_ProcUIDriver; - SysAllocator> s_ProcUIDriverName; + CafeStaticVar s_ProcUIDriver{s_procuiStaticData}; + CafeStaticVar> s_ProcUIDriverName{s_procuiStaticData}; void* _AllocMem(uint32 size) @@ -854,8 +856,14 @@ namespace proc_ui return "proc_ui"; } + void RPLUnmapped() override + { + s_procuiStaticData.Deallocate(); + } + void RPLMapped() override { + s_procuiStaticData.Allocate(); reset(); cafeExportRegister("proc_ui", ProcUIInit, LogType::ProcUi); diff --git a/src/Cafe/OS/libs/snd_core/ax_aux.cpp b/src/Cafe/OS/libs/snd_core/ax_aux.cpp index a9176562..46b22aa1 100644 --- a/src/Cafe/OS/libs/snd_core/ax_aux.cpp +++ b/src/Cafe/OS/libs/snd_core/ax_aux.cpp @@ -1,6 +1,7 @@ #include "Cafe/OS/libs/snd_core/ax.h" #include "Cafe/OS/libs/snd_core/ax_internal.h" #include "Cafe/HW/Espresso/PPCState.h" +#include "Common/CafeStaticVar.h" namespace snd_core { @@ -56,8 +57,8 @@ namespace snd_core } }; - SysAllocator __AXAuxTVBuffer; - SysAllocator __AXAuxDRCBuffer; + CafeStaticVar __AXAuxTVBuffer{g_sndStaticData}; + CafeStaticVar __AXAuxDRCBuffer{g_sndStaticData}; uint32 __AXCurrentAuxInputFrameIndex = 0; @@ -188,8 +189,8 @@ namespace snd_core return 0; } - SysAllocator, 6> __AXAuxCB_dataPtrs; - SysAllocator __AXAuxCB_auxCBStruct; + CafeStaticVar, 6> __AXAuxCB_dataPtrs{g_sndStaticData}; + CafeStaticVar __AXAuxCB_auxCBStruct{g_sndStaticData}; void AXAux_Process() { diff --git a/src/Cafe/OS/libs/snd_core/ax_exports.cpp b/src/Cafe/OS/libs/snd_core/ax_exports.cpp index a1ba69c9..6cf8663a 100644 --- a/src/Cafe/OS/libs/snd_core/ax_exports.cpp +++ b/src/Cafe/OS/libs/snd_core/ax_exports.cpp @@ -7,13 +7,19 @@ namespace snd_core { + // snd_core and sndcore2 share the AX implementation in Cemu, but technically they are exclusive/conflicting implementations and no game should use them at the same time + // but just in case we keep g_sndStaticData alive until both modules are unloaded + COSStaticData g_sndStaticData; + static uint32 s_mappedSoundModules = 0; + sndGeneric_t sndGeneric; void AXResetToDefaultState() { sndGeneric = {}; resetNumProcessedFrames(); - AXVBP_Reset(); + if (g_sndStaticData.IsAllocated()) + AXVBP_Reset(); } bool AXIsInit() @@ -473,8 +479,19 @@ namespace snd_core return "snd_core"; } + void RPLUnmapped() override + { + cemu_assert(s_mappedSoundModules > 0); + --s_mappedSoundModules; + if (s_mappedSoundModules == 0) + g_sndStaticData.Deallocate(); + } + void RPLMapped() override { + if (s_mappedSoundModules == 0) + g_sndStaticData.Allocate(); + ++s_mappedSoundModules; AXResetToDefaultState(); cafeExportRegisterFunc(sndcore1_AXInit, "snd_core", "AXInit", LogType::SoundAPI); cafeExportRegisterFunc(sndcore1_AXInitEx, "snd_core", "AXInitEx", LogType::SoundAPI); @@ -548,8 +565,19 @@ namespace snd_core return "sndcore2"; } + void RPLUnmapped() override + { + cemu_assert(s_mappedSoundModules > 0); + --s_mappedSoundModules; + if (s_mappedSoundModules == 0) + g_sndStaticData.Deallocate(); + } + void RPLMapped() override { + if (s_mappedSoundModules == 0) + g_sndStaticData.Allocate(); + ++s_mappedSoundModules; cafeExportRegisterFunc(sndcore2_AXInitWithParams, "sndcore2", "AXInitWithParams", LogType::SoundAPI); cafeExportRegisterFunc(sndcore2_AXInit, "sndcore2", "AXInit", LogType::SoundAPI); cafeExportRegisterFunc(sndcore2_AXInitEx, "sndcore2", "AXInitEx", LogType::SoundAPI); diff --git a/src/Cafe/OS/libs/snd_core/ax_internal.h b/src/Cafe/OS/libs/snd_core/ax_internal.h index cb7c153e..741dd722 100644 --- a/src/Cafe/OS/libs/snd_core/ax_internal.h +++ b/src/Cafe/OS/libs/snd_core/ax_internal.h @@ -1,8 +1,12 @@ #pragma once #include "Cafe/OS/libs/snd_core/ax.h" +class COSStaticData; +template class CafeStaticVar; + namespace snd_core { + extern COSStaticData g_sndStaticData; struct sndGeneric_t { bool isInitialized{false}; @@ -218,7 +222,7 @@ namespace snd_core void AXAux_incrementBufferIndex(); // internal mix buffers - extern SysAllocator __AXTVOutputBuffer; - extern SysAllocator __AXDRCOutputBuffer; + extern CafeStaticVar __AXTVOutputBuffer; + extern CafeStaticVar __AXDRCOutputBuffer; } \ No newline at end of file diff --git a/src/Cafe/OS/libs/snd_core/ax_ist.cpp b/src/Cafe/OS/libs/snd_core/ax_ist.cpp index 9be0c400..85bc3dd3 100644 --- a/src/Cafe/OS/libs/snd_core/ax_ist.cpp +++ b/src/Cafe/OS/libs/snd_core/ax_ist.cpp @@ -4,6 +4,7 @@ #include "Cafe/HW/Espresso/PPCCallback.h" #include "Cafe/OS/libs/coreinit/coreinit_Thread.h" #include "Cafe/OS/libs/coreinit/coreinit_MessageQueue.h" +#include "Common/CafeStaticVar.h" namespace snd_core { @@ -76,12 +77,12 @@ namespace snd_core static_assert(offsetof(AXFINALMIXCBPARAM, numDevices) == 0x08); static_assert(offsetof(AXFINALMIXCBPARAM, numChannelOutput) == 0x0A); - SysAllocator __AXFinalMixCBStructTV; - SysAllocator __AXFinalMixCBStructDRC; - SysAllocator __AXFinalMixCBStructRMT; + CafeStaticVar __AXFinalMixCBStructTV{g_sndStaticData}; + CafeStaticVar __AXFinalMixCBStructDRC{g_sndStaticData}; + CafeStaticVar __AXFinalMixCBStructRMT{g_sndStaticData}; - SysAllocator, 6> __AXFinalMixCBStructTV_dataPtrArray; - SysAllocator, 4 * 2> __AXFinalMixCBStructDRC_dataPtrArray; + CafeStaticVar, 6> __AXFinalMixCBStructTV_dataPtrArray{g_sndStaticData}; + CafeStaticVar, 4 * 2> __AXFinalMixCBStructDRC_dataPtrArray{g_sndStaticData}; sint32 __AXFinalMixOutputChannelCount[AX_DEV_COUNT] = { 0 }; // number of output channels returned by final mix callback @@ -89,7 +90,7 @@ namespace snd_core MPTR __AXFrameCallback = MPTR_NULL; // set via AXRegisterFrameCallback() MPTR __AXAppFrameCallback[AX_APP_FRAME_CALLBACK_MAX]; MPTR __AXDeviceFinalMixCallback[AX_DEV_COUNT]; - SysAllocator __AXAppFrameCallbackMutex; + CafeStaticVar __AXAppFrameCallbackMutex{g_sndStaticData}; void AXResetCallbacks() { @@ -211,8 +212,7 @@ namespace snd_core return 0; } - - SysAllocator g_remix_matrices; + CafeStaticVar g_remix_matrices{g_sndStaticData}; sint32 AXSetDeviceRemixMatrix(sint32 deviceId, uint32 inputChannelCount, uint32 outputChannelCount, const MEMPTR& matrix) { @@ -307,15 +307,15 @@ namespace snd_core return -10; } - SysAllocator __AXTVOutputBuffer; - SysAllocator __AXDRCOutputBuffer; + CafeStaticVar __AXTVOutputBuffer{g_sndStaticData}; + CafeStaticVar __AXDRCOutputBuffer{g_sndStaticData}; - SysAllocator __AXTempFinalMixTVBuffer; - SysAllocator __AXTempFinalMixDRCBuffer; + CafeStaticVar __AXTempFinalMixTVBuffer{g_sndStaticData}; + CafeStaticVar __AXTempFinalMixDRCBuffer{g_sndStaticData}; // 48KHz buffers - SysAllocator __AXTVBuffer48; - SysAllocator __AXDRCBuffer48; + CafeStaticVar __AXTVBuffer48{g_sndStaticData}; + CafeStaticVar __AXDRCBuffer48{g_sndStaticData}; sint32 AXUpsampleLinear32To48(sint32* inputBuffer, sint32* outputBuffer, sint32* sampleHistory, sint32 sampleCount, bool shiftSamples, sint32 channelCount) { @@ -937,7 +937,7 @@ namespace snd_core void AXIst_HandleDeviceRemix() { - extern SysAllocator g_remix_matrices; + extern CafeStaticVar g_remix_matrices; extern sint32 __AXOutTVOutputChannelCount; extern sint32 __AXOutDRCOutputChannelCount; @@ -966,11 +966,11 @@ namespace snd_core std::atomic_bool __AXIstIsProcessingFrame = false; - SysAllocator __AXIstThread; - SysAllocator __AXIstThreadStack; + CafeStaticVar __AXIstThread{g_sndStaticData}; + CafeStaticVar __AXIstThreadStack{g_sndStaticData}; - SysAllocator __AXIstThreadMsgArray; - SysAllocator __AXIstThreadMsgQueue; + CafeStaticVar __AXIstThreadMsgArray{g_sndStaticData}; + CafeStaticVar __AXIstThreadMsgQueue{g_sndStaticData}; void AXIst_InitThread() { @@ -1040,7 +1040,7 @@ namespace snd_core } } - SysAllocator _queueFrameMsg; + CafeStaticVar _queueFrameMsg{g_sndStaticData}; void AXIst_QueueFrame() { diff --git a/src/Cafe/OS/libs/snd_core/ax_mix.cpp b/src/Cafe/OS/libs/snd_core/ax_mix.cpp index 02483cf4..87f43082 100644 --- a/src/Cafe/OS/libs/snd_core/ax_mix.cpp +++ b/src/Cafe/OS/libs/snd_core/ax_mix.cpp @@ -2,6 +2,7 @@ #include "Cafe/OS/libs/snd_core/ax_internal.h" #include "Cafe/HW/MMU/MMU.h" #include "config/ActiveSettings.h" +#include "Common/CafeStaticVar.h" void mic_updateOnAXFrame(); diff --git a/src/Cafe/OS/libs/snd_core/ax_multivoice.cpp b/src/Cafe/OS/libs/snd_core/ax_multivoice.cpp index 0b2b2550..e41e6f0f 100644 --- a/src/Cafe/OS/libs/snd_core/ax_multivoice.cpp +++ b/src/Cafe/OS/libs/snd_core/ax_multivoice.cpp @@ -1,12 +1,13 @@ #include "Cafe/OS/libs/snd_core/ax.h" #include "Cafe/OS/libs/snd_core/ax_internal.h" #include "Cafe/HW/MMU/MMU.h" +#include "Common/CafeStaticVar.h" namespace snd_core { static_assert(sizeof(AXVPBMULTI) == 0x20, ""); - SysAllocator _buffer__AXVPBMultiVoiceArray; + CafeStaticVar _buffer__AXVPBMultiVoiceArray{g_sndStaticData}; AXVPBMULTI* __AXVPBMultiVoiceArray; void AXMultiVoice_Init() diff --git a/src/Cafe/OS/libs/snd_core/ax_out.cpp b/src/Cafe/OS/libs/snd_core/ax_out.cpp index 6cb1599a..dec1a194 100644 --- a/src/Cafe/OS/libs/snd_core/ax_out.cpp +++ b/src/Cafe/OS/libs/snd_core/ax_out.cpp @@ -1,9 +1,8 @@ #include "Cafe/OS/libs/snd_core/ax.h" #include "Cafe/OS/libs/snd_core/ax_internal.h" -#include "Cafe/HW/MMU/MMU.h" #include "audio/IAudioAPI.h" -//#include "ax.h" #include "config/CemuConfig.h" +#include "Common/CafeStaticVar.h" namespace snd_core { @@ -140,8 +139,8 @@ namespace snd_core _AXOutInitDeviceModes(); } - extern SysAllocator __AXTVBuffer48; - extern SysAllocator __AXDRCBuffer48; + extern CafeStaticVar __AXTVBuffer48; + extern CafeStaticVar __AXDRCBuffer48; sint16 __buf_AXTVDMABuffers_0[AX_SAMPLES_MAX * AX_TV_CHANNEL_COUNT]; sint16 __buf_AXTVDMABuffers_1[AX_SAMPLES_MAX * AX_TV_CHANNEL_COUNT]; diff --git a/src/Cafe/OS/libs/snd_core/ax_voice.cpp b/src/Cafe/OS/libs/snd_core/ax_voice.cpp index 0b2f881d..5303c5e3 100644 --- a/src/Cafe/OS/libs/snd_core/ax_voice.cpp +++ b/src/Cafe/OS/libs/snd_core/ax_voice.cpp @@ -83,16 +83,16 @@ namespace snd_core __AXVoicesPerPriority[i].clear(); } - SysAllocator _buffer__AXVPBInternalVoiceArray; + CafeStaticVar _buffer__AXVPBInternalVoiceArray{g_sndStaticData}; AXVPBInternal_t* __AXVPBInternalVoiceArray; - SysAllocator _buffer__AXVPBInternalVoiceShadowCopyArray; + CafeStaticVar _buffer__AXVPBInternalVoiceShadowCopyArray{g_sndStaticData}; AXVPBInternal_t* __AXVPBInternalVoiceShadowCopyArrayPtr; // this is the array used by audio mixing (it's synced at the beginning of every audio frame with __AXVPBInternalVoiceArray) - SysAllocator _buffer__AXVPBItdArray; + CafeStaticVar _buffer__AXVPBItdArray{g_sndStaticData}; AXVPBItd* __AXVPBItdArrayPtr; - SysAllocator _buffer__AXVPBArray; + CafeStaticVar _buffer__AXVPBArray{g_sndStaticData}; AXVPB* __AXVPBArrayPtr; struct AXUSERPROTECTION diff --git a/src/Cafe/OS/libs/swkbd/swkbd.cpp b/src/Cafe/OS/libs/swkbd/swkbd.cpp index 16b8d73c..765c20e8 100644 --- a/src/Cafe/OS/libs/swkbd/swkbd.cpp +++ b/src/Cafe/OS/libs/swkbd/swkbd.cpp @@ -8,6 +8,8 @@ #include "util/helpers/helpers.h" #include "resource/IconsFontAwesome5.h" +constinit COSStaticData s_swkbdStaticData; + #define SWKBD_FORM_STRING_MAX_LENGTH (4096) // counted in 16-bit characters #define SWKBD_STATE_BLANK (0) // not visible @@ -85,18 +87,14 @@ typedef struct bool cancelState; }swkbdInternalState_t; -swkbdInternalState_t* swkbdInternalState = nullptr; sint32 isNeedCalcSubThreadFont = 0; sint32 isNeedCalcSubThreadPredict = 0; +CafeStaticVar swkbdInternalState{s_swkbdStaticData}; + void SwkbdCreate(uint8* workMemory, uint32 regionType, uint32 unk, coreinit::FSClient_t* fsClient) { - if( swkbdInternalState == nullptr ) - { - MPTR swkbdInternalStateMPTR = coreinit_allocFromSysArea(sizeof(swkbdInternalState_t), 4); - swkbdInternalState = (swkbdInternalState_t*)memory_getPointerFromVirtualOffset(swkbdInternalStateMPTR); - memset(swkbdInternalState, 0x00, sizeof(swkbdInternalState_t)); - } + memset(swkbdInternalState.GetPtr(), 0, sizeof(swkbdInternalState_t)); coreinit::OSSleepTicks(ESPRESSO_TIMER_CLOCK); // simulate this function taking a bit of time to run. MH3U/MH3G requires this to not softlock // pretend that there is some work to do isNeedCalcSubThreadFont = 3; @@ -574,7 +572,7 @@ typedef struct uint32be endIndex; }changeStringParam_t; -SysAllocator _changeStringParam; +CafeStaticVar _changeStringParam{s_swkbdStaticData}; void swkbd_inputStringChanged() { @@ -679,8 +677,14 @@ namespace swkbd return "swkbd"; } + void RPLUnmapped() override + { + s_swkbdStaticData.Deallocate(); + } + void RPLMapped() override { + s_swkbdStaticData.Allocate(); cafeExportRegisterFunc(SwkbdCreate, "swkbd", "SwkbdCreate__3RplFPUcQ3_2nn5swkbd10RegionTypeUiP8FSClient", LogType::SWKBD); cafeExportRegisterFunc(SwkbdCalc, "swkbd", "SwkbdCalc__3RplFRCQ3_2nn5swkbd14ControllerInfo", LogType::SWKBD); cafeExportRegisterFunc(SwkbdGetStateKeyboard, "swkbd", "SwkbdGetStateKeyboard__3RplFv", LogType::SWKBD); @@ -704,7 +708,7 @@ namespace swkbd { if (reason == coreinit::RplEntryReason::Loaded) { - swkbdInternalState = nullptr; + } else if (reason == coreinit::RplEntryReason::Unloaded) { diff --git a/src/Cafe/OS/libs/vpad/vpad.cpp b/src/Cafe/OS/libs/vpad/vpad.cpp index dc6b6adb..7a711a5b 100644 --- a/src/Cafe/OS/libs/vpad/vpad.cpp +++ b/src/Cafe/OS/libs/vpad/vpad.cpp @@ -50,6 +50,8 @@ extern bool isLaunchTypeELF; +constinit COSStaticData s_vpadStaticData; + VPADDir g_vpadGyroDirOverwrite[VPAD_MAX_CONTROLLERS] = { {{1.0f,0.0f,0.0f}, {0.0f,1.0f,0.0f}, {0.0f, 0.0f, 0.1f}}, @@ -162,7 +164,7 @@ namespace vpad struct { - SysAllocator alarm; + CafeStaticVar alarm{s_vpadStaticData}; struct { @@ -1169,8 +1171,21 @@ namespace vpad return "vpad"; } + void RPLUnmapped() override + { + coreinit::OSCancelAlarm(g_vpad.alarm.GetPtr()); + s_vpadStaticData.Deallocate(); + } + + void rpl_entry(uint32 moduleHandle, coreinit::RplEntryReason reason) override + { + if (reason == coreinit::RplEntryReason::Loaded) + start(); + } + void RPLMapped() override { + s_vpadStaticData.Allocate(); cafeExportRegister("vpad", VPADSetBtnRepeat, LogType::InputAPI); cafeExportRegister("vpad", VPADSetSamplingCallback, LogType::InputAPI); cafeExportRegister("vpad", VPADRead, LogType::InputAPI); diff --git a/src/Common/CMakeLists.txt b/src/Common/CMakeLists.txt index cb80eb69..d3ffb711 100644 --- a/src/Common/CMakeLists.txt +++ b/src/Common/CMakeLists.txt @@ -1,5 +1,7 @@ add_library(CemuCommon betype.h + CafeStaticVar.cpp + CafeStaticVar.h cpu_features.cpp cpu_features.h enumFlags.h diff --git a/src/Common/CafeStaticVar.cpp b/src/Common/CafeStaticVar.cpp new file mode 100644 index 00000000..22bb124a --- /dev/null +++ b/src/Common/CafeStaticVar.cpp @@ -0,0 +1,120 @@ +#include "CafeStaticVar.h" +#include "Cafe/HW/MMU/MMU.h" +#include "util/ChunkedHeap/ChunkedHeap.h" + +namespace +{ + uint32 AlignOffset(uint32 offset, uint32 alignment) + { + cemu_assert_debug((offset+alignment) >= offset); + uint64 aligned = (offset + alignment - 1u) & ~(alignment - 1u); + return static_cast(aligned); + } + + std::unique_ptr s_iosuStaticDataHeap{}; + std::set s_iosuStaticDataBlocks; + std::mutex s_cafeStaticDataMutex; +} + +CafeStaticVarBase::CafeStaticVarBase(CafeStaticData& owner, uint32 size, uint32 alignment) + : m_owner(&owner), m_size(size), m_alignment(alignment) +{ + std::unique_lock _l(s_cafeStaticDataMutex); + if (!owner.m_vars) + owner.m_vars = new std::vector(); + owner.m_vars->push_back(this); +} + +CafeStaticVarBase::~CafeStaticVarBase() +{ + std::unique_lock _l(s_cafeStaticDataMutex); + if (m_owner) + { + cemu_assert(!m_owner->IsAllocated()); + std::erase(*m_owner->m_vars, this); + } +} + +bool CafeStaticData::HasAnyAllocations() +{ + std::unique_lock _l(s_cafeStaticDataMutex); + return !s_iosuStaticDataBlocks.empty(); +} + +MPTR coreinit_allocFromSysArea(uint32 size, uint32 alignment); +void coreinit_freeToSysArea(MPTR mem); + +void CafeStaticData::Allocate() +{ + std::unique_lock _l(s_cafeStaticDataMutex); + if (!m_vars) + return; // empty + // register this static block + cemu_assert_debug(!s_iosuStaticDataBlocks.contains(this)); + s_iosuStaticDataBlocks.emplace(this); + // calculate total allocation size + uint32 size = 0; + uint32 alignment = 32; + for (auto& var : *m_vars) + { + size = AlignOffset(size, var->m_alignment); + cemu_assert(var->m_size < 1024 * 1024 * 128); // sanity check size + size += var->m_size; + alignment = std::max(alignment, var->m_alignment); + } + cemu_assert_debug(size > 0); // zero sized variables are not allowed + // get heap + VHeap* heap = nullptr; + if (m_mode == Mode::IOSU) + { + cemu_assert(mmuRange_IOSU_AREA.isMapped()); + if (!s_iosuStaticDataHeap) + s_iosuStaticDataHeap = std::make_unique(mmuRange_IOSU_AREA.getPtr(), mmuRange_IOSU_AREA.getSize()); + heap = s_iosuStaticDataHeap.get(); + m_allocation = heap->alloc(size, alignment); + } + else if (m_mode == Mode::COS) + { + MPTR allocOffset = coreinit_allocFromSysArea(size, alignment); + cemu_assert(allocOffset != MPTR_NULL); + m_allocation = MEMPTR(allocOffset).GetPtr(); + } + cemu_assert(m_allocation); + uint32 offset = 0; + for (auto& var : *m_vars) + { + offset = AlignOffset(offset, var->m_alignment); + var->m_memory = static_cast(m_allocation) + offset; + offset += var->m_size; + } + for (auto& var : *m_vars) + var->Initialize(); +} + +void CafeStaticData::Deallocate() +{ + std::unique_lock _l(s_cafeStaticDataMutex); + if (!m_vars) + return; // empty + cemu_assert(m_allocation); + for (auto& var : *m_vars) + var->m_memory = nullptr; + if (m_mode == Mode::IOSU) + { + s_iosuStaticDataHeap->free(m_allocation); + } + else // COS + { + coreinit_freeToSysArea(MEMPTR(m_allocation).GetMPTR()); + } + m_allocation = nullptr; + s_iosuStaticDataBlocks.erase(this); +} + +CafeStaticData::~CafeStaticData() +{ + std::unique_lock _l(s_cafeStaticDataMutex); + for (auto& it : *m_vars) + it->m_owner = nullptr; + delete m_vars; +} \ No newline at end of file diff --git a/src/Common/CafeStaticVar.h b/src/Common/CafeStaticVar.h new file mode 100644 index 00000000..403c8281 --- /dev/null +++ b/src/Common/CafeStaticVar.h @@ -0,0 +1,164 @@ +#pragma once + +class CafeStaticVarBase; + +class CafeStaticData +{ +protected: + enum class Mode : uint8 + { + COS = 0, + IOSU = 1 + }; + + constexpr CafeStaticData(Mode mode) : m_mode(mode) {}; + CafeStaticData(const CafeStaticData&) = delete; + CafeStaticData& operator=(const CafeStaticData&) = delete; + + ~CafeStaticData(); + +public: + void Allocate(); + void Deallocate(); + bool IsAllocated() const { return m_allocation != nullptr; } + + static bool HasAnyAllocations(); +private: + friend class CafeStaticVarBase; + std::vector* m_vars{}; // pointer to make this class constinit compatible + void* m_allocation{}; + Mode m_mode; +}; + +class CafeStaticVarBase +{ +public: + CafeStaticVarBase(const CafeStaticVarBase&) = delete; + CafeStaticVarBase& operator=(const CafeStaticVarBase&) = delete; + +protected: + CafeStaticVarBase(CafeStaticData& owner, uint32 size, uint32 alignment); + virtual ~CafeStaticVarBase(); + MEMPTR m_memory; + +private: + friend class CafeStaticData; + virtual void Initialize() = 0; + CafeStaticData* m_owner{}; + CafeStaticVarBase* m_next{}; + uint32 m_size; + uint32 m_alignment; +}; + +template +class CafeStaticVar : public CafeStaticVarBase +{ + static_assert(count > 0 && count <= std::numeric_limits::max() / sizeof(T)); + static_assert(alignment > 0 && (alignment & (alignment - 1)) == 0); + static_assert(alignment >= alignof(T) && alignment <= 0x400000); + static_assert(std::is_trivially_copyable_v && std::is_trivially_destructible_v); + static_assert(!std::is_const_v); + +public: + explicit CafeStaticVar(CafeStaticData& owner) : CafeStaticVarBase(owner, GetByteSize(), alignment) + { + cemu_assert_debug(!owner.IsAllocated()); + } + + CafeStaticVar(CafeStaticData& owner, const T& value) requires(count == 1) : CafeStaticVar(owner) + { + cemu_assert_debug(!owner.IsAllocated()); + m_initializer = [value](T* ptr) { std::construct_at(ptr, value); }; + } + + CafeStaticVar(CafeStaticData& owner, std::initializer_list values) requires(count != 1) : CafeStaticVar(owner) + { + cemu_assert_debug(!owner.IsAllocated()); + cemu_assert(values.size() <= count); + std::array initial{}; + std::copy(values.begin(), values.end(), initial.begin()); + m_initializer = [initial](T* ptr) { std::uninitialized_copy_n(initial.data(), count, ptr); }; + } + + template + CafeStaticVar(CafeStaticData& owner, const char (&value)[N]) requires(std::is_same_v) : CafeStaticVar(owner) + { + cemu_assert_debug(!owner.IsAllocated()); + static_assert(N <= count); + std::array initial{}; + std::copy_n(value, N, initial.begin()); + m_initializer = [initial](T* ptr) { std::uninitialized_copy_n(initial.data(), count, ptr); }; + } + + template + CafeStaticVar(CafeStaticData& owner, F initializer) requires(count == 1 && std::is_invocable_r_v) : CafeStaticVar(owner) + { + cemu_assert_debug(!owner.IsAllocated()); + m_initializer = [initializer](T* ptr) mutable { std::construct_at(ptr, initializer()); }; + } + + static constexpr uint32 GetCount() { return static_cast(count); } + static constexpr uint32 GetByteSize() { return static_cast(sizeof(T) * count); } + bool IsAllocated() const { return !m_memory.IsNull(); } + uint32 GetMPTR() const { return m_memory.GetMPTR(); } + T* GetPtr() const { return static_cast(m_memory.GetPtr()); } + + CafeStaticVar& operator=(const T& value) requires(count == 1) + { + *CheckedPtr() = value; + return *this; + } + + operator T() const requires(count == 1) { return *CheckedPtr(); } + operator T*() const { return GetPtr(); } + T& operator*() const { return *CheckedPtr(); } + T* operator->() const requires(count == 1) { return CheckedPtr(); } + T* operator&() const requires(count == 1) { return GetPtr(); } + T& operator[](size_t index) const + { + cemu_assert(index < count); + return CheckedPtr()[index]; + } + T* operator+(sint32 offset) const { return CheckedPtr() + offset; } + T* operator-(sint32 offset) const { return CheckedPtr() - offset; } + +private: + T* CheckedPtr() const + { + cemu_assert_debug(IsAllocated()); + return GetPtr(); + } + + void Initialize() override + { + if (m_initializer) + m_initializer(GetPtr()); + else + std::uninitialized_value_construct_n(GetPtr(), count); + } + + std::function m_initializer; +}; + +template +CafeStaticVar(CafeStaticData&, const char (&)[N]) -> CafeStaticVar; + +// IOSU storage +class IOSUStaticData : public CafeStaticData +{ +public: + constexpr IOSUStaticData() : CafeStaticData(CafeStaticData::Mode::IOSU) + { + + } +}; + +// COS storage +class COSStaticData : public CafeStaticData +{ +public: + constexpr COSStaticData() : CafeStaticData(CafeStaticData::Mode::COS) + { + + } +}; \ No newline at end of file diff --git a/src/util/ChunkedHeap/ChunkedHeap.h b/src/util/ChunkedHeap/ChunkedHeap.h index 88a0bdfd..8a6120fb 100644 --- a/src/util/ChunkedHeap/ChunkedHeap.h +++ b/src/util/ChunkedHeap/ChunkedHeap.h @@ -372,6 +372,7 @@ public: void free(void* addr) override { + cemu_assert_debug(addr >= m_heapBase && addr < (m_heapBase + m_heapSize)); _free((uint32)((uint8*)addr - (uint8*)m_heapBase)); }