Compare commits

...

7 Commits
1.2.5 ... 1.2.6

Author SHA1 Message Date
Michael Scire
173d5c2d3a docs: add changelog for 1.2.6 2022-01-19 16:41:20 -08:00
Michael Scire
52c1cef064 git subrepo push libraries
subrepo:
  subdir:   "libraries"
  merged:   "0d161b858"
upstream:
  origin:   "https://github.com/Atmosphere-NX/Atmosphere-libs"
  branch:   "master"
  commit:   "0d161b858"
git-subrepo:
  version:  "0.4.1"
  origin:   "???"
  commit:   "???"
2022-01-19 16:29:16 -08:00
Michael Scire
4efa5d7dd0 ams: first attempt at 13.2.1 support 2022-01-19 16:28:32 -08:00
Michael Scire
275da52305 kern: add missing debug mode check to WriteDebugProcessMemory 2022-01-03 08:59:27 -08:00
Michael Scire
30fac905af ams: deduplicate static initialization logic 2021-12-13 13:07:03 -08:00
Michael Scire
78f7218c4f kern: fix vi devicename missing in HsSupported device list 2021-12-10 18:58:18 -08:00
Michael Scire
09c6aa29dd sf/cmif: optimize dispatch table walk to use binary search over linear search 2021-12-06 13:13:46 -08:00
37 changed files with 335 additions and 291 deletions

View File

@@ -1,4 +1,10 @@
# Changelog # Changelog
## 1.2.6
+ Support was added for 13.2.1.
+ A number of minor issues were fixed and improvements were made, including:
+ A minor performance improvement was implemented in service table dispatch by sorting and binary-searching the service command table instead of using linear search.
+ Static initialization logic in Atmosphere was made much more regular.
+ General system stability improvements to enhance the user's experience.
## 1.2.5 ## 1.2.5
+ Support was added for 13.2.0. + Support was added for 13.2.0.
+ A number of minor issues were fixed and improvements were made, including: + A number of minor issues were fixed and improvements were made, including:

View File

@@ -249,6 +249,8 @@ namespace ams::nxboot {
return ams::TargetFirmware_12_1_0; return ams::TargetFirmware_12_1_0;
} else if (std::memcmp(package1 + 0x10, "20210805", 8) == 0) { } else if (std::memcmp(package1 + 0x10, "20210805", 8) == 0) {
return ams::TargetFirmware_13_0_0; return ams::TargetFirmware_13_0_0;
} else if (std::memcmp(package1 + 0x10, "20220105", 8) == 0) {
return ams::TargetFirmware_13_2_1;
} }
break; break;
default: default:

View File

@@ -6,7 +6,7 @@
[subrepo] [subrepo]
remote = https://github.com/Atmosphere-NX/Atmosphere-libs remote = https://github.com/Atmosphere-NX/Atmosphere-libs
branch = master branch = master
commit = c4d0335b79da7207b49abf1988f45b0168b692f0 commit = 0d161b8588aa6482b84f3c44dd001055b01a047f
parent = 96631d8225611b2b490ec1e8b5a84c1b0e53157a parent = 4efa5d7dd0bfbdf89a6261af0aef3878ca784b05
method = merge method = merge
cmdver = 0.4.1 cmdver = 0.4.1

View File

