From 30fac905af24f78053f0b1e4f915c73e0ddd08a2 Mon Sep 17 00:00:00 2001 From: Michael Scire Date: Mon, 13 Dec 2021 13:07:03 -0800 Subject: [PATCH] ams: deduplicate static initialization logic --- .../arm/kern_generic_interrupt_controller.hpp | 2 +- .../source/arch/arm64/kern_cpu.cpp | 2 +- .../util/util_singleton_traits.hpp | 57 ++++++-------- .../source/erpt/srv/erpt_srv_keys.cpp | 13 +--- .../fssystem_crypto_configuration.cpp | 10 +-- .../gpio/driver/impl/gpio_driver_core.cpp | 32 ++------ .../board/nintendo/nx/i2c_driver_api.cpp | 13 ++-- .../i2c/driver/impl/i2c_driver_core.cpp | 17 +--- .../lm/srv/lm_event_log_transmitter.cpp | 3 +- .../source/lm/srv/lm_log_buffer.cpp | 8 +- .../source/lm/srv/lm_log_getter_impl.cpp | 5 +- .../source/lm/srv/lm_log_packet_parser.cpp | 2 +- .../source/ncm/ncm_install_task_base.cpp | 2 +- .../source/ncm/ncm_memory_report.cpp | 3 +- .../powctl/impl/powctl_device_management.cpp | 60 ++++++--------- .../pwm/driver/impl/pwm_driver_core.cpp | 17 +--- .../impl/settings_key_value_store.cpp | 77 ++++--------------- .../source/settings/impl/settings_spl.cpp | 42 +++++----- .../settings/impl/settings_static_object.hpp | 22 +----- .../settings/impl/settings_system_data.hpp | 5 ++ .../impl/settings_system_save_data.hpp | 8 ++ libraries/libvapours/include/vapours/util.hpp | 2 + .../util/util_function_local_static.hpp | 51 ++++++++++++ .../vapours/util/util_typed_storage.hpp | 11 ++- 24 files changed, 202 insertions(+), 262 deletions(-) create mode 100644 libraries/libvapours/include/vapours/util/util_function_local_static.hpp diff --git a/libraries/libmesosphere/include/mesosphere/arch/arm/kern_generic_interrupt_controller.hpp b/libraries/libmesosphere/include/mesosphere/arch/arm/kern_generic_interrupt_controller.hpp index 146f38f87..63e245659 100644 --- a/libraries/libmesosphere/include/mesosphere/arch/arm/kern_generic_interrupt_controller.hpp +++ b/libraries/libmesosphere/include/mesosphere/arch/arm/kern_generic_interrupt_controller.hpp @@ -133,7 +133,7 @@ namespace ams::kern::arch::arm { PriorityLevel_Scheduler = 2, }; private: - static inline u32 s_mask[cpu::NumCores]; + static constinit inline u32 s_mask[cpu::NumCores]; private: volatile GicDistributor *m_gicd; volatile GicCpuInterface *m_gicc; diff --git a/libraries/libmesosphere/source/arch/arm64/kern_cpu.cpp b/libraries/libmesosphere/source/arch/arm64/kern_cpu.cpp index bd07b173e..1a491671d 100644 --- a/libraries/libmesosphere/source/arch/arm64/kern_cpu.cpp +++ b/libraries/libmesosphere/source/arch/arm64/kern_cpu.cpp @@ -44,7 +44,7 @@ namespace ams::kern::arch::arm64::cpu { class KPerformanceCounterInterruptHandler : public KInterruptHandler { private: - static inline KLightLock s_lock; + static constinit inline KLightLock s_lock; private: u64 m_counter; s32 m_which; diff --git a/libraries/libstratosphere/include/stratosphere/util/util_singleton_traits.hpp b/libraries/libstratosphere/include/stratosphere/util/util_singleton_traits.hpp index 040dbe4a9..ba56dfb6d 100644 --- a/libraries/libstratosphere/include/stratosphere/util/util_singleton_traits.hpp +++ b/libraries/libstratosphere/include/stratosphere/util/util_singleton_traits.hpp @@ -18,41 +18,28 @@ #include #include -#define AMS_SINGLETON_TRAITS(_CLASSNAME_) \ - private: \ - NON_COPYABLE(_CLASSNAME_); \ - NON_MOVEABLE(_CLASSNAME_); \ - private: \ - _CLASSNAME_ (); \ - public: \ - static _CLASSNAME_ &GetInstance() { \ - /* Declare singleton instance variables. */ \ - static constinit ::ams::util::TypedStorage<_CLASSNAME_> s_singleton_storage; \ - static constinit ::ams::os::SdkMutex s_singleton_mutex; \ - static constinit bool s_initialized_singleton = false; \ - \ - /* Ensure the instance is created. */ \ - if (AMS_UNLIKELY(!s_initialized_singleton)) { \ - std::scoped_lock lk(s_singleton_mutex); \ - \ - if (AMS_LIKELY(!s_initialized_singleton)) { \ - new (::ams::util::GetPointer(s_singleton_storage)) _CLASSNAME_; \ - s_initialized_singleton = true; \ - } \ - } \ - \ - return ::ams::util::GetReference(s_singleton_storage); \ +#define AMS_SINGLETON_TRAITS(_CLASSNAME_) \ + private: \ + NON_COPYABLE(_CLASSNAME_); \ + NON_MOVEABLE(_CLASSNAME_); \ + private: \ + _CLASSNAME_ (); \ + public: \ + static _CLASSNAME_ &GetInstance() { \ + AMS_FUNCTION_LOCAL_STATIC(_CLASSNAME_, s_singleton_instance); \ + \ + return s_singleton_instance; \ } -#define AMS_CONSTINIT_SINGLETON_TRAITS(_CLASSNAME_) \ - private: \ - NON_COPYABLE(_CLASSNAME_); \ - NON_MOVEABLE(_CLASSNAME_); \ - private: \ - constexpr _CLASSNAME_ () = default; \ - public: \ - static _CLASSNAME_ &GetInstance() { \ - /* Declare singleton instance variables. */ \ - static constinit _CLASSNAME_ s_singleton_instance; \ - return s_singleton_instance; \ +#define AMS_CONSTINIT_SINGLETON_TRAITS(_CLASSNAME_) \ + private: \ + NON_COPYABLE(_CLASSNAME_); \ + NON_MOVEABLE(_CLASSNAME_); \ + private: \ + constexpr _CLASSNAME_ () = default; \ + public: \ + static _CLASSNAME_ &GetInstance() { \ + /* Declare singleton instance variables. */ \ + AMS_FUNCTION_LOCAL_STATIC_CONSTINIT(_CLASSNAME_, s_singleton_instance); \ + return s_singleton_instance; \ } diff --git a/libraries/libstratosphere/source/erpt/srv/erpt_srv_keys.cpp b/libraries/libstratosphere/source/erpt/srv/erpt_srv_keys.cpp index 49fc15f35..95f226a4b 100644 --- a/libraries/libstratosphere/source/erpt/srv/erpt_srv_keys.cpp +++ b/libraries/libstratosphere/source/erpt/srv/erpt_srv_keys.cpp @@ -73,18 +73,7 @@ namespace ams::erpt::srv { } bool IsProductionMode() { - static constinit bool s_initialized = false; - static constinit bool s_is_prod_mode = true; - static constinit os::SdkMutex s_mutex; - - if (AMS_UNLIKELY(!s_initialized)) { - std::scoped_lock lk(s_mutex); - - if (AMS_LIKELY(!s_initialized)) { - s_is_prod_mode = IsProductionModeImpl(); - s_initialized = true; - } - } + AMS_FUNCTION_LOCAL_STATIC(bool, s_is_prod_mode, IsProductionModeImpl()); return s_is_prod_mode; } diff --git a/libraries/libstratosphere/source/fssystem/fssystem_crypto_configuration.cpp b/libraries/libstratosphere/source/fssystem/fssystem_crypto_configuration.cpp index f68c4a8c2..56cd79df0 100644 --- a/libraries/libstratosphere/source/fssystem/fssystem_crypto_configuration.cpp +++ b/libraries/libstratosphere/source/fssystem/fssystem_crypto_configuration.cpp @@ -112,13 +112,13 @@ namespace ams::fssystem { NcaCryptoConfiguration g_nca_crypto_configuration_prod; constexpr inline s32 KeySlotCacheEntryCount = 3; - KeySlotCache g_key_slot_cache; - util::optional g_key_slot_cache_entry[KeySlotCacheEntryCount]; + constinit KeySlotCache g_key_slot_cache; + constinit util::optional g_key_slot_cache_entry[KeySlotCacheEntryCount]; spl::AccessKey &GetNcaKekAccessKey(s32 key_type) { - static spl::AccessKey s_nca_kek_access_key_array[KeyAreaEncryptionKeyCount] = {}; - static spl::AccessKey s_nca_header_kek_access_key = {}; - static spl::AccessKey s_invalid_nca_kek_access_key = {}; + AMS_FUNCTION_LOCAL_STATIC_CONSTINIT(spl::AccessKey, s_nca_kek_access_key_array[KeyAreaEncryptionKeyCount]); + AMS_FUNCTION_LOCAL_STATIC_CONSTINIT(spl::AccessKey, s_nca_header_kek_access_key); + AMS_FUNCTION_LOCAL_STATIC_CONSTINIT(spl::AccessKey, s_invalid_nca_kek_access_key); if (key_type > static_cast(KeyType::NcaHeaderKey) || IsInvalidKeyTypeValue(key_type)) { return s_invalid_nca_kek_access_key; diff --git a/libraries/libstratosphere/source/gpio/driver/impl/gpio_driver_core.cpp b/libraries/libstratosphere/source/gpio/driver/impl/gpio_driver_core.cpp index 73ec1b35d..a3bf7c080 100644 --- a/libraries/libstratosphere/source/gpio/driver/impl/gpio_driver_core.cpp +++ b/libraries/libstratosphere/source/gpio/driver/impl/gpio_driver_core.cpp @@ -26,42 +26,20 @@ namespace ams::gpio::driver::impl { alignas(os::MemoryPageSize) u8 g_interrupt_thread_stack[InterruptThreadStackSize]; gpio::driver::IGpioDriver::List &GetGpioDriverList() { - static constinit gpio::driver::IGpioDriver::List s_gpio_driver_list; + AMS_FUNCTION_LOCAL_STATIC_CONSTINIT(gpio::driver::IGpioDriver::List, s_gpio_driver_list); return s_gpio_driver_list; } ddsf::EventHandlerManager &GetInterruptHandlerManager() { - static constinit util::TypedStorage s_interrupt_handler_manager; - static constinit bool s_initialized = false; - static constinit os::SdkMutex s_mutex; + AMS_FUNCTION_LOCAL_STATIC(ddsf::EventHandlerManager, s_interrupt_handler_manager); - if (AMS_UNLIKELY(!s_initialized)) { - std::scoped_lock lk(s_mutex); - - if (AMS_LIKELY(!s_initialized)) { - util::ConstructAt(s_interrupt_handler_manager); - s_initialized = true; - } - } - - return util::GetReference(s_interrupt_handler_manager); + return s_interrupt_handler_manager; } ddsf::DeviceCodeEntryManager &GetDeviceCodeEntryManager() { - static constinit util::TypedStorage s_device_code_entry_manager; - static constinit bool s_initialized = false; - static constinit os::SdkMutex s_mutex; + AMS_FUNCTION_LOCAL_STATIC(ddsf::DeviceCodeEntryManager, s_device_code_entry_manager, ddsf::GetDeviceCodeEntryHolderMemoryResource()); - if (AMS_UNLIKELY(!s_initialized)) { - std::scoped_lock lk(s_mutex); - - if (AMS_LIKELY(!s_initialized)) { - util::ConstructAt(s_device_code_entry_manager, ddsf::GetDeviceCodeEntryHolderMemoryResource()); - s_initialized = true; - } - } - - return util::GetReference(s_device_code_entry_manager); + return s_device_code_entry_manager; } void InterruptThreadFunction(void *arg) { diff --git a/libraries/libstratosphere/source/i2c/driver/board/nintendo/nx/i2c_driver_api.cpp b/libraries/libstratosphere/source/i2c/driver/board/nintendo/nx/i2c_driver_api.cpp index fee708243..09a174e2f 100644 --- a/libraries/libstratosphere/source/i2c/driver/board/nintendo/nx/i2c_driver_api.cpp +++ b/libraries/libstratosphere/source/i2c/driver/board/nintendo/nx/i2c_driver_api.cpp @@ -95,16 +95,17 @@ namespace ams::i2c::driver::board::nintendo::nx { } } + constinit util::TypedStorage g_bus_accessor_manager; + constinit util::TypedStorage g_device_manager; + } void Initialize() { - static constinit util::TypedStorage s_bus_accessor_manager; - static constinit util::TypedStorage s_device_manager; + /* Initialize managers. */ + util::ConstructAt(g_bus_accessor_manager, ddsf::GetMemoryResource()); + util::ConstructAt(g_device_manager, ddsf::GetMemoryResource()); - util::ConstructAt(s_bus_accessor_manager, ddsf::GetMemoryResource()); - util::ConstructAt(s_device_manager, ddsf::GetMemoryResource()); - - return Initialize(util::GetReference(s_bus_accessor_manager), util::GetReference(s_device_manager)); + return Initialize(util::GetReference(g_bus_accessor_manager), util::GetReference(g_device_manager)); } } diff --git a/libraries/libstratosphere/source/i2c/driver/impl/i2c_driver_core.cpp b/libraries/libstratosphere/source/i2c/driver/impl/i2c_driver_core.cpp index 97893f202..105aaf4f0 100644 --- a/libraries/libstratosphere/source/i2c/driver/impl/i2c_driver_core.cpp +++ b/libraries/libstratosphere/source/i2c/driver/impl/i2c_driver_core.cpp @@ -24,25 +24,14 @@ namespace ams::i2c::driver::impl { constinit int g_init_count = 0; i2c::driver::II2cDriver::List &GetI2cDriverList() { - static constinit i2c::driver::II2cDriver::List s_driver_list; + AMS_FUNCTION_LOCAL_STATIC_CONSTINIT(i2c::driver::II2cDriver::List, s_driver_list); return s_driver_list; } ddsf::DeviceCodeEntryManager &GetDeviceCodeEntryManager() { - static constinit util::TypedStorage s_device_code_entry_manager; - static constinit bool s_initialized = false; - static constinit os::SdkMutex s_mutex; + AMS_FUNCTION_LOCAL_STATIC(ddsf::DeviceCodeEntryManager, s_device_code_entry_manager, ddsf::GetDeviceCodeEntryHolderMemoryResource()); - if (AMS_UNLIKELY(!s_initialized)) { - std::scoped_lock lk(s_mutex); - - if (AMS_LIKELY(!s_initialized)) { - util::ConstructAt(s_device_code_entry_manager, ddsf::GetDeviceCodeEntryHolderMemoryResource()); - s_initialized = true; - } - } - - return util::GetReference(s_device_code_entry_manager); + return s_device_code_entry_manager; } } diff --git a/libraries/libstratosphere/source/lm/srv/lm_event_log_transmitter.cpp b/libraries/libstratosphere/source/lm/srv/lm_event_log_transmitter.cpp index 1aefac415..b516db76a 100644 --- a/libraries/libstratosphere/source/lm/srv/lm_event_log_transmitter.cpp +++ b/libraries/libstratosphere/source/lm/srv/lm_event_log_transmitter.cpp @@ -34,7 +34,8 @@ namespace ams::lm::srv { } EventLogTransmitter &EventLogTransmitter::GetDefaultInstance() { - static constinit EventLogTransmitter s_default_event_log_transmitter(DefaultFlushFunction); + AMS_FUNCTION_LOCAL_STATIC_CONSTINIT(EventLogTransmitter, s_default_event_log_transmitter, DefaultFlushFunction); + return s_default_event_log_transmitter; } diff --git a/libraries/libstratosphere/source/lm/srv/lm_log_buffer.cpp b/libraries/libstratosphere/source/lm/srv/lm_log_buffer.cpp index 109377ff5..bc9b99e03 100644 --- a/libraries/libstratosphere/source/lm/srv/lm_log_buffer.cpp +++ b/libraries/libstratosphere/source/lm/srv/lm_log_buffer.cpp @@ -63,8 +63,10 @@ namespace ams::lm::srv { } bool DefaultFlushFunction(const u8 *data, size_t size) { + /* Declare persistent clock-updated state storage. */ + AMS_FUNCTION_LOCAL_STATIC_CONSTINIT(bool, s_is_user_system_clock_updated, false); + /* Update clock. */ - static constinit bool s_is_user_system_clock_updated = false; if (!s_is_user_system_clock_updated) { UpdateUserSystemClock(data, size); s_is_user_system_clock_updated = true; @@ -84,8 +86,8 @@ namespace ams::lm::srv { } LogBuffer &LogBuffer::GetDefaultInstance() { - static constinit u8 s_default_buffers[128_KB * 2]; - static constinit LogBuffer s_default_log_buffer(s_default_buffers, sizeof(s_default_buffers), DefaultFlushFunction); + AMS_FUNCTION_LOCAL_STATIC_CONSTINIT(u8, s_default_buffers[128_KB * 2]); + AMS_FUNCTION_LOCAL_STATIC_CONSTINIT(LogBuffer, s_default_log_buffer, s_default_buffers, sizeof(s_default_buffers), DefaultFlushFunction); return s_default_log_buffer; } diff --git a/libraries/libstratosphere/source/lm/srv/lm_log_getter_impl.cpp b/libraries/libstratosphere/source/lm/srv/lm_log_getter_impl.cpp index ea07aa95f..fc109cf80 100644 --- a/libraries/libstratosphere/source/lm/srv/lm_log_getter_impl.cpp +++ b/libraries/libstratosphere/source/lm/srv/lm_log_getter_impl.cpp @@ -19,8 +19,9 @@ namespace ams::lm::srv { CustomSinkBuffer &LogGetterImpl::GetBuffer() { - static constinit u8 s_buffer[32_KB]; - static constinit CustomSinkBuffer s_custom_sink_buffer(s_buffer, sizeof(s_buffer), FlushFunction); + AMS_FUNCTION_LOCAL_STATIC_CONSTINIT(u8, s_buffer[32_KB]); + AMS_FUNCTION_LOCAL_STATIC_CONSTINIT(CustomSinkBuffer, s_custom_sink_buffer, s_buffer, sizeof(s_buffer), FlushFunction); + return s_custom_sink_buffer; } diff --git a/libraries/libstratosphere/source/lm/srv/lm_log_packet_parser.cpp b/libraries/libstratosphere/source/lm/srv/lm_log_packet_parser.cpp index 278cb570d..cc6401b1e 100644 --- a/libraries/libstratosphere/source/lm/srv/lm_log_packet_parser.cpp +++ b/libraries/libstratosphere/source/lm/srv/lm_log_packet_parser.cpp @@ -188,7 +188,7 @@ namespace ams::lm::srv { size_t carry_size; bool ends_with_text_log; }; - static constinit PreviousPacketContext s_previous_packet_context = {}; + AMS_FUNCTION_LOCAL_STATIC_CONSTINIT(PreviousPacketContext, s_previous_packet_context); /* Get the packet header. */ auto *header = static_cast(buffer); diff --git a/libraries/libstratosphere/source/ncm/ncm_install_task_base.cpp b/libraries/libstratosphere/source/ncm/ncm_install_task_base.cpp index 8dccff0a7..151b0fefd 100644 --- a/libraries/libstratosphere/source/ncm/ncm_install_task_base.cpp +++ b/libraries/libstratosphere/source/ncm/ncm_install_task_base.cpp @@ -635,7 +635,7 @@ namespace ams::ncm { for (s32 i = 0; i < count; i++) { R_UNLESS(!this->IsCancelRequested(), ncm::ResultCreatePlaceHolderCancelled()); - static constinit os::SdkMutex s_placeholder_mutex; + AMS_FUNCTION_LOCAL_STATIC_CONSTINIT(os::SdkMutex, s_placeholder_mutex); std::scoped_lock lk(s_placeholder_mutex); InstallContentMeta content_meta; diff --git a/libraries/libstratosphere/source/ncm/ncm_memory_report.cpp b/libraries/libstratosphere/source/ncm/ncm_memory_report.cpp index dfdab9aa2..5bfa968b0 100644 --- a/libraries/libstratosphere/source/ncm/ncm_memory_report.cpp +++ b/libraries/libstratosphere/source/ncm/ncm_memory_report.cpp @@ -44,7 +44,8 @@ namespace ams::ncm { } HeapState &GetHeapState() { - static HeapState s_heap_state = {}; + AMS_FUNCTION_LOCAL_STATIC_CONSTINIT(HeapState, s_heap_state); + return s_heap_state; } diff --git a/libraries/libstratosphere/source/powctl/impl/powctl_device_management.cpp b/libraries/libstratosphere/source/powctl/impl/powctl_device_management.cpp index e3364b68f..28e10c179 100644 --- a/libraries/libstratosphere/source/powctl/impl/powctl_device_management.cpp +++ b/libraries/libstratosphere/source/powctl/impl/powctl_device_management.cpp @@ -20,60 +20,44 @@ namespace ams::powctl::impl { namespace { - os::ThreadType g_interrupt_thread; + constinit os::ThreadType g_interrupt_thread; constexpr inline size_t InterruptThreadStackSize = os::MemoryPageSize; alignas(os::MemoryPageSize) u8 g_interrupt_thread_stack[InterruptThreadStackSize]; - constinit u8 g_unit_heap_memory[2_KB]; - constinit lmem::HeapHandle g_unit_heap_handle; - constinit sf::UnitHeapMemoryResource g_unit_heap_memory_resource; - IPowerControlDriver::List &GetDriverList() { - static constinit IPowerControlDriver::List s_driver_list; + AMS_FUNCTION_LOCAL_STATIC_CONSTINIT(IPowerControlDriver::List, s_driver_list); return s_driver_list; } ddsf::EventHandlerManager &GetInterruptHandlerManager() { - static constinit util::TypedStorage s_interrupt_handler_manager; - static constinit bool s_initialized = false; - static constinit os::SdkMutex s_mutex; + AMS_FUNCTION_LOCAL_STATIC(ddsf::EventHandlerManager, s_interrupt_handler_manager); - if (AMS_UNLIKELY(!s_initialized)) { - std::scoped_lock lk(s_mutex); - - if (AMS_LIKELY(!s_initialized)) { - util::ConstructAt(s_interrupt_handler_manager); - s_initialized = true; - } - } - - return util::GetReference(s_interrupt_handler_manager); + return s_interrupt_handler_manager; } ddsf::DeviceCodeEntryManager &GetDeviceCodeEntryManager() { - static constinit util::TypedStorage s_device_code_entry_manager; - static constinit bool s_initialized = false; - static constinit os::SdkMutex s_mutex; + class DeviceCodeEntryManagerWithUnitHeap { + private: + u8 m_heap_memory[2_KB]; + sf::UnitHeapMemoryResource m_memory_resource; + util::TypedStorage m_manager; + public: + DeviceCodeEntryManagerWithUnitHeap() { + /* Initialize the memory resource. */ + m_memory_resource.Attach(lmem::CreateUnitHeap(m_heap_memory, sizeof(m_heap_memory), sizeof(ddsf::DeviceCodeEntryHolder), lmem::CreateOption_ThreadSafe)); - if (AMS_UNLIKELY(!s_initialized)) { - std::scoped_lock lk(s_mutex); + /* Construct the entry manager. */ + util::ConstructAt(m_manager, std::addressof(m_memory_resource)); + } - if (AMS_LIKELY(!s_initialized)) { - /* Initialize the entry code heap. */ - g_unit_heap_handle = lmem::CreateUnitHeap(g_unit_heap_memory, sizeof(g_unit_heap_memory), sizeof(ddsf::DeviceCodeEntryHolder), lmem::CreateOption_ThreadSafe); + ALWAYS_INLINE operator ddsf::DeviceCodeEntryManager &() { + return util::GetReference(m_manager); + } + }; + AMS_FUNCTION_LOCAL_STATIC(DeviceCodeEntryManagerWithUnitHeap, s_device_code_entry_manager_holder); - /* Initialize the entry code memory resource. */ - g_unit_heap_memory_resource.Attach(g_unit_heap_handle); - - /* Make the entry manager using the newly initialized memory resource. */ - util::ConstructAt(s_device_code_entry_manager, std::addressof(g_unit_heap_memory_resource)); - - s_initialized = true; - } - } - - return util::GetReference(s_device_code_entry_manager); + return s_device_code_entry_manager_holder; } void InterruptThreadFunction(void *arg) { diff --git a/libraries/libstratosphere/source/pwm/driver/impl/pwm_driver_core.cpp b/libraries/libstratosphere/source/pwm/driver/impl/pwm_driver_core.cpp index 224991684..19fead5c1 100644 --- a/libraries/libstratosphere/source/pwm/driver/impl/pwm_driver_core.cpp +++ b/libraries/libstratosphere/source/pwm/driver/impl/pwm_driver_core.cpp @@ -24,25 +24,14 @@ namespace ams::pwm::driver::impl { constinit int g_init_count = 0; pwm::driver::IPwmDriver::List &GetPwmDriverList() { - static constinit pwm::driver::IPwmDriver::List s_driver_list; + AMS_FUNCTION_LOCAL_STATIC_CONSTINIT(pwm::driver::IPwmDriver::List, s_driver_list); return s_driver_list; } ddsf::DeviceCodeEntryManager &GetDeviceCodeEntryManager() { - static constinit util::TypedStorage s_device_code_entry_manager; - static constinit bool s_initialized = false; - static constinit os::SdkMutex s_mutex; + AMS_FUNCTION_LOCAL_STATIC(ddsf::DeviceCodeEntryManager, s_device_code_entry_manager, ddsf::GetDeviceCodeEntryHolderMemoryResource()); - if (AMS_UNLIKELY(!s_initialized)) { - std::scoped_lock lk(s_mutex); - - if (AMS_LIKELY(!s_initialized)) { - util::ConstructAt(s_device_code_entry_manager, ddsf::GetDeviceCodeEntryHolderMemoryResource()); - s_initialized = true; - } - } - - return util::GetReference(s_device_code_entry_manager); + return s_device_code_entry_manager; } } diff --git a/libraries/libstratosphere/source/settings/impl/settings_key_value_store.cpp b/libraries/libstratosphere/source/settings/impl/settings_key_value_store.cpp index c6233ff76..b95cdccec 100644 --- a/libraries/libstratosphere/source/settings/impl/settings_key_value_store.cpp +++ b/libraries/libstratosphere/source/settings/impl/settings_key_value_store.cpp @@ -289,14 +289,8 @@ namespace ams::settings::impl { } lmem::HeapHandle &GetHeapHandle() { - static constinit bool s_is_initialized = false; - static constinit lmem::HeapHandle s_heap_handle; - static constinit u8 s_heap_memory[HeapMemorySize]; - - if (!s_is_initialized) { - s_heap_handle = lmem::CreateExpHeap(s_heap_memory, sizeof(s_heap_memory), lmem::CreateOption_None); - s_is_initialized = true; - } + AMS_FUNCTION_LOCAL_STATIC_CONSTINIT(u8, s_heap_memory[HeapMemorySize]); + AMS_FUNCTION_LOCAL_STATIC(lmem::HeapHandle, s_heap_handle, lmem::CreateExpHeap(s_heap_memory, sizeof(s_heap_memory), lmem::CreateOption_ThreadSafe)); return s_heap_handle; } @@ -314,24 +308,15 @@ namespace ams::settings::impl { AMS_ASSERT(out != nullptr); /* Declare static instance variables. */ - static constinit util::TypedStorage s_storage = {}; - static constinit bool s_is_initialized = false; - static constinit bool s_is_loaded = false; + AMS_FUNCTION_LOCAL_STATIC(Map, s_map); + AMS_FUNCTION_LOCAL_STATIC_CONSTINIT(bool, s_is_map_loaded, false); /* Get pointer to the map. */ - Map *map = util::GetPointer(s_storage); - - /* Construct the map, if we haven't already. */ - if (AMS_UNLIKELY(!s_is_initialized)) { - /* Construct the instance. */ - util::ConstructAt(s_storage); - - /* Note that we constructed. */ - s_is_initialized = true; - } + Map * const map = std::addressof(s_map); + /* TODO: Mutex? */ /* Load the map, if we haven't already. */ - if (AMS_UNLIKELY(!s_is_loaded)) { + if (AMS_UNLIKELY(!s_is_map_loaded)) { /* Attempt to load the map, allowing for failure if acceptable. */ const auto result = LoadKeyValueStoreMap(map); @@ -340,7 +325,7 @@ namespace ams::settings::impl { } /* Note that the map is loaded. */ - s_is_loaded = true; + s_is_map_loaded = true; } /* Set the output pointer. */ @@ -425,26 +410,13 @@ namespace ams::settings::impl { AMS_ASSERT(out_data != nullptr); /* Declare static instance variables. */ - static constinit util::TypedStorage s_storage = {}; - static constinit bool s_initialized = false; - static constinit bool s_mounted = false; + AMS_FUNCTION_LOCAL_STATIC(SystemData, s_data, id, GetSystemDataMountName()); + AMS_FUNCTION_LOCAL_STATIC_CONSTINIT(bool, s_mounted, false); /* Get pointer to the system data. */ - SystemData *data = util::GetPointer(s_storage); - - /* Construct the system data, if we haven't already. */ - if (AMS_UNLIKELY(!s_initialized)) { - /* Construct the instance. */ - util::ConstructAt(s_storage); - - /* Setup system data. */ - data->SetSystemDataId(id); - data->SetMountName(GetSystemDataMountName()); - - /* Note that we constructed. */ - s_initialized = true; - } + SystemData *data = std::addressof(s_data); + /* TODO: Mutex? */ /* Mount the system data, if we haven't already. */ if (AMS_UNLIKELY(!s_mounted)) { /* Mount the system data. */ @@ -464,28 +436,11 @@ namespace ams::settings::impl { AMS_ASSERT(out_data != nullptr); /* Declare static instance variables. */ - static constinit util::TypedStorage s_storage = {}; - static constinit bool s_initialized = false; - static constinit bool s_mounted = false; + AMS_FUNCTION_LOCAL_STATIC(SystemSaveData, s_data, SystemSaveDataId, SystemSaveDataSize, SystemSaveDataJournalSize, SystemSaveDataFlags, SystemSaveDataMountName); + AMS_FUNCTION_LOCAL_STATIC_CONSTINIT(bool, s_mounted, false); - /* Get pointer to the system data. */ - SystemSaveData *data = util::GetPointer(s_storage); - - /* Construct the system data, if we haven't already. */ - if (AMS_UNLIKELY(!s_initialized)) { - /* Construct the instance. */ - util::ConstructAt(s_storage); - - /* Setup system data. */ - data->SetSystemSaveDataId(SystemSaveDataId); - data->SetTotalSize(SystemSaveDataSize); - data->SetJournalSize(SystemSaveDataJournalSize); - data->SetFlags(SystemSaveDataFlags); - data->SetMountName(SystemSaveDataMountName); - - /* Note that we constructed. */ - s_initialized = true; - } + /* Get pointer to the system save data. */ + SystemSaveData *data = std::addressof(s_data); /* Mount the system data, if we haven't already. */ if (AMS_UNLIKELY(!s_mounted)) { diff --git a/libraries/libstratosphere/source/settings/impl/settings_spl.cpp b/libraries/libstratosphere/source/settings/impl/settings_spl.cpp index ef711dfe8..23669b679 100644 --- a/libraries/libstratosphere/source/settings/impl/settings_spl.cpp +++ b/libraries/libstratosphere/source/settings/impl/settings_spl.cpp @@ -56,27 +56,33 @@ namespace ams::settings::impl { } SplConfig GetSplConfig() { - static constinit bool s_is_initialized = false; - static constinit SplConfig s_config; + class SplConfigHolder { + NON_COPYABLE(SplConfigHolder); + NON_MOVEABLE(SplConfigHolder); + private: + SplConfig m_config; + public: + SplConfigHolder() { + /* Initialize spl. */ + spl::Initialize(); + ON_SCOPE_EXIT { spl::Finalize(); }; - if (!s_is_initialized) { - /* Initialize spl. */ - spl::Initialize(); - ON_SCOPE_EXIT { spl::Finalize(); }; + /* Create the config. */ + m_config = { + .is_development = spl::IsDevelopment(), + .hardware_type = ConvertToSplHardwareType(spl::GetHardwareType()), + .is_quest = IsSplRetailInteractiveDisplayStateEnabled(spl::GetRetailInteractiveDisplayState()), + .device_id_low = spl::GetDeviceIdLow(), + }; + } - /* Create the config. */ - s_config = { - .is_development = spl::IsDevelopment(), - .hardware_type = ConvertToSplHardwareType(spl::GetHardwareType()), - .is_quest = IsSplRetailInteractiveDisplayStateEnabled(spl::GetRetailInteractiveDisplayState()), - .device_id_low = spl::GetDeviceIdLow(), - }; + ALWAYS_INLINE operator SplConfig() { + return m_config; + } + }; - /* Mark as initialized. */ - s_is_initialized = true; - } - - return s_config; + AMS_FUNCTION_LOCAL_STATIC(SplConfigHolder, s_config_holder); + return s_config_holder; } } diff --git a/libraries/libstratosphere/source/settings/impl/settings_static_object.hpp b/libraries/libstratosphere/source/settings/impl/settings_static_object.hpp index b13b2b994..4311fc939 100644 --- a/libraries/libstratosphere/source/settings/impl/settings_static_object.hpp +++ b/libraries/libstratosphere/source/settings/impl/settings_static_object.hpp @@ -25,27 +25,9 @@ namespace ams::settings::impl { StaticObject(); public: static T &Get() { - /* Declare static instance variables. */ - static constinit util::TypedStorage s_storage = {}; - static constinit bool s_initialized = false; - static constinit os::SdkMutex s_mutex; + AMS_FUNCTION_LOCAL_STATIC(T, s_object); - /* If we haven't already done so, construct the instance. */ - if (AMS_UNLIKELY(!s_initialized)) { - std::scoped_lock lk(s_mutex); - - /* Check that we didn't concurrently construct the instance. */ - if (AMS_LIKELY(!s_initialized)) { - /* Construct the instance. */ - util::ConstructAt(s_storage); - - /* Note that we constructed. */ - s_initialized = true; - } - } - - /* Return the constructed instance. */ - return util::GetReference(s_storage); + return s_object; } }; diff --git a/libraries/libstratosphere/source/settings/impl/settings_system_data.hpp b/libraries/libstratosphere/source/settings/impl/settings_system_data.hpp index 2cc37cae5..204316c15 100644 --- a/libraries/libstratosphere/source/settings/impl/settings_system_data.hpp +++ b/libraries/libstratosphere/source/settings/impl/settings_system_data.hpp @@ -30,6 +30,11 @@ namespace ams::settings::impl { public: SystemData() : m_system_data_id(), m_mount_name(), m_file_path() { /* ... */ } + SystemData(ncm::SystemDataId id, const char *mn) : SystemData() { + this->SetSystemDataId(id); + this->SetMountName(mn); + } + void SetSystemDataId(ncm::SystemDataId id); void SetMountName(const char *name); Result Mount(); diff --git a/libraries/libstratosphere/source/settings/impl/settings_system_save_data.hpp b/libraries/libstratosphere/source/settings/impl/settings_system_save_data.hpp index 7fc85d883..4d01172d7 100644 --- a/libraries/libstratosphere/source/settings/impl/settings_system_save_data.hpp +++ b/libraries/libstratosphere/source/settings/impl/settings_system_save_data.hpp @@ -30,6 +30,14 @@ namespace ams::settings::impl { public: SystemSaveData() : m_system_save_data_id(0), m_save_data_space_id(fs::SaveDataSpaceId::System), m_total_size(0), m_journal_size(0), m_flags(0) { /* ... */ } + SystemSaveData(u64 id, s64 total_size, s64 journal_size, u32 flags, const char *mn) : SystemSaveData() { + this->SetSystemSaveDataId(id); + this->SetTotalSize(total_size); + this->SetJournalSize(journal_size); + this->SetFlags(flags); + this->SetMountName(mn); + } + void SetSystemSaveDataId(u64 id); void SetTotalSize(s64 size); void SetJournalSize(s64 size); diff --git a/libraries/libvapours/include/vapours/util.hpp b/libraries/libvapours/include/vapours/util.hpp index 7075630d4..081273728 100644 --- a/libraries/libvapours/include/vapours/util.hpp +++ b/libraries/libvapours/include/vapours/util.hpp @@ -55,6 +55,8 @@ #include +#include + #ifdef ATMOSPHERE_IS_STRATOSPHERE #include #endif diff --git a/libraries/libvapours/include/vapours/util/util_function_local_static.hpp b/libraries/libvapours/include/vapours/util/util_function_local_static.hpp new file mode 100644 index 000000000..399b4e753 --- /dev/null +++ b/libraries/libvapours/include/vapours/util/util_function_local_static.hpp @@ -0,0 +1,51 @@ +/* + * Copyright (c) Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#pragma once +#include +#include +#include + +namespace ams::util { + + #define AMS_FUNCTION_LOCAL_STATIC_CONSTINIT(_TYPE_, _NAME_, ...) static constinit _TYPE_ _NAME_ { __VA_ARGS__ } + + /* NOTE: This must use placement new, to support private constructors. */ + #define AMS_FUNCTION_LOCAL_STATIC_IMPL(_LOCKTYPE_, _SCOPELOCKTYPE_, _TYPE_, _NAME_, ...) \ + static constinit ::ams::util::TypedStorage<_TYPE_> s_fls_storage_for_##_NAME_ {}; \ + static constinit bool s_fls_initialized_##_NAME_ = false; \ + static constinit _LOCKTYPE_ s_fls_init_lock_##_NAME_ {}; \ + if (AMS_UNLIKELY(!(s_fls_initialized_##_NAME_))) { \ + _SCOPELOCKTYPE_ sl_fls_for_##_NAME_ { s_fls_init_lock_##_NAME_ }; \ + if (AMS_LIKELY(!(s_fls_initialized_##_NAME_))) { \ + new (::ams::util::impl::GetPointerForConstructAt(s_fls_storage_for_##_NAME_)) _TYPE_( __VA_ARGS__ ); \ + s_fls_initialized_##_NAME_ = true; \ + } \ + } \ + \ + _TYPE_ & _NAME_ = util::GetReference(s_fls_storage_for_##_NAME_) + + #if defined(ATMOSPHERE_IS_MESOSPHERE) + + #define AMS_FUNCTION_LOCAL_STATIC(_TYPE_, _NAME_, ...) AMS_FUNCTION_LOCAL_STATIC_IMPL(KSpinLock, KScopedSpinLock, _TYPE_, _NAME_, ##__VA_ARGS__) + + #elif defined(ATMOSPHERE_IS_STRATOSPHERE) + + #define AMS_FUNCTION_LOCAL_STATIC(_TYPE_, _NAME_, ...) AMS_FUNCTION_LOCAL_STATIC_IMPL(os::SdkMutex, std::scoped_lock, _TYPE_, _NAME_, ##__VA_ARGS__) + + #endif + +} \ No newline at end of file diff --git a/libraries/libvapours/include/vapours/util/util_typed_storage.hpp b/libraries/libvapours/include/vapours/util/util_typed_storage.hpp index 40b20c591..710050465 100644 --- a/libraries/libvapours/include/vapours/util/util_typed_storage.hpp +++ b/libraries/libvapours/include/vapours/util/util_typed_storage.hpp @@ -45,9 +45,18 @@ namespace ams::util { return *GetPointer(ts); } + namespace impl { + + template + static ALWAYS_INLINE T *GetPointerForConstructAt(TypedStorage &ts) { + return reinterpret_cast(std::addressof(ts._storage)); + } + + } + template static ALWAYS_INLINE T *ConstructAt(TypedStorage &ts, Args &&... args) { - return std::construct_at(reinterpret_cast(std::addressof(ts._storage)), std::forward(args)...); + return std::construct_at(impl::GetPointerForConstructAt(ts), std::forward(args)...); } template