kern: avoid constexpr init for many objects (avoids unnecessary memory clear) (#1668)

This commit is contained in:
SciresM 2021-10-23 15:25:20 -07:00 committed by GitHub
parent 20716cb3de
commit 36e4914be8
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
77 changed files with 489 additions and 339 deletions

View file

@ -168,7 +168,8 @@ namespace ams::kern::arch::arm64 {
return entry;
}
public:
constexpr KPageTable() : KPageTableBase(), m_manager(), m_ttbr(), m_asid() { /* ... */ }
constexpr explicit KPageTable(util::ConstantInitializeTag) : KPageTableBase(util::ConstantInitialize), m_manager(), m_ttbr(), m_asid() { /* ... */ }
explicit KPageTable() { /* ... */ }
static NOINLINE void Initialize(s32 core_id);

View file

@ -105,7 +105,9 @@ namespace ams::kern::arch::arm64 {
return GetL3EntryFromTable(KMemoryLayout::GetLinearVirtualAddress(entry->GetTable()), address);
}
public:
constexpr KPageTableImpl() : m_table(), m_is_kernel(), m_num_entries() { /* ... */ }
constexpr explicit KPageTableImpl(util::ConstantInitializeTag) : m_table(), m_is_kernel(), m_num_entries() { /* ... */ }
explicit KPageTableImpl() { /* ... */ }
NOINLINE void InitializeForKernel(void *tb, KVirtualAddress start, KVirtualAddress end);
NOINLINE void InitializeForProcess(void *tb, KVirtualAddress start, KVirtualAddress end);

View file

@ -23,8 +23,6 @@ namespace ams::kern::arch::arm64 {
private:
KPageTable m_page_table;
public:
constexpr KProcessPageTable() : m_page_table() { /* ... */ }
void Activate(u64 id) {
/* Activate the page table with the specified contextidr. */
m_page_table.Activate(id);

View file

@ -25,7 +25,7 @@ namespace ams::kern::arch::arm64 {
KPageTable m_page_table;
u64 m_ttbr0_identity[cpu::NumCores];
public:
constexpr KSupervisorPageTable() : m_page_table(), m_ttbr0_identity() { /* ... */ }
constexpr KSupervisorPageTable() : m_page_table(util::ConstantInitialize), m_ttbr0_identity() { /* ... */ }
NOINLINE void Initialize(s32 core_id);

View file

@ -57,7 +57,8 @@ namespace ams::kern::arch::arm64 {
static void RestoreFpuRegisters64(const KThreadContext &);
static void RestoreFpuRegisters32(const KThreadContext &);
public:
constexpr explicit KThreadContext() : m_callee_saved(), m_lr(), m_sp(), m_cpacr(), m_fpcr(), m_fpsr(), m_fpu_registers(), m_locked() { /* ... */ }
constexpr explicit KThreadContext(util::ConstantInitializeTag) : m_callee_saved(), m_lr(), m_sp(), m_cpacr(), m_fpcr(), m_fpsr(), m_fpu_registers(), m_locked() { /* ... */ }
explicit KThreadContext() { /* ... */ }
Result Initialize(KVirtualAddress u_pc, KVirtualAddress k_sp, KVirtualAddress u_sp, uintptr_t arg, bool is_user, bool is_64_bit, bool is_main);
Result Finalize();

View file

@ -61,7 +61,12 @@ namespace ams::kern::board::nintendo::nx {
return KPageTable::GetPageTablePhysicalAddress(addr);
}
public:
constexpr KDevicePageTable() : m_tables(), m_table_asids(), m_attached_device(), m_attached_value(), m_detached_value(), m_hs_attached_value(), m_hs_detached_value() { /* ... */ }
constexpr KDevicePageTable()
: m_tables{Null<KVirtualAddress>, Null<KVirtualAddress>, Null<KVirtualAddress>, Null<KVirtualAddress>},
m_table_asids(), m_attached_device(), m_attached_value(), m_detached_value(), m_hs_attached_value(), m_hs_detached_value()
{
/* ... */
}
Result Initialize(u64 space_address, u64 space_size);
void Finalize();

View file

@ -25,7 +25,7 @@ namespace ams::kern {
private:
ThreadTree m_tree;
public:
constexpr KAddressArbiter() : m_tree() { /* ... */ }
constexpr KAddressArbiter() = default;
Result SignalToAddress(uintptr_t addr, ams::svc::SignalType type, s32 value, s32 count) {
switch (type) {

View file

@ -121,7 +121,7 @@ namespace ams::kern {
public:
static KAutoObject *Create(KAutoObject *ptr);
public:
constexpr ALWAYS_INLINE explicit KAutoObject() : m_next_closed_object(nullptr), m_ref_count(0)
constexpr ALWAYS_INLINE explicit KAutoObject(util::ConstantInitializeTag) : m_next_closed_object(nullptr), m_ref_count(0)
#if defined(MESOSPHERE_ENABLE_DEVIRTUALIZED_DYNAMIC_CAST)
, m_class_token(0)
#endif
@ -129,6 +129,8 @@ namespace ams::kern {
MESOSPHERE_ASSERT_THIS();
}
ALWAYS_INLINE explicit KAutoObject() : m_ref_count(0) { MESOSPHERE_ASSERT_THIS(); }
/* Destroy is responsible for destroying the auto object's resources when ref_count hits zero. */
virtual void Destroy() { MESOSPHERE_ASSERT_THIS(); }
@ -208,9 +210,11 @@ namespace ams::kern {
class KAutoObjectWithListBase : public KAutoObject {
private:
void *m_alignment_forcer_unused[0]{};
void *m_alignment_forcer_unused[0];
public:
constexpr ALWAYS_INLINE KAutoObjectWithListBase() = default;
constexpr ALWAYS_INLINE explicit KAutoObjectWithListBase(util::ConstantInitializeTag) : KAutoObject(util::ConstantInitialize), m_alignment_forcer_unused{} { /* ... */ }
ALWAYS_INLINE explicit KAutoObjectWithListBase() { /* ... */ }
};
class KAutoObjectWithList : public KAutoObjectWithListBase {
@ -219,7 +223,8 @@ namespace ams::kern {
private:
util::IntrusiveRedBlackTreeNode m_list_node;
public:
constexpr ALWAYS_INLINE KAutoObjectWithList() : m_list_node() { /* ... */ }
constexpr ALWAYS_INLINE KAutoObjectWithList(util::ConstantInitializeTag) : KAutoObjectWithListBase(util::ConstantInitialize), m_list_node(util::ConstantInitialize) { /* ... */ }
ALWAYS_INLINE explicit KAutoObjectWithList() { /* ... */ }
static ALWAYS_INLINE int Compare(const KAutoObjectWithList &lhs, const KAutoObjectWithList &rhs) {
const u64 lid = lhs.GetId();
@ -252,7 +257,6 @@ namespace ams::kern {
std::swap(m_obj, rhs.m_obj);
}
public:
constexpr ALWAYS_INLINE KScopedAutoObject() : m_obj(nullptr) { /* ... */ }
constexpr ALWAYS_INLINE KScopedAutoObject(T *o) : m_obj(o) {
if (m_obj != nullptr) {
m_obj->Open();

View file

@ -171,14 +171,14 @@ namespace ams::kern {
CapabilityFlag<CapabilityType::HandleTable> |
CapabilityFlag<CapabilityType::DebugFlags>;
private:
svc::SvcAccessFlagSet m_svc_access_flags{};
InterruptFlagSet m_irq_access_flags{};
u64 m_core_mask{};
u64 m_priority_mask{};
util::BitPack32 m_debug_capabilities{0};
s32 m_handle_table_size{};
util::BitPack32 m_intended_kernel_version{0};
u32 m_program_type{};
svc::SvcAccessFlagSet m_svc_access_flags;
InterruptFlagSet m_irq_access_flags;
u64 m_core_mask;
u64 m_priority_mask;
util::BitPack32 m_debug_capabilities;
s32 m_handle_table_size;
util::BitPack32 m_intended_kernel_version;
u32 m_program_type;
private:
constexpr bool SetSvcAllowed(u32 id) {
if (AMS_LIKELY(id < m_svc_access_flags.GetCount())) {
@ -213,7 +213,8 @@ namespace ams::kern {
Result SetCapabilities(const u32 *caps, s32 num_caps, KProcessPageTable *page_table);
Result SetCapabilities(svc::KUserPointer<const u32 *> user_caps, s32 num_caps, KProcessPageTable *page_table);
public:
constexpr KCapabilities() = default;
constexpr explicit KCapabilities(util::ConstantInitializeTag) : m_svc_access_flags{}, m_irq_access_flags{}, m_core_mask{}, m_priority_mask{}, m_debug_capabilities{0}, m_handle_table_size{}, m_intended_kernel_version{}, m_program_type{} { /* ... */ }
KCapabilities() { /* ... */ }
Result Initialize(const u32 *caps, s32 num_caps, KProcessPageTable *page_table);
Result Initialize(svc::KUserPointer<const u32 *> user_caps, s32 num_caps, KProcessPageTable *page_table);

View file

@ -33,7 +33,9 @@ namespace ams::kern {
s32 m_max_sessions;
KPort *m_parent;
public:
constexpr KClientPort() : m_num_sessions(0), m_peak_sessions(0), m_max_sessions(), m_parent() { /* ... */ }
constexpr explicit KClientPort(util::ConstantInitializeTag) : KSynchronizationObject(util::ConstantInitialize), m_num_sessions(0), m_peak_sessions(0), m_max_sessions(), m_parent() { /* ... */ }
explicit KClientPort() { /* ... */ }
void Initialize(KPort *parent, s32 max_sessions);
void OnSessionFinalized();

View file

@ -27,7 +27,8 @@ namespace ams::kern {
private:
KSession *m_parent;
public:
constexpr KClientSession() : m_parent() { /* ... */ }
constexpr explicit KClientSession(util::ConstantInitializeTag) : KAutoObject(util::ConstantInitialize), m_parent() { /* ... */ }
explicit KClientSession() { /* ... */ }
void Initialize(KSession *parent) {
/* Set member variables. */

View file

@ -26,7 +26,7 @@ namespace ams::kern {
private:
ThreadTree m_tree;
public:
constexpr KConditionVariable() : m_tree() { /* ... */ }
constexpr KConditionVariable() = default;
/* Arbitration. */
static Result SignalToAddress(KProcessAddress addr);

View file

@ -33,7 +33,7 @@ namespace ams::kern {
KProcess::State m_old_process_state;
bool m_is_attached;
public:
explicit KDebugBase() : m_event_info_list(), m_process_holder(), m_lock() { /* ... */ }
explicit KDebugBase() { /* ... */ }
protected:
bool Is64Bit() const;
public:

View file

@ -30,7 +30,7 @@ namespace ams::kern {
u64 m_space_size;
bool m_is_initialized;
public:
constexpr KDeviceAddressSpace() : m_lock(), m_table(), m_space_address(), m_space_size(), m_is_initialized() { /* ... */ }
explicit KDeviceAddressSpace() : m_is_initialized(false) { /* ... */ }
Result Initialize(u64 address, u64 size);
virtual void Finalize() override;

View file

@ -40,7 +40,7 @@ namespace ams::kern {
KVirtualAddress m_address;
size_t m_size;
public:
KDynamicPageManager() : m_lock(), m_page_bitmap(), m_used(), m_peak(), m_count(), m_address(), m_size() { /* ... */ }
KDynamicPageManager() : m_lock(), m_page_bitmap(), m_used(), m_peak(), m_count(), m_address(Null<KVirtualAddress>), m_size() { /* ... */ }
Result Initialize(KVirtualAddress memory, size_t sz) {
/* We need to have positive size. */

View file

@ -32,7 +32,7 @@ namespace ams::kern {
util::Atomic<size_t> m_used{0};
util::Atomic<size_t> m_peak{0};
util::Atomic<size_t> m_count{0};
KVirtualAddress m_address{};
KVirtualAddress m_address{Null<KVirtualAddress>};
size_t m_size{};
public:
constexpr KDynamicSlabHeap() = default;

View file

@ -29,12 +29,15 @@ namespace ams::kern {
bool m_initialized;
bool m_readable_event_destroyed;
public:
constexpr KEvent()
: m_readable_event(), m_owner(), m_initialized(), m_readable_event_destroyed()
constexpr explicit KEvent(util::ConstantInitializeTag)
: KAutoObjectWithSlabHeapAndContainer<KEvent, KAutoObjectWithList, true>(util::ConstantInitialize),
m_readable_event(util::ConstantInitialize), m_owner(), m_initialized(), m_readable_event_destroyed()
{
/* ... */
}
explicit KEvent() : m_readable_event(), m_owner(), m_initialized(), m_readable_event_destroyed() { /* ... */ }
void Initialize();
virtual void Finalize() override;

View file

@ -63,16 +63,16 @@ namespace ams::kern {
private:
EntryInfo m_entry_infos[MaxTableSize];
KAutoObject *m_objects[MaxTableSize];
mutable KSpinLock m_lock;
s32 m_free_head_index;
u16 m_table_size;
u16 m_max_count;
u16 m_next_linear_id;
u16 m_count;
mutable KSpinLock m_lock;
public:
constexpr KHandleTable() :
m_entry_infos(), m_objects(), m_free_head_index(-1), m_table_size(0), m_max_count(0), m_next_linear_id(MinLinearId), m_count(0), m_lock()
{ MESOSPHERE_ASSERT_THIS(); }
constexpr explicit KHandleTable(util::ConstantInitializeTag) : m_entry_infos(), m_objects(), m_lock(), m_free_head_index(-1), m_table_size(), m_max_count(), m_next_linear_id(MinLinearId), m_count() { /* ... */ }
explicit KHandleTable() : m_free_head_index(-1), m_lock(), m_count() { MESOSPHERE_ASSERT_THIS(); }
constexpr NOINLINE Result Initialize(s32 size) {
MESOSPHERE_ASSERT_THIS();

View file

@ -31,7 +31,9 @@ namespace ams::kern {
s32 m_core_id;
bool m_is_initialized;
public:
constexpr KInterruptEvent() : m_interrupt_id(-1), m_core_id(-1), m_is_initialized(false) { /* ... */ }
constexpr explicit KInterruptEvent(util::ConstantInitializeTag) : KAutoObjectWithSlabHeapAndContainer<KInterruptEvent, KReadableEvent>(util::ConstantInitialize), m_interrupt_id(-1), m_core_id(-1), m_is_initialized(false) { /* ... */ }
explicit KInterruptEvent() : m_interrupt_id(-1), m_is_initialized(false) { /* ... */ }
Result Initialize(int32_t interrupt_name, ams::svc::InterruptType type);
virtual void Finalize() override;

View file

@ -33,7 +33,7 @@ namespace ams::kern {
public:
static bool IsValidIoPoolType(ams::svc::IoPoolType pool_type);
public:
explicit KIoPool() : m_lock(), m_io_region_list(), m_is_initialized(false) {
explicit KIoPool() : m_is_initialized(false) {
/* ... */
}

View file

@ -40,11 +40,7 @@ namespace ams::kern {
util::IntrusiveListNode m_process_list_node;
util::IntrusiveListNode m_pool_list_node;
public:
explicit KIoRegion()
: m_lock(), m_pool(nullptr), m_is_initialized(false), m_process_list_node(), m_pool_list_node()
{
/* ... */
}
explicit KIoRegion() : m_pool(nullptr), m_is_initialized(false) { /* ... */ }
Result Initialize(KIoPool *pool, KPhysicalAddress phys_addr, size_t size, ams::svc::MemoryMapping mapping, ams::svc::MemoryPermission perm);
virtual void Finalize() override;

View file

@ -26,7 +26,7 @@ namespace ams::kern {
private:
KLightSession *m_parent;
public:
constexpr KLightClientSession() : m_parent() { /* ... */ }
explicit KLightClientSession() { /* ... */ }
void Initialize(KLightSession *parent) {
/* Set member variables. */

View file

@ -26,7 +26,9 @@ namespace ams::kern {
private:
KThread::WaiterList m_wait_list;
public:
constexpr ALWAYS_INLINE KLightConditionVariable() : m_wait_list() { /* ... */ }
constexpr explicit ALWAYS_INLINE KLightConditionVariable(util::ConstantInitializeTag) : m_wait_list() { /* ... */ }
explicit ALWAYS_INLINE KLightConditionVariable() { /* ... */ }
public:
void Wait(KLightLock *lock, s64 timeout = -1ll, bool allow_terminating_thread = true);
void Broadcast();

View file

@ -25,7 +25,7 @@ namespace ams::kern {
private:
util::Atomic<uintptr_t> m_tag;
public:
constexpr KLightLock() : m_tag(0) { /* ... */ }
constexpr ALWAYS_INLINE KLightLock() : m_tag(0) { /* ... */ }
void Lock() {
MESOSPHERE_ASSERT_THIS();

View file

@ -32,7 +32,7 @@ namespace ams::kern {
u64 m_server_thread_id;
KThread *m_server_thread;
public:
constexpr KLightServerSession() : m_parent(), m_request_list(), m_current_request(), m_server_thread_id(), m_server_thread() { /* ... */ }
explicit KLightServerSession() : m_current_request(nullptr), m_server_thread_id(std::numeric_limits<u64>::max()), m_server_thread() { /* ... */ }
void Initialize(KLightSession *parent) {
/* Set member variables. */

View file

@ -46,11 +46,7 @@ namespace ams::kern {
KProcess *m_process;
bool m_initialized;
public:
constexpr KLightSession()
: m_server(), m_client(), m_state(State::Invalid), m_port(), m_name(), m_process(), m_initialized()
{
/* ... */
}
explicit KLightSession() : m_state(State::Invalid), m_process(), m_initialized() { /* ... */ }
void Initialize(KClientPort *client_port, uintptr_t name);
virtual void Finalize() override;

View file

@ -349,28 +349,30 @@ namespace ams::kern {
};
}
public:
constexpr KMemoryBlock()
: m_device_disable_merge_left_count(), m_device_disable_merge_right_count(), m_address(), m_num_pages(), m_memory_state(KMemoryState_None), m_ipc_lock_count(), m_device_use_count(), m_ipc_disable_merge_count(), m_permission(), m_original_permission(), m_attribute(), m_disable_merge_attribute()
{
/* ... */
}
explicit KMemoryBlock() { /* ... */ }
constexpr KMemoryBlock(KProcessAddress addr, size_t np, KMemoryState ms, KMemoryPermission p, KMemoryAttribute attr)
: m_device_disable_merge_left_count(), m_device_disable_merge_right_count(), m_address(addr), m_num_pages(np), m_memory_state(ms), m_ipc_lock_count(0), m_device_use_count(0), m_ipc_disable_merge_count(), m_permission(p), m_original_permission(KMemoryPermission_None), m_attribute(attr), m_disable_merge_attribute()
constexpr KMemoryBlock(util::ConstantInitializeTag, KProcessAddress addr, size_t np, KMemoryState ms, KMemoryPermission p, KMemoryAttribute attr)
: util::IntrusiveRedBlackTreeBaseNode<KMemoryBlock>(util::ConstantInitialize), m_device_disable_merge_left_count(),
m_device_disable_merge_right_count(), m_address(addr), m_num_pages(np), m_memory_state(ms), m_ipc_lock_count(0),
m_device_use_count(0), m_ipc_disable_merge_count(), m_permission(p), m_original_permission(KMemoryPermission_None),
m_attribute(attr), m_disable_merge_attribute()
{
/* ... */
}
constexpr void Initialize(KProcessAddress addr, size_t np, KMemoryState ms, KMemoryPermission p, KMemoryAttribute attr) {
MESOSPHERE_ASSERT_THIS();
m_address = addr;
m_num_pages = np;
m_memory_state = ms;
m_ipc_lock_count = 0;
m_device_use_count = 0;
m_permission = p;
m_original_permission = KMemoryPermission_None;
m_attribute = attr;
m_device_disable_merge_left_count = 0;
m_device_disable_merge_right_count = 0;
m_address = addr;
m_num_pages = np;
m_memory_state = ms;
m_ipc_lock_count = 0;
m_device_use_count = 0;
m_permission = p;
m_original_permission = KMemoryPermission_None;
m_attribute = attr;
m_disable_merge_attribute = KMemoryBlockDisableMergeAttribute_None;
}
constexpr bool HasProperties(KMemoryState s, KMemoryPermission p, KMemoryAttribute a) const {

View file

@ -88,7 +88,9 @@ namespace ams::kern {
private:
void CoalesceForUpdate(KMemoryBlockManagerUpdateAllocator *allocator, KProcessAddress address, size_t num_pages);
public:
constexpr KMemoryBlockManager() : m_memory_block_tree(), m_start_address(), m_end_address() { /* ... */ }
constexpr explicit KMemoryBlockManager(util::ConstantInitializeTag) : m_memory_block_tree(), m_start_address(Null<KProcessAddress>), m_end_address(Null<KProcessAddress>) { /* ... */ }
explicit KMemoryBlockManager() { /* ... */ }
iterator end() { return m_memory_block_tree.end(); }
const_iterator end() const { return m_memory_block_tree.end(); }
@ -105,7 +107,7 @@ namespace ams::kern {
void UpdateIfMatch(KMemoryBlockManagerUpdateAllocator *allocator, KProcessAddress address, size_t num_pages, KMemoryState test_state, KMemoryPermission test_perm, KMemoryAttribute test_attr, KMemoryState state, KMemoryPermission perm, KMemoryAttribute attr);
iterator FindIterator(KProcessAddress address) const {
return m_memory_block_tree.find(KMemoryBlock(address, 1, KMemoryState_Free, KMemoryPermission_None, KMemoryAttribute_None));
return m_memory_block_tree.find(KMemoryBlock(util::ConstantInitialize, address, 1, KMemoryState_Free, KMemoryPermission_None, KMemoryAttribute_None));
}
const KMemoryBlock *FindBlock(KProcessAddress address) const {

View file

@ -54,12 +54,12 @@ namespace ams::kern {
class KMemoryLayout {
private:
static /* constinit */ inline uintptr_t s_linear_phys_to_virt_diff;
static /* constinit */ inline uintptr_t s_linear_virt_to_phys_diff;
static /* constinit */ inline KMemoryRegionTree s_virtual_tree;
static /* constinit */ inline KMemoryRegionTree s_physical_tree;
static /* constinit */ inline KMemoryRegionTree s_virtual_linear_tree;
static /* constinit */ inline KMemoryRegionTree s_physical_linear_tree;
static constinit inline uintptr_t s_linear_phys_to_virt_diff;
static constinit inline uintptr_t s_linear_virt_to_phys_diff;
static constinit inline KMemoryRegionTree s_virtual_tree;
static constinit inline KMemoryRegionTree s_physical_tree;
static constinit inline KMemoryRegionTree s_virtual_linear_tree;
static constinit inline KMemoryRegionTree s_physical_linear_tree;
private:
template<typename AddressType> requires IsKTypedAddress<AddressType>
static ALWAYS_INLINE bool IsTypedAddress(const KMemoryRegion *&region, AddressType address, KMemoryRegionTree &tree, KMemoryRegionType type) {

View file

@ -68,7 +68,7 @@ namespace ams::kern {
Impl *m_next;
Impl *m_prev;
public:
Impl() : m_heap(), m_page_reference_counts(), m_management_region(), m_pool(), m_next(), m_prev() { /* ... */ }
Impl() : m_heap(), m_page_reference_counts(), m_management_region(Null<KVirtualAddress>), m_pool(), m_next(), m_prev() { /* ... */ }
size_t Initialize(KPhysicalAddress address, size_t size, KVirtualAddress management, KVirtualAddress management_end, Pool p);

View file

@ -43,13 +43,14 @@ namespace ams::kern {
}
}
public:
constexpr ALWAYS_INLINE KMemoryRegion() : m_address(0), m_pair_address(0), m_last_address(0), m_attributes(0), m_type_id(0) { /* ... */ }
constexpr ALWAYS_INLINE KMemoryRegion(uintptr_t a, size_t la, uintptr_t p, u32 r, u32 t) :
constexpr ALWAYS_INLINE KMemoryRegion() : util::IntrusiveRedBlackTreeBaseNode<KMemoryRegion>(util::ConstantInitialize), m_address(0), m_pair_address(0), m_last_address(0), m_attributes(0), m_type_id(0) { /* ... */ }
ALWAYS_INLINE KMemoryRegion(uintptr_t a, size_t la, uintptr_t p, u32 r, u32 t) :
m_address(a), m_pair_address(p), m_last_address(la), m_attributes(r), m_type_id(t)
{
/* ... */
}
constexpr ALWAYS_INLINE KMemoryRegion(uintptr_t a, size_t la, u32 r, u32 t) : KMemoryRegion(a, la, std::numeric_limits<uintptr_t>::max(), r, t) { /* ... */ }
ALWAYS_INLINE KMemoryRegion(uintptr_t a, size_t la, u32 r, u32 t) : KMemoryRegion(a, la, std::numeric_limits<uintptr_t>::max(), r, t) { /* ... */ }
private:
constexpr ALWAYS_INLINE void Reset(uintptr_t a, uintptr_t la, uintptr_t p, u32 r, u32 t) {
m_address = a;

View file

@ -29,8 +29,6 @@ namespace ams::kern {
private:
char m_name[NameLengthMax];
KAutoObject *m_object;
public:
constexpr KObjectName() : m_name(), m_object() { /* ... */ }
public:
static Result NewFromName(KAutoObject *obj, const char *name);
static Result Delete(KAutoObject *obj, const char *name);

View file

@ -43,7 +43,7 @@ namespace ams::kern {
return rnd_bit;
}
public:
RandomBitGenerator() : m_rng(), m_entropy(), m_bits_available() {
RandomBitGenerator() : m_entropy(), m_bits_available() {
m_rng.Initialize(static_cast<u32>(KSystemControl::GenerateRandomU64()));
}

View file

@ -28,11 +28,11 @@ namespace ams::kern {
private:
friend class KPageGroup;
private:
KBlockInfo *m_next{};
u32 m_page_index{};
u32 m_num_pages{};
KBlockInfo *m_next;
u32 m_page_index;
u32 m_num_pages;
public:
constexpr KBlockInfo() = default;
KBlockInfo() : m_next(nullptr) { /* ... */ }
constexpr ALWAYS_INLINE void Initialize(KPhysicalAddress addr, size_t np) {
MESOSPHERE_ASSERT(util::IsAligned(GetInteger(addr), PageSize));

View file

@ -59,7 +59,7 @@ namespace ams::kern {
size_t m_block_shift;
size_t m_next_block_shift;
public:
Block() : m_bitmap(), m_heap_address(), m_end_offset(), m_block_shift(), m_next_block_shift() { /* ... */ }
Block() : m_bitmap(), m_heap_address(Null<KPhysicalAddress>), m_end_offset(), m_block_shift(), m_next_block_shift() { /* ... */ }
constexpr size_t GetShift() const { return m_block_shift; }
constexpr size_t GetNextShift() const { return m_next_block_shift; }
@ -134,7 +134,7 @@ namespace ams::kern {
void FreeBlock(KPhysicalAddress block, s32 index);
public:
KPageHeap() : m_heap_address(), m_heap_size(), m_initial_used_size(), m_num_blocks(), m_blocks() { /* ... */ }
KPageHeap() : m_heap_address(Null<KPhysicalAddress>), m_heap_size(), m_initial_used_size(), m_num_blocks(), m_blocks() { /* ... */ }
constexpr KPhysicalAddress GetAddress() const { return m_heap_address; }
constexpr size_t GetSize() const { return m_heap_size; }

View file

@ -144,45 +144,60 @@ namespace ams::kern {
PageLinkedList *GetPageList() { return std::addressof(m_ll); }
};
private:
KProcessAddress m_address_space_start{};
KProcessAddress m_address_space_end{};
KProcessAddress m_heap_region_start{};
KProcessAddress m_heap_region_end{};
KProcessAddress m_current_heap_end{};
KProcessAddress m_alias_region_start{};
KProcessAddress m_alias_region_end{};
KProcessAddress m_stack_region_start{};
KProcessAddress m_stack_region_end{};
KProcessAddress m_kernel_map_region_start{};
KProcessAddress m_kernel_map_region_end{};
KProcessAddress m_alias_code_region_start{};
KProcessAddress m_alias_code_region_end{};
KProcessAddress m_code_region_start{};
KProcessAddress m_code_region_end{};
size_t m_max_heap_size{};
size_t m_mapped_physical_memory_size{};
size_t m_mapped_unsafe_physical_memory{};
size_t m_mapped_ipc_server_memory{};
mutable KLightLock m_general_lock{};
mutable KLightLock m_map_physical_memory_lock{};
KLightLock m_device_map_lock{};
KPageTableImpl m_impl{};
KMemoryBlockManager m_memory_block_manager{};
u32 m_allocate_option{};
u32 m_address_space_width{};
bool m_is_kernel{};
bool m_enable_aslr{};
bool m_enable_device_address_space_merge{};
KMemoryBlockSlabManager *m_memory_block_slab_manager{};
KBlockInfoManager *m_block_info_manager{};
KResourceLimit *m_resource_limit{};
const KMemoryRegion *m_cached_physical_linear_region{};
const KMemoryRegion *m_cached_physical_heap_region{};
MemoryFillValue m_heap_fill_value{};
MemoryFillValue m_ipc_fill_value{};
MemoryFillValue m_stack_fill_value{};
KProcessAddress m_address_space_start;
KProcessAddress m_address_space_end;
KProcessAddress m_heap_region_start;
KProcessAddress m_heap_region_end;
KProcessAddress m_current_heap_end;
KProcessAddress m_alias_region_start;
KProcessAddress m_alias_region_end;
KProcessAddress m_stack_region_start;
KProcessAddress m_stack_region_end;
KProcessAddress m_kernel_map_region_start;
KProcessAddress m_kernel_map_region_end;
KProcessAddress m_alias_code_region_start;
KProcessAddress m_alias_code_region_end;
KProcessAddress m_code_region_start;
KProcessAddress m_code_region_end;
size_t m_max_heap_size;
size_t m_mapped_physical_memory_size;
size_t m_mapped_unsafe_physical_memory;
size_t m_mapped_ipc_server_memory;
mutable KLightLock m_general_lock;
mutable KLightLock m_map_physical_memory_lock;
KLightLock m_device_map_lock;
KPageTableImpl m_impl;
KMemoryBlockManager m_memory_block_manager;
u32 m_allocate_option;
u32 m_address_space_width;
bool m_is_kernel;
bool m_enable_aslr;
bool m_enable_device_address_space_merge;
KMemoryBlockSlabManager *m_memory_block_slab_manager;
KBlockInfoManager *m_block_info_manager;
KResourceLimit *m_resource_limit;
const KMemoryRegion *m_cached_physical_linear_region;
const KMemoryRegion *m_cached_physical_heap_region;
MemoryFillValue m_heap_fill_value;
MemoryFillValue m_ipc_fill_value;
MemoryFillValue m_stack_fill_value;
public:
constexpr KPageTableBase() { /* ... */ }
constexpr explicit KPageTableBase(util::ConstantInitializeTag)
: m_address_space_start(Null<KProcessAddress>), m_address_space_end(Null<KProcessAddress>), m_heap_region_start(Null<KProcessAddress>),
m_heap_region_end(Null<KProcessAddress>), m_current_heap_end(Null<KProcessAddress>), m_alias_region_start(Null<KProcessAddress>),
m_alias_region_end(Null<KProcessAddress>), m_stack_region_start(Null<KProcessAddress>), m_stack_region_end(Null<KProcessAddress>),
m_kernel_map_region_start(Null<KProcessAddress>), m_kernel_map_region_end(Null<KProcessAddress>), m_alias_code_region_start(Null<KProcessAddress>),
m_alias_code_region_end(Null<KProcessAddress>), m_code_region_start(Null<KProcessAddress>), m_code_region_end(Null<KProcessAddress>),
m_max_heap_size(), m_mapped_physical_memory_size(), m_mapped_unsafe_physical_memory(), m_mapped_ipc_server_memory(), m_general_lock(),
m_map_physical_memory_lock(), m_device_map_lock(), m_impl(util::ConstantInitialize), m_memory_block_manager(util::ConstantInitialize),
m_allocate_option(), m_address_space_width(), m_is_kernel(), m_enable_aslr(), m_enable_device_address_space_merge(),
m_memory_block_slab_manager(), m_block_info_manager(), m_resource_limit(), m_cached_physical_linear_region(), m_cached_physical_heap_region(),
m_heap_fill_value(), m_ipc_fill_value(), m_stack_fill_value()
{
/* ... */
}
explicit KPageTableBase() { /* ... */ }
NOINLINE Result InitializeForKernel(bool is_64_bit, void *table, KVirtualAddress start, KVirtualAddress end);
NOINLINE Result InitializeForProcess(ams::svc::CreateProcessFlag as_type, bool enable_aslr, bool enable_device_address_space_merge, bool from_back, KMemoryManager::Pool pool, void *table, KProcessAddress start, KProcessAddress end, KProcessAddress code_address, size_t code_size, KMemoryBlockSlabManager *mem_block_slab_manager, KBlockInfoManager *block_info_manager, KResourceLimit *resource_limit);

View file

@ -27,9 +27,10 @@ namespace ams::kern {
private:
using BaseHeap = KDynamicResourceManager<impl::PageTablePage, true>;
private:
KPageTableSlabHeap *m_pt_heap{};
KPageTableSlabHeap *m_pt_heap;
public:
constexpr KPageTableManager() = default;
constexpr explicit KPageTableManager(util::ConstantInitializeTag) : m_pt_heap() { /* ... */ }
explicit KPageTableManager() { /* ... */ }
ALWAYS_INLINE void Initialize(KDynamicPageManager *page_allocator, KPageTableSlabHeap *pt_heap) {
m_pt_heap = pt_heap;

View file

@ -41,7 +41,7 @@ namespace ams::kern {
State m_state;
bool m_is_light;
public:
constexpr KPort() : m_server(), m_client(), m_name(), m_state(State::Invalid), m_is_light() { /* ... */ }
explicit KPort() : m_state(State::Invalid), m_is_light() { /* ... */ }
static void PostDestroy(uintptr_t arg) { MESOSPHERE_UNUSED(arg); /* ... */ }

View file

@ -57,73 +57,73 @@ namespace ams::kern {
using TLPTree = util::IntrusiveRedBlackTreeBaseTraits<KThreadLocalPage>::TreeType<KThreadLocalPage>;
using TLPIterator = TLPTree::iterator;
private:
KProcessPageTable m_page_table{};
util::Atomic<size_t> m_used_kernel_memory_size{0};
TLPTree m_fully_used_tlp_tree{};
TLPTree m_partially_used_tlp_tree{};
s32 m_ideal_core_id{};
void *m_attached_object{};
KResourceLimit *m_resource_limit{};
KVirtualAddress m_system_resource_address{};
size_t m_system_resource_num_pages{};
size_t m_memory_release_hint{};
State m_state{};
KLightLock m_state_lock{};
KLightLock m_list_lock{};
KConditionVariable m_cond_var{};
KAddressArbiter m_address_arbiter{};
u64 m_entropy[4]{};
bool m_is_signaled{};
bool m_is_initialized{};
bool m_is_application{};
char m_name[13]{};
util::Atomic<u16> m_num_running_threads{0};
u32 m_flags{};
KMemoryManager::Pool m_memory_pool{};
s64 m_schedule_count{};
KCapabilities m_capabilities{};
ams::svc::ProgramId m_program_id{};
u64 m_process_id{};
s64 m_creation_time{};
KProcessAddress m_code_address{};
size_t m_code_size{};
size_t m_main_thread_stack_size{};
size_t m_max_process_memory{};
u32 m_version{};
KHandleTable m_handle_table{};
KProcessAddress m_plr_address{};
void *m_plr_heap_address{};
KThread *m_exception_thread{};
ThreadList m_thread_list{};
SharedMemoryInfoList m_shared_memory_list{};
IoRegionList m_io_region_list{};
bool m_is_suspended{};
bool m_is_immortal{};
bool m_is_jit_debug{};
bool m_is_handle_table_initialized{};
ams::svc::DebugEvent m_jit_debug_event_type{};
ams::svc::DebugException m_jit_debug_exception_type{};
uintptr_t m_jit_debug_params[4]{};
u64 m_jit_debug_thread_id{};
KWaitObject m_wait_object{};
KThread *m_running_threads[cpu::NumCores]{};
u64 m_running_thread_idle_counts[cpu::NumCores]{};
KThread *m_pinned_threads[cpu::NumCores]{};
util::Atomic<s64> m_cpu_time{0};
util::Atomic<s64> m_num_process_switches{0};
util::Atomic<s64> m_num_thread_switches{0};
util::Atomic<s64> m_num_fpu_switches{0};
util::Atomic<s64> m_num_supervisor_calls{0};
util::Atomic<s64> m_num_ipc_messages{0};
util::Atomic<s64> m_num_ipc_replies{0};
util::Atomic<s64> m_num_ipc_receives{0};
KDynamicPageManager m_dynamic_page_manager{};
KMemoryBlockSlabManager m_memory_block_slab_manager{};
KBlockInfoManager m_block_info_manager{};
KPageTableManager m_page_table_manager{};
KMemoryBlockSlabHeap m_memory_block_heap{};
KBlockInfoSlabHeap m_block_info_heap{};
KPageTableSlabHeap m_page_table_heap{};
KProcessPageTable m_page_table;
util::Atomic<size_t> m_used_kernel_memory_size;
TLPTree m_fully_used_tlp_tree;
TLPTree m_partially_used_tlp_tree;
s32 m_ideal_core_id;
void *m_attached_object;
KResourceLimit *m_resource_limit;
KVirtualAddress m_system_resource_address;
size_t m_system_resource_num_pages;
size_t m_memory_release_hint;
State m_state;
KLightLock m_state_lock;
KLightLock m_list_lock;
KConditionVariable m_cond_var;
KAddressArbiter m_address_arbiter;
u64 m_entropy[4];
bool m_is_signaled;
bool m_is_initialized;
bool m_is_application;
char m_name[13];
util::Atomic<u16> m_num_running_threads;
u32 m_flags;
KMemoryManager::Pool m_memory_pool;
s64 m_schedule_count;
KCapabilities m_capabilities;
ams::svc::ProgramId m_program_id;
u64 m_process_id;
s64 m_creation_time;
KProcessAddress m_code_address;
size_t m_code_size;
size_t m_main_thread_stack_size;
size_t m_max_process_memory;
u32 m_version;
KHandleTable m_handle_table;
KProcessAddress m_plr_address;
void *m_plr_heap_address;
KThread *m_exception_thread;
ThreadList m_thread_list;
SharedMemoryInfoList m_shared_memory_list;
IoRegionList m_io_region_list;
bool m_is_suspended;
bool m_is_immortal;
bool m_is_jit_debug;
bool m_is_handle_table_initialized;
ams::svc::DebugEvent m_jit_debug_event_type;
ams::svc::DebugException m_jit_debug_exception_type;
uintptr_t m_jit_debug_params[4];
u64 m_jit_debug_thread_id;
KWaitObject m_wait_object;
KThread *m_running_threads[cpu::NumCores];
u64 m_running_thread_idle_counts[cpu::NumCores];
KThread *m_pinned_threads[cpu::NumCores];
util::Atomic<s64> m_cpu_time;
util::Atomic<s64> m_num_process_switches;
util::Atomic<s64> m_num_thread_switches;
util::Atomic<s64> m_num_fpu_switches;
util::Atomic<s64> m_num_supervisor_calls;
util::Atomic<s64> m_num_ipc_messages;
util::Atomic<s64> m_num_ipc_replies;
util::Atomic<s64> m_num_ipc_receives;
KDynamicPageManager m_dynamic_page_manager;
KMemoryBlockSlabManager m_memory_block_slab_manager;
KBlockInfoManager m_block_info_manager;
KPageTableManager m_page_table_manager;
KMemoryBlockSlabHeap m_memory_block_heap;
KBlockInfoSlabHeap m_block_info_heap;
KPageTableSlabHeap m_page_table_heap;
private:
Result Initialize(const ams::svc::CreateProcessParameter &params);
@ -145,7 +145,7 @@ namespace ams::kern {
m_pinned_threads[core_id] = nullptr;
}
public:
KProcess() { /* ... */ }
explicit KProcess() : m_is_initialized(false) { /* ... */ }
Result Initialize(const ams::svc::CreateProcessParameter &params, const KPageGroup &pg, const u32 *caps, s32 num_caps, KResourceLimit *res_limit, KMemoryManager::Pool pool, bool immortal);
Result Initialize(const ams::svc::CreateProcessParameter &params, svc::KUserPointer<const u32 *> caps, s32 num_caps, KResourceLimit *res_limit, KMemoryManager::Pool pool);

View file

@ -27,7 +27,9 @@ namespace ams::kern {
bool m_is_signaled;
KEvent *m_parent;
public:
constexpr explicit KReadableEvent() : KSynchronizationObject(), m_is_signaled(), m_parent() { MESOSPHERE_ASSERT_THIS(); }
constexpr explicit KReadableEvent(util::ConstantInitializeTag) : KSynchronizationObject(util::ConstantInitialize), m_is_signaled(), m_parent() { MESOSPHERE_ASSERT_THIS(); }
explicit KReadableEvent() { /* ... */ }
void Initialize(KEvent *parent);

View file

@ -33,7 +33,15 @@ namespace ams::kern {
s32 m_waiter_count;
KLightConditionVariable m_cond_var;
public:
constexpr ALWAYS_INLINE KResourceLimit() : m_limit_values(), m_current_values(), m_current_hints(), m_peak_values(), m_lock(), m_waiter_count(), m_cond_var() { /* ... */ }
constexpr explicit ALWAYS_INLINE KResourceLimit(util::ConstantInitializeTag)
: KAutoObjectWithSlabHeapAndContainer<KResourceLimit, KAutoObjectWithList>(util::ConstantInitialize),
m_limit_values(), m_current_values(), m_current_hints(), m_peak_values(), m_lock(), m_waiter_count(),
m_cond_var(util::ConstantInitialize)
{
/* ... */
}
explicit ALWAYS_INLINE KResourceLimit() { /* ... */ }
static void PostDestroy(uintptr_t arg) { MESOSPHERE_UNUSED(arg); /* ... */ }

View file

@ -62,8 +62,7 @@ namespace ams::kern {
KThread *m_idle_thread;
util::Atomic<KThread *> m_current_thread;
public:
constexpr KScheduler()
: m_state(), m_is_active(false), m_core_id(0), m_last_context_switch_time(0), m_idle_thread(nullptr), m_current_thread(nullptr)
constexpr KScheduler() : m_state(), m_is_active(false), m_core_id(0), m_last_context_switch_time(0), m_idle_thread(nullptr), m_current_thread(nullptr)
{
m_state.needs_scheduling = true;
m_state.interrupt_task_runnable = false;

View file

@ -34,7 +34,8 @@ namespace ams::kern {
LightSessionList m_light_session_list;
KPort *m_parent;
public:
constexpr KServerPort() : m_session_list(), m_light_session_list(), m_parent() { /* ... */ }
constexpr explicit KServerPort(util::ConstantInitializeTag) : KSynchronizationObject(util::ConstantInitialize), m_session_list(), m_light_session_list(), m_parent() { /* ... */ }
explicit KServerPort() { /* ... */ }
void Initialize(KPort *parent);
void EnqueueSession(KServerSession *session);

View file

@ -33,7 +33,8 @@ namespace ams::kern {
KSessionRequest *m_current_request;
KLightLock m_lock;
public:
constexpr KServerSession() : m_parent(), m_request_list(), m_current_request(), m_lock() { /* ... */ }
constexpr explicit KServerSession(util::ConstantInitializeTag) : KSynchronizationObject(util::ConstantInitialize), m_parent(), m_request_list(), m_current_request(), m_lock() { /* ... */ }
explicit KServerSession() : m_current_request(nullptr), m_lock() { /* ... */ }
virtual void Destroy() override;

View file

@ -51,12 +51,16 @@ namespace ams::kern {
return static_cast<State>(m_atomic_state.Load());
}
public:
constexpr KSession()
: m_atomic_state(static_cast<std::underlying_type<State>::type>(State::Invalid)), m_initialized(), m_server(), m_client(), m_port(), m_name(), m_process()
constexpr explicit KSession(util::ConstantInitializeTag)
: KAutoObjectWithSlabHeapAndContainer<KSession, KAutoObjectWithList, true>(util::ConstantInitialize),
m_atomic_state(static_cast<std::underlying_type<State>::type>(State::Invalid)), m_initialized(),
m_server(util::ConstantInitialize), m_client(util::ConstantInitialize), m_port(), m_name(), m_process()
{
/* ... */
}
explicit KSession() : m_atomic_state(util::ToUnderlying(State::Invalid)), m_initialized(false), m_process(nullptr) { /* ... */ }
void Initialize(KClientPort *client_port, uintptr_t name);
virtual void Finalize() override;

View file

@ -33,14 +33,14 @@ namespace ams::kern {
class Mapping {
private:
KProcessAddress m_client_address;
KProcessAddress m_server_address;
uintptr_t m_client_address;
uintptr_t m_server_address;
size_t m_size;
KMemoryState m_state;
public:
constexpr void Set(KProcessAddress c, KProcessAddress s, size_t sz, KMemoryState st) {
m_client_address = c;
m_server_address = s;
m_client_address = GetInteger(c);
m_server_address = GetInteger(s);
m_size = sz;
m_state = st;
}
@ -57,7 +57,9 @@ namespace ams::kern {
u8 m_num_recv;
u8 m_num_exch;
public:
constexpr explicit SessionMappings() : m_static_mappings(), m_mappings(), m_num_send(), m_num_recv(), m_num_exch() { /* ... */ }
constexpr explicit SessionMappings(util::ConstantInitializeTag) : m_static_mappings(), m_mappings(), m_num_send(), m_num_recv(), m_num_exch() { /* ... */ }
explicit SessionMappings() : m_mappings(nullptr), m_num_send(), m_num_recv(), m_num_exch() { /* ... */ }
void Initialize() { /* ... */ }
void Finalize();
@ -119,8 +121,6 @@ namespace ams::kern {
return m_mappings[index - NumStaticMappings];
}
}
};
private:
SessionMappings m_mappings;
@ -130,11 +130,13 @@ namespace ams::kern {
uintptr_t m_address;
size_t m_size;
public:
constexpr KSessionRequest() : m_mappings(), m_thread(), m_server(), m_event(), m_address(), m_size() { /* ... */ }
constexpr explicit KSessionRequest(util::ConstantInitializeTag) : KAutoObject(util::ConstantInitialize), m_mappings(util::ConstantInitialize), m_thread(), m_server(), m_event(), m_address(), m_size() { /* ... */ }
explicit KSessionRequest() : m_thread(nullptr), m_server(nullptr), m_event(nullptr) { /* ... */ }
static KSessionRequest *Create() {
KSessionRequest *req = KSessionRequest::Allocate();
if (req != nullptr) {
if (AMS_LIKELY(req != nullptr)) {
KAutoObject::Create(req);
}
return req;
@ -142,7 +144,7 @@ namespace ams::kern {
static KSessionRequest *CreateFromUnusedSlabMemory() {
KSessionRequest *req = KSessionRequest::AllocateFromUnusedSlabMemory();
if (req != nullptr) {
if (AMS_LIKELY(req != nullptr)) {
KAutoObject::Create(req);
}
return req;

View file

@ -26,7 +26,7 @@ namespace ams::kern {
KSharedMemory *m_shared_memory;
size_t m_reference_count;
public:
constexpr KSharedMemoryInfo() : m_shared_memory(), m_reference_count() { /* ... */ }
explicit KSharedMemoryInfo() { /* ... */ }
~KSharedMemoryInfo() { /* ... */ }
constexpr void Initialize(KSharedMemory *m) {

View file

@ -32,7 +32,8 @@ namespace ams::kern {
ThreadListNode *m_thread_list_head;
ThreadListNode *m_thread_list_tail;
protected:
constexpr ALWAYS_INLINE explicit KSynchronizationObject() : KAutoObjectWithList(), m_thread_list_head(), m_thread_list_tail() { MESOSPHERE_ASSERT_THIS(); }
constexpr ALWAYS_INLINE explicit KSynchronizationObject(util::ConstantInitializeTag) : KAutoObjectWithList(util::ConstantInitialize), m_thread_list_head(), m_thread_list_tail() { MESOSPHERE_ASSERT_THIS(); }
ALWAYS_INLINE explicit KSynchronizationObject() : m_thread_list_head(), m_thread_list_tail() { MESOSPHERE_ASSERT_THIS(); }
virtual void OnFinalizeSynchronizationObject() { MESOSPHERE_ASSERT_THIS(); }

View file

@ -120,8 +120,6 @@ namespace ams::kern {
KThread *m_prev;
KThread *m_next;
public:
constexpr QueueEntry() : m_prev(nullptr), m_next(nullptr) { /* ... */ }
constexpr void Initialize() {
m_prev = nullptr;
m_next = nullptr;
@ -140,7 +138,9 @@ namespace ams::kern {
KSynchronizationObject *m_sync_objects[ams::svc::ArgumentHandleCountMax];
ams::svc::Handle m_handles[ams::svc::ArgumentHandleCountMax * (sizeof(KSynchronizationObject *) / sizeof(ams::svc::Handle))];
constexpr SyncObjectBuffer() : m_sync_objects() { /* ... */ }
constexpr explicit SyncObjectBuffer(util::ConstantInitializeTag) : m_sync_objects() { /* ... */ }
explicit SyncObjectBuffer() { /* ... */ }
};
static_assert(sizeof(SyncObjectBuffer::m_sync_objects) == sizeof(SyncObjectBuffer::m_handles));
@ -177,64 +177,79 @@ namespace ams::kern {
static_assert(ams::util::HasRedBlackKeyType<ConditionVariableComparator>);
static_assert(std::same_as<ams::util::RedBlackKeyType<ConditionVariableComparator, void>, ConditionVariableComparator::RedBlackKeyType>);
private:
util::IntrusiveListNode m_process_list_node{};
util::IntrusiveRedBlackTreeNode m_condvar_arbiter_tree_node{};
s32 m_priority{};
util::IntrusiveListNode m_process_list_node;
util::IntrusiveRedBlackTreeNode m_condvar_arbiter_tree_node;
s32 m_priority;
using ConditionVariableThreadTreeTraits = util::IntrusiveRedBlackTreeMemberTraitsDeferredAssert<&KThread::m_condvar_arbiter_tree_node>;
using ConditionVariableThreadTree = ConditionVariableThreadTreeTraits::TreeType<ConditionVariableComparator>;
ConditionVariableThreadTree *m_condvar_tree{};
uintptr_t m_condvar_key{};
alignas(16) KThreadContext m_thread_context{};
u64 m_virtual_affinity_mask{};
KAffinityMask m_physical_affinity_mask{};
u64 m_thread_id{};
util::Atomic<s64> m_cpu_time{0};
KProcessAddress m_address_key{};
KProcess *m_parent{};
void *m_kernel_stack_top{};
u32 *m_light_ipc_data{};
KProcessAddress m_tls_address{};
void *m_tls_heap_address{};
KLightLock m_activity_pause_lock{};
SyncObjectBuffer m_sync_object_buffer{};
s64 m_schedule_count{};
s64 m_last_scheduled_tick{};
QueueEntry m_per_core_priority_queue_entry[cpu::NumCores]{};
KThreadQueue *m_wait_queue{};
WaiterList m_waiter_list{};
WaiterList m_pinned_waiter_list{};
KThread *m_lock_owner{};
uintptr_t m_debug_params[3]{};
KAutoObject *m_closed_object{};
u32 m_address_key_value{};
u32 m_suspend_request_flags{};
u32 m_suspend_allowed_flags{};
s32 m_synced_index{};
ConditionVariableThreadTree *m_condvar_tree;
uintptr_t m_condvar_key;
alignas(16) KThreadContext m_thread_context;
u64 m_virtual_affinity_mask;
KAffinityMask m_physical_affinity_mask;
u64 m_thread_id;
util::Atomic<s64> m_cpu_time;
KProcessAddress m_address_key;
KProcess *m_parent;
void *m_kernel_stack_top;
u32 *m_light_ipc_data;
KProcessAddress m_tls_address;
void *m_tls_heap_address;
KLightLock m_activity_pause_lock;
SyncObjectBuffer m_sync_object_buffer;
s64 m_schedule_count;
s64 m_last_scheduled_tick;
QueueEntry m_per_core_priority_queue_entry[cpu::NumCores];
KThreadQueue *m_wait_queue;
WaiterList m_waiter_list;
WaiterList m_pinned_waiter_list;
KThread *m_lock_owner;
uintptr_t m_debug_params[3];
KAutoObject *m_closed_object;
u32 m_address_key_value;
u32 m_suspend_request_flags;
u32 m_suspend_allowed_flags;
s32 m_synced_index;
Result m_wait_result;
Result m_debug_exception_result;
s32 m_base_priority{};
s32 m_base_priority_on_unpin{};
s32 m_physical_ideal_core_id{};
s32 m_virtual_ideal_core_id{};
s32 m_num_kernel_waiters{};
s32 m_current_core_id{};
s32 m_core_id{};
KAffinityMask m_original_physical_affinity_mask{};
s32 m_original_physical_ideal_core_id{};
s32 m_num_core_migration_disables{};
ThreadState m_thread_state{};
util::Atomic<bool> m_termination_requested{false};
bool m_wait_cancelled{};
bool m_cancellable{};
bool m_signaled{};
bool m_initialized{};
bool m_debug_attached{};
s8 m_priority_inheritance_count{};
bool m_resource_limit_release_hint{};
s32 m_base_priority;
s32 m_base_priority_on_unpin;
s32 m_physical_ideal_core_id;
s32 m_virtual_ideal_core_id;
s32 m_num_kernel_waiters;
s32 m_current_core_id;
s32 m_core_id;
KAffinityMask m_original_physical_affinity_mask;
s32 m_original_physical_ideal_core_id;
s32 m_num_core_migration_disables;
ThreadState m_thread_state;
util::Atomic<bool> m_termination_requested;
bool m_wait_cancelled;
bool m_cancellable;
bool m_signaled;
bool m_initialized;
bool m_debug_attached;
s8 m_priority_inheritance_count;
bool m_resource_limit_release_hint;
public:
constexpr KThread() : m_wait_result(svc::ResultNoSynchronizationObject()), m_debug_exception_result(ResultSuccess()) { /* ... */ }
constexpr explicit KThread(util::ConstantInitializeTag)
: KAutoObjectWithSlabHeapAndContainer<KThread, KSynchronizationObject>(util::ConstantInitialize), KTimerTask(util::ConstantInitialize),
m_process_list_node{}, m_condvar_arbiter_tree_node{util::ConstantInitialize}, m_priority{-1}, m_condvar_tree{}, m_condvar_key{},
m_thread_context{util::ConstantInitialize}, m_virtual_affinity_mask{}, m_physical_affinity_mask{}, m_thread_id{}, m_cpu_time{0}, m_address_key{Null<KProcessAddress>}, m_parent{},
m_kernel_stack_top{}, m_light_ipc_data{}, m_tls_address{Null<KProcessAddress>}, m_tls_heap_address{}, m_activity_pause_lock{}, m_sync_object_buffer{util::ConstantInitialize},
m_schedule_count{}, m_last_scheduled_tick{}, m_per_core_priority_queue_entry{}, m_wait_queue{}, m_waiter_list{}, m_pinned_waiter_list{},
m_lock_owner{}, m_debug_params{}, m_closed_object{}, m_address_key_value{}, m_suspend_request_flags{}, m_suspend_allowed_flags{}, m_synced_index{},
m_wait_result{svc::ResultNoSynchronizationObject()}, m_debug_exception_result{ResultSuccess()}, m_base_priority{}, m_base_priority_on_unpin{},
m_physical_ideal_core_id{}, m_virtual_ideal_core_id{}, m_num_kernel_waiters{}, m_current_core_id{}, m_core_id{}, m_original_physical_affinity_mask{},
m_original_physical_ideal_core_id{}, m_num_core_migration_disables{}, m_thread_state{}, m_termination_requested{false}, m_wait_cancelled{},
m_cancellable{}, m_signaled{}, m_initialized{}, m_debug_attached{}, m_priority_inheritance_count{}, m_resource_limit_release_hint{}
{
/* ... */
}
explicit KThread() : m_priority(-1), m_condvar_tree(nullptr), m_condvar_key(0), m_parent(nullptr), m_initialized(false) { /* ... */ }
Result Initialize(KThreadFunction func, uintptr_t arg, void *kern_stack_top, KProcessAddress user_stack_top, s32 prio, s32 virt_core, KProcess *owner, ThreadType type);
private:

View file

@ -33,13 +33,13 @@ namespace ams::kern {
KProcess *m_owner;
bool m_is_region_free[RegionsPerPage];
public:
constexpr explicit KThreadLocalPage(KProcessAddress addr) : m_virt_addr(addr), m_owner(nullptr), m_is_region_free() {
for (size_t i = 0; i < RegionsPerPage; i++) {
explicit KThreadLocalPage(KProcessAddress addr) : m_virt_addr(addr), m_owner(nullptr) {
for (size_t i = 0; i < util::size(m_is_region_free); i++) {
m_is_region_free[i] = true;
}
}
constexpr explicit KThreadLocalPage() : KThreadLocalPage(Null<KProcessAddress>) { /* ... */ }
explicit KThreadLocalPage() : KThreadLocalPage(Null<KProcessAddress>) { /* ... */ }
constexpr ALWAYS_INLINE KProcessAddress GetAddress() const { return m_virt_addr; }

View file

@ -30,7 +30,8 @@ namespace ams::kern {
}
}
public:
constexpr ALWAYS_INLINE KTimerTask() : m_time(0) { /* ... */ }
constexpr explicit ALWAYS_INLINE KTimerTask(util::ConstantInitializeTag) : util::IntrusiveRedBlackTreeBaseNode<KTimerTask>(util::ConstantInitialize), m_time(0) { /* ... */ }
explicit ALWAYS_INLINE KTimerTask() : m_time(0) { /* ... */ }
constexpr ALWAYS_INLINE void SetTime(s64 t) {
m_time = t;

View file

@ -26,7 +26,7 @@ namespace ams::kern {
uintptr_t m_address;
public:
/* Constructors. */
constexpr ALWAYS_INLINE KTypedAddress() : m_address(0) { /* ... */ }
ALWAYS_INLINE KTypedAddress() { /* ... */ }
constexpr ALWAYS_INLINE KTypedAddress(uintptr_t a) : m_address(a) { /* ... */ }
template<typename U>
constexpr ALWAYS_INLINE explicit KTypedAddress(U *ptr) : m_address(reinterpret_cast<uintptr_t>(ptr)) { /* ... */ }
@ -146,13 +146,13 @@ namespace ams::kern {
}
template<typename T, typename U>
constexpr ALWAYS_INLINE T *GetPointer(KTypedAddress<true, U> address) {
return CONST_FOLD(reinterpret_cast<T *>(address.GetValue()));
ALWAYS_INLINE T *GetPointer(KTypedAddress<true, U> address) {
return reinterpret_cast<T *>(address.GetValue());
}
template<typename T>
constexpr ALWAYS_INLINE void *GetVoidPointer(KTypedAddress<true, T> address) {
return CONST_FOLD(reinterpret_cast<void *>(address.GetValue()));
ALWAYS_INLINE void *GetVoidPointer(KTypedAddress<true, T> address) {
return reinterpret_cast<void *>(address.GetValue());
}
#else
@ -170,12 +170,12 @@ namespace ams::kern {
template<typename T>
constexpr ALWAYS_INLINE T *GetPointer(uintptr_t address) {
return CONST_FOLD(reinterpret_cast<T *>(address));
return reinterpret_cast<T *>(address);
}
template<typename T>
constexpr ALWAYS_INLINE void *GetVoidPointer(uintptr_t address) {
return CONST_FOLD(reinterpret_cast<void *>(address));
return reinterpret_cast<void *>(address);
}
#endif

View file

@ -85,7 +85,9 @@ namespace ams::kern {
ALWAYS_INLINE ~ListAccessor() { /* ... */ }
};
public:
constexpr KAutoObjectWithSlabHeapAndContainer() = default;
constexpr explicit KAutoObjectWithSlabHeapAndContainer(util::ConstantInitializeTag) : Base(util::ConstantInitialize) { /* ... */ }
explicit KAutoObjectWithSlabHeapAndContainer() { /* ... */ }
virtual void Destroy() override {
const bool is_initialized = this->IsInitialized();

View file

@ -129,7 +129,7 @@ namespace ams::kern::arch::arm64::cpu {
void ProcessOperation();
public:
constexpr KCacheHelperInterruptHandler() : KInterruptHandler(), m_lock(), m_cv_lock(), m_cv(), m_target_cores(0), m_operation(Operation::Idle) { /* ... */ }
constexpr KCacheHelperInterruptHandler() : KInterruptHandler(), m_lock(), m_cv_lock(), m_cv(util::ConstantInitialize), m_target_cores(0), m_operation(Operation::Idle) { /* ... */ }
void Initialize(s32 core_id) {
/* Reserve a thread from the system limit. */

View file

@ -283,9 +283,6 @@ namespace ams::kern::arch::arm64 {
/* Check that the name is a valid instruction breakpoint. */
R_UNLESS((name - ams::svc::HardwareBreakPointRegisterName_I0) <= num_bp, svc::ResultNotSupported());
/* We may be getting the process, so prepare a scoped reference holder. */
KScopedAutoObject<KProcess> process;
/* Configure flags/value. */
if ((flags & 1) != 0) {
/* We're enabling the breakpoint. Check that the flags are allowable. */

View file

@ -233,7 +233,7 @@ namespace ams::kern::arch::arm64 {
/* Begin the traversal. */
TraversalContext context;
TraversalEntry cur_entry = {};
TraversalEntry cur_entry = { .phys_addr = Null<KPhysicalAddress>, .block_size = 0, .sw_reserved_bits = 0 };
bool cur_valid = false;
TraversalEntry next_entry;
bool next_valid;

View file

@ -345,8 +345,8 @@ namespace ams::kern::board::nintendo::nx {
/* Globals. */
constinit KLightLock g_lock;
constinit u8 g_reserved_asid;
constinit KPhysicalAddress g_memory_controller_address;
constinit KPhysicalAddress g_reserved_table_phys_addr;
constinit KPhysicalAddress g_memory_controller_address{Null<KPhysicalAddress>};
constinit KPhysicalAddress g_reserved_table_phys_addr{Null<KPhysicalAddress>};
constinit KDeviceAsidManager g_asid_manager;
constinit u32 g_saved_page_tables[AsidCount];
constinit u32 g_saved_asid_registers[ams::svc::DeviceName_Count];

View file

@ -66,7 +66,7 @@ namespace ams::kern::board::nintendo::nx {
constinit u64 g_sleep_target_cores;
constinit KLightLock g_request_lock;
constinit KLightLock g_cv_lock;
constinit KLightConditionVariable g_cv;
constinit KLightConditionVariable g_cv{util::ConstantInitialize};
constinit KPhysicalAddress g_sleep_buffer_phys_addrs[cpu::NumCores];
alignas(1_KB) constinit u64 g_sleep_buffers[cpu::NumCores][1_KB / sizeof(u64)];
constinit SavedSystemRegisters g_sleep_system_registers[cpu::NumCores] = {};

View file

@ -43,7 +43,7 @@ namespace ams::kern::board::nintendo::nx {
/* To save space (and because mt19337_t isn't secure anyway), */
/* We will use TinyMT. */
constinit bool g_initialized_random_generator;
constinit util::TinyMT g_random_generator;
constinit util::TinyMT g_random_generator{util::ConstantInitialize};
constinit KSpinLock g_random_lock;
ALWAYS_INLINE size_t GetRealMemorySizeForInit() {

View file

@ -19,7 +19,12 @@ namespace ams::kern {
Result KCapabilities::Initialize(const u32 *caps, s32 num_caps, KProcessPageTable *page_table) {
/* We're initializing an initial process. */
/* Most fields have already been cleared by our constructor. */
m_svc_access_flags.Reset();
m_irq_access_flags.Reset();
m_debug_capabilities = {0};
m_handle_table_size = 0;
m_intended_kernel_version = {0};
m_program_type = 0;
/* Initial processes may run on all cores. */
m_core_mask = cpu::VirtualCoreMask;
@ -38,7 +43,16 @@ namespace ams::kern {
Result KCapabilities::Initialize(svc::KUserPointer<const u32 *> user_caps, s32 num_caps, KProcessPageTable *page_table) {
/* We're initializing a user process. */
/* Most fields have already been cleared by our constructor. */
m_svc_access_flags.Reset();
m_irq_access_flags.Reset();
m_debug_capabilities = {0};
m_handle_table_size = 0;
m_intended_kernel_version = {0};
m_program_type = 0;
/* User processes must specify what cores/priorities they can use. */
m_core_mask = 0;
m_priority_mask = 0;
/* Parse the user capabilities array. */
return this->SetCapabilities(user_caps, num_caps, page_table);

View file

@ -23,7 +23,7 @@ namespace ams::kern {
private:
static constinit inline KLightLock s_req_lock;
static constinit inline KLightLock s_lock;
static constinit inline KLightConditionVariable s_cond_var;
static constinit inline KLightConditionVariable s_cond_var{util::ConstantInitialize};
static constinit inline u64 s_core_mask;
static constinit inline KDpcTask *s_task;
private:

View file

@ -195,9 +195,11 @@ namespace ams::kern::KDumpObject {
char name[9] = {};
{
/* Find the client port process. */
KScopedAutoObject<KProcess> client_port_process;
KProcess *client_port_process = nullptr;
ON_SCOPE_EXIT { if (client_port_process != nullptr) { client_port_process->Close(); } };
{
for (auto it = accessor.begin(); it != end && client_port_process.IsNull(); ++it) {
for (auto it = accessor.begin(); it != end && client_port_process == nullptr; ++it) {
KProcess *cur = static_cast<KProcess *>(std::addressof(*it));
for (size_t j = 0; j < cur->GetHandleTable().GetTableSize(); ++j) {
ams::svc::Handle cur_h = ams::svc::InvalidHandle;
@ -205,6 +207,7 @@ namespace ams::kern::KDumpObject {
if (cur_o.IsNotNull()) {
if (cur_o.GetPointerUnsafe() == client) {
client_port_process = cur;
client_port_process->Open();
break;
}
}
@ -213,7 +216,7 @@ namespace ams::kern::KDumpObject {
}
/* Read the port name. */
if (client_port_process.IsNotNull()) {
if (client_port_process != nullptr) {
if (R_FAILED(client_port_process->GetPageTable().CopyMemoryFromLinearToKernel(KProcessAddress(name), 8, port_name, KMemoryState_None, KMemoryState_None, KMemoryPermission_UserRead, KMemoryAttribute_None, KMemoryAttribute_None))) {
std::memset(name, 0, sizeof(name));
}

View file

@ -26,8 +26,8 @@ namespace ams::kern {
/* Set our members. */
m_heap_address = address;
m_heap_size = size;
m_num_blocks = num_block_shifts;
m_heap_size = size;
m_num_blocks = num_block_shifts;
/* Setup bitmaps. */
u64 *cur_bitmap_storage = GetPointer<u64>(management_address);

View file

@ -706,7 +706,7 @@ namespace ams::kern {
/* Begin traversal. */
TraversalContext context;
TraversalEntry cur_entry = {};
TraversalEntry cur_entry = { .phys_addr = Null<KPhysicalAddress>, .block_size = 0, .sw_reserved_bits = 0 };
bool cur_valid = false;
TraversalEntry next_entry;
bool next_valid;
@ -1400,7 +1400,7 @@ namespace ams::kern {
/* Begin a traversal. */
TraversalContext context;
TraversalEntry cur_entry = {};
TraversalEntry cur_entry = { .phys_addr = Null<KPhysicalAddress>, .block_size = 0, .sw_reserved_bits = 0 };
R_UNLESS(impl.BeginTraversal(std::addressof(cur_entry), std::addressof(context), address), svc::ResultInvalidCurrentMemory());
/* The region we're traversing has to be heap. */
@ -4423,7 +4423,7 @@ namespace ams::kern {
/* Begin traversal. */
TraversalContext context;
TraversalEntry cur_entry = {};
TraversalEntry cur_entry = { .phys_addr = Null<KPhysicalAddress>, .block_size = 0, .sw_reserved_bits = 0 };
bool cur_valid = false;
TraversalEntry next_entry;
bool next_valid;

View file

@ -220,8 +220,8 @@ namespace ams::kern {
/* Set thread fields. */
for (size_t i = 0; i < cpu::NumCores; i++) {
m_running_threads[i] = nullptr;
m_running_thread_idle_counts[i] = 0;
m_pinned_threads[i] = nullptr;
m_running_thread_idle_counts[i] = 0;
}
/* Set max memory based on address space type. */

View file

@ -24,17 +24,11 @@ namespace ams::kern {
}
void KResourceLimit::Initialize() {
/* This should be unnecessary for us, because our constructor will clear all fields. */
/* The following is analagous to what Nintendo's implementation (no constexpr constructor) would do, though. */
/*
m_waiter_count = 0;
for (size_t i = 0; i < util::size(m_limit_values); i++) {
m_limit_values[i] = 0;
m_current_values[i] = 0;
m_current_hints[i] = 0;
m_peak_values[i] = 0;
}
*/
m_waiter_count = 0;
std::memset(m_limit_values, 0, sizeof(m_limit_values));
std::memset(m_current_values, 0, sizeof(m_current_values));
std::memset(m_current_hints, 0, sizeof(m_current_hints));
std::memset(m_peak_values, 0, sizeof(m_peak_values));
}
void KResourceLimit::Finalize() {

View file

@ -973,7 +973,7 @@ namespace ams::kern {
/* Get the request and client thread. */
KSessionRequest *request;
KScopedAutoObject<KThread> client_thread;
KThread *client_thread;
{
KScopedSchedulerLock sl;
@ -991,9 +991,13 @@ namespace ams::kern {
m_request_list.pop_front();
/* Get the thread for the request. */
client_thread = KScopedAutoObject<KThread>(request->GetThread());
R_UNLESS(client_thread.IsNotNull(), svc::ResultSessionClosed());
client_thread = request->GetThread();
R_UNLESS(client_thread != nullptr, svc::ResultSessionClosed());
/* Open the client thread. */
client_thread->Open();
}
ON_SCOPE_EXIT { client_thread->Close(); };
/* Set the request as our current. */
m_current_request = request;
@ -1004,7 +1008,7 @@ namespace ams::kern {
bool recv_list_broken = false;
/* Receive the message. */
Result result = ReceiveMessage(recv_list_broken, server_message, server_buffer_size, server_message_paddr, *client_thread.GetPointerUnsafe(), client_message, client_buffer_size, this, request);
Result result = ReceiveMessage(recv_list_broken, server_message, server_buffer_size, server_message_paddr, *client_thread, client_message, client_buffer_size, this, request);
/* Handle cleanup on receive failure. */
if (R_FAILED(result)) {

View file

@ -132,6 +132,7 @@ namespace ams::kern {
/* Set parent and condvar tree. */
m_parent = nullptr;
m_condvar_tree = nullptr;
m_condvar_key = 0;
/* Set sync booleans. */
m_signaled = false;
@ -179,7 +180,7 @@ namespace ams::kern {
m_current_core_id = phys_core;
/* We haven't released our resource limit hint, and we've spent no time on the cpu. */
m_resource_limit_release_hint = 0;
m_resource_limit_release_hint = false;
m_cpu_time = 0;
/* Setup our kernel stack. */
@ -1328,7 +1329,7 @@ namespace ams::kern {
private:
u64 m_id;
public:
constexpr explicit IdObjectHelper(u64 id) : m_id(id) { /* ... */ }
explicit IdObjectHelper(u64 id) : m_id(id) { /* ... */ }
virtual u64 GetId() const override { return m_id; }
};

View file

@ -42,7 +42,7 @@ namespace ams::kern {
}
}
public:
constexpr KUnusedSlabMemory(size_t size) : m_size(size) { /* ... */ }
KUnusedSlabMemory(size_t size) : m_size(size) { /* ... */ }
constexpr ALWAYS_INLINE KVirtualAddress GetAddress() const { return reinterpret_cast<uintptr_t>(this); }
constexpr ALWAYS_INLINE size_t GetSize() const { return m_size; }

View file

@ -26,7 +26,7 @@ namespace ams::os::impl {
private:
void Initialize();
public:
constexpr RngManager() : m_mt(), m_lock(), m_initialized() { /* ... */ }
RngManager() : m_mt(), m_lock(), m_initialized() { /* ... */ }
public:
u64 GenerateRandomU64();
};

View file

@ -20,7 +20,7 @@ namespace ams::os {
namespace {
constinit util::TinyMT g_random;
constinit util::TinyMT g_random{util::ConstantInitialize};
constinit os::SdkMutex g_random_mutex;
constinit bool g_initialized_random;

View file

@ -28,6 +28,7 @@
#pragma once
#include <vapours/common.hpp>
#include <vapours/assert.hpp>
#include <vapours/util/util_type_traits.hpp>
#pragma GCC push_options
#pragma GCC optimize ("-O3")
@ -57,11 +58,14 @@ namespace ams::freebsd {
template<typename T>
class RBEntry {
private:
T *m_rbe_left = nullptr;
T *m_rbe_right = nullptr;
T *m_rbe_parent = nullptr;
RBColor m_rbe_color = RBColor::RB_BLACK;
T *m_rbe_left ;
T *m_rbe_right;
T *m_rbe_parent;
RBColor m_rbe_color;
public:
constexpr ALWAYS_INLINE explicit RBEntry(util::ConstantInitializeTag) : m_rbe_left(nullptr), m_rbe_right(nullptr), m_rbe_parent(nullptr), m_rbe_color(RBColor::RB_BLACK) { /* ... */ }
explicit ALWAYS_INLINE RBEntry() { /* ... */ }
[[nodiscard]] constexpr ALWAYS_INLINE T *Left() { return m_rbe_left; }
[[nodiscard]] constexpr ALWAYS_INLINE const T *Left() const { return m_rbe_left; }

View file

@ -39,7 +39,8 @@ namespace ams::util {
private:
RBEntry m_entry;
public:
constexpr ALWAYS_INLINE IntrusiveRedBlackTreeNode() = default;
constexpr explicit ALWAYS_INLINE IntrusiveRedBlackTreeNode(util::ConstantInitializeTag) : m_entry(util::ConstantInitialize) { /* ... */ }
explicit ALWAYS_INLINE IntrusiveRedBlackTreeNode() { /* ... */ }
[[nodiscard]] constexpr ALWAYS_INLINE RBEntry &GetRBEntry() { return m_entry; }
[[nodiscard]] constexpr ALWAYS_INLINE const RBEntry &GetRBEntry() const { return m_entry; }
@ -544,6 +545,8 @@ namespace ams::util {
template<class Derived>
class alignas(void *) IntrusiveRedBlackTreeBaseNode : public IntrusiveRedBlackTreeNode {
public:
using IntrusiveRedBlackTreeNode::IntrusiveRedBlackTreeNode;
constexpr ALWAYS_INLINE Derived *GetPrev() { return static_cast< Derived *>(static_cast< IntrusiveRedBlackTreeBaseNode *>(impl::IntrusiveRedBlackTreeImpl::GetPrev(this))); }
constexpr ALWAYS_INLINE const Derived *GetPrev() const { return static_cast<const Derived *>(static_cast<const IntrusiveRedBlackTreeBaseNode *>(impl::IntrusiveRedBlackTreeImpl::GetPrev(this))); }

View file

@ -102,9 +102,8 @@ namespace ams::util {
state2 ^= y;
}
public:
constexpr TinyMT() : m_state() { /* ... */ }
/* Public API. */
constexpr explicit TinyMT(util::ConstantInitializeTag) : m_state() { /* ... */ }
explicit TinyMT() { /* ... */ }
/* Initialization. */
void Initialize(u32 seed) {

View file

@ -23,4 +23,7 @@ namespace ams::util {
template<typename T>
using is_pod = std::bool_constant<std::is_standard_layout<T>::value && std::is_trivial<T>::value>;
struct ConstantInitializeTag final {};
constexpr inline const ConstantInitializeTag ConstantInitialize{};
}

View file

@ -19,7 +19,7 @@ namespace ams::kern {
/* Declare kernel data members in kernel TU. */
constinit Kernel::State Kernel::s_state = Kernel::State::Invalid;
constinit KResourceLimit Kernel::s_system_resource_limit;
constinit KResourceLimit Kernel::s_system_resource_limit{util::ConstantInitialize};
KMemoryManager Kernel::s_memory_manager;
constinit KSupervisorPageTable Kernel::s_supervisor_page_table;
constinit KUnsafeMemory Kernel::s_unsafe_memory;
@ -33,8 +33,8 @@ namespace ams::kern {
constinit KMemoryBlockSlabHeap Kernel::s_app_memory_block_heap;
constinit KMemoryBlockSlabHeap Kernel::s_sys_memory_block_heap;
constinit KBlockInfoSlabHeap Kernel::s_block_info_heap;
constinit KPageTableManager Kernel::s_app_page_table_manager;
constinit KPageTableManager Kernel::s_sys_page_table_manager;
constinit KPageTableManager Kernel::s_app_page_table_manager{util::ConstantInitialize};
constinit KPageTableManager Kernel::s_sys_page_table_manager{util::ConstantInitialize};
constinit KMemoryBlockSlabManager Kernel::s_app_memory_block_manager;
constinit KMemoryBlockSlabManager Kernel::s_sys_memory_block_manager;
constinit KBlockInfoManager Kernel::s_app_block_info_manager;
@ -42,11 +42,70 @@ namespace ams::kern {
namespace {
constinit std::array<KThread, cpu::NumCores> g_main_threads;
constinit std::array<KThread, cpu::NumCores> g_idle_threads;
template<size_t N> requires (N > 0)
union KThreadArray {
struct RecursiveHolder {
KThread m_thread;
KThreadArray<N - 1> m_next;
consteval RecursiveHolder() : m_thread{util::ConstantInitialize}, m_next() { /* ... */ }
} m_holder;
KThread m_arr[N];
consteval KThreadArray() : m_holder() { /* ... */ }
};
template<>
union KThreadArray<1>{
struct RecursiveHolder {
KThread m_thread;
consteval RecursiveHolder() : m_thread{util::ConstantInitialize} { /* ... */ }
} m_holder;
KThread m_arr[1];
consteval KThreadArray() : m_holder() { /* ... */ }
};
template<size_t Ix>
consteval bool IsKThreadArrayValid(const KThreadArray<Ix> &v, const KThread *thread) {
if (std::addressof(v.m_holder.m_thread) != thread) {
return false;
}
if constexpr (Ix == 1) {
return true;
} else {
return IsKThreadArrayValid(v.m_holder.m_next, thread + 1);
}
}
template<size_t N>
consteval bool IsKThreadArrayValid() {
const KThreadArray<N> v{};
if (!IsKThreadArrayValid(v, v.m_arr)) {
return false;
}
if constexpr (N == 1) {
return true;
} else {
return IsKThreadArrayValid<N - 1>();
}
}
static_assert(IsKThreadArrayValid<cpu::NumCores>());
constinit KThreadArray<cpu::NumCores> g_main_threads;
constinit KThreadArray<cpu::NumCores> g_idle_threads;
static_assert(sizeof(g_main_threads) == cpu::NumCores * sizeof(KThread));
static_assert(sizeof(g_main_threads.m_holder) == sizeof(g_main_threads.m_arr));
}
KThread &Kernel::GetMainThread(s32 core_id) { return g_main_threads[core_id]; }
KThread &Kernel::GetIdleThread(s32 core_id) { return g_idle_threads[core_id]; }
KThread &Kernel::GetMainThread(s32 core_id) { return g_main_threads.m_arr[core_id]; }
KThread &Kernel::GetIdleThread(s32 core_id) { return g_idle_threads.m_arr[core_id]; }
}

View file

@ -33,7 +33,7 @@ namespace ams::dmnt::cheat::impl {
u64 m_address;
FrozenAddressValue m_value;
public:
constexpr FrozenAddressMapEntry(u64 address, FrozenAddressValue value) : m_address(address), m_value(value) { /* ... */ }
FrozenAddressMapEntry(u64 address, FrozenAddressValue value) : m_address(address), m_value(value) { /* ... */ }
constexpr u64 GetAddress() const { return m_address; }