From ad636f721615c4f174e0ea3aa84f68f9dae9f05a Mon Sep 17 00:00:00 2001 From: Tony Wasserka Date: Tue, 19 Jun 2018 18:07:31 +0000 Subject: [PATCH] Modernize C++ usage (#144) * Stratosphere: Use modern C++ idioms in some places * algorithms like std::for_each are used instead of raw loops * Stratosphere: Replace more raw loops with algorithms * Stratosphere: Add a utility predicate function to test for equality with a reference element This can be used to rewrite some common raw loops using algorithms instead * fs.mitm: Use variant * fs.mitm: Use enum class * fs.mitm: Turn RomFSSourceInfo::Cleanup into a destructor This obsoletes the need for a custom deleter in other places * fs.mitm: Use enum class some more * fs.mitm: Use unique_ptr * fs.mitm: Simplify initialization * Stratosphere: Simplify initialization * fs.mitm: Use unique_ptr (fix memory leak along the way) The previous code was using "delete" rather than "delete[]" * fs.mitm: Use vector::emplace_back rather than push_back emplace_back constructs elements in-place, hence avoiding a redundant element copy. * Stratosphere: Replace more raw loops with algorithms * Stratosphere: Use unique_ptr * fs.mitm: Replace more raw loops with algorithms * Stratosphere: Prefer move-construction over copy-construction when moving sink parameters around --- stratosphere/fs_mitm/source/fs_istorage.hpp | 26 ++-- .../fs_mitm/source/fsmitm_layeredrom.cpp | 83 ++++------- .../fs_mitm/source/fsmitm_layeredrom.hpp | 2 +- stratosphere/fs_mitm/source/fsmitm_main.cpp | 10 +- .../fs_mitm/source/fsmitm_romfsbuild.cpp | 32 ++-- .../fs_mitm/source/fsmitm_romfsbuild.hpp | 141 +++++++++++------- .../fs_mitm/source/fsmitm_service.cpp | 26 ++-- .../fs_mitm/source/fsmitm_service.hpp | 10 +- stratosphere/fs_mitm/source/fsmitm_worker.cpp | 6 +- .../fs_mitm/source/imitmserviceobject.hpp | 8 +- stratosphere/fs_mitm/source/mitm_session.hpp | 22 +-- .../libstratosphere/include/meta_tools.hpp | 37 +++++ .../include/stratosphere/domainowner.hpp | 58 +++---- .../include/stratosphere/ievent.hpp | 7 +- .../include/stratosphere/ipcsession.hpp | 8 +- .../include/stratosphere/iserver.hpp | 3 +- .../include/stratosphere/isession.hpp | 41 ++--- .../include/stratosphere/waitablemanager.hpp | 15 +- .../stratosphere/waitablemanagerbase.hpp | 12 +- .../source/multithreadedwaitablemanager.cpp | 15 +- .../source/waitablemanager.cpp | 15 +- .../loader/source/ldr_launch_queue.cpp | 17 ++- stratosphere/loader/source/ldr_main.cpp | 4 +- stratosphere/loader/source/ldr_nro.cpp | 10 +- .../loader/source/ldr_registration.cpp | 73 ++++----- .../loader/source/ldr_registration.hpp | 9 +- stratosphere/pm/source/pm_registration.cpp | 7 +- stratosphere/sm/source/sm_registration.cpp | 30 ++-- 28 files changed, 353 insertions(+), 374 deletions(-) create mode 100644 stratosphere/libstratosphere/include/meta_tools.hpp diff --git a/stratosphere/fs_mitm/source/fs_istorage.hpp b/stratosphere/fs_mitm/source/fs_istorage.hpp index db5ace19b..a5e99fadd 100644 --- a/stratosphere/fs_mitm/source/fs_istorage.hpp +++ b/stratosphere/fs_mitm/source/fs_istorage.hpp @@ -5,13 +5,13 @@ #include "debug.hpp" -enum FsIStorageCmd { - FsIStorage_Cmd_Read = 0, - FsIStorage_Cmd_Write = 1, - FsIStorage_Cmd_Flush = 2, - FsIStorage_Cmd_SetSize = 3, - FsIStorage_Cmd_GetSize = 4, - FsIStorage_Cmd_OperateRange = 5, +enum class FsIStorageCmd { + Read = 0, + Write = 1, + Flush = 2, + SetSize = 3, + GetSize = 4, + OperateRange = 5, }; class IStorage { @@ -49,22 +49,22 @@ class IStorageInterface : public IServiceObject { Result dispatch(IpcParsedCommand &r, IpcCommand &out_c, u64 cmd_id, u8 *pointer_buffer, size_t pointer_buffer_size) final { Result rc = 0xF601; switch ((FsIStorageCmd)cmd_id) { - case FsIStorage_Cmd_Read: + case FsIStorageCmd::Read: rc = WrapIpcCommandImpl<&IStorageInterface::read>(this, r, out_c, pointer_buffer, pointer_buffer_size); break; - case FsIStorage_Cmd_Write: + case FsIStorageCmd::Write: rc = WrapIpcCommandImpl<&IStorageInterface::write>(this, r, out_c, pointer_buffer, pointer_buffer_size); break; - case FsIStorage_Cmd_Flush: + case FsIStorageCmd::Flush: rc = WrapIpcCommandImpl<&IStorageInterface::flush>(this, r, out_c, pointer_buffer, pointer_buffer_size); break; - case FsIStorage_Cmd_SetSize: + case FsIStorageCmd::SetSize: rc = WrapIpcCommandImpl<&IStorageInterface::set_size>(this, r, out_c, pointer_buffer, pointer_buffer_size); break; - case FsIStorage_Cmd_GetSize: + case FsIStorageCmd::GetSize: rc = WrapIpcCommandImpl<&IStorageInterface::get_size>(this, r, out_c, pointer_buffer, pointer_buffer_size); break; - case FsIStorage_Cmd_OperateRange: + case FsIStorageCmd::OperateRange: if (kernelAbove400()) { rc = WrapIpcCommandImpl<&IStorageInterface::operate_range>(this, r, out_c, pointer_buffer, pointer_buffer_size); } diff --git a/stratosphere/fs_mitm/source/fsmitm_layeredrom.cpp b/stratosphere/fs_mitm/source/fsmitm_layeredrom.cpp index 68a259a06..819029f53 100644 --- a/stratosphere/fs_mitm/source/fsmitm_layeredrom.cpp +++ b/stratosphere/fs_mitm/source/fsmitm_layeredrom.cpp @@ -9,28 +9,19 @@ LayeredRomFS::LayeredRomFS(std::shared_ptr s_r, std::shared_ptr f_r, u64 tid) : storage_romfs(s_r), file_romfs(f_r), title_id(tid) { /* Start building the new virtual romfs. */ RomFSBuildContext build_ctx(this->title_id); - this->p_source_infos = std::shared_ptr>(new std::vector(), [](std::vector *to_delete) { - for (unsigned int i = 0; i < to_delete->size(); i++) { - (*to_delete)[i].Cleanup(); - } - delete to_delete; - }); + this->p_source_infos = std::make_shared>(); if (Utils::IsSdInitialized()) { build_ctx.MergeSdFiles(); } if (this->file_romfs) { - build_ctx.MergeRomStorage(this->file_romfs.get(), RomFSDataSource_FileRomFS); + build_ctx.MergeRomStorage(this->file_romfs.get(), RomFSDataSource::FileRomFS); } if (this->storage_romfs) { - build_ctx.MergeRomStorage(this->storage_romfs.get(), RomFSDataSource_BaseRomFS); + build_ctx.MergeRomStorage(this->storage_romfs.get(), RomFSDataSource::BaseRomFS); } build_ctx.Build(this->p_source_infos.get()); } -LayeredRomFS::~LayeredRomFS() { - /* ... */ -} - Result LayeredRomFS::Read(void *buffer, size_t size, u64 offset) { /* Validate size. */ @@ -60,7 +51,6 @@ Result LayeredRomFS::Read(void *buffer, size_t size, u64 offset) { } } - Result rc; size_t read_so_far = 0; while (read_so_far < size) { RomFSSourceInfo *cur_source = &((*this->p_source_infos)[cur_source_ind]); @@ -69,47 +59,38 @@ Result LayeredRomFS::Read(void *buffer, size_t size, u64 offset) { if (cur_read_size > cur_source->size - (offset - cur_source->virtual_offset)) { cur_read_size = cur_source->size - (offset - cur_source->virtual_offset); } - switch (cur_source->type) { - case RomFSDataSource_LooseFile: - { - FsFile file; - if (R_FAILED((rc = Utils::OpenRomFSSdFile(this->title_id, cur_source->loose_source_info.path, FS_OPEN_READ, &file)))) { - fatalSimple(rc); - } - size_t out_read; - if (R_FAILED((rc = fsFileRead(&file, (offset - cur_source->virtual_offset), (void *)((uintptr_t)buffer + read_so_far), cur_read_size, &out_read)))) { - fatalSimple(rc); - } - if (out_read != cur_read_size) { - Reboot(); - } - fsFileClose(&file); + auto source_info_visitor = [&](auto& info) -> Result { + Result rc = 0; + if constexpr (std::is_same_v) { + FsFile file; + if (R_FAILED((rc = Utils::OpenRomFSSdFile(this->title_id, info.path, FS_OPEN_READ, &file)))) { + fatalSimple(rc); } - break; - case RomFSDataSource_Memory: - { - memcpy((void *)((uintptr_t)buffer + read_so_far), cur_source->memory_source_info.data + (offset - cur_source->virtual_offset), cur_read_size); + size_t out_read; + if (R_FAILED((rc = fsFileRead(&file, (offset - cur_source->virtual_offset), (void *)((uintptr_t)buffer + read_so_far), cur_read_size, &out_read)))) { + fatalSimple(rc); } - break; - case RomFSDataSource_BaseRomFS: - { - if (R_FAILED((rc = this->storage_romfs->Read((void *)((uintptr_t)buffer + read_so_far), cur_read_size, cur_source->base_source_info.offset + (offset - cur_source->virtual_offset))))) { - /* TODO: Can this ever happen? */ - /* fatalSimple(rc); */ - return rc; - } + if (out_read != cur_read_size) { + Reboot(); } - break; - case RomFSDataSource_FileRomFS: - { - if (R_FAILED((rc = this->file_romfs->Read((void *)((uintptr_t)buffer + read_so_far), cur_read_size, cur_source->base_source_info.offset + (offset - cur_source->virtual_offset))))) { - fatalSimple(rc); - } + fsFileClose(&file); + } else if constexpr (std::is_same_v) { + memcpy((void *)((uintptr_t)buffer + read_so_far), info.data + (offset - cur_source->virtual_offset), cur_read_size); + } else if constexpr (std::is_same_v) { + if (R_FAILED((rc = this->storage_romfs->Read((void *)((uintptr_t)buffer + read_so_far), cur_read_size, info.offset + (offset - cur_source->virtual_offset))))) { + /* TODO: Can this ever happen? */ + /* fatalSimple(rc); */ + return rc; } - break; - default: - fatalSimple(0xF601); - } + } else if constexpr (std::is_same_v) { + if (R_FAILED((rc = this->file_romfs->Read((void *)((uintptr_t)buffer + read_so_far), cur_read_size, info.offset + (offset - cur_source->virtual_offset))))) { + fatalSimple(rc); + } + } + return rc; + }; + Result rc = std::visit(source_info_visitor, cur_source->info); + read_so_far += cur_read_size; } else { /* Handle padding explicitly. */ @@ -132,4 +113,4 @@ Result LayeredRomFS::OperateRange(u32 operation_type, u64 offset, u64 size, FsRa *out_range_info = {0}; } return 0; -} \ No newline at end of file +} diff --git a/stratosphere/fs_mitm/source/fsmitm_layeredrom.hpp b/stratosphere/fs_mitm/source/fsmitm_layeredrom.hpp index a27f7c211..fea9ccecd 100644 --- a/stratosphere/fs_mitm/source/fsmitm_layeredrom.hpp +++ b/stratosphere/fs_mitm/source/fsmitm_layeredrom.hpp @@ -23,7 +23,7 @@ class LayeredRomFS : public IROStorage { public: LayeredRomFS(std::shared_ptr s_r, std::shared_ptr f_r, u64 tid); - virtual ~LayeredRomFS(); + virtual ~LayeredRomFS() = default; Result Read(void *buffer, size_t size, u64 offset) override; Result GetSize(u64 *out_size) override; diff --git a/stratosphere/fs_mitm/source/fsmitm_main.cpp b/stratosphere/fs_mitm/source/fsmitm_main.cpp index 43ac4a53e..700100bdf 100644 --- a/stratosphere/fs_mitm/source/fsmitm_main.cpp +++ b/stratosphere/fs_mitm/source/fsmitm_main.cpp @@ -99,8 +99,8 @@ int main(int argc, char **argv) } /* TODO: What's a good timeout value to use here? */ - MultiThreadedWaitableManager *server_manager = new MultiThreadedWaitableManager(1, U64_MAX, 0x20000); - //WaitableManager *server_manager = new WaitableManager(U64_MAX); + auto server_manager = std::make_unique(1, U64_MAX, 0x20000); + //auto server_manager = std::make_unique(U64_MAX); /* Create fsp-srv mitm. */ ISession> *fs_query_srv = NULL; @@ -110,9 +110,7 @@ int main(int argc, char **argv) /* Loop forever, servicing our services. */ server_manager->process(); - - /* Cleanup. */ - delete server_manager; - return 0; + + return 0; } diff --git a/stratosphere/fs_mitm/source/fsmitm_romfsbuild.cpp b/stratosphere/fs_mitm/source/fsmitm_romfsbuild.cpp index a9beabc76..b8c954796 100644 --- a/stratosphere/fs_mitm/source/fsmitm_romfsbuild.cpp +++ b/stratosphere/fs_mitm/source/fsmitm_romfsbuild.cpp @@ -77,7 +77,7 @@ void RomFSBuildContext::MergeSdFiles() { if (R_FAILED(fsMountSdcard(&sd_filesystem))) { return; } - this->cur_source_type = RomFSDataSource_LooseFile; + this->cur_source_type = RomFSDataSource::LooseFile; this->VisitDirectory(&sd_filesystem, this->root); fsFsClose(&sd_filesystem); } @@ -158,19 +158,17 @@ void RomFSBuildContext::MergeRomStorage(IROStorage *storage, RomFSDataSource sou } /* Read tables. */ - u8 *dir_table = new u8[header.dir_table_size]; - u8 *file_table = new u8[header.file_table_size]; - if (R_FAILED((rc = storage->Read(dir_table, header.dir_table_size, header.dir_table_ofs)))) { + auto dir_table = std::make_unique(header.dir_table_size); + auto file_table = std::make_unique(header.file_table_size); + if (R_FAILED((rc = storage->Read(dir_table.get(), header.dir_table_size, header.dir_table_ofs)))) { fatalSimple(rc); } - if (R_FAILED((rc = storage->Read(file_table, header.file_table_size, header.file_table_ofs)))) { + if (R_FAILED((rc = storage->Read(file_table.get(), header.file_table_size, header.file_table_ofs)))) { fatalSimple(rc); } this->cur_source_type = source; - this->VisitDirectory(this->root, 0x0, dir_table, (size_t)header.dir_table_size, file_table, (size_t)header.file_table_size); - delete dir_table; - delete file_table; + this->VisitDirectory(this->root, 0x0, dir_table.get(), (size_t)header.dir_table_size, file_table.get(), (size_t)header.file_table_size); } bool RomFSBuildContext::AddDirectory(RomFSBuildDirectoryContext *parent_dir_ctx, RomFSBuildDirectoryContext *dir_ctx, RomFSBuildDirectoryContext **out_dir_ctx) { @@ -310,7 +308,7 @@ void RomFSBuildContext::Build(std::vector *out_infos) { } out_infos->clear(); - out_infos->push_back(RomFSSourceInfo(0, sizeof(*header), header, RomFSDataSource_Memory)); + out_infos->emplace_back(0, sizeof(*header), header, RomFSDataSource::Memory); /* Determine file offsets. */ cur_file = this->files; @@ -356,20 +354,20 @@ void RomFSBuildContext::Build(std::vector *out_infos) { switch (cur_file->source) { - case RomFSDataSource_BaseRomFS: - case RomFSDataSource_FileRomFS: + case RomFSDataSource::BaseRomFS: + case RomFSDataSource::FileRomFS: /* Try to compact, if possible. */ - if (out_infos->back().type == cur_file->source) { + if (out_infos->back().GetType() == cur_file->source) { out_infos->back().size = cur_file->offset + ROMFS_FILEPARTITION_OFS + cur_file->size - out_infos->back().virtual_offset; } else { - out_infos->push_back(RomFSSourceInfo(cur_file->offset + ROMFS_FILEPARTITION_OFS, cur_file->size, cur_file->orig_offset + ROMFS_FILEPARTITION_OFS, cur_file->source)); + out_infos->emplace_back(cur_file->offset + ROMFS_FILEPARTITION_OFS, cur_file->size, cur_file->orig_offset + ROMFS_FILEPARTITION_OFS, cur_file->source); } break; - case RomFSDataSource_LooseFile: + case RomFSDataSource::LooseFile: { char *path = new char[cur_file->path_len + 1]; strcpy(path, cur_file->path); - out_infos->push_back(RomFSSourceInfo(cur_file->offset + ROMFS_FILEPARTITION_OFS, cur_file->size, path, cur_file->source)); + out_infos->emplace_back(cur_file->offset + ROMFS_FILEPARTITION_OFS, cur_file->size, path, cur_file->source); } break; default: @@ -416,5 +414,5 @@ void RomFSBuildContext::Build(std::vector *out_infos) { header->file_hash_table_ofs = header->dir_table_ofs + header->dir_table_size; header->file_table_ofs = header->file_hash_table_ofs + header->file_hash_table_size; - out_infos->push_back(RomFSSourceInfo(header->dir_hash_table_ofs, this->dir_hash_table_size + this->dir_table_size + this->file_hash_table_size + this->file_table_size, metadata, RomFSDataSource_Memory)); -} \ No newline at end of file + out_infos->emplace_back(header->dir_hash_table_ofs, this->dir_hash_table_size + this->dir_table_size + this->file_hash_table_size + this->file_table_size, metadata, RomFSDataSource::Memory); +} diff --git a/stratosphere/fs_mitm/source/fsmitm_romfsbuild.hpp b/stratosphere/fs_mitm/source/fsmitm_romfsbuild.hpp index 004da24ed..473880306 100644 --- a/stratosphere/fs_mitm/source/fsmitm_romfsbuild.hpp +++ b/stratosphere/fs_mitm/source/fsmitm_romfsbuild.hpp @@ -1,5 +1,6 @@ #pragma once #include +#include #include "fsmitm_romstorage.hpp" @@ -7,11 +8,11 @@ #define ROMFS_FILEPARTITION_OFS 0x200 /* Types for RomFS Meta construction. */ -enum RomFSDataSource { - RomFSDataSource_BaseRomFS, - RomFSDataSource_FileRomFS, - RomFSDataSource_LooseFile, - RomFSDataSource_Memory, +enum class RomFSDataSource { + BaseRomFS, + FileRomFS, + LooseFile, + Memory, }; struct RomFSBaseSourceInfo { @@ -30,66 +31,92 @@ struct RomFSMemorySourceInfo { const u8 *data; }; -struct RomFSSourceInfo { +class RomFSSourceInfo { + using InfoVariant = std::variant; + + static InfoVariant MakeInfoVariantFromOffset(u64 offset, RomFSDataSource t) { + switch(t) { + case RomFSDataSource::BaseRomFS: + return RomFSBaseSourceInfo { offset }; + + case RomFSDataSource::FileRomFS: + return RomFSFileSourceInfo { offset }; + + default: + fatalSimple(0xF601); + } + } + + static InfoVariant MakeInfoVariantFromPointer(const void *arg, RomFSDataSource t) { + switch(t) { + case RomFSDataSource::LooseFile: + return RomFSLooseSourceInfo { (decltype(RomFSLooseSourceInfo::path))arg }; + + case RomFSDataSource::Memory: + return RomFSMemorySourceInfo { (decltype(RomFSMemorySourceInfo::data))arg }; + + default: + fatalSimple(0xF601); + } + } + + struct InfoCleanupHelper { + void operator()(RomFSBaseSourceInfo& info) { + } + + void operator()(RomFSFileSourceInfo& info) { + } + + void operator()(RomFSLooseSourceInfo& info) { + delete info.path; + } + + void operator()(RomFSMemorySourceInfo& info) { + delete info.data; + } + }; + + struct GetTypeHelper { + RomFSDataSource operator()(const RomFSBaseSourceInfo& info) const { + return RomFSDataSource::BaseRomFS; + } + + RomFSDataSource operator()(const RomFSFileSourceInfo& info) const { + return RomFSDataSource::FileRomFS; + } + + RomFSDataSource operator()(const RomFSLooseSourceInfo& info) const { + return RomFSDataSource::LooseFile; + } + + RomFSDataSource operator()(const RomFSMemorySourceInfo& info) const { + return RomFSDataSource::Memory; + } + }; + +public: u64 virtual_offset; u64 size; - union { - RomFSBaseSourceInfo base_source_info; - RomFSFileSourceInfo file_source_info; - RomFSLooseSourceInfo loose_source_info; - RomFSMemorySourceInfo memory_source_info; - }; - RomFSDataSource type; - - RomFSSourceInfo(u64 v_o, u64 s, u64 offset, RomFSDataSource t) : virtual_offset(v_o), size(s), type(t) { - switch (this->type) { - case RomFSDataSource_BaseRomFS: - this->base_source_info.offset = offset; - break; - case RomFSDataSource_FileRomFS: - this->file_source_info.offset = offset; - break; - case RomFSDataSource_LooseFile: - case RomFSDataSource_Memory: - default: - fatalSimple(0xF601); - } + + InfoVariant info; + + RomFSSourceInfo(u64 v_o, u64 s, u64 offset, RomFSDataSource t) : virtual_offset(v_o), size(s), info(MakeInfoVariantFromOffset(offset, t)) { } - - RomFSSourceInfo(u64 v_o, u64 s, const void *arg, RomFSDataSource t) : virtual_offset(v_o), size(s), type(t) { - switch (this->type) { - case RomFSDataSource_LooseFile: - this->loose_source_info.path = (decltype(this->loose_source_info.path))arg; - break; - case RomFSDataSource_Memory: - this->memory_source_info.data = (decltype(this->memory_source_info.data))arg; - break; - case RomFSDataSource_BaseRomFS: - case RomFSDataSource_FileRomFS: - default: - fatalSimple(0xF601); - } + + RomFSSourceInfo(u64 v_o, u64 s, const void *arg, RomFSDataSource t) : virtual_offset(v_o), size(s), info(MakeInfoVariantFromPointer(arg, t)) { } - - void Cleanup() { - switch (this->type) { - case RomFSDataSource_BaseRomFS: - case RomFSDataSource_FileRomFS: - break; - case RomFSDataSource_LooseFile: - delete this->loose_source_info.path; - break; - case RomFSDataSource_Memory: - delete this->memory_source_info.data; - break; - default: - fatalSimple(0xF601); - } + + ~RomFSSourceInfo() { + std::visit(InfoCleanupHelper{}, info); } - + static bool Compare(RomFSSourceInfo *a, RomFSSourceInfo *b) { return (a->virtual_offset < b->virtual_offset); } + + RomFSDataSource GetType() const { + return std::visit(GetTypeHelper{}, info); + } }; /* Types for building a RomFS. */ diff --git a/stratosphere/fs_mitm/source/fsmitm_service.cpp b/stratosphere/fs_mitm/source/fsmitm_service.cpp index a57326dda..41d6ae8b9 100644 --- a/stratosphere/fs_mitm/source/fsmitm_service.cpp +++ b/stratosphere/fs_mitm/source/fsmitm_service.cpp @@ -13,16 +13,18 @@ Result FsMitMService::dispatch(IpcParsedCommand &r, IpcCommand &out_c, u64 cmd_id, u8 *pointer_buffer, size_t pointer_buffer_size) { Result rc = 0xF601; if (this->has_initialized) { - switch (cmd_id) { - case FspSrv_Cmd_OpenDataStorageByCurrentProcess: + switch (static_cast(cmd_id)) { + case FspSrvCmd::OpenDataStorageByCurrentProcess: rc = WrapIpcCommandImpl<&FsMitMService::open_data_storage_by_current_process>(this, r, out_c, pointer_buffer, pointer_buffer_size); break; - case FspSrv_Cmd_OpenDataStorageByDataId: + case FspSrvCmd::OpenDataStorageByDataId: rc = WrapIpcCommandImpl<&FsMitMService::open_data_storage_by_data_id>(this, r, out_c, pointer_buffer, pointer_buffer_size); break; + default: + break; } } else { - if (cmd_id == FspSrv_Cmd_SetCurrentProcess) { + if (static_cast(cmd_id) == FspSrvCmd::SetCurrentProcess) { if (r.HasPid) { this->init_pid = r.Pid; } @@ -38,14 +40,12 @@ void FsMitMService::postprocess(IpcParsedCommand &r, IpcCommand &out_c, u64 cmd_ } *resp = (decltype(resp))r.Raw; u64 *tls = (u64 *)armGetTls(); - u64 backup_tls[0x100/sizeof(u64)]; - for (unsigned int i = 0; i < sizeof(backup_tls)/sizeof(u64); i++) { - backup_tls[i] = tls[i]; - } + std::array backup_tls; + std::copy(tls, tls + backup_tls.size(), backup_tls.begin()); Result rc = (Result)resp->result; - switch (cmd_id) { - case FspSrv_Cmd_SetCurrentProcess: + switch (static_cast(cmd_id)) { + case FspSrvCmd::SetCurrentProcess: if (R_SUCCEEDED(rc)) { this->has_initialized = true; } @@ -54,9 +54,9 @@ void FsMitMService::postprocess(IpcParsedCommand &r, IpcCommand &out_c, u64 cmd_ if (R_FAILED(MitMQueryUtils::get_associated_tid_for_pid(this->process_id, &this->title_id))) { /* Log here, if desired. */ } - for (unsigned int i = 0; i < sizeof(backup_tls)/sizeof(u64); i++) { - tls[i] = backup_tls[i]; - } + std::copy(backup_tls.begin(), backup_tls.end(), tls); + break; + default: break; } resp->result = rc; diff --git a/stratosphere/fs_mitm/source/fsmitm_service.hpp b/stratosphere/fs_mitm/source/fsmitm_service.hpp index cf14377f0..f34709fd3 100644 --- a/stratosphere/fs_mitm/source/fsmitm_service.hpp +++ b/stratosphere/fs_mitm/source/fsmitm_service.hpp @@ -4,10 +4,10 @@ #include "imitmserviceobject.hpp" #include "fs_istorage.hpp" -enum FspSrvCmd { - FspSrv_Cmd_SetCurrentProcess = 1, - FspSrv_Cmd_OpenDataStorageByCurrentProcess = 200, - FspSrv_Cmd_OpenDataStorageByDataId = 202, +enum class FspSrvCmd { + SetCurrentProcess = 1, + OpenDataStorageByCurrentProcess = 200, + OpenDataStorageByDataId = 202, }; class FsMitMService : public IMitMServiceObject { @@ -43,4 +43,4 @@ class FsMitMService : public IMitMServiceObject { /* Overridden commands. */ std::tuple> open_data_storage_by_current_process(); std::tuple> open_data_storage_by_data_id(u64 storage_id, u64 data_id); -}; \ No newline at end of file +}; diff --git a/stratosphere/fs_mitm/source/fsmitm_worker.cpp b/stratosphere/fs_mitm/source/fsmitm_worker.cpp index 6973a19a4..5146e8135 100644 --- a/stratosphere/fs_mitm/source/fsmitm_worker.cpp +++ b/stratosphere/fs_mitm/source/fsmitm_worker.cpp @@ -7,7 +7,7 @@ static SystemEvent *g_new_waitable_event = NULL; static HosMutex g_new_waitable_mutex; static HosSemaphore g_sema_new_waitable_finish; -static WaitableManager *g_worker_waiter = NULL; +static std::unique_ptr g_worker_waiter; Result FsMitMWorker::AddWaitableCallback(void *arg, Handle *handles, size_t num_handles, u64 timeout) { (void)arg; @@ -29,11 +29,9 @@ void FsMitMWorker::Main(void *arg) { g_new_waitable_event = new SystemEvent(NULL, &FsMitMWorker::AddWaitableCallback); /* Make a new waitable manager. */ - g_worker_waiter = new WaitableManager(U64_MAX); + g_worker_waiter = std::make_unique(U64_MAX); g_worker_waiter->add_waitable(g_new_waitable_event); /* Service processes. */ g_worker_waiter->process(); - - delete g_worker_waiter; } diff --git a/stratosphere/fs_mitm/source/imitmserviceobject.hpp b/stratosphere/fs_mitm/source/imitmserviceobject.hpp index eea88363b..30cdd052e 100644 --- a/stratosphere/fs_mitm/source/imitmserviceobject.hpp +++ b/stratosphere/fs_mitm/source/imitmserviceobject.hpp @@ -9,10 +9,10 @@ class IMitMServiceObject : public IServiceObject { protected: Service *forward_service; - u64 process_id; - u64 title_id; + u64 process_id = 0; + u64 title_id = 0; public: - IMitMServiceObject(Service *s) : forward_service(s), process_id(0), title_id(0) { + IMitMServiceObject(Service *s) : forward_service(s) { } @@ -22,7 +22,7 @@ class IMitMServiceObject : public IServiceObject { virtual void clone_to(void *o) = 0; protected: - virtual ~IMitMServiceObject() { } + virtual ~IMitMServiceObject() = default; virtual Result dispatch(IpcParsedCommand &r, IpcCommand &out_c, u64 cmd_id, u8 *pointer_buffer, size_t pointer_buffer_size) = 0; virtual void postprocess(IpcParsedCommand &r, IpcCommand &out_c, u64 cmd_id, u8 *pointer_buffer, size_t pointer_buffer_size) = 0; virtual Result handle_deferred() = 0; diff --git a/stratosphere/fs_mitm/source/mitm_session.hpp b/stratosphere/fs_mitm/source/mitm_session.hpp index 3e3a778cd..e1afef72e 100644 --- a/stratosphere/fs_mitm/source/mitm_session.hpp +++ b/stratosphere/fs_mitm/source/mitm_session.hpp @@ -19,33 +19,35 @@ class MitMSession final : public ISession { /* This will be for the actual session. */ Service forward_service; IpcParsedCommand cur_out_r; - u32 mitm_domain_id; + u32 mitm_domain_id = 0; bool got_first_message; public: - MitMSession(MitMServer *s, Handle s_h, Handle c_h, const char *srv) : ISession(s, s_h, c_h, NULL, 0), mitm_domain_id(0), got_first_message(false) { + MitMSession(MitMServer *s, Handle s_h, Handle c_h, const char *srv) : ISession(s, s_h, c_h, NULL, 0), got_first_message(false) { this->server = s; this->server_handle = s_h; this->client_handle = c_h; if (R_FAILED(smMitMGetService(&forward_service, srv))) { /* TODO: Panic. */ } - if (R_FAILED(ipcQueryPointerBufferSize(forward_service.handle, &this->pointer_buffer_size))) { + size_t pointer_buffer_size = 0; + if (R_FAILED(ipcQueryPointerBufferSize(forward_service.handle, &pointer_buffer_size))) { /* TODO: Panic. */ } this->service_object = std::make_shared(&forward_service); - this->pointer_buffer = new char[this->pointer_buffer_size]; + this->pointer_buffer.resize(pointer_buffer_size); } - MitMSession(MitMServer *s, Handle s_h, Handle c_h, Handle f_h) : ISession(s, s_h, c_h, NULL, 0), mitm_domain_id(0), got_first_message(true) { + MitMSession(MitMServer *s, Handle s_h, Handle c_h, Handle f_h) : ISession(s, s_h, c_h, NULL, 0), got_first_message(true) { this->server = s; this->server_handle = s_h; this->client_handle = c_h; serviceCreate(&this->forward_service, f_h); - if (R_FAILED(ipcQueryPointerBufferSize(forward_service.handle, &this->pointer_buffer_size))) { + size_t pointer_buffer_size = 0; + if (R_FAILED(ipcQueryPointerBufferSize(forward_service.handle, &pointer_buffer_size))) { /* TODO: Panic. */ } this->service_object = std::make_shared(&forward_service); - this->pointer_buffer = new char[this->pointer_buffer_size]; + this->pointer_buffer.resize(pointer_buffer_size); } virtual ~MitMSession() { @@ -92,7 +94,7 @@ class MitMSession final : public ISession { obj = this->service_object; } if (obj != nullptr) { - retval = obj->dispatch(r, c, cmd_id, (u8 *)this->pointer_buffer, this->pointer_buffer_size); + retval = obj->dispatch(r, c, cmd_id, (u8 *)this->pointer_buffer.data(), this->pointer_buffer.size()); if (R_SUCCEEDED(retval)) { if (r.IsDomainMessage) { ipcParseForDomain(&cur_out_r); @@ -197,7 +199,7 @@ class MitMSession final : public ISession { if (this->active_object == this->service_object && (r.CommandType == IpcCommandType_Request || r.CommandType == IpcCommandType_RequestWithContext)) { IpcCommand c; ipcInitialize(&c); - this->service_object->postprocess(cur_out_r, c, cmd_id, (u8 *)this->pointer_buffer, this->pointer_buffer_size); + this->service_object->postprocess(cur_out_r, c, cmd_id, (u8 *)this->pointer_buffer.data(), this->pointer_buffer.size()); } else if (r.CommandType == IpcCommandType_Control || r.CommandType == IpcCommandType_ControlWithContext) { if (cmd_id == IpcCtrl_Cmd_ConvertCurrentObjectToDomain) { this->is_domain = true; @@ -226,4 +228,4 @@ class MitMSession final : public ISession { } } } -}; \ No newline at end of file +}; diff --git a/stratosphere/libstratosphere/include/meta_tools.hpp b/stratosphere/libstratosphere/include/meta_tools.hpp new file mode 100644 index 000000000..27da96a58 --- /dev/null +++ b/stratosphere/libstratosphere/include/meta_tools.hpp @@ -0,0 +1,37 @@ +#pragma once + +#include + +namespace detail { + +template +struct class_of; + +template +struct class_of { + using type = C; +}; + +template +using class_of_t = typename class_of::type; + +template> +struct member_equals_fn_helper { + T ref; + Mem mem_fn; + + bool operator()(const C& val) const { + return (std::mem_fn(mem_fn)(val) == ref); + } + + bool operator()(C&& val) const { + return (std::mem_fn(mem_fn)(std::move(val)) == ref); + } +}; + +} // namespace detail + +template +auto member_equals_fn(Mem mem, T ref) { + return detail::member_equals_fn_helper{std::move(ref), std::move(mem)}; +} diff --git a/stratosphere/libstratosphere/include/stratosphere/domainowner.hpp b/stratosphere/libstratosphere/include/stratosphere/domainowner.hpp index 09dde7918..adb64b9c3 100644 --- a/stratosphere/libstratosphere/include/stratosphere/domainowner.hpp +++ b/stratosphere/libstratosphere/include/stratosphere/domainowner.hpp @@ -1,5 +1,6 @@ #pragma once #include +#include #include #include @@ -11,18 +12,13 @@ class IServiceObject; class DomainOwner { private: - std::shared_ptr domain_objects[DOMAIN_ID_MAX]; + std::array, DOMAIN_ID_MAX> domain_objects; public: - DomainOwner() { - for (unsigned int i = 0; i < DOMAIN_ID_MAX; i++) { - domain_objects[i].reset(); - } - } - - virtual ~DomainOwner() { - /* Shared ptrs should auto delete here. */ - } - + DomainOwner() = default; + + /* Shared ptrs should auto delete here. */ + virtual ~DomainOwner() = default; + std::shared_ptr get_domain_object(unsigned int i) { if (i < DOMAIN_ID_MAX) { return domain_objects[i]; @@ -31,20 +27,20 @@ class DomainOwner { } Result reserve_object(std::shared_ptr object, unsigned int *out_i) { - for (unsigned int i = 4; i < DOMAIN_ID_MAX; i++) { - if (domain_objects[i] == NULL) { - domain_objects[i] = object; - object->set_owner(this); - *out_i = i; - return 0; - } + auto object_it = std::find(domain_objects.begin() + 4, domain_objects.end(), nullptr); + if (object_it == domain_objects.end()) { + return 0x1900B; } - return 0x1900B; + + *out_i = std::distance(domain_objects.begin(), object_it); + *object_it = std::move(object); + (*object_it)->set_owner(this); + return 0; } Result set_object(std::shared_ptr object, unsigned int i) { if (domain_objects[i] == NULL) { - domain_objects[i] = object; + domain_objects[i] = std::move(object); object->set_owner(this); return 0; } @@ -52,26 +48,18 @@ class DomainOwner { } unsigned int get_object_id(std::shared_ptr object) { - for (unsigned int i = 0; i < DOMAIN_ID_MAX; i++) { - if (domain_objects[i] == object) { - return i; - } - } - return DOMAIN_ID_MAX; + auto object_it = std::find(domain_objects.begin(), domain_objects.end(), object); + return std::distance(domain_objects.begin(), object_it); } void delete_object(unsigned int i) { - if (domain_objects[i]) { - domain_objects[i].reset(); - } + domain_objects[i].reset(); } void delete_object(std::shared_ptr object) { - for (unsigned int i = 0; i < DOMAIN_ID_MAX; i++) { - if (domain_objects[i] == object) { - domain_objects[i].reset(); - break; - } + auto object_it = std::find(domain_objects.begin(), domain_objects.end(), object); + if (object_it != domain_objects.end()) { + object_it->reset(); } } -}; \ No newline at end of file +}; diff --git a/stratosphere/libstratosphere/include/stratosphere/ievent.hpp b/stratosphere/libstratosphere/include/stratosphere/ievent.hpp index 4d5b1582d..cdff65c1c 100644 --- a/stratosphere/libstratosphere/include/stratosphere/ievent.hpp +++ b/stratosphere/libstratosphere/include/stratosphere/ievent.hpp @@ -1,5 +1,6 @@ #pragma once #include +#include #include #include "iwaitable.hpp" @@ -22,9 +23,7 @@ class IEvent : public IWaitable { } ~IEvent() { - for (auto &h : this->handles) { - svcCloseHandle(h); - } + std::for_each(handles.begin(), handles.end(), svcCloseHandle); } virtual Result signal_event() = 0; @@ -50,4 +49,4 @@ class IEvent : public IWaitable { /* TODO: Panic. */ return 0xCAFE; } -}; \ No newline at end of file +}; diff --git a/stratosphere/libstratosphere/include/stratosphere/ipcsession.hpp b/stratosphere/libstratosphere/include/stratosphere/ipcsession.hpp index e39677237..9983a1535 100644 --- a/stratosphere/libstratosphere/include/stratosphere/ipcsession.hpp +++ b/stratosphere/libstratosphere/include/stratosphere/ipcsession.hpp @@ -18,9 +18,7 @@ class IPCSession final : public ISession { fatalSimple(rc); } this->service_object = std::make_shared(); - this->pointer_buffer_size = pbs; - this->pointer_buffer = new char[this->pointer_buffer_size]; - this->is_domain = false; + this->pointer_buffer.resize(pbs); } IPCSession(std::shared_ptr so, size_t pbs = 0x400) : ISession(NULL, 0, 0, so, 0) { @@ -28,8 +26,6 @@ class IPCSession final : public ISession { if (R_FAILED((rc = svcCreateSession(&this->server_handle, &this->client_handle, 0, 0)))) { fatalSimple(rc); } - this->pointer_buffer_size = pbs; - this->pointer_buffer = new char[this->pointer_buffer_size]; - this->is_domain = false; + this->pointer_buffer.resize(pbs); } }; diff --git a/stratosphere/libstratosphere/include/stratosphere/iserver.hpp b/stratosphere/libstratosphere/include/stratosphere/iserver.hpp index 24ff1ee67..06d140408 100644 --- a/stratosphere/libstratosphere/include/stratosphere/iserver.hpp +++ b/stratosphere/libstratosphere/include/stratosphere/iserver.hpp @@ -1,5 +1,6 @@ #pragma once #include +#include #include #include "iserviceobject.hpp" @@ -51,4 +52,4 @@ class IServer : public IWaitable { this->get_manager()->add_waitable(this->get_new_session(session_h)); return 0; } -}; \ No newline at end of file +}; diff --git a/stratosphere/libstratosphere/include/stratosphere/isession.hpp b/stratosphere/libstratosphere/include/stratosphere/isession.hpp index 52df6c426..c0e44d0b2 100644 --- a/stratosphere/libstratosphere/include/stratosphere/isession.hpp +++ b/stratosphere/libstratosphere/include/stratosphere/isession.hpp @@ -17,7 +17,6 @@ enum IpcControlCommand { IpcCtrl_Cmd_CloneCurrentObjectEx = 4 }; -#define POINTER_BUFFER_SIZE_MAX 0xFFFF #define RESULT_DEFER_SESSION (0x6580A) @@ -34,39 +33,23 @@ class ISession : public IWaitable { IServer *server; Handle server_handle; Handle client_handle; - char *pointer_buffer; - size_t pointer_buffer_size; + std::vector pointer_buffer; - bool is_domain; + bool is_domain = false; std::shared_ptr domain; std::shared_ptr active_object; - static_assert(sizeof(pointer_buffer) <= POINTER_BUFFER_SIZE_MAX, "Incorrect Size for PointerBuffer!"); - public: - ISession(IServer *s, Handle s_h, Handle c_h, size_t pbs = 0x400) : server(s), server_handle(s_h), client_handle(c_h), pointer_buffer_size(pbs) { + ISession(IServer *s, Handle s_h, Handle c_h, size_t pbs = 0x400) : server(s), server_handle(s_h), client_handle(c_h), pointer_buffer(pbs) { this->service_object = std::make_shared(); - if (this->pointer_buffer_size) { - this->pointer_buffer = new char[this->pointer_buffer_size]; - } - this->is_domain = false; - this->domain.reset(); - this->active_object.reset(); } - ISession(IServer *s, Handle s_h, Handle c_h, std::shared_ptr so, size_t pbs = 0x400) : service_object(so), server(s), server_handle(s_h), client_handle(c_h), pointer_buffer_size(pbs) { - if (this->pointer_buffer_size) { - this->pointer_buffer = new char[this->pointer_buffer_size]; - } - this->is_domain = false; - this->domain.reset(); - this->active_object.reset(); + ISession(IServer *s, Handle s_h, Handle c_h, std::shared_ptr so, size_t pbs = 0x400) : service_object(so), server(s), server_handle(s_h), client_handle(c_h), pointer_buffer(pbs) { } ~ISession() override { - delete this->pointer_buffer; if (server_handle) { svcCloseHandle(server_handle); } @@ -153,7 +136,7 @@ class ISession : public IWaitable { break; case IpcCommandType_Request: case IpcCommandType_RequestWithContext: - retval = this->active_object->dispatch(r, c, cmd_id, (u8 *)this->pointer_buffer, this->pointer_buffer_size); + retval = this->active_object->dispatch(r, c, cmd_id, (u8 *)pointer_buffer.data(), pointer_buffer.size()); break; case IpcCommandType_Control: case IpcCommandType_ControlWithContext: @@ -185,7 +168,7 @@ class ISession : public IWaitable { /* Prepare pointer buffer... */ IpcCommand c_for_reply; ipcInitialize(&c_for_reply); - ipcAddRecvStatic(&c_for_reply, this->pointer_buffer, this->pointer_buffer_size, 0); + ipcAddRecvStatic(&c_for_reply, this->pointer_buffer.data(), this->pointer_buffer.size(), 0); ipcPrepareHeader(&c_for_reply, 0); if (R_SUCCEEDED(rc = svcReplyAndReceive(&handle_index, &this->server_handle, 1, 0, U64_MAX))) { @@ -247,19 +230,19 @@ class ISession : public IWaitable { /* TODO: Implement. */ switch ((IpcControlCommand)cmd_id) { case IpcCtrl_Cmd_ConvertCurrentObjectToDomain: - rc = WrapIpcCommandImpl<&ISession::ConvertCurrentObjectToDomain>(this, r, out_c, (u8 *)this->pointer_buffer, this->pointer_buffer_size); + rc = WrapIpcCommandImpl<&ISession::ConvertCurrentObjectToDomain>(this, r, out_c, (u8 *)this->pointer_buffer.data(), pointer_buffer.size()); break; case IpcCtrl_Cmd_CopyFromCurrentDomain: - rc = WrapIpcCommandImpl<&ISession::CopyFromCurrentDomain>(this, r, out_c, (u8 *)this->pointer_buffer, this->pointer_buffer_size); + rc = WrapIpcCommandImpl<&ISession::CopyFromCurrentDomain>(this, r, out_c, (u8 *)this->pointer_buffer.data(), pointer_buffer.size()); break; case IpcCtrl_Cmd_CloneCurrentObject: - rc = WrapIpcCommandImpl<&ISession::CloneCurrentObject>(this, r, out_c, (u8 *)this->pointer_buffer, this->pointer_buffer_size); + rc = WrapIpcCommandImpl<&ISession::CloneCurrentObject>(this, r, out_c, (u8 *)this->pointer_buffer.data(), pointer_buffer.size()); break; case IpcCtrl_Cmd_QueryPointerBufferSize: - rc = WrapIpcCommandImpl<&ISession::QueryPointerBufferSize>(this, r, out_c, (u8 *)this->pointer_buffer, this->pointer_buffer_size); + rc = WrapIpcCommandImpl<&ISession::QueryPointerBufferSize>(this, r, out_c, (u8 *)this->pointer_buffer.data(), pointer_buffer.size()); break; case IpcCtrl_Cmd_CloneCurrentObjectEx: - rc = WrapIpcCommandImpl<&ISession::CloneCurrentObjectEx>(this, r, out_c, (u8 *)this->pointer_buffer, sizeof(this->pointer_buffer)); + rc = WrapIpcCommandImpl<&ISession::CloneCurrentObjectEx>(this, r, out_c, (u8 *)this->pointer_buffer.data(), pointer_buffer.size()); break; default: break; @@ -282,7 +265,7 @@ class ISession : public IWaitable { return {0xF601}; } std::tuple QueryPointerBufferSize() { - return {0x0, (u32)this->pointer_buffer_size}; + return {0x0, (u32)this->pointer_buffer.size()}; } std::tuple CloneCurrentObjectEx() { /* TODO */ diff --git a/stratosphere/libstratosphere/include/stratosphere/waitablemanager.hpp b/stratosphere/libstratosphere/include/stratosphere/waitablemanager.hpp index 5c0006e4a..4b42cd2cd 100644 --- a/stratosphere/libstratosphere/include/stratosphere/waitablemanager.hpp +++ b/stratosphere/libstratosphere/include/stratosphere/waitablemanager.hpp @@ -1,5 +1,7 @@ #pragma once #include +#include +#include #include #include "waitablemanagerbase.hpp" @@ -12,22 +14,19 @@ class WaitableManager : public WaitableManagerBase { protected: std::vector to_add_waitables; std::vector waitables; - u64 timeout; + u64 timeout = 0; HosMutex lock; - std::atomic_bool has_new_items; + std::atomic_bool has_new_items = false; private: void process_internal(bool break_on_timeout); public: - WaitableManager(u64 t) : waitables(0), timeout(t), has_new_items(false) { } + WaitableManager(u64 t) : timeout(t) { } ~WaitableManager() override { /* This should call the destructor for every waitable. */ - for (auto & waitable : waitables) { - delete waitable; - } - waitables.clear(); + std::for_each(waitables.begin(), waitables.end(), std::default_delete{}); } virtual void add_waitable(IWaitable *waitable); virtual void process(); virtual void process_until_timeout(); -}; \ No newline at end of file +}; diff --git a/stratosphere/libstratosphere/include/stratosphere/waitablemanagerbase.hpp b/stratosphere/libstratosphere/include/stratosphere/waitablemanagerbase.hpp index 972710064..ed4c7775a 100644 --- a/stratosphere/libstratosphere/include/stratosphere/waitablemanagerbase.hpp +++ b/stratosphere/libstratosphere/include/stratosphere/waitablemanagerbase.hpp @@ -4,12 +4,12 @@ #include class WaitableManagerBase { - std::atomic cur_priority; + std::atomic cur_priority = 0; public: - WaitableManagerBase() : cur_priority(0) { } - virtual ~WaitableManagerBase() { } - - u64 get_priority() { + WaitableManagerBase() = default; + virtual ~WaitableManagerBase() = default; + + u64 get_priority() { return std::atomic_fetch_add(&cur_priority, (u64)1); } -}; \ No newline at end of file +}; diff --git a/stratosphere/libstratosphere/source/multithreadedwaitablemanager.cpp b/stratosphere/libstratosphere/source/multithreadedwaitablemanager.cpp index 6acc53a65..dcf1a931c 100644 --- a/stratosphere/libstratosphere/source/multithreadedwaitablemanager.cpp +++ b/stratosphere/libstratosphere/source/multithreadedwaitablemanager.cpp @@ -1,6 +1,7 @@ #include #include +#include #include @@ -44,21 +45,15 @@ IWaitable *MultiThreadedWaitableManager::get_waitable() { rc = svcWaitSynchronization(&handle_index, handles.data(), this->waitables.size(), this->timeout); IWaitable *w = this->waitables[handle_index]; if (R_SUCCEEDED(rc)) { - for (int i = 0; i < handle_index; i++) { - this->waitables[i]->update_priority(); - } + std::for_each(waitables.begin(), waitables.begin() + handle_index, std::mem_fn(&IWaitable::update_priority)); this->waitables.erase(this->waitables.begin() + handle_index); } else if (rc == 0xEA01) { /* Timeout. */ - for (auto & waitable : this->waitables) { - waitable->update_priority(); - } + std::for_each(waitables.begin(), waitables.end(), std::mem_fn(&IWaitable::update_priority)); } else if (rc != 0xF601 && rc != 0xE401) { /* TODO: Panic. When can this happen? */ } else { - for (int i = 0; i < handle_index; i++) { - this->waitables[i]->update_priority(); - } + std::for_each(waitables.begin(), waitables.begin() + handle_index, std::mem_fn(&IWaitable::update_priority)); this->waitables.erase(this->waitables.begin() + handle_index); delete w; } @@ -107,4 +102,4 @@ void MultiThreadedWaitableManager::thread_func(void *t) { } } } -} \ No newline at end of file +} diff --git a/stratosphere/libstratosphere/source/waitablemanager.cpp b/stratosphere/libstratosphere/source/waitablemanager.cpp index fee21cb4b..89b899629 100644 --- a/stratosphere/libstratosphere/source/waitablemanager.cpp +++ b/stratosphere/libstratosphere/source/waitablemanager.cpp @@ -1,6 +1,7 @@ #include #include +#include #include @@ -43,14 +44,10 @@ void WaitableManager::process_internal(bool break_on_timeout) { rc = this->waitables[handle_index]->handle_signaled(0); - for (int i = 0; i < handle_index; i++) { - this->waitables[i]->update_priority(); - } + std::for_each(waitables.begin(), waitables.begin() + handle_index, std::mem_fn(&IWaitable::update_priority)); } else if (rc == 0xEA01) { /* Timeout. */ - for (auto & waitable : this->waitables) { - waitable->update_priority(); - } + std::for_each(waitables.begin(), waitables.end(), std::mem_fn(&IWaitable::update_priority)); if (break_on_timeout) { return; } @@ -72,9 +69,7 @@ void WaitableManager::process_internal(bool break_on_timeout) { /* Delete it. */ delete to_delete; - for (int i = 0; i < handle_index; i++) { - this->waitables[i]->update_priority(); - } + std::for_each(waitables.begin(), waitables.begin() + handle_index, std::mem_fn(&IWaitable::update_priority)); } /* Do deferred callback for each waitable. */ @@ -92,4 +87,4 @@ void WaitableManager::process() { void WaitableManager::process_until_timeout() { WaitableManager::process_internal(true); -} \ No newline at end of file +} diff --git a/stratosphere/loader/source/ldr_launch_queue.cpp b/stratosphere/loader/source/ldr_launch_queue.cpp index 456027b03..b43e061b4 100644 --- a/stratosphere/loader/source/ldr_launch_queue.cpp +++ b/stratosphere/loader/source/ldr_launch_queue.cpp @@ -1,9 +1,11 @@ #include #include +#include #include #include "ldr_launch_queue.hpp" +#include "meta_tools.hpp" -static LaunchQueue::LaunchItem g_launch_queue[LAUNCH_QUEUE_SIZE] = {0}; +static std::array g_launch_queue = {0}; Result LaunchQueue::add(u64 tid, const char *args, u64 arg_size) { if(arg_size > LAUNCH_QUEUE_ARG_SIZE_MAX) { @@ -45,12 +47,11 @@ Result LaunchQueue::add_item(const LaunchItem *item) { } int LaunchQueue::get_index(u64 tid) { - for(unsigned int i = 0; i < LAUNCH_QUEUE_SIZE; i++) { - if(g_launch_queue[i].tid == tid) { - return i; - } + auto it = std::find_if(g_launch_queue.begin(), g_launch_queue.end(), member_equals_fn(&LaunchQueue::LaunchItem::tid, tid)); + if (it == g_launch_queue.end()) { + return LAUNCH_QUEUE_FULL; } - return LAUNCH_QUEUE_FULL; + return std::distance(g_launch_queue.begin(), it); } int LaunchQueue::get_free_index(u64 tid) { @@ -74,8 +75,8 @@ void LaunchQueue::clear() { LaunchQueue::LaunchItem *LaunchQueue::get_item(u64 tid) { - int idx; - if ((idx = get_index(tid)) == LAUNCH_QUEUE_FULL) { + int idx = get_index(tid); + if (idx == LAUNCH_QUEUE_FULL) { return NULL; } return &g_launch_queue[idx]; diff --git a/stratosphere/loader/source/ldr_main.cpp b/stratosphere/loader/source/ldr_main.cpp index e1633cb66..5d6f5a01c 100644 --- a/stratosphere/loader/source/ldr_main.cpp +++ b/stratosphere/loader/source/ldr_main.cpp @@ -93,7 +93,7 @@ int main(int argc, char **argv) consoleDebugInit(debugDevice_SVC); /* TODO: What's a good timeout value to use here? */ - WaitableManager *server_manager = new WaitableManager(U64_MAX); + auto server_manager = std::make_unique(U64_MAX); /* Add services to manager. */ server_manager->add_waitable(new ServiceServer("ldr:pm", 1)); @@ -107,8 +107,6 @@ int main(int argc, char **argv) /* Loop forever, servicing our services. */ server_manager->process(); - /* Cleanup. */ - delete server_manager; return 0; } diff --git a/stratosphere/loader/source/ldr_nro.cpp b/stratosphere/loader/source/ldr_nro.cpp index 45575f78a..52f1bdf03 100644 --- a/stratosphere/loader/source/ldr_nro.cpp +++ b/stratosphere/loader/source/ldr_nro.cpp @@ -1,6 +1,7 @@ #include #include #include +#include #include #include "sha256.h" #include "ldr_nro.hpp" @@ -37,12 +38,7 @@ Result NroUtils::LoadNro(Registration::Process *target_proc, Handle process_h, u u8 nro_hash[0x20]; SHA256_CTX sha_ctx; /* Ensure there is an available NRO slot. */ - for (i = 0; i < NRO_INFO_MAX; i++) { - if (!target_proc->nro_infos[i].in_use) { - break; - } - } - if (i >= NRO_INFO_MAX) { + if (std::all_of(target_proc->nro_infos.begin(), target_proc->nro_infos.end(), std::mem_fn(&Registration::NroInfo::in_use))) { return 0x6E09; } for (i = 0; i < 0x200; i++) { @@ -118,4 +114,4 @@ LOAD_NRO_END: mcm_bss.Close(); } return 0x0; -} \ No newline at end of file +} diff --git a/stratosphere/loader/source/ldr_registration.cpp b/stratosphere/loader/source/ldr_registration.cpp index afe955418..8a0d2a6ed 100644 --- a/stratosphere/loader/source/ldr_registration.cpp +++ b/stratosphere/loader/source/ldr_registration.cpp @@ -2,6 +2,7 @@ #include #include #include +#include #include "ldr_registration.hpp" #include "ldr_nro.hpp" @@ -9,12 +10,11 @@ static Registration::List g_registration_list = {0}; static u64 g_num_registered = 1; Registration::Process *Registration::GetFreeProcess() { - for (unsigned int i = 0; i < REGISTRATION_LIST_MAX; i++) { - if (!g_registration_list.processes[i].in_use) { - return &g_registration_list.processes[i]; - } + auto process_it = std::find_if_not(g_registration_list.processes.begin(), g_registration_list.processes.end(), std::mem_fn(&Registration::Process::in_use)); + if (process_it == g_registration_list.processes.end()) { + return nullptr; } - return NULL; + return &*process_it; } Registration::Process *Registration::GetProcess(u64 index) { @@ -98,15 +98,13 @@ void Registration::AddNsoInfo(u64 index, u64 base_address, u64 size, const unsig if (target_process == NULL) { return; } - - for (unsigned int i = 0; i < NSO_INFO_MAX; i++) { - if (!target_process->nso_infos[i].in_use) { - target_process->nso_infos[i].info.base_address = base_address; - target_process->nso_infos[i].info.size = size; - std::copy(build_id, build_id + sizeof(target_process->nso_infos[i].info.build_id), target_process->nso_infos[i].info.build_id); - target_process->nso_infos[i].in_use = true; - return; - } + + auto nso_info_it = std::find_if_not(target_process->nso_infos.begin(), target_process->nso_infos.end(), std::mem_fn(&Registration::NsoInfoHolder::in_use)); + if (nso_info_it != target_process->nso_infos.end()) { + nso_info_it->info.base_address = base_address; + nso_info_it->info.size = size; + std::copy(build_id, build_id + sizeof(nso_info_it->info.build_id), nso_info_it->info.build_id); + nso_info_it->in_use = true; } } @@ -130,13 +128,12 @@ Result Registration::AddNrrInfo(u64 index, MappedCodeMemory *nrr_info) { return 0x7009; } - for (unsigned int i = 0; i < NRR_INFO_MAX; i++) { - if (!target_process->nrr_infos[i].IsActive()) { - target_process->nrr_infos[i] = *nrr_info; - return 0; - } + auto nrr_info_it = std::find_if_not(target_process->nrr_infos.begin(), target_process->nrr_infos.end(), std::mem_fn(&MappedCodeMemory::IsActive)); + if (nrr_info_it == target_process->nrr_infos.end()) { + return 0x7009; } - return 0x7009; + *nrr_info_it = *nrr_info; + return 0; } Result Registration::RemoveNrrInfo(u64 index, u64 base_address) { @@ -193,7 +190,7 @@ bool Registration::IsNroAlreadyLoaded(u64 index, u8 *build_id) { } for (unsigned int i = 0; i < NRO_INFO_MAX; i++) { - if (target_process->nro_infos[i].in_use && std::memcmp(target_process->nro_infos[i].build_id, build_id, 0x20) == 0) { + if (target_process->nro_infos[i].in_use && std::equal(build_id, build_id + 0x20, target_process->nro_infos[i].build_id)) { return true; } } @@ -207,20 +204,18 @@ void Registration::AddNroToProcess(u64 index, MappedCodeMemory *nro, MappedCodeM return; } - for (unsigned int i = 0; i < NRO_INFO_MAX; i++) { - if (!target_process->nro_infos[i].in_use) { - target_process->nro_infos[i].base_address = nro->code_memory_address; - target_process->nro_infos[i].nro_heap_address = nro->base_address; - target_process->nro_infos[i].nro_heap_size = nro->size; - target_process->nro_infos[i].bss_heap_address = bss->base_address; - target_process->nro_infos[i].bss_heap_size = bss->size; - target_process->nro_infos[i].text_size = text_size; - target_process->nro_infos[i].ro_size = ro_size; - target_process->nro_infos[i].rw_size = rw_size; - std::copy(build_id, build_id + sizeof(target_process->nro_infos[i].build_id), target_process->nro_infos[i].build_id); - target_process->nro_infos[i].in_use = true; - break; - } + auto nro_info_it = std::find_if_not(target_process->nro_infos.begin(), target_process->nro_infos.end(), std::mem_fn(&Registration::NroInfo::in_use)); + if (nro_info_it != target_process->nro_infos.end()) { + nro_info_it->base_address = nro->code_memory_address; + nro_info_it->nro_heap_address = nro->base_address; + nro_info_it->nro_heap_size = nro->size; + nro_info_it->bss_heap_address = bss->base_address; + nro_info_it->bss_heap_size = bss->size; + nro_info_it->text_size = text_size; + nro_info_it->ro_size = ro_size; + nro_info_it->rw_size = rw_size; + std::copy(build_id, build_id + sizeof(nro_info_it->build_id), nro_info_it->build_id); + nro_info_it->in_use = true; } } @@ -254,11 +249,9 @@ Result Registration::GetNsoInfosForProcessId(Registration::NsoInfo *out, u32 max } u32 cur = 0; - if (max_out > 0) { - for (unsigned int i = 0; i < NSO_INFO_MAX && cur < max_out; i++) { - if (target_process->nso_infos[i].in_use) { - out[cur++] = target_process->nso_infos[i].info; - } + for (unsigned int i = 0; i < NSO_INFO_MAX && cur < max_out; i++) { + if (target_process->nso_infos[i].in_use) { + out[cur++] = target_process->nso_infos[i].info; } } diff --git a/stratosphere/loader/source/ldr_registration.hpp b/stratosphere/loader/source/ldr_registration.hpp index c6aac0d55..eda625223 100644 --- a/stratosphere/loader/source/ldr_registration.hpp +++ b/stratosphere/loader/source/ldr_registration.hpp @@ -1,5 +1,6 @@ #pragma once #include +#include #include "ldr_map.hpp" @@ -48,14 +49,14 @@ class Registration { u64 process_id; u64 title_id; Registration::TidSid tid_sid; - Registration::NsoInfoHolder nso_infos[NSO_INFO_MAX]; - Registration::NroInfo nro_infos[NRO_INFO_MAX]; - MappedCodeMemory nrr_infos[NRR_INFO_MAX]; + std::array nso_infos; + std::array nro_infos; + std::array nrr_infos; void *owner_ro_service; }; struct List { - Registration::Process processes[REGISTRATION_LIST_MAX]; + std::array processes; u64 num_processes; }; diff --git a/stratosphere/pm/source/pm_registration.cpp b/stratosphere/pm/source/pm_registration.cpp index 405903515..d3c0c05b7 100644 --- a/stratosphere/pm/source/pm_registration.cpp +++ b/stratosphere/pm/source/pm_registration.cpp @@ -71,9 +71,9 @@ void Registration::HandleProcessLaunch() { u64 *out_pid = g_process_launch_state.out_pid; Process new_process = {0}; new_process.tid_sid = g_process_launch_state.tid_sid; - u8 *ac_buf = new u8[4 * sizeof(LoaderProgramInfo)]; - std::fill(ac_buf, ac_buf + 4 * sizeof(LoaderProgramInfo), 0xCC); - u8 *acid_sac = ac_buf, *aci0_sac = acid_sac + sizeof(LoaderProgramInfo), *fac = aci0_sac + sizeof(LoaderProgramInfo), *fah = fac + sizeof(LoaderProgramInfo); + auto ac_buf = std::vector(4 * sizeof(LoaderProgramInfo)); + std::fill(ac_buf.begin(), ac_buf.end(), 0xCC); + u8 *acid_sac = ac_buf.data(), *aci0_sac = acid_sac + sizeof(LoaderProgramInfo), *fac = aci0_sac + sizeof(LoaderProgramInfo), *fah = fac + sizeof(LoaderProgramInfo); /* Check that this is a real program. */ if (R_FAILED((rc = ldrPmGetProgramInfo(new_process.tid_sid.title_id, new_process.tid_sid.storage_id, &program_info)))) { @@ -180,7 +180,6 @@ HANDLE_PROCESS_LAUNCH_END: if (R_SUCCEEDED(rc)) { *out_pid = new_process.pid; } - delete ac_buf; g_sema_finish_launch.Signal(); } diff --git a/stratosphere/sm/source/sm_registration.cpp b/stratosphere/sm/source/sm_registration.cpp index 46483a758..226a7b192 100644 --- a/stratosphere/sm/source/sm_registration.cpp +++ b/stratosphere/sm/source/sm_registration.cpp @@ -2,9 +2,10 @@ #include #include #include "sm_registration.hpp" +#include "meta_tools.hpp" -static Registration::Process g_process_list[REGISTRATION_LIST_MAX_PROCESS] = {0}; -static Registration::Service g_service_list[REGISTRATION_LIST_MAX_SERVICE] = {0}; +static std::array g_process_list = {0}; +static std::array g_service_list = {0}; static u64 g_initial_process_id_low = 0; static u64 g_initial_process_id_high = 0; @@ -21,12 +22,11 @@ u64 GetServiceNameLength(u64 service) { /* Utilities. */ Registration::Process *Registration::GetProcessForPid(u64 pid) { - for (auto &process : g_process_list) { - if (process.pid == pid) { - return &process; - } + auto process_it = std::find_if(g_process_list.begin(), g_process_list.end(), member_equals_fn(&Process::pid, pid)); + if (process_it == g_process_list.end()) { + return nullptr; } - return NULL; + return &*process_it; } Registration::Process *Registration::GetFreeProcess() { @@ -34,12 +34,11 @@ Registration::Process *Registration::GetFreeProcess() { } Registration::Service *Registration::GetService(u64 service_name) { - for (auto &service : g_service_list) { - if (service.service_name == service_name) { - return &service; - } + auto service_it = std::find_if(g_service_list.begin(), g_service_list.end(), member_equals_fn(&Service::service_name, service_name)); + if (service_it == g_service_list.end()) { + return nullptr; } - return NULL; + return &*service_it; } Registration::Service *Registration::GetFreeService() { @@ -168,12 +167,7 @@ Result Registration::UnregisterProcess(u64 pid) { /* Service management. */ bool Registration::HasService(u64 service) { - for (unsigned int i = 0; i < REGISTRATION_LIST_MAX_SERVICE; i++) { - if (g_service_list[i].service_name == service) { - return true; - } - } - return false; + return std::any_of(g_service_list.begin(), g_service_list.end(), member_equals_fn(&Service::service_name, service)); } Result Registration::GetServiceHandle(u64 pid, u64 service, Handle *out) {