@@ -23,8 +23,8 @@ namespace ams::pkg2 {
constexpr inline int PayloadCount = 3; constexpr inline int PayloadCount = 3;
constexpr inline int MinimumValidDataVersion = 0; /* We allow older package2 to load; this value is currently 0x13 in Nintendo's code. */ constexpr inline int MinimumValidDataVersion = 0; /* We allow older package2 to load; this value is currently 0x14 in Nintendo's code. */
constexpr inline int CurrentBootloaderVersion = 0xF; constexpr inline int CurrentBootloaderVersion = 0x10;
struct Package2Meta { struct Package2Meta {
using Magic = util::FourCC<'P','K','2','1'>; using Magic = util::FourCC<'P','K','2','1'>;

View File

@@ -167,6 +167,7 @@ namespace ams::fuse {
} }
constexpr const TargetFirmware FuseVersionIncrementFirmwares[] = { constexpr const TargetFirmware FuseVersionIncrementFirmwares[] = {
TargetFirmware_13_2_1,
TargetFirmware_12_0_2, TargetFirmware_12_0_2,
TargetFirmware_11_0_0, TargetFirmware_11_0_0,
TargetFirmware_10_0_0, TargetFirmware_10_0_0,

View File

@@ -133,7 +133,7 @@ namespace ams::kern::arch::arm {
PriorityLevel_Scheduler = 2, PriorityLevel_Scheduler = 2,
}; };
private: private:
static inline u32 s_mask[cpu::NumCores]; static constinit inline u32 s_mask[cpu::NumCores];
private: private:
volatile GicDistributor *m_gicd; volatile GicDistributor *m_gicd;
volatile GicCpuInterface *m_gicc; volatile GicCpuInterface *m_gicc;

View File

@@ -44,7 +44,7 @@ namespace ams::kern::arch::arm64::cpu {
class KPerformanceCounterInterruptHandler : public KInterruptHandler { class KPerformanceCounterInterruptHandler : public KInterruptHandler {
private: private:
static inline KLightLock s_lock; static constinit inline KLightLock s_lock;
private: private:
u64 m_counter; u64 m_counter;
s32 m_which; s32 m_which;

View File

@@ -114,6 +114,7 @@ namespace ams::kern::board::nintendo::nx {
ams::svc::DeviceName_Hda, ams::svc::DeviceName_Hda,
ams::svc::DeviceName_Isp2, ams::svc::DeviceName_Isp2,
ams::svc::DeviceName_Sata, ams::svc::DeviceName_Sata,
ams::svc::DeviceName_Vi,
ams::svc::DeviceName_XusbHost, ams::svc::DeviceName_XusbHost,
ams::svc::DeviceName_XusbDev, ams::svc::DeviceName_XusbDev,
ams::svc::DeviceName_Tsec, ams::svc::DeviceName_Tsec,

View File

@@ -277,6 +277,9 @@ namespace ams::kern::svc {
} }
Result WriteDebugProcessMemory(ams::svc::Handle debug_handle, uintptr_t buffer, uintptr_t address, size_t size) { Result WriteDebugProcessMemory(ams::svc::Handle debug_handle, uintptr_t buffer, uintptr_t address, size_t size) {
/* Only allow invoking the svc on development hardware. */
R_UNLESS(KTargetSystem::IsDebugMode(), svc::ResultNotImplemented());
/* Validate address / size. */ /* Validate address / size. */
R_UNLESS(size > 0, svc::ResultInvalidSize()); R_UNLESS(size > 0, svc::ResultInvalidSize());
R_UNLESS((address < address + size), svc::ResultInvalidCurrentMemory()); R_UNLESS((address < address + size), svc::ResultInvalidCurrentMemory());

View File

@@ -68,6 +68,7 @@ namespace ams::hos {
Version_13_0_0 = ::ams::TargetFirmware_13_0_0, Version_13_0_0 = ::ams::TargetFirmware_13_0_0,
Version_13_1_0 = ::ams::TargetFirmware_13_1_0, Version_13_1_0 = ::ams::TargetFirmware_13_1_0,
Version_13_2_0 = ::ams::TargetFirmware_13_2_0, Version_13_2_0 = ::ams::TargetFirmware_13_2_0,
Version_13_2_1 = ::ams::TargetFirmware_13_2_1,
Version_Current = ::ams::TargetFirmware_Current, Version_Current = ::ams::TargetFirmware_Current,

View File

@@ -53,16 +53,32 @@ namespace ams::sf::cmif {
u32 cmd_id; u32 cmd_id;
Result (*handler)(CmifOutHeader **out_header_ptr, ServiceDispatchContext &ctx, const cmif::PointerAndSize &in_raw_data); Result (*handler)(CmifOutHeader **out_header_ptr, ServiceDispatchContext &ctx, const cmif::PointerAndSize &in_raw_data);
constexpr inline bool Matches(u32 cmd_id, hos::Version hosver) const { constexpr inline bool MatchesVersion(hos::Version hosver) const {
const bool min_valid = this->hosver_low == hos::Version_Min; const bool min_valid = this->hosver_low == hos::Version_Min;
const bool max_valid = this->hosver_high == hos::Version_Max; const bool max_valid = this->hosver_high == hos::Version_Max;
return this->cmd_id == cmd_id && (min_valid || this->hosver_low <= hosver) && (max_valid || hosver <= this->hosver_high); return (min_valid || this->hosver_low <= hosver) && (max_valid || hosver <= this->hosver_high);
}
constexpr inline bool Matches(u32 cmd_id, hos::Version hosver) const {
return this->cmd_id == cmd_id && this->MatchesVersion(hosver);
} }
constexpr inline decltype(handler) GetHandler() const { constexpr inline decltype(handler) GetHandler() const {
return this->handler; return this->handler;
} }
constexpr inline bool operator>(const ServiceCommandMeta &rhs) const {
if (this->cmd_id > rhs.cmd_id) {
return true;
} else if (this->cmd_id == rhs.cmd_id && this->hosver_low > rhs.hosver_low) {
return true;
} else if (this->cmd_id == rhs.cmd_id && this->hosver_low == rhs.hosver_low && this->hosver_high == rhs.hosver_high){
return true;
} else {
return false;
}
}
}; };
static_assert(util::is_pod<ServiceCommandMeta>::value && sizeof(ServiceCommandMeta) == 0x18, "sizeof(ServiceCommandMeta)"); static_assert(util::is_pod<ServiceCommandMeta>::value && sizeof(ServiceCommandMeta) == 0x18, "sizeof(ServiceCommandMeta)");

View File

@@ -85,12 +85,37 @@ namespace ams::sf::impl {
constexpr const auto &BaseEntries = ::ams::sf::cmif::ServiceDispatchTraits<BASECLASS>::DispatchTable.GetEntries(); \ constexpr const auto &BaseEntries = ::ams::sf::cmif::ServiceDispatchTraits<BASECLASS>::DispatchTable.GetEntries(); \
constexpr size_t BaseSize = BaseEntries.size(); \ constexpr size_t BaseSize = BaseEntries.size(); \
\ \
std::array<::ams::sf::cmif::ServiceCommandMeta, BaseSize + CurSize> combined_entries{}; \ constexpr size_t CombinedSize = BaseSize + CurSize; \
for (size_t i = 0; i < BaseSize; ++i) { \ \
combined_entries[i] = BaseEntries[i]; \ std::array<size_t, CombinedSize> map{}; \
for (size_t i = 0; i < CombinedSize; ++i) { map[i] = i; } \
\
for (size_t i = 1; i < CombinedSize; ++i) { \
size_t j = i; \
while (j > 0) { \
const auto li = map[j]; \
const auto ri = map[j - 1]; \
\
const auto &lhs = (li < BaseSize) ? BaseEntries[li] : cur_entries[li - BaseSize]; \
const auto &rhs = (ri < BaseSize) ? BaseEntries[ri] : cur_entries[ri - BaseSize]; \
\
if (!(rhs > lhs)) { \
break; \
} \
\
std::swap(map[j], map[j - 1]); \
\
--j; \
} \
} \
\
std::array<::ams::sf::cmif::ServiceCommandMeta, CombinedSize> combined_entries{}; \
for (size_t i = 0; i < CombinedSize; ++i) { \
if (map[i] < BaseSize) { \
combined_entries[i] = BaseEntries[map[i]]; \
} else { \
combined_entries[i] = cur_entries[map[i] - BaseSize]; \
} \ } \
for (size_t i = 0; i < CurSize; ++i) { \
combined_entries[BaseSize + i] = cur_entries[i]; \
} \ } \
\ \
return ::ams::sf::cmif::ServiceDispatchTable { combined_entries }; \ return ::ams::sf::cmif::ServiceDispatchTable { combined_entries }; \

View File

@@ -26,22 +26,9 @@
_CLASSNAME_ (); \ _CLASSNAME_ (); \
public: \ public: \
static _CLASSNAME_ &GetInstance() { \ static _CLASSNAME_ &GetInstance() { \
/* Declare singleton instance variables. */ \ AMS_FUNCTION_LOCAL_STATIC(_CLASSNAME_, s_singleton_instance); \
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. */ \ return s_singleton_instance; \
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_CONSTINIT_SINGLETON_TRAITS(_CLASSNAME_) \ #define AMS_CONSTINIT_SINGLETON_TRAITS(_CLASSNAME_) \
@@ -53,6 +40,6 @@
public: \ public: \
static _CLASSNAME_ &GetInstance() { \ static _CLASSNAME_ &GetInstance() { \
/* Declare singleton instance variables. */ \ /* Declare singleton instance variables. */ \
static constinit _CLASSNAME_ s_singleton_instance; \ AMS_FUNCTION_LOCAL_STATIC_CONSTINIT(_CLASSNAME_, s_singleton_instance); \
return s_singleton_instance; \ return s_singleton_instance; \
} }

View File

@@ -73,18 +73,7 @@ namespace ams::erpt::srv {
} }
bool IsProductionMode() { bool IsProductionMode() {
static constinit bool s_initialized = false; AMS_FUNCTION_LOCAL_STATIC(bool, s_is_prod_mode, IsProductionModeImpl());
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;
}
}
return s_is_prod_mode; return s_is_prod_mode;
} }

View File

@@ -112,13 +112,13 @@ namespace ams::fssystem {
NcaCryptoConfiguration g_nca_crypto_configuration_prod; NcaCryptoConfiguration g_nca_crypto_configuration_prod;
constexpr inline s32 KeySlotCacheEntryCount = 3; constexpr inline s32 KeySlotCacheEntryCount = 3;
KeySlotCache g_key_slot_cache; constinit KeySlotCache g_key_slot_cache;
util::optional<KeySlotCacheEntry> g_key_slot_cache_entry[KeySlotCacheEntryCount]; constinit util::optional<KeySlotCacheEntry> g_key_slot_cache_entry[KeySlotCacheEntryCount];
spl::AccessKey &GetNcaKekAccessKey(s32 key_type) { spl::AccessKey &GetNcaKekAccessKey(s32 key_type) {
static spl::AccessKey s_nca_kek_access_key_array[KeyAreaEncryptionKeyCount] = {}; AMS_FUNCTION_LOCAL_STATIC_CONSTINIT(spl::AccessKey, s_nca_kek_access_key_array[KeyAreaEncryptionKeyCount]);
static spl::AccessKey s_nca_header_kek_access_key = {}; AMS_FUNCTION_LOCAL_STATIC_CONSTINIT(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_invalid_nca_kek_access_key);
if (key_type > static_cast<s32>(KeyType::NcaHeaderKey) || IsInvalidKeyTypeValue(key_type)) { if (key_type > static_cast<s32>(KeyType::NcaHeaderKey) || IsInvalidKeyTypeValue(key_type)) {
return s_invalid_nca_kek_access_key; return s_invalid_nca_kek_access_key;

View File

@@ -26,42 +26,20 @@ namespace ams::gpio::driver::impl {
alignas(os::MemoryPageSize) u8 g_interrupt_thread_stack[InterruptThreadStackSize]; alignas(os::MemoryPageSize) u8 g_interrupt_thread_stack[InterruptThreadStackSize];
gpio::driver::IGpioDriver::List &GetGpioDriverList() { 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; return s_gpio_driver_list;
} }
ddsf::EventHandlerManager &GetInterruptHandlerManager() { ddsf::EventHandlerManager &GetInterruptHandlerManager() {
static constinit util::TypedStorage<ddsf::EventHandlerManager> s_interrupt_handler_manager; AMS_FUNCTION_LOCAL_STATIC(ddsf::EventHandlerManager, s_interrupt_handler_manager);
static constinit bool s_initialized = false;
static constinit os::SdkMutex s_mutex;
if (AMS_UNLIKELY(!s_initialized)) { return s_interrupt_handler_manager;
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);
} }
ddsf::DeviceCodeEntryManager &GetDeviceCodeEntryManager() { ddsf::DeviceCodeEntryManager &GetDeviceCodeEntryManager() {
static constinit util::TypedStorage<ddsf::DeviceCodeEntryManager> s_device_code_entry_manager; AMS_FUNCTION_LOCAL_STATIC(ddsf::DeviceCodeEntryManager, s_device_code_entry_manager, ddsf::GetDeviceCodeEntryHolderMemoryResource());
static constinit bool s_initialized = false;
static constinit os::SdkMutex s_mutex;
if (AMS_UNLIKELY(!s_initialized)) { return s_device_code_entry_manager;
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);
} }
void InterruptThreadFunction(void *arg) { void InterruptThreadFunction(void *arg) {

View File

@@ -95,16 +95,17 @@ namespace ams::i2c::driver::board::nintendo::nx {
} }
} }
constinit util::TypedStorage<impl::I2cBusAccessorManager> g_bus_accessor_manager;
constinit util::TypedStorage<impl::I2cDevicePropertyManager> g_device_manager;
} }
void Initialize() { void Initialize() {
static constinit util::TypedStorage<impl::I2cBusAccessorManager> s_bus_accessor_manager; /* Initialize managers. */
static constinit util::TypedStorage<impl::I2cDevicePropertyManager> s_device_manager; util::ConstructAt(g_bus_accessor_manager, ddsf::GetMemoryResource());
util::ConstructAt(g_device_manager, ddsf::GetMemoryResource());
util::ConstructAt(s_bus_accessor_manager, ddsf::GetMemoryResource()); return Initialize(util::GetReference(g_bus_accessor_manager), util::GetReference(g_device_manager));
util::ConstructAt(s_device_manager, ddsf::GetMemoryResource());
return Initialize(util::GetReference(s_bus_accessor_manager), util::GetReference(s_device_manager));
} }
} }

View File

@@ -24,25 +24,14 @@ namespace ams::i2c::driver::impl {
constinit int g_init_count = 0; constinit int g_init_count = 0;
i2c::driver::II2cDriver::List &GetI2cDriverList() { 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; return s_driver_list;
} }
ddsf::DeviceCodeEntryManager &GetDeviceCodeEntryManager() { ddsf::DeviceCodeEntryManager &GetDeviceCodeEntryManager() {
static constinit util::TypedStorage<ddsf::DeviceCodeEntryManager> s_device_code_entry_manager; AMS_FUNCTION_LOCAL_STATIC(ddsf::DeviceCodeEntryManager, s_device_code_entry_manager, ddsf::GetDeviceCodeEntryHolderMemoryResource());
static constinit bool s_initialized = false;
static constinit os::SdkMutex s_mutex;
if (AMS_UNLIKELY(!s_initialized)) { return s_device_code_entry_manager;
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);
} }
} }

View File

@@ -34,7 +34,8 @@ namespace ams::lm::srv {
} }
EventLogTransmitter &EventLogTransmitter::GetDefaultInstance() { 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; return s_default_event_log_transmitter;
} }

View File

@@ -63,8 +63,10 @@ namespace ams::lm::srv {
} }
bool DefaultFlushFunction(const u8 *data, size_t size) { 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. */ /* Update clock. */
static constinit bool s_is_user_system_clock_updated = false;
if (!s_is_user_system_clock_updated) { if (!s_is_user_system_clock_updated) {
UpdateUserSystemClock(data, size); UpdateUserSystemClock(data, size);
s_is_user_system_clock_updated = true; s_is_user_system_clock_updated = true;
@@ -84,8 +86,8 @@ namespace ams::lm::srv {
} }
LogBuffer &LogBuffer::GetDefaultInstance() { LogBuffer &LogBuffer::GetDefaultInstance() {
static constinit u8 s_default_buffers[128_KB * 2]; AMS_FUNCTION_LOCAL_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(LogBuffer, s_default_log_buffer, s_default_buffers, sizeof(s_default_buffers), DefaultFlushFunction);
return s_default_log_buffer; return s_default_log_buffer;
} }

View File

@@ -19,8 +19,9 @@
namespace ams::lm::srv { namespace ams::lm::srv {
CustomSinkBuffer &LogGetterImpl::GetBuffer() { CustomSinkBuffer &LogGetterImpl::GetBuffer() {
static constinit u8 s_buffer[32_KB]; AMS_FUNCTION_LOCAL_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(CustomSinkBuffer, s_custom_sink_buffer, s_buffer, sizeof(s_buffer), FlushFunction);
return s_custom_sink_buffer; return s_custom_sink_buffer;
} }

View File

@@ -188,7 +188,7 @@ namespace ams::lm::srv {
size_t carry_size; size_t carry_size;
bool ends_with_text_log; 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. */ /* Get the packet header. */
auto *header = static_cast<const impl::LogPacketHeader *>(buffer); auto *header = static_cast<const impl::LogPacketHeader *>(buffer);

View File

@@ -635,7 +635,7 @@ namespace ams::ncm {
for (s32 i = 0; i < count; i++) { for (s32 i = 0; i < count; i++) {
R_UNLESS(!this->IsCancelRequested(), ncm::ResultCreatePlaceHolderCancelled()); 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); std::scoped_lock lk(s_placeholder_mutex);
InstallContentMeta content_meta; InstallContentMeta content_meta;

View File

@@ -44,7 +44,8 @@ namespace ams::ncm {
} }
HeapState &GetHeapState() { HeapState &GetHeapState() {
static HeapState s_heap_state = {}; AMS_FUNCTION_LOCAL_STATIC_CONSTINIT(HeapState, s_heap_state);
return s_heap_state; return s_heap_state;
} }

View File

@@ -20,60 +20,44 @@ namespace ams::powctl::impl {
namespace { namespace {
os::ThreadType g_interrupt_thread; constinit os::ThreadType g_interrupt_thread;
constexpr inline size_t InterruptThreadStackSize = os::MemoryPageSize; constexpr inline size_t InterruptThreadStackSize = os::MemoryPageSize;
alignas(os::MemoryPageSize) u8 g_interrupt_thread_stack[InterruptThreadStackSize]; 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() { IPowerControlDriver::List &GetDriverList() {
static constinit IPowerControlDriver::List s_driver_list; AMS_FUNCTION_LOCAL_STATIC_CONSTINIT(IPowerControlDriver::List, s_driver_list);
return s_driver_list; return s_driver_list;
} }
ddsf::EventHandlerManager &GetInterruptHandlerManager() { ddsf::EventHandlerManager &GetInterruptHandlerManager() {
static constinit util::TypedStorage<ddsf::EventHandlerManager> s_interrupt_handler_manager; AMS_FUNCTION_LOCAL_STATIC(ddsf::EventHandlerManager, s_interrupt_handler_manager);
static constinit bool s_initialized = false;
static constinit os::SdkMutex s_mutex;
if (AMS_UNLIKELY(!s_initialized)) { return s_interrupt_handler_manager;
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);
} }
ddsf::DeviceCodeEntryManager &GetDeviceCodeEntryManager() { ddsf::DeviceCodeEntryManager &GetDeviceCodeEntryManager() {
static constinit util::TypedStorage<ddsf::DeviceCodeEntryManager> s_device_code_entry_manager; class DeviceCodeEntryManagerWithUnitHeap {
static constinit bool s_initialized = false; private:
static constinit os::SdkMutex s_mutex; u8 m_heap_memory[2_KB];
sf::UnitHeapMemoryResource m_memory_resource;
util::TypedStorage<ddsf::DeviceCodeEntryManager> 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)) { /* Construct the entry manager. */
std::scoped_lock lk(s_mutex); 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);
/* 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); ALWAYS_INLINE operator ddsf::DeviceCodeEntryManager &() {
return util::GetReference(m_manager);
}
};
AMS_FUNCTION_LOCAL_STATIC(DeviceCodeEntryManagerWithUnitHeap, s_device_code_entry_manager_holder);
return s_device_code_entry_manager_holder;
} }
void InterruptThreadFunction(void *arg) { void InterruptThreadFunction(void *arg) {

View File

@@ -24,25 +24,14 @@ namespace ams::pwm::driver::impl {
constinit int g_init_count = 0; constinit int g_init_count = 0;
pwm::driver::IPwmDriver::List &GetPwmDriverList() { 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; return s_driver_list;
} }
ddsf::DeviceCodeEntryManager &GetDeviceCodeEntryManager() { ddsf::DeviceCodeEntryManager &GetDeviceCodeEntryManager() {
static constinit util::TypedStorage<ddsf::DeviceCodeEntryManager> s_device_code_entry_manager; AMS_FUNCTION_LOCAL_STATIC(ddsf::DeviceCodeEntryManager, s_device_code_entry_manager, ddsf::GetDeviceCodeEntryHolderMemoryResource());
static constinit bool s_initialized = false;
static constinit os::SdkMutex s_mutex;
if (AMS_UNLIKELY(!s_initialized)) { return s_device_code_entry_manager;
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);
} }
} }

View File

@@ -289,14 +289,8 @@ namespace ams::settings::impl {
} }
lmem::HeapHandle &GetHeapHandle() { lmem::HeapHandle &GetHeapHandle() {
static constinit bool s_is_initialized = false; AMS_FUNCTION_LOCAL_STATIC_CONSTINIT(u8, s_heap_memory[HeapMemorySize]);
static constinit lmem::HeapHandle s_heap_handle; AMS_FUNCTION_LOCAL_STATIC(lmem::HeapHandle, s_heap_handle, lmem::CreateExpHeap(s_heap_memory, sizeof(s_heap_memory), lmem::CreateOption_ThreadSafe));
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;
}
return s_heap_handle; return s_heap_handle;
} }
@@ -314,24 +308,15 @@ namespace ams::settings::impl {
AMS_ASSERT(out != nullptr); AMS_ASSERT(out != nullptr);
/* Declare static instance variables. */ /* Declare static instance variables. */
static constinit util::TypedStorage<Map> s_storage = {}; AMS_FUNCTION_LOCAL_STATIC(Map, s_map);
static constinit bool s_is_initialized = false; AMS_FUNCTION_LOCAL_STATIC_CONSTINIT(bool, s_is_map_loaded, false);
static constinit bool s_is_loaded = false;
/* Get pointer to the map. */ /* Get pointer to the map. */
Map *map = util::GetPointer(s_storage); Map * const map = std::addressof(s_map);
/* 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;
}
/* TODO: Mutex? */
/* Load the map, if we haven't already. */ /* 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. */ /* Attempt to load the map, allowing for failure if acceptable. */
const auto result = LoadKeyValueStoreMap(map); const auto result = LoadKeyValueStoreMap(map);
@@ -340,7 +325,7 @@ namespace ams::settings::impl {
} }
/* Note that the map is loaded. */ /* Note that the map is loaded. */
s_is_loaded = true; s_is_map_loaded = true;
} }
/* Set the output pointer. */ /* Set the output pointer. */
@@ -425,26 +410,13 @@ namespace ams::settings::impl {
AMS_ASSERT(out_data != nullptr); AMS_ASSERT(out_data != nullptr);
/* Declare static instance variables. */ /* Declare static instance variables. */
static constinit util::TypedStorage<SystemData> s_storage = {}; AMS_FUNCTION_LOCAL_STATIC(SystemData, s_data, id, GetSystemDataMountName<T>());
static constinit bool s_initialized = false; AMS_FUNCTION_LOCAL_STATIC_CONSTINIT(bool, s_mounted, false);
static constinit bool s_mounted = false;
/* Get pointer to the system data. */ /* Get pointer to the system data. */
SystemData *data = util::GetPointer(s_storage); SystemData *data = std::addressof(s_data);
/* 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<T>());
/* Note that we constructed. */
s_initialized = true;
}
/* TODO: Mutex? */
/* Mount the system data, if we haven't already. */ /* Mount the system data, if we haven't already. */
if (AMS_UNLIKELY(!s_mounted)) { if (AMS_UNLIKELY(!s_mounted)) {
/* Mount the system data. */ /* Mount the system data. */
@@ -464,28 +436,11 @@ namespace ams::settings::impl {
AMS_ASSERT(out_data != nullptr); AMS_ASSERT(out_data != nullptr);
/* Declare static instance variables. */ /* Declare static instance variables. */
static constinit util::TypedStorage<SystemSaveData> s_storage = {}; AMS_FUNCTION_LOCAL_STATIC(SystemSaveData, s_data, SystemSaveDataId, SystemSaveDataSize, SystemSaveDataJournalSize, SystemSaveDataFlags, SystemSaveDataMountName);
static constinit bool s_initialized = false; AMS_FUNCTION_LOCAL_STATIC_CONSTINIT(bool, s_mounted, false);
static constinit bool s_mounted = false;
/* Get pointer to the system data. */ /* Get pointer to the system save data. */
SystemSaveData *data = util::GetPointer(s_storage); SystemSaveData *data = std::addressof(s_data);
/* 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;
}
/* Mount the system data, if we haven't already. */ /* Mount the system data, if we haven't already. */
if (AMS_UNLIKELY(!s_mounted)) { if (AMS_UNLIKELY(!s_mounted)) {

View File

@@ -56,27 +56,33 @@ namespace ams::settings::impl {
} }
SplConfig GetSplConfig() { SplConfig GetSplConfig() {
static constinit bool s_is_initialized = false; class SplConfigHolder {
static constinit SplConfig s_config; NON_COPYABLE(SplConfigHolder);
NON_MOVEABLE(SplConfigHolder);
if (!s_is_initialized) { private:
SplConfig m_config;
public:
SplConfigHolder() {
/* Initialize spl. */ /* Initialize spl. */
spl::Initialize(); spl::Initialize();
ON_SCOPE_EXIT { spl::Finalize(); }; ON_SCOPE_EXIT { spl::Finalize(); };
/* Create the config. */ /* Create the config. */
s_config = { m_config = {
.is_development = spl::IsDevelopment(), .is_development = spl::IsDevelopment(),
.hardware_type = ConvertToSplHardwareType(spl::GetHardwareType()), .hardware_type = ConvertToSplHardwareType(spl::GetHardwareType()),
.is_quest = IsSplRetailInteractiveDisplayStateEnabled(spl::GetRetailInteractiveDisplayState()), .is_quest = IsSplRetailInteractiveDisplayStateEnabled(spl::GetRetailInteractiveDisplayState()),
.device_id_low = spl::GetDeviceIdLow(), .device_id_low = spl::GetDeviceIdLow(),
}; };
/* Mark as initialized. */
s_is_initialized = true;
} }
return s_config; ALWAYS_INLINE operator SplConfig() {
return m_config;
}
};
AMS_FUNCTION_LOCAL_STATIC(SplConfigHolder, s_config_holder);
return s_config_holder;
} }
} }

View File

@@ -25,27 +25,9 @@ namespace ams::settings::impl {
StaticObject(); StaticObject();
public: public:
static T &Get() { static T &Get() {
/* Declare static instance variables. */ AMS_FUNCTION_LOCAL_STATIC(T, s_object);
static constinit util::TypedStorage<T> s_storage = {};
static constinit bool s_initialized = false;
static constinit os::SdkMutex s_mutex;
/* If we haven't already done so, construct the instance. */ return s_object;
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);
} }
}; };

View File

@@ -30,6 +30,11 @@ namespace ams::settings::impl {
public: public:
SystemData() : m_system_data_id(), m_mount_name(), m_file_path() { /* ... */ } 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 SetSystemDataId(ncm::SystemDataId id);
void SetMountName(const char *name); void SetMountName(const char *name);
Result Mount(); Result Mount();

View File

@@ -30,6 +30,14 @@ namespace ams::settings::impl {
public: 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() : 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 SetSystemSaveDataId(u64 id);
void SetTotalSize(s64 size); void SetTotalSize(s64 size);
void SetJournalSize(s64 size); void SetJournalSize(s64 size);

View File

@@ -17,6 +17,65 @@
namespace ams::sf::cmif { namespace ams::sf::cmif {
namespace {
ALWAYS_INLINE decltype(ServiceCommandMeta::handler) FindCommandHandlerByBinarySearch(const ServiceCommandMeta *entries, const size_t entry_count, const u32 cmd_id, const hos::Version hos_version) {
/* Binary search for the handler. */
ssize_t lo = 0;
ssize_t hi = entry_count - 1;
while (lo <= hi) {
const size_t mid = (lo + hi) / 2;
if (entries[mid].cmd_id < cmd_id) {
lo = mid + 1;
} else if (entries[mid].cmd_id > cmd_id) {
hi = mid - 1;
} else {
/* Find start. */
size_t start = mid;
while (start > 0 && entries[start - 1].cmd_id == cmd_id) {
--start;
}
/* Find end. */
size_t end = mid + 1;
while (end < entry_count && entries[end].cmd_id == cmd_id) {
++end;
}
for (size_t idx = start; idx < end; ++idx) {
if (entries[idx].MatchesVersion(hos_version)) {
return entries[idx].GetHandler();
}
}
break;
}
}
return nullptr;
}
ALWAYS_INLINE decltype(ServiceCommandMeta::handler) FindCommandHandlerByLinearSearch(const ServiceCommandMeta *entries, const size_t entry_count, const u32 cmd_id, const hos::Version hos_version) {
for (size_t i = 0; i < entry_count; ++i) {
if (entries[i].Matches(cmd_id, hos_version)) {
return entries[i].GetHandler();
break;
}
}
return nullptr;
}
ALWAYS_INLINE decltype(ServiceCommandMeta::handler) FindCommandHandler(const ServiceCommandMeta *entries, const size_t entry_count, const u32 cmd_id, const hos::Version hos_version) {
if (entry_count >= 8) {
return FindCommandHandlerByBinarySearch(entries, entry_count, cmd_id, hos_version);
} else {
return FindCommandHandlerByLinearSearch(entries, entry_count, cmd_id, hos_version);
}
}
}
Result impl::ServiceDispatchTableBase::ProcessMessageImpl(ServiceDispatchContext &ctx, const cmif::PointerAndSize &in_raw_data, const ServiceCommandMeta *entries, const size_t entry_count) const { Result impl::ServiceDispatchTableBase::ProcessMessageImpl(ServiceDispatchContext &ctx, const cmif::PointerAndSize &in_raw_data, const ServiceCommandMeta *entries, const size_t entry_count) const {
/* Get versioning info. */ /* Get versioning info. */
const auto hos_version = hos::GetVersion(); const auto hos_version = hos::GetVersion();
@@ -30,13 +89,7 @@ namespace ams::sf::cmif {
const u32 cmd_id = in_header->command_id; const u32 cmd_id = in_header->command_id;
/* Find a handler. */ /* Find a handler. */
decltype(ServiceCommandMeta::handler) cmd_handler = nullptr; const auto cmd_handler = FindCommandHandler(entries, entry_count, cmd_id, hos_version);
for (size_t i = 0; i < entry_count; i++) {
if (entries[i].Matches(cmd_id, hos_version)) {
cmd_handler = entries[i].GetHandler();
break;
}
}
R_UNLESS(cmd_handler != nullptr, sf::cmif::ResultUnknownCommandId()); R_UNLESS(cmd_handler != nullptr, sf::cmif::ResultUnknownCommandId());
/* Invoke handler. */ /* Invoke handler. */
@@ -73,13 +126,7 @@ namespace ams::sf::cmif {
const u32 cmd_id = in_header->command_id; const u32 cmd_id = in_header->command_id;
/* Find a handler. */ /* Find a handler. */
decltype(ServiceCommandMeta::handler) cmd_handler = nullptr; const auto cmd_handler = FindCommandHandler(entries, entry_count, cmd_id, hos_version);
for (size_t i = 0; i < entry_count; i++) {
if (entries[i].Matches(cmd_id, hos_version)) {
cmd_handler = entries[i].GetHandler();
break;
}
}
/* If we didn't find a handler, forward the request. */ /* If we didn't find a handler, forward the request. */
if (cmd_handler == nullptr) { if (cmd_handler == nullptr) {

View File

@@ -17,10 +17,10 @@
#define ATMOSPHERE_RELEASE_VERSION_MAJOR 1 #define ATMOSPHERE_RELEASE_VERSION_MAJOR 1
#define ATMOSPHERE_RELEASE_VERSION_MINOR 2 #define ATMOSPHERE_RELEASE_VERSION_MINOR 2
#define ATMOSPHERE_RELEASE_VERSION_MICRO 5 #define ATMOSPHERE_RELEASE_VERSION_MICRO 6
#define ATMOSPHERE_RELEASE_VERSION ATMOSPHERE_RELEASE_VERSION_MAJOR, ATMOSPHERE_RELEASE_VERSION_MINOR, ATMOSPHERE_RELEASE_VERSION_MICRO #define ATMOSPHERE_RELEASE_VERSION ATMOSPHERE_RELEASE_VERSION_MAJOR, ATMOSPHERE_RELEASE_VERSION_MINOR, ATMOSPHERE_RELEASE_VERSION_MICRO
#define ATMOSPHERE_SUPPORTED_HOS_VERSION_MAJOR 13 #define ATMOSPHERE_SUPPORTED_HOS_VERSION_MAJOR 13
#define ATMOSPHERE_SUPPORTED_HOS_VERSION_MINOR 2 #define ATMOSPHERE_SUPPORTED_HOS_VERSION_MINOR 2
#define ATMOSPHERE_SUPPORTED_HOS_VERSION_MICRO 0 #define ATMOSPHERE_SUPPORTED_HOS_VERSION_MICRO 1

View File

@@ -66,8 +66,9 @@
#define ATMOSPHERE_TARGET_FIRMWARE_13_0_0 ATMOSPHERE_TARGET_FIRMWARE(13, 0, 0) #define ATMOSPHERE_TARGET_FIRMWARE_13_0_0 ATMOSPHERE_TARGET_FIRMWARE(13, 0, 0)
#define ATMOSPHERE_TARGET_FIRMWARE_13_1_0 ATMOSPHERE_TARGET_FIRMWARE(13, 1, 0) #define ATMOSPHERE_TARGET_FIRMWARE_13_1_0 ATMOSPHERE_TARGET_FIRMWARE(13, 1, 0)
#define ATMOSPHERE_TARGET_FIRMWARE_13_2_0 ATMOSPHERE_TARGET_FIRMWARE(13, 2, 0) #define ATMOSPHERE_TARGET_FIRMWARE_13_2_0 ATMOSPHERE_TARGET_FIRMWARE(13, 2, 0)
#define ATMOSPHERE_TARGET_FIRMWARE_13_2_1 ATMOSPHERE_TARGET_FIRMWARE(13, 2, 1)
#define ATMOSPHERE_TARGET_FIRMWARE_CURRENT ATMOSPHERE_TARGET_FIRMWARE_13_2_0 #define ATMOSPHERE_TARGET_FIRMWARE_CURRENT ATMOSPHERE_TARGET_FIRMWARE_13_2_1
#define ATMOSPHERE_TARGET_FIRMWARE_MIN ATMOSPHERE_TARGET_FIRMWARE(0, 0, 0) #define ATMOSPHERE_TARGET_FIRMWARE_MIN ATMOSPHERE_TARGET_FIRMWARE(0, 0, 0)
#define ATMOSPHERE_TARGET_FIRMWARE_MAX ATMOSPHERE_TARGET_FIRMWARE_CURRENT #define ATMOSPHERE_TARGET_FIRMWARE_MAX ATMOSPHERE_TARGET_FIRMWARE_CURRENT
@@ -126,6 +127,7 @@ namespace ams {
TargetFirmware_13_0_0 = ATMOSPHERE_TARGET_FIRMWARE_13_0_0, TargetFirmware_13_0_0 = ATMOSPHERE_TARGET_FIRMWARE_13_0_0,
TargetFirmware_13_1_0 = ATMOSPHERE_TARGET_FIRMWARE_13_1_0, TargetFirmware_13_1_0 = ATMOSPHERE_TARGET_FIRMWARE_13_1_0,
TargetFirmware_13_2_0 = ATMOSPHERE_TARGET_FIRMWARE_13_2_0, TargetFirmware_13_2_0 = ATMOSPHERE_TARGET_FIRMWARE_13_2_0,
TargetFirmware_13_2_1 = ATMOSPHERE_TARGET_FIRMWARE_13_2_1,
TargetFirmware_Current = ATMOSPHERE_TARGET_FIRMWARE_CURRENT, TargetFirmware_Current = ATMOSPHERE_TARGET_FIRMWARE_CURRENT,

View File

@@ -55,6 +55,8 @@
#include <vapours/util/util_atomic.hpp> #include <vapours/util/util_atomic.hpp>
#include <vapours/util/util_function_local_static.hpp>
#ifdef ATMOSPHERE_IS_STRATOSPHERE #ifdef ATMOSPHERE_IS_STRATOSPHERE
#include <vapours/util/util_mutex_utils.hpp> #include <vapours/util/util_mutex_utils.hpp>
#endif #endif

View File

@@ -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 <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <vapours/common.hpp>
#include <vapours/assert.hpp>
#include <vapours/util/util_typed_storage.hpp>
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
}

View File

@@ -45,9 +45,18 @@ namespace ams::util {
return *GetPointer(ts); return *GetPointer(ts);
} }
namespace impl {
template<typename T>
static ALWAYS_INLINE T *GetPointerForConstructAt(TypedStorage<T> &ts) {
return reinterpret_cast<T *>(std::addressof(ts._storage));
}
}
template<typename T, typename... Args> template<typename T, typename... Args>
static ALWAYS_INLINE T *ConstructAt(TypedStorage<T> &ts, Args &&... args) { static ALWAYS_INLINE T *ConstructAt(TypedStorage<T> &ts, Args &&... args) {
return std::construct_at(reinterpret_cast<T *>(std::addressof(ts._storage)), std::forward<Args>(args)...); return std::construct_at(impl::GetPointerForConstructAt(ts), std::forward<Args>(args)...);
} }
template<typename T> template<typename T>