mirror of
https://github.com/Atmosphere-NX/Atmosphere
synced 2024-12-22 20:31:14 +00:00
ams: take care of most TODO C++20s
This commit is contained in:
parent
13bfeed2d5
commit
232203f4c0
30 changed files with 174 additions and 431 deletions
|
@ -185,10 +185,7 @@ namespace ams::kern {
|
||||||
T *obj;
|
T *obj;
|
||||||
private:
|
private:
|
||||||
constexpr ALWAYS_INLINE void Swap(KScopedAutoObject &rhs) {
|
constexpr ALWAYS_INLINE void Swap(KScopedAutoObject &rhs) {
|
||||||
/* TODO: C++20 constexpr std::swap */
|
std::swap(this->obj, rhs.obj);
|
||||||
T *tmp = rhs.obj;
|
|
||||||
rhs.obj = this->obj;
|
|
||||||
this->obj = tmp;
|
|
||||||
}
|
}
|
||||||
public:
|
public:
|
||||||
constexpr ALWAYS_INLINE KScopedAutoObject() : obj(nullptr) { /* ... */ }
|
constexpr ALWAYS_INLINE KScopedAutoObject() : obj(nullptr) { /* ... */ }
|
||||||
|
|
|
@ -64,7 +64,7 @@ namespace ams::kern {
|
||||||
|
|
||||||
static constexpr u32 GetCapabilityId(CapabilityType type) {
|
static constexpr u32 GetCapabilityId(CapabilityType type) {
|
||||||
const u32 flag = GetCapabilityFlag(type);
|
const u32 flag = GetCapabilityFlag(type);
|
||||||
if (true /* C++20: std::is_constant_evaluated() */) {
|
if (std::is_constant_evaluated()) {
|
||||||
return CountTrailingZero(flag);
|
return CountTrailingZero(flag);
|
||||||
} else {
|
} else {
|
||||||
return static_cast<u32>(__builtin_ctz(flag));
|
return static_cast<u32>(__builtin_ctz(flag));
|
||||||
|
@ -84,7 +84,7 @@ namespace ams::kern {
|
||||||
template<CapabilityType Type>
|
template<CapabilityType Type>
|
||||||
static constexpr inline u32 CapabilityId = []() -> u32 {
|
static constexpr inline u32 CapabilityId = []() -> u32 {
|
||||||
const u32 flag = static_cast<u32>(Type) + 1;
|
const u32 flag = static_cast<u32>(Type) + 1;
|
||||||
if (true /* C++20: std::is_constant_evaluated() */) {
|
if (std::is_constant_evaluated()) {
|
||||||
for (u32 i = 0; i < BITSIZEOF(u32); i++) {
|
for (u32 i = 0; i < BITSIZEOF(u32); i++) {
|
||||||
if (flag & (1u << i)) {
|
if (flag & (1u << i)) {
|
||||||
return i;
|
return i;
|
||||||
|
|
|
@ -18,39 +18,34 @@
|
||||||
|
|
||||||
namespace ams::kern {
|
namespace ams::kern {
|
||||||
|
|
||||||
/*
|
template<typename T>
|
||||||
TODO: C++20
|
concept KPriorityQueueAffinityMask = !std::is_reference<T>::value && requires (T &t) {
|
||||||
|
{ t.GetAffinityMask() } -> std::convertible_to<u64>;
|
||||||
|
{ t.SetAffinityMask(std::declval<u64>()) };
|
||||||
|
|
||||||
template<typename T>
|
{ t.GetAffinity(std::declval<int32_t>()) } -> std::same_as<bool>;
|
||||||
concept KPriorityQueueAffinityMask = !std::is_reference<T>::value && requires (T &t) {
|
{ t.SetAffinity(std::declval<int32_t>(), std::declval<bool>()) };
|
||||||
{ t.GetAffinityMask() } -> std::convertible_to<u64>;
|
{ t.SetAll() };
|
||||||
{ t.SetAffinityMask(std::declval<u64>()) };
|
};
|
||||||
|
|
||||||
{ t.GetAffinity(std::declval<int32_t>()) } -> std::same_as<bool>;
|
template<typename T>
|
||||||
{ t.SetAffinity(std::declval<int32_t>(), std::declval<bool>()) };
|
concept KPriorityQueueMember = !std::is_reference<T>::value && requires (T &t) {
|
||||||
{ t.SetAll() };
|
{ typename T::QueueEntry() };
|
||||||
};
|
{ (typename T::QueueEntry()).Initialize() };
|
||||||
|
{ (typename T::QueueEntry()).SetPrev(std::addressof(t)) };
|
||||||
|
{ (typename T::QueueEntry()).SetNext(std::addressof(t)) };
|
||||||
|
{ (typename T::QueueEntry()).GetNext() } -> std::same_as<T*>;
|
||||||
|
{ (typename T::QueueEntry()).GetPrev() } -> std::same_as<T*>;
|
||||||
|
{ t.GetPriorityQueueEntry(std::declval<s32>()) } -> std::same_as<typename T::QueueEntry &>;
|
||||||
|
|
||||||
template<typename T>
|
{ t.GetAffinityMask() };
|
||||||
concept KPriorityQueueMember = !std::is_reference<T>::value && requires (T &t) {
|
{ typename std::remove_cvref<decltype(t.GetAffinityMask())>::type() } -> KPriorityQueueAffinityMask;
|
||||||
{ typename T::QueueEntry() };
|
|
||||||
{ (typename T::QueueEntry()).Initialize() };
|
|
||||||
{ (typename T::QueueEntry()).SetPrev(std::addressof(t)) };
|
|
||||||
{ (typename T::QueueEntry()).SetNext(std::addressof(t)) };
|
|
||||||
{ (typename T::QueueEntry()).GetNext() } -> std::same_as<T*>;
|
|
||||||
{ (typename T::QueueEntry()).GetPrev() } -> std::same_as<T*>;
|
|
||||||
{ t.GetPriorityQueueEntry(std::declval<s32>()) } -> std::same_as<typename T::QueueEntry &>;
|
|
||||||
|
|
||||||
{ t.GetAffinityMask() };
|
{ t.GetActiveCore() } -> std::convertible_to<s32>;
|
||||||
{ typename std::remove_cvref<decltype(t.GetAffinityMask())>::type() } -> KPriorityQueueAffinityMask;
|
{ t.GetPriority() } -> std::convertible_to<s32>;
|
||||||
|
};
|
||||||
|
|
||||||
{ t.GetActiveCore() } -> std::convertible_to<s32>;
|
template<typename Member, size_t _NumCores, int LowestPriority, int HighestPriority> requires KPriorityQueueMember<Member>
|
||||||
{ t.GetPriority() } -> std::convertible_to<s32>;
|
|
||||||
};
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
template<typename Member, size_t _NumCores, int LowestPriority, int HighestPriority> /* TODO C++20: requires KPriorityQueueMember<Member> */
|
|
||||||
class KPriorityQueue {
|
class KPriorityQueue {
|
||||||
public:
|
public:
|
||||||
using AffinityMaskType = typename std::remove_cv<typename std::remove_reference<decltype(std::declval<Member>().GetAffinityMask())>::type>::type;
|
using AffinityMaskType = typename std::remove_cv<typename std::remove_reference<decltype(std::declval<Member>().GetAffinityMask())>::type>::type;
|
||||||
|
|
|
@ -33,8 +33,6 @@ namespace ams::kern {
|
||||||
NON_COPYABLE(KScheduler);
|
NON_COPYABLE(KScheduler);
|
||||||
NON_MOVEABLE(KScheduler);
|
NON_MOVEABLE(KScheduler);
|
||||||
public:
|
public:
|
||||||
using LockType = KAbstractSchedulerLock<KScheduler>;
|
|
||||||
|
|
||||||
static constexpr s32 HighestCoreMigrationAllowedPriority = 2;
|
static constexpr s32 HighestCoreMigrationAllowedPriority = 2;
|
||||||
static_assert(ams::svc::LowestThreadPriority >= HighestCoreMigrationAllowedPriority);
|
static_assert(ams::svc::LowestThreadPriority >= HighestCoreMigrationAllowedPriority);
|
||||||
static_assert(ams::svc::HighestThreadPriority <= HighestCoreMigrationAllowedPriority);
|
static_assert(ams::svc::HighestThreadPriority <= HighestCoreMigrationAllowedPriority);
|
||||||
|
@ -50,9 +48,6 @@ namespace ams::kern {
|
||||||
private:
|
private:
|
||||||
friend class KScopedSchedulerLock;
|
friend class KScopedSchedulerLock;
|
||||||
friend class KScopedSchedulerLockAndSleep;
|
friend class KScopedSchedulerLockAndSleep;
|
||||||
static bool s_scheduler_update_needed;
|
|
||||||
static LockType s_scheduler_lock;
|
|
||||||
static KSchedulerPriorityQueue s_priority_queue;
|
|
||||||
private:
|
private:
|
||||||
SchedulingState state;
|
SchedulingState state;
|
||||||
bool is_active;
|
bool is_active;
|
||||||
|
@ -160,6 +155,12 @@ namespace ams::kern {
|
||||||
}
|
}
|
||||||
|
|
||||||
NOINLINE u64 UpdateHighestPriorityThread(KThread *thread);
|
NOINLINE u64 UpdateHighestPriorityThread(KThread *thread);
|
||||||
|
public:
|
||||||
|
using LockType = KAbstractSchedulerLock<KScheduler>;
|
||||||
|
private:
|
||||||
|
static bool s_scheduler_update_needed;
|
||||||
|
static KSchedulerPriorityQueue s_priority_queue;
|
||||||
|
static LockType s_scheduler_lock;
|
||||||
};
|
};
|
||||||
|
|
||||||
class KScopedSchedulerLock : KScopedLock<KScheduler::LockType> {
|
class KScopedSchedulerLock : KScopedLock<KScheduler::LockType> {
|
||||||
|
|
|
@ -23,19 +23,14 @@ namespace ams::kern {
|
||||||
|
|
||||||
class KThread;
|
class KThread;
|
||||||
|
|
||||||
/*
|
template<typename T>
|
||||||
TODO: C++20
|
concept KSchedulerLockable = !std::is_reference<T>::value && requires(T) {
|
||||||
|
{ T::DisableScheduling() } -> std::same_as<void>;
|
||||||
|
{ T::EnableScheduling(std::declval<u64>()) } -> std::same_as<void>;
|
||||||
|
{ T::UpdateHighestPriorityThreads() } -> std::convertible_to<u64>;
|
||||||
|
};
|
||||||
|
|
||||||
template<typename T>
|
template<typename SchedulerType> requires KSchedulerLockable<SchedulerType>
|
||||||
concept KSchedulerLockable = !std::is_reference<T>::value && requires {
|
|
||||||
{ T::DisableScheduling() } -> std::same_as<void>;
|
|
||||||
{ T::EnableScheduling(std::declval<u64>()) } -> std::same_as<void>;
|
|
||||||
{ T::UpdateHighestPriorityThreads() } -> std::convertible_to<u64>;
|
|
||||||
};
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
template<typename SchedulerType> /* TODO C++20: requires KSchedulerLockable<SchedulerType> */
|
|
||||||
class KAbstractSchedulerLock {
|
class KAbstractSchedulerLock {
|
||||||
private:
|
private:
|
||||||
KAlignedSpinLock spin_lock;
|
KAlignedSpinLock spin_lock;
|
||||||
|
|
|
@ -18,18 +18,13 @@
|
||||||
|
|
||||||
namespace ams::kern {
|
namespace ams::kern {
|
||||||
|
|
||||||
/*
|
template<typename T>
|
||||||
TODO: C++20
|
concept KLockable = !std::is_reference<T>::value && requires (T &t) {
|
||||||
|
{ t.Lock() } -> std::same_as<void>;
|
||||||
|
{ t.Unlock() } -> std::same_as<void>;
|
||||||
|
};
|
||||||
|
|
||||||
template<typename T>
|
template<typename T> requires KLockable<T>
|
||||||
concept KLockable = !std::is_reference<T>::value && requires (T &t) {
|
|
||||||
{ t.Lock() } -> std::same_as<void>;
|
|
||||||
{ t.Unlock() } -> std::same_as<void>;
|
|
||||||
};
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
template<typename T> /* TODO C++20: requires KLockable<T> */
|
|
||||||
class KScopedLock {
|
class KScopedLock {
|
||||||
NON_COPYABLE(KScopedLock);
|
NON_COPYABLE(KScopedLock);
|
||||||
NON_MOVEABLE(KScopedLock);
|
NON_MOVEABLE(KScopedLock);
|
||||||
|
|
|
@ -22,47 +22,35 @@ namespace ams::kern::svc {
|
||||||
|
|
||||||
namespace impl {
|
namespace impl {
|
||||||
|
|
||||||
/* TODO: C++20
|
template<typename T>
|
||||||
template<typename T>
|
concept Pointer = std::is_pointer<T>::value;
|
||||||
concept Pointer = std::is_pointer<T>::value;
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
concept NonConstPointer = Pointer<T> && !std::is_const<typename std::remove_pointer<T>::type>::value;
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
concept ConstPointer = Pointer<T> && std::is_const<typename std::remove_pointer<T>::type>::value;
|
|
||||||
|
|
||||||
template<typename T, size_t N>
|
|
||||||
concept AlignedNPointer = Pointer<T> && alignof(typename std::remove_pointer<T>::type) >= N && util::IsAligned(sizeof(typename std::remove_pointer<T>::type), N);
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
concept Aligned8Pointer = AlignedNPointer<T, sizeof(u8)>;
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
concept Aligned16Pointer = AlignedNPointer<T, sizeof(u16)> && Aligned8<T>;
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
concept Aligned32Pointer = AlignedNPointer<T, sizeof(u32)> && Aligned16<T>;
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
concept Aligned64Pointer = AlignedNPointer<T, sizeof(u64)> && Aligned32<T>;
|
|
||||||
*/
|
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
constexpr inline bool IsPointer = std::is_pointer<T>::value;
|
concept NonConstPointer = Pointer<T> && !std::is_const<typename std::remove_pointer<T>::type>::value;
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
constexpr inline bool IsConstPointer = IsPointer<T> && std::is_const<typename std::remove_pointer<T>::type>::value;
|
concept ConstPointer = Pointer<T> && std::is_const<typename std::remove_pointer<T>::type>::value;
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
constexpr inline bool IsNonConstPointer = IsPointer<T> && !std::is_const<typename std::remove_pointer<T>::type>::value;
|
|
||||||
|
|
||||||
template<typename T, size_t N>
|
template<typename T, size_t N>
|
||||||
constexpr inline bool IsAlignedNPointer = IsPointer<T> && alignof(typename std::remove_pointer<T>::type) >= N && util::IsAligned(sizeof(typename std::remove_pointer<T>::type), N);
|
concept AlignedNPointer = Pointer<T> && alignof(typename std::remove_pointer<T>::type) >= N && util::IsAligned(sizeof(typename std::remove_pointer<T>::type), N);
|
||||||
|
|
||||||
template<typename _T, typename = void> /* requires Aligned8Pointer<_T> */
|
template<typename T>
|
||||||
class KUserPointerImplTraits {
|
concept Aligned8Pointer = AlignedNPointer<T, sizeof(u8)>;
|
||||||
static_assert(IsAlignedNPointer<_T, sizeof(u8)>);
|
|
||||||
|
template<typename T>
|
||||||
|
concept Aligned16Pointer = AlignedNPointer<T, sizeof(u16)> && Aligned8Pointer<T>;
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
concept Aligned32Pointer = AlignedNPointer<T, sizeof(u32)> && Aligned16Pointer<T>;
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
concept Aligned64Pointer = AlignedNPointer<T, sizeof(u64)> && Aligned32Pointer<T>;
|
||||||
|
|
||||||
|
template<typename _T>
|
||||||
|
class KUserPointerImplTraits;
|
||||||
|
|
||||||
|
template<typename _T> requires Aligned8Pointer<_T>
|
||||||
|
class KUserPointerImplTraits<_T> {
|
||||||
public:
|
public:
|
||||||
using T = typename std::remove_const<typename std::remove_pointer<_T>::type>::type;
|
using T = typename std::remove_const<typename std::remove_pointer<_T>::type>::type;
|
||||||
public:
|
public:
|
||||||
|
@ -77,9 +65,8 @@ namespace ams::kern::svc {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename _T> /* requires Aligned32Pointer<_T> */
|
template<typename _T> requires Aligned32Pointer<_T>
|
||||||
class KUserPointerImplTraits<_T, typename std::enable_if<IsAlignedNPointer<_T, sizeof(u32)> && !IsAlignedNPointer<_T, sizeof(u64)>>::type> {
|
class KUserPointerImplTraits<_T> {
|
||||||
static_assert(IsAlignedNPointer<_T, sizeof(u32)>);
|
|
||||||
public:
|
public:
|
||||||
using T = typename std::remove_const<typename std::remove_pointer<_T>::type>::type;
|
using T = typename std::remove_const<typename std::remove_pointer<_T>::type>::type;
|
||||||
public:
|
public:
|
||||||
|
@ -94,9 +81,8 @@ namespace ams::kern::svc {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename _T> /* requires Aligned64Pointer<_T> */
|
template<typename _T> requires Aligned64Pointer<_T>
|
||||||
class KUserPointerImplTraits<_T, typename std::enable_if<IsAlignedNPointer<_T, sizeof(u64)>>::type> {
|
class KUserPointerImplTraits<_T> {
|
||||||
static_assert(IsAlignedNPointer<_T, sizeof(u64)>);
|
|
||||||
public:
|
public:
|
||||||
using T = typename std::remove_const<typename std::remove_pointer<_T>::type>::type;
|
using T = typename std::remove_const<typename std::remove_pointer<_T>::type>::type;
|
||||||
public:
|
public:
|
||||||
|
@ -111,8 +97,11 @@ namespace ams::kern::svc {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename _T> /* requires Aligned8Pointer<_T> */
|
template<typename _T>
|
||||||
class KUserPointerImpl : impl::KUserPointerTag {
|
class KUserPointerImpl;
|
||||||
|
|
||||||
|
template<typename _T> requires Aligned8Pointer<_T>
|
||||||
|
class KUserPointerImpl<_T> : impl::KUserPointerTag {
|
||||||
private:
|
private:
|
||||||
using Traits = KUserPointerImplTraits<_T>;
|
using Traits = KUserPointerImplTraits<_T>;
|
||||||
protected:
|
protected:
|
||||||
|
@ -170,11 +159,11 @@ namespace ams::kern::svc {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T, typename = void>
|
template<typename T>
|
||||||
class KUserPointer;
|
struct KUserPointer;
|
||||||
|
|
||||||
template<typename T> /* requires impl::ConstPointer<T> */
|
template<typename T> requires impl::ConstPointer<T>
|
||||||
struct KUserPointer<T, typename std::enable_if<impl::IsConstPointer<T>>::type> : public impl::KUserPointerImpl<T> {
|
struct KUserPointer<T> : public impl::KUserPointerImpl<T> {
|
||||||
public:
|
public:
|
||||||
static constexpr bool IsInput = true;
|
static constexpr bool IsInput = true;
|
||||||
public:
|
public:
|
||||||
|
@ -186,8 +175,8 @@ namespace ams::kern::svc {
|
||||||
using impl::KUserPointerImpl<T>::GetUnsafePointer;
|
using impl::KUserPointerImpl<T>::GetUnsafePointer;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename T> /* requires impl::NonConstPointer<T> */
|
template<typename T> requires impl::NonConstPointer<T>
|
||||||
struct KUserPointer<T, typename std::enable_if<impl::IsNonConstPointer<T>>::type> : public impl::KUserPointerImpl<T> {
|
struct KUserPointer<T> : public impl::KUserPointerImpl<T> {
|
||||||
public:
|
public:
|
||||||
static constexpr bool IsInput = false;
|
static constexpr bool IsInput = false;
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -19,9 +19,8 @@ namespace ams::kern {
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
/* TODO: C++20 constinit */
|
constinit KLightLock g_object_list_lock;
|
||||||
KLightLock g_object_list_lock;
|
constinit KObjectName::List g_object_list;
|
||||||
KObjectName::List g_object_list;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -77,7 +77,7 @@ namespace ams::sf {
|
||||||
class Out<std::shared_ptr<ServiceImpl>> : public impl::OutObjectTag {
|
class Out<std::shared_ptr<ServiceImpl>> : public impl::OutObjectTag {
|
||||||
static_assert(std::is_base_of<sf::IServiceObject, ServiceImpl>::value, "Out<std::shared_ptr<ServiceImpl>> requires ServiceObject base.");
|
static_assert(std::is_base_of<sf::IServiceObject, ServiceImpl>::value, "Out<std::shared_ptr<ServiceImpl>> requires ServiceObject base.");
|
||||||
|
|
||||||
template<typename, typename>
|
template<typename>
|
||||||
friend class Out;
|
friend class Out;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@ -308,11 +308,7 @@ namespace ams::sf::impl {
|
||||||
/* Use insertion sort, which is stable and optimal for small numbers of parameters. */
|
/* Use insertion sort, which is stable and optimal for small numbers of parameters. */
|
||||||
for (size_t i = 1; i < sizeof...(Ts); i++) {
|
for (size_t i = 1; i < sizeof...(Ts); i++) {
|
||||||
for (size_t j = i; j > 0 && values[map[j-1]] > values[map[j]]; j--) {
|
for (size_t j = i; j > 0 && values[map[j-1]] > values[map[j]]; j--) {
|
||||||
/* std::swap is not constexpr until c++20 :( */
|
std::swap(map[j], map[j-1]);
|
||||||
/* TODO: std::swap(map[j], map[j-1]); */
|
|
||||||
const size_t tmp = map[j];
|
|
||||||
map[j] = map[j-1];
|
|
||||||
map[j-1] = tmp;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,9 +33,9 @@ namespace ams::sf {
|
||||||
struct IsOutForceEnabled<::ams::Result> : public std::true_type{};
|
struct IsOutForceEnabled<::ams::Result> : public std::true_type{};
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
using IsOutEnabled = typename std::enable_if<std::is_trivial<T>::value || IsOutForceEnabled<T>::value>::type;
|
concept OutEnabled = (std::is_trivial<T>::value || IsOutForceEnabled<T>::value) && !std::is_pointer<T>::value;
|
||||||
|
|
||||||
template<typename T, typename = IsOutEnabled<T>>
|
template<typename T> requires OutEnabled<T>
|
||||||
class Out : public impl::OutBaseTag {
|
class Out : public impl::OutBaseTag {
|
||||||
public:
|
public:
|
||||||
static constexpr size_t TypeSize = sizeof(T);
|
static constexpr size_t TypeSize = sizeof(T);
|
||||||
|
|
|
@ -18,7 +18,6 @@
|
||||||
|
|
||||||
namespace ams::os::impl {
|
namespace ams::os::impl {
|
||||||
|
|
||||||
/* TODO: C++20 constinit */
|
constinit TYPED_STORAGE(OsResourceManager) ResourceManagerHolder::s_resource_manager_storage = {};
|
||||||
TYPED_STORAGE(OsResourceManager) ResourceManagerHolder::s_resource_manager_storage = {};
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,7 +23,7 @@
|
||||||
|
|
||||||
namespace ams::crypto {
|
namespace ams::crypto {
|
||||||
|
|
||||||
template<size_t ModulusSize, typename Hash> /* requires HashFunction<Hash> */
|
template<size_t ModulusSize, typename Hash> requires impl::HashFunction<Hash>
|
||||||
class RsaOaepDecryptor {
|
class RsaOaepDecryptor {
|
||||||
NON_COPYABLE(RsaOaepDecryptor);
|
NON_COPYABLE(RsaOaepDecryptor);
|
||||||
NON_MOVEABLE(RsaOaepDecryptor);
|
NON_MOVEABLE(RsaOaepDecryptor);
|
||||||
|
|
|
@ -23,7 +23,7 @@
|
||||||
|
|
||||||
namespace ams::crypto {
|
namespace ams::crypto {
|
||||||
|
|
||||||
template<size_t ModulusSize, typename Hash> /* requires HashFunction<Hash> */
|
template<size_t ModulusSize, typename Hash> requires impl::HashFunction<Hash>
|
||||||
class RsaOaepEncryptor {
|
class RsaOaepEncryptor {
|
||||||
NON_COPYABLE(RsaOaepEncryptor);
|
NON_COPYABLE(RsaOaepEncryptor);
|
||||||
NON_MOVEABLE(RsaOaepEncryptor);
|
NON_MOVEABLE(RsaOaepEncryptor);
|
||||||
|
|
|
@ -23,7 +23,7 @@
|
||||||
|
|
||||||
namespace ams::crypto {
|
namespace ams::crypto {
|
||||||
|
|
||||||
template<size_t _ModulusSize, typename Hash> /* requires HashFunction<Hash> */
|
template<size_t _ModulusSize, typename Hash> requires impl::HashFunction<Hash>
|
||||||
class RsaPssVerifier {
|
class RsaPssVerifier {
|
||||||
NON_COPYABLE(RsaPssVerifier);
|
NON_COPYABLE(RsaPssVerifier);
|
||||||
NON_MOVEABLE(RsaPssVerifier);
|
NON_MOVEABLE(RsaPssVerifier);
|
||||||
|
|
|
@ -23,15 +23,13 @@
|
||||||
|
|
||||||
namespace ams::crypto::impl {
|
namespace ams::crypto::impl {
|
||||||
|
|
||||||
/* TODO: C++20
|
template<typename T>
|
||||||
template<typename T>
|
concept HashFunction = requires(T &t, const void *cv, void *v, size_t sz) {
|
||||||
concept HashFunction = requires(T &t, const void *cv, void *v, size_t sz) {
|
{ T::HashSize } -> std::convertible_to<size_t>;
|
||||||
{ T::HashSize } -> std::same_as<size_t>;
|
{ T::BlockSize } -> std::convertible_to<size_t>;
|
||||||
{ T::BlockSize } -> std::same_as<size_t>;
|
{ t.Initialize() } -> std::same_as<void>;
|
||||||
{ t.Initialize() } -> std::same_as<void>;
|
{ t.Update(cv, sz) } -> std::same_as<void>;
|
||||||
{ t.Update(cv, sz) } -> std::same_as<void>;
|
{ t.GetHash(v, sz) } -> std::same_as<void>;
|
||||||
{ t.GetHash(v, sz) } -> std::same_as<void>;
|
};
|
||||||
};
|
|
||||||
*/
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,7 +22,7 @@
|
||||||
|
|
||||||
namespace ams::crypto::impl {
|
namespace ams::crypto::impl {
|
||||||
|
|
||||||
template<typename Hash> /* requires HashFunction<Hash> */
|
template<typename Hash> requires HashFunction<Hash>
|
||||||
class RsaOaepImpl {
|
class RsaOaepImpl {
|
||||||
NON_COPYABLE(RsaOaepImpl);
|
NON_COPYABLE(RsaOaepImpl);
|
||||||
NON_MOVEABLE(RsaOaepImpl);
|
NON_MOVEABLE(RsaOaepImpl);
|
||||||
|
|
|
@ -22,7 +22,7 @@
|
||||||
|
|
||||||
namespace ams::crypto::impl {
|
namespace ams::crypto::impl {
|
||||||
|
|
||||||
template<typename Hash> /* requires HashFunction<Hash> */
|
template<typename Hash> requires HashFunction<Hash>
|
||||||
class RsaPssImpl {
|
class RsaPssImpl {
|
||||||
NON_COPYABLE(RsaPssImpl);
|
NON_COPYABLE(RsaPssImpl);
|
||||||
NON_MOVEABLE(RsaPssImpl);
|
NON_MOVEABLE(RsaPssImpl);
|
||||||
|
|
|
@ -66,6 +66,6 @@ namespace ams::crypto::impl {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/* static_assert(HashFunction<Sha256Impl>); */
|
static_assert(HashFunction<Sha256Impl>);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,6 +28,7 @@
|
||||||
|
|
||||||
/* C++ headers. */
|
/* C++ headers. */
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
|
#include <concepts>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <iterator>
|
#include <iterator>
|
||||||
#include <limits>
|
#include <limits>
|
||||||
|
@ -38,6 +39,8 @@
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <tuple>
|
#include <tuple>
|
||||||
#include <array>
|
#include <array>
|
||||||
|
#include <bit>
|
||||||
|
#include <span>
|
||||||
|
|
||||||
/* Stratosphere wants additional libstdc++ headers, others do not. */
|
/* Stratosphere wants additional libstdc++ headers, others do not. */
|
||||||
#ifdef ATMOSPHERE_IS_STRATOSPHERE
|
#ifdef ATMOSPHERE_IS_STRATOSPHERE
|
||||||
|
|
|
@ -19,207 +19,7 @@
|
||||||
|
|
||||||
namespace ams {
|
namespace ams {
|
||||||
|
|
||||||
/* TODO C++20 switch to template<typename T> using Span = std::span<T> */
|
|
||||||
|
|
||||||
namespace impl {
|
|
||||||
|
|
||||||
template<typename Span>
|
|
||||||
class SpanConstIterator;
|
|
||||||
|
|
||||||
template<typename Span, typename Derived, typename Reference>
|
|
||||||
class SpanIteratorImpl {
|
|
||||||
public:
|
|
||||||
friend class SpanConstIterator<Span>;
|
|
||||||
|
|
||||||
using index_type = typename Span::index_type;
|
|
||||||
using difference_type = typename Span::difference_type;
|
|
||||||
using value_type = typename std::remove_cv<typename Span::element_type>::type;
|
|
||||||
using pointer = typename std::add_pointer<Reference>::type;
|
|
||||||
using reference = Reference;
|
|
||||||
using iterator_category = std::random_access_iterator_tag;
|
|
||||||
private:
|
|
||||||
const Span *span = nullptr;
|
|
||||||
index_type index = 0;
|
|
||||||
public:
|
|
||||||
constexpr ALWAYS_INLINE SpanIteratorImpl() = default;
|
|
||||||
constexpr ALWAYS_INLINE SpanIteratorImpl(const Span *s, index_type idx) : span(s), index(idx) { /* ... */ }
|
|
||||||
|
|
||||||
constexpr ALWAYS_INLINE pointer operator->() const {
|
|
||||||
return this->span->data() + this->index;
|
|
||||||
}
|
|
||||||
|
|
||||||
constexpr ALWAYS_INLINE reference operator*() const {
|
|
||||||
return *this->operator->();
|
|
||||||
}
|
|
||||||
|
|
||||||
constexpr ALWAYS_INLINE Derived operator++(int) {
|
|
||||||
auto prev = static_cast<Derived &>(*this);
|
|
||||||
++(*this);
|
|
||||||
return prev;
|
|
||||||
}
|
|
||||||
|
|
||||||
constexpr ALWAYS_INLINE Derived operator--(int) {
|
|
||||||
auto prev = static_cast<Derived &>(*this);
|
|
||||||
--(*this);
|
|
||||||
return prev;
|
|
||||||
}
|
|
||||||
|
|
||||||
constexpr ALWAYS_INLINE Derived &operator++() { ++this->index; return static_cast<Derived &>(*this); }
|
|
||||||
constexpr ALWAYS_INLINE Derived &operator--() { --this->index; return static_cast<Derived &>(*this); }
|
|
||||||
|
|
||||||
constexpr ALWAYS_INLINE Derived &operator+=(difference_type n) { this->index += n; return static_cast<Derived &>(*this); }
|
|
||||||
constexpr ALWAYS_INLINE Derived &operator-=(difference_type n) { this->index -= n; return static_cast<Derived &>(*this); }
|
|
||||||
|
|
||||||
constexpr ALWAYS_INLINE Derived operator+(difference_type n) const { auto r = static_cast<const Derived &>(*this); return r += n; }
|
|
||||||
constexpr ALWAYS_INLINE Derived operator-(difference_type n) const { auto r = static_cast<const Derived &>(*this); return r -= n; }
|
|
||||||
|
|
||||||
constexpr ALWAYS_INLINE friend Derived operator+(difference_type n, Derived it) { return it + n; }
|
|
||||||
constexpr ALWAYS_INLINE difference_type operator-(Derived rhs) const { AMS_ASSERT(this->span == rhs.span); return this->index - rhs.index; }
|
|
||||||
|
|
||||||
constexpr ALWAYS_INLINE reference operator[](difference_type n) const { return *(*this + n); }
|
|
||||||
|
|
||||||
constexpr ALWAYS_INLINE friend bool operator==(Derived lhs, Derived rhs) {
|
|
||||||
return lhs.span == rhs.span && lhs.index == rhs.index;
|
|
||||||
}
|
|
||||||
|
|
||||||
constexpr ALWAYS_INLINE friend bool operator<(Derived lhs, Derived rhs) {
|
|
||||||
AMS_ASSERT(lhs.span == rhs.span);
|
|
||||||
return lhs.index < rhs.index;
|
|
||||||
}
|
|
||||||
|
|
||||||
constexpr ALWAYS_INLINE friend bool operator!=(Derived lhs, Derived rhs) { return !(lhs == rhs); }
|
|
||||||
|
|
||||||
constexpr ALWAYS_INLINE friend bool operator>(Derived lhs, Derived rhs) { return rhs < lhs; }
|
|
||||||
|
|
||||||
constexpr ALWAYS_INLINE friend bool operator<=(Derived lhs, Derived rhs) { return !(lhs > rhs); }
|
|
||||||
constexpr ALWAYS_INLINE friend bool operator>=(Derived lhs, Derived rhs) { return !(lhs < rhs); }
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename Span>
|
|
||||||
class SpanIterator : public SpanIteratorImpl<Span, SpanIterator<Span>, typename Span::element_type&> {
|
|
||||||
public:
|
|
||||||
using SpanIteratorImpl<Span, SpanIterator<Span>, typename Span::element_type&>::SpanIteratorImpl;
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename Span>
|
|
||||||
class SpanConstIterator : public SpanIteratorImpl<Span, SpanConstIterator<Span>, const typename Span::element_type&> {
|
|
||||||
public:
|
|
||||||
using SpanIteratorImpl<Span, SpanConstIterator<Span>, const typename Span::element_type&>::SpanIteratorImpl;
|
|
||||||
|
|
||||||
constexpr ALWAYS_INLINE SpanConstIterator() = default;
|
|
||||||
constexpr ALWAYS_INLINE SpanConstIterator(const SpanIterator<Span> &rhs) : SpanConstIterator(rhs.span, rhs.index) { /* ... */ }
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
class Span {
|
using Span = std::span<T>;
|
||||||
public:
|
|
||||||
using element_type = T;
|
|
||||||
using value_type = typename std::remove_cv<element_type>::type;
|
|
||||||
using index_type = std::ptrdiff_t;
|
|
||||||
using difference_type = std::ptrdiff_t;
|
|
||||||
using pointer = element_type *;
|
|
||||||
using reference = element_type &;
|
|
||||||
using iterator = ::ams::impl::SpanIterator<Span>;
|
|
||||||
using const_iterator = ::ams::impl::SpanConstIterator<Span>;
|
|
||||||
using reverse_iterator = std::reverse_iterator<iterator>;
|
|
||||||
using const_reverse_iterator = std::reverse_iterator<const_iterator>;
|
|
||||||
private:
|
|
||||||
T *ptr;
|
|
||||||
index_type num_elements;
|
|
||||||
public:
|
|
||||||
constexpr ALWAYS_INLINE Span() : ptr(), num_elements() { /* ... */ }
|
|
||||||
|
|
||||||
constexpr ALWAYS_INLINE Span(T *p, index_type size) : ptr(p), num_elements(size) {
|
|
||||||
AMS_ASSERT(this->num_elements > 0 || this->ptr == nullptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
constexpr ALWAYS_INLINE Span(T *start, T *end) : Span(start, end - start) { /* ... */ }
|
|
||||||
|
|
||||||
template<size_t Size>
|
|
||||||
constexpr ALWAYS_INLINE Span(T (&arr)[Size]) : Span(static_cast<T *>(arr), static_cast<index_type>(Size)) { /* ... */ }
|
|
||||||
|
|
||||||
template<size_t Size>
|
|
||||||
constexpr ALWAYS_INLINE Span(std::array<value_type, Size> &arr) : Span(arr.data(), static_cast<index_type>(Size)) { /* ... */ }
|
|
||||||
|
|
||||||
template<size_t Size>
|
|
||||||
constexpr ALWAYS_INLINE Span(const std::array<value_type, Size> &arr) : Span(arr.data(), static_cast<index_type>(Size)) { /* ... */ }
|
|
||||||
|
|
||||||
template<typename U, typename = typename std::enable_if<std::is_convertible<U(*)[], T(*)[]>::value>::type>
|
|
||||||
constexpr ALWAYS_INLINE Span(const Span<U> &rhs) : Span(rhs.data(), rhs.size()) { /* ... */ }
|
|
||||||
public:
|
|
||||||
constexpr ALWAYS_INLINE iterator begin() const { return { this, 0 }; }
|
|
||||||
constexpr ALWAYS_INLINE iterator end() const { return { this, this->num_elements }; }
|
|
||||||
|
|
||||||
constexpr ALWAYS_INLINE const_iterator cbegin() const { return { this, 0 }; }
|
|
||||||
constexpr ALWAYS_INLINE const_iterator cend() const { return { this, this->num_elements }; }
|
|
||||||
|
|
||||||
constexpr ALWAYS_INLINE reverse_iterator rbegin() const { return reverse_iterator(this->end()); }
|
|
||||||
constexpr ALWAYS_INLINE reverse_iterator rend() const { return reverse_iterator(this->begin()); }
|
|
||||||
|
|
||||||
constexpr ALWAYS_INLINE const_reverse_iterator crbegin() const { return reverse_iterator(this->cend()); }
|
|
||||||
constexpr ALWAYS_INLINE const_reverse_iterator crend() const { return reverse_iterator(this->cbegin()); }
|
|
||||||
|
|
||||||
constexpr ALWAYS_INLINE pointer data() const { return this->ptr; }
|
|
||||||
|
|
||||||
constexpr ALWAYS_INLINE index_type size() const { return this->num_elements; }
|
|
||||||
constexpr ALWAYS_INLINE index_type size_bytes() const { return this->size() * sizeof(T); }
|
|
||||||
|
|
||||||
constexpr ALWAYS_INLINE bool empty() const { return this->size() == 0; }
|
|
||||||
|
|
||||||
constexpr ALWAYS_INLINE T &operator[](index_type idx) const {
|
|
||||||
AMS_ASSERT(idx < this->size());
|
|
||||||
return this->ptr[idx];
|
|
||||||
}
|
|
||||||
|
|
||||||
constexpr ALWAYS_INLINE T &operator()(index_type idx) const { return (*this)[idx]; }
|
|
||||||
|
|
||||||
constexpr ALWAYS_INLINE Span first(index_type size) const {
|
|
||||||
AMS_ASSERT(size <= this->size());
|
|
||||||
return { this->ptr, size };
|
|
||||||
}
|
|
||||||
|
|
||||||
constexpr ALWAYS_INLINE Span last(index_type size) const {
|
|
||||||
AMS_ASSERT(size <= this->size());
|
|
||||||
return { this->ptr + (this->size() - size), size };
|
|
||||||
}
|
|
||||||
|
|
||||||
constexpr ALWAYS_INLINE Span subspan(index_type idx, index_type size) const {
|
|
||||||
AMS_ASSERT(size <= this->size());
|
|
||||||
AMS_ASSERT(this->size() - size >= idx);
|
|
||||||
return { this->ptr + idx, size };
|
|
||||||
}
|
|
||||||
|
|
||||||
constexpr ALWAYS_INLINE Span subspan(index_type idx) const {
|
|
||||||
AMS_ASSERT(idx <= this->size());
|
|
||||||
return { this->ptr + idx, this->size() - idx };
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
constexpr ALWAYS_INLINE Span<T> MakeSpan(T *start, T *end) {
|
|
||||||
return { start, end };
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
constexpr ALWAYS_INLINE Span<T> MakeSpan(T *p, typename Span<T>::index_type size) {
|
|
||||||
return { p, size };
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T, size_t Size>
|
|
||||||
constexpr ALWAYS_INLINE Span<T> MakeSpan(T (&arr)[Size]) {
|
|
||||||
return Span<T>(arr);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T, size_t Size>
|
|
||||||
constexpr ALWAYS_INLINE Span<T> MakeSpan(std::array<T, Size> &arr) {
|
|
||||||
return Span<T>(arr);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T, size_t Size>
|
|
||||||
constexpr ALWAYS_INLINE Span<const T> MakeSpan(const std::array<T, Size> &arr) {
|
|
||||||
return Span<const T>(arr);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -220,11 +220,7 @@ namespace ams::svc::codegen::impl {
|
||||||
}
|
}
|
||||||
for (size_t i = 1; i < num_parameters; i++) {
|
for (size_t i = 1; i < num_parameters; i++) {
|
||||||
for (size_t j = i; j > 0 && param_layout.GetParameter(map[j-1]).GetLocation(0) > param_layout.GetParameter(map[j]).GetLocation(0); j--) {
|
for (size_t j = i; j > 0 && param_layout.GetParameter(map[j-1]).GetLocation(0) > param_layout.GetParameter(map[j]).GetLocation(0); j--) {
|
||||||
/* std::swap is not constexpr until c++20 :( */
|
std::swap(map[j], map[j-1]);
|
||||||
/* TODO: std::swap(map[j], map[j-1]); */
|
|
||||||
const size_t tmp = map[j];
|
|
||||||
map[j] = map[j-1];
|
|
||||||
map[j-1] = tmp;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -313,11 +313,7 @@ namespace ams::svc::codegen::impl {
|
||||||
}
|
}
|
||||||
for (size_t i = 1; i < num_parameters; i++) {
|
for (size_t i = 1; i < num_parameters; i++) {
|
||||||
for (size_t j = i; j > 0 && CapturedSvc.GetParameter(map[j-1]).GetLocation(0) > CapturedSvc.GetParameter(map[j]).GetLocation(0); j--) {
|
for (size_t j = i; j > 0 && CapturedSvc.GetParameter(map[j-1]).GetLocation(0) > CapturedSvc.GetParameter(map[j]).GetLocation(0); j--) {
|
||||||
/* std::swap is not constexpr until c++20 :( */
|
std::swap(map[j], map[j-1]);
|
||||||
/* TODO: std::swap(map[j], map[j-1]); */
|
|
||||||
const size_t tmp = map[j];
|
|
||||||
map[j] = map[j-1];
|
|
||||||
map[j-1] = tmp;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return map;
|
return map;
|
||||||
|
@ -376,7 +372,6 @@ namespace ams::svc::codegen::impl {
|
||||||
constexpr size_t RegisterSize = SvcAbiType::RegisterSize;
|
constexpr size_t RegisterSize = SvcAbiType::RegisterSize;
|
||||||
constexpr size_t PassedSize = ProcedureParam.GetTypeSize();
|
constexpr size_t PassedSize = ProcedureParam.GetTypeSize();
|
||||||
|
|
||||||
/* TODO: C++20 templated lambdas. For now, use GCC extension syntax. */
|
|
||||||
constexpr auto SvcIndexSequence = []<auto CapturedSvcParam, size_t... Is>(std::index_sequence<Is...>) {
|
constexpr auto SvcIndexSequence = []<auto CapturedSvcParam, size_t... Is>(std::index_sequence<Is...>) {
|
||||||
return std::index_sequence<CapturedSvcParam.GetLocation(Is).GetIndex()...>{};
|
return std::index_sequence<CapturedSvcParam.GetLocation(Is).GetIndex()...>{};
|
||||||
}.template operator()<SvcParam>(std::make_index_sequence<SvcParam.GetNumLocations()>());
|
}.template operator()<SvcParam>(std::make_index_sequence<SvcParam.GetNumLocations()>());
|
||||||
|
|
|
@ -30,11 +30,9 @@ namespace ams::util {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T> requires std::integral<T>
|
||||||
class BitsOf {
|
class BitsOf {
|
||||||
private:
|
private:
|
||||||
static_assert(std::is_integral<T>::value);
|
|
||||||
|
|
||||||
static constexpr ALWAYS_INLINE int GetLsbPos(T v) {
|
static constexpr ALWAYS_INLINE int GetLsbPos(T v) {
|
||||||
return __builtin_ctzll(static_cast<u64>(v));
|
return __builtin_ctzll(static_cast<u64>(v));
|
||||||
}
|
}
|
||||||
|
@ -78,69 +76,68 @@ namespace ams::util {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename T = u64, typename ...Args>
|
template<typename T = u64, typename ...Args> requires std::integral<T>
|
||||||
constexpr ALWAYS_INLINE T CombineBits(Args... args) {
|
constexpr ALWAYS_INLINE T CombineBits(Args... args) {
|
||||||
return (... | (T(1u) << args));
|
return (... | (T(1u) << args));
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T> requires std::integral<T>
|
||||||
constexpr ALWAYS_INLINE T ResetLeastSignificantOneBit(T x) {
|
constexpr ALWAYS_INLINE T ResetLeastSignificantOneBit(T x) {
|
||||||
return x & (x - 1);
|
return x & (x - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T> requires std::integral<T>
|
||||||
constexpr ALWAYS_INLINE T SetLeastSignificantZeroBit(T x) {
|
constexpr ALWAYS_INLINE T SetLeastSignificantZeroBit(T x) {
|
||||||
return x | (x + 1);
|
return x | (x + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T> requires std::integral<T>
|
||||||
constexpr ALWAYS_INLINE T LeastSignificantOneBit(T x) {
|
constexpr ALWAYS_INLINE T LeastSignificantOneBit(T x) {
|
||||||
return x & ~(x - 1);
|
return x & ~(x - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T> requires std::integral<T>
|
||||||
constexpr ALWAYS_INLINE T LeastSignificantZeroBit(T x) {
|
constexpr ALWAYS_INLINE T LeastSignificantZeroBit(T x) {
|
||||||
return ~x & (x + 1);
|
return ~x & (x + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T> requires std::integral<T>
|
||||||
constexpr ALWAYS_INLINE T ResetTrailingOnes(T x) {
|
constexpr ALWAYS_INLINE T ResetTrailingOnes(T x) {
|
||||||
return x & (x + 1);
|
return x & (x + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T> requires std::integral<T>
|
||||||
constexpr ALWAYS_INLINE T SetTrailingZeros(T x) {
|
constexpr ALWAYS_INLINE T SetTrailingZeros(T x) {
|
||||||
return x | (x - 1);
|
return x | (x - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T> requires std::integral<T>
|
||||||
constexpr ALWAYS_INLINE T MaskTrailingZeros(T x) {
|
constexpr ALWAYS_INLINE T MaskTrailingZeros(T x) {
|
||||||
return (~x) & (x - 1);
|
return (~x) & (x - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T> requires std::integral<T>
|
||||||
constexpr ALWAYS_INLINE T MaskTrailingOnes(T x) {
|
constexpr ALWAYS_INLINE T MaskTrailingOnes(T x) {
|
||||||
return ~((~x) | (x + 1));
|
return ~((~x) | (x + 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T> requires std::integral<T>
|
||||||
constexpr ALWAYS_INLINE T MaskTrailingZerosAndLeastSignificantOneBit(T x) {
|
constexpr ALWAYS_INLINE T MaskTrailingZerosAndLeastSignificantOneBit(T x) {
|
||||||
return x ^ (x - 1);
|
return x ^ (x - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T> requires std::integral<T>
|
||||||
constexpr ALWAYS_INLINE T MaskTrailingOnesAndLeastSignificantZeroBit(T x) {
|
constexpr ALWAYS_INLINE T MaskTrailingOnesAndLeastSignificantZeroBit(T x) {
|
||||||
return x ^ (x + 1);
|
return x ^ (x + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T> requires std::integral<T>
|
||||||
constexpr ALWAYS_INLINE int PopCount(T x) {
|
constexpr ALWAYS_INLINE int PopCount(T x) {
|
||||||
/* TODO: C++20 std::bit_cast */
|
/* TODO: C++20 std::bit_cast */
|
||||||
using U = typename std::make_unsigned<T>::type;
|
using U = typename std::make_unsigned<T>::type;
|
||||||
U u = static_cast<U>(x);
|
U u = static_cast<U>(x);
|
||||||
|
|
||||||
/* TODO: C++20 std::is_constant_evaluated */
|
if (std::is_constant_evaluated()) {
|
||||||
if (false) {
|
|
||||||
/* https://en.wikipedia.org/wiki/Hamming_weight */
|
/* https://en.wikipedia.org/wiki/Hamming_weight */
|
||||||
constexpr U m1 = U(-1) / 0x03;
|
constexpr U m1 = U(-1) / 0x03;
|
||||||
constexpr U m2 = U(-1) / 0x05;
|
constexpr U m2 = U(-1) / 0x05;
|
||||||
|
@ -168,10 +165,9 @@ namespace ams::util {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T> requires std::integral<T>
|
||||||
constexpr ALWAYS_INLINE int CountLeadingZeros(T x) {
|
constexpr ALWAYS_INLINE int CountLeadingZeros(T x) {
|
||||||
/* TODO: C++20 std::is_constant_evaluated */
|
if (std::is_constant_evaluated()) {
|
||||||
if (false) {
|
|
||||||
for (size_t i = 0; i < impl::Log2<BITSIZEOF(T)>; ++i) {
|
for (size_t i = 0; i < impl::Log2<BITSIZEOF(T)>; ++i) {
|
||||||
const size_t shift = (0x1 << i);
|
const size_t shift = (0x1 << i);
|
||||||
x |= x >> shift;
|
x |= x >> shift;
|
||||||
|
@ -195,18 +191,18 @@ namespace ams::util {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T> requires std::integral<T>
|
||||||
constexpr ALWAYS_INLINE bool IsPowerOfTwo(T x) {
|
constexpr ALWAYS_INLINE bool IsPowerOfTwo(T x) {
|
||||||
return x > 0 && ResetLeastSignificantOneBit(x) == 0;
|
return x > 0 && ResetLeastSignificantOneBit(x) == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T> requires std::integral<T>
|
||||||
constexpr ALWAYS_INLINE T CeilingPowerOfTwo(T x) {
|
constexpr ALWAYS_INLINE T CeilingPowerOfTwo(T x) {
|
||||||
AMS_ASSERT(x > 0);
|
AMS_ASSERT(x > 0);
|
||||||
return T(1) << (BITSIZEOF(T) - CountLeadingZeros(T(x - 1)));
|
return T(1) << (BITSIZEOF(T) - CountLeadingZeros(T(x - 1)));
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T> requires std::integral<T>
|
||||||
constexpr ALWAYS_INLINE T FloorPowerOfTwo(T x) {
|
constexpr ALWAYS_INLINE T FloorPowerOfTwo(T x) {
|
||||||
AMS_ASSERT(x > 0);
|
AMS_ASSERT(x > 0);
|
||||||
return T(1) << (BITSIZEOF(T) - CountLeadingZeros(x) - 1);
|
return T(1) << (BITSIZEOF(T) - CountLeadingZeros(x) - 1);
|
||||||
|
|
|
@ -20,27 +20,17 @@
|
||||||
|
|
||||||
namespace ams::util {
|
namespace ams::util {
|
||||||
|
|
||||||
/* TODO: C++20 std::endian */
|
|
||||||
|
|
||||||
constexpr bool IsLittleEndian() {
|
constexpr bool IsLittleEndian() {
|
||||||
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
|
return std::endian::native == std::endian::little;
|
||||||
return true;
|
|
||||||
#else
|
|
||||||
return false;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr bool IsBigEndian() {
|
constexpr bool IsBigEndian() {
|
||||||
#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
|
return std::endian::native == std::endian::big;
|
||||||
return true;
|
|
||||||
#else
|
|
||||||
return false;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static_assert(IsLittleEndian() ^ IsBigEndian());
|
static_assert(IsLittleEndian() ^ IsBigEndian());
|
||||||
|
|
||||||
template<typename U> /* requires unsigned_integral<U> */
|
template<typename U> requires std::unsigned_integral<U>
|
||||||
constexpr ALWAYS_INLINE U SwapBytes(const U u) {
|
constexpr ALWAYS_INLINE U SwapBytes(const U u) {
|
||||||
static_assert(BITSIZEOF(u8) == 8);
|
static_assert(BITSIZEOF(u8) == 8);
|
||||||
constexpr U ByteMask = 0xFFu;
|
constexpr U ByteMask = 0xFFu;
|
||||||
|
@ -85,14 +75,14 @@ namespace ams::util {
|
||||||
((u & (ByteMask << 0)) << 40);
|
((u & (ByteMask << 0)) << 40);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T> /* requires integral<T> */
|
template<typename T> requires std::integral<T>
|
||||||
constexpr ALWAYS_INLINE void SwapBytes(T *ptr) {
|
constexpr ALWAYS_INLINE void SwapBytes(T *ptr) {
|
||||||
using U = typename std::make_unsigned<T>::type;
|
using U = typename std::make_unsigned<T>::type;
|
||||||
|
|
||||||
*ptr = static_cast<T>(SwapBytes(static_cast<U>(*ptr)));
|
*ptr = static_cast<T>(SwapBytes(static_cast<U>(*ptr)));
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T> /* requires integral<T> */
|
template<typename T> requires std::integral<T>
|
||||||
constexpr ALWAYS_INLINE T ConvertToBigEndian(const T val) {
|
constexpr ALWAYS_INLINE T ConvertToBigEndian(const T val) {
|
||||||
using U = typename std::make_unsigned<T>::type;
|
using U = typename std::make_unsigned<T>::type;
|
||||||
|
|
||||||
|
@ -104,7 +94,7 @@ namespace ams::util {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T> /* requires integral<T> */
|
template<typename T> requires std::integral<T>
|
||||||
constexpr ALWAYS_INLINE T ConvertToLittleEndian(const T val) {
|
constexpr ALWAYS_INLINE T ConvertToLittleEndian(const T val) {
|
||||||
using U = typename std::make_unsigned<T>::type;
|
using U = typename std::make_unsigned<T>::type;
|
||||||
|
|
||||||
|
@ -116,7 +106,7 @@ namespace ams::util {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T> /* requires integral<T> */
|
template<typename T> requires std::integral<T>
|
||||||
constexpr ALWAYS_INLINE T ConvertToBigEndian48(const T val) {
|
constexpr ALWAYS_INLINE T ConvertToBigEndian48(const T val) {
|
||||||
using U = typename std::make_unsigned<T>::type;
|
using U = typename std::make_unsigned<T>::type;
|
||||||
static_assert(sizeof(T) == sizeof(u64));
|
static_assert(sizeof(T) == sizeof(u64));
|
||||||
|
@ -130,7 +120,7 @@ namespace ams::util {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T> /* requires integral<T> */
|
template<typename T> requires std::integral<T>
|
||||||
constexpr ALWAYS_INLINE T ConvertToLittleEndian48(const T val) {
|
constexpr ALWAYS_INLINE T ConvertToLittleEndian48(const T val) {
|
||||||
using U = typename std::make_unsigned<T>::type;
|
using U = typename std::make_unsigned<T>::type;
|
||||||
static_assert(sizeof(T) == sizeof(u64));
|
static_assert(sizeof(T) == sizeof(u64));
|
||||||
|
@ -144,12 +134,12 @@ namespace ams::util {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T> /* requires integral<T> */
|
template<typename T> requires std::integral<T>
|
||||||
constexpr ALWAYS_INLINE T LoadBigEndian(T *ptr) {
|
constexpr ALWAYS_INLINE T LoadBigEndian(T *ptr) {
|
||||||
return ConvertToBigEndian(*ptr);
|
return ConvertToBigEndian(*ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T> /* requires integral<T> */
|
template<typename T> requires std::integral<T>
|
||||||
constexpr ALWAYS_INLINE T LoadLittleEndian(T *ptr) {
|
constexpr ALWAYS_INLINE T LoadLittleEndian(T *ptr) {
|
||||||
return ConvertToLittleEndian(*ptr);
|
return ConvertToLittleEndian(*ptr);
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,16 +17,14 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
#include <vapours/common.hpp>
|
#include <vapours/common.hpp>
|
||||||
#include <vapours/assert.hpp>
|
#include <vapours/assert.hpp>
|
||||||
|
#include <vapours/util/util_endian.hpp>
|
||||||
|
|
||||||
namespace ams::util {
|
namespace ams::util {
|
||||||
|
|
||||||
template<char A, char B, char C, char D>
|
template<char A, char B, char C, char D>
|
||||||
struct FourCC {
|
struct FourCC {
|
||||||
/* TODO: C++20 std::endian */
|
static constexpr u32 Code = IsLittleEndian() ? ((static_cast<u32>(A) << 0x00) | (static_cast<u32>(B) << 0x08) | (static_cast<u32>(C) << 0x10) | (static_cast<u32>(D) << 0x18))
|
||||||
static constexpr u32 Code = (static_cast<u32>(A) << 0x00) |
|
: ((static_cast<u32>(A) << 0x18) | (static_cast<u32>(B) << 0x10) | (static_cast<u32>(C) << 0x08) | (static_cast<u32>(D) << 0x00));
|
||||||
(static_cast<u32>(B) << 0x08) |
|
|
||||||
(static_cast<u32>(C) << 0x10) |
|
|
||||||
(static_cast<u32>(D) << 0x18);
|
|
||||||
|
|
||||||
static constexpr const char String[] = {A, B, C, D};
|
static constexpr const char String[] = {A, B, C, D};
|
||||||
|
|
||||||
|
@ -36,11 +34,8 @@ namespace ams::util {
|
||||||
|
|
||||||
template<char A, char B, char C, char D>
|
template<char A, char B, char C, char D>
|
||||||
struct ReverseFourCC {
|
struct ReverseFourCC {
|
||||||
/* TODO: C++20 std::endian */
|
static constexpr u32 Code = IsLittleEndian() ? ((static_cast<u32>(A) << 0x18) | (static_cast<u32>(B) << 0x10) | (static_cast<u32>(C) << 0x08) | (static_cast<u32>(D) << 0x00))
|
||||||
static constexpr u32 Code = (static_cast<u32>(A) << 0x18) |
|
: ((static_cast<u32>(A) << 0x00) | (static_cast<u32>(B) << 0x08) | (static_cast<u32>(C) << 0x10) | (static_cast<u32>(D) << 0x18));
|
||||||
(static_cast<u32>(B) << 0x10) |
|
|
||||||
(static_cast<u32>(C) << 0x08) |
|
|
||||||
(static_cast<u32>(D) << 0x00);
|
|
||||||
|
|
||||||
static constexpr const char String[] = {D, C, B, A};
|
static constexpr const char String[] = {D, C, B, A};
|
||||||
|
|
||||||
|
|
|
@ -18,22 +18,22 @@
|
||||||
namespace ams::kern {
|
namespace ams::kern {
|
||||||
|
|
||||||
/* Declare kernel data members in kernel TU. */
|
/* Declare kernel data members in kernel TU. */
|
||||||
Kernel::State Kernel::s_state = Kernel::State::Invalid;
|
constinit Kernel::State Kernel::s_state = Kernel::State::Invalid;
|
||||||
KResourceLimit Kernel::s_system_resource_limit;
|
constinit KResourceLimit Kernel::s_system_resource_limit;
|
||||||
KMemoryManager Kernel::s_memory_manager;
|
KMemoryManager Kernel::s_memory_manager;
|
||||||
KPageTableManager Kernel::s_page_table_manager;
|
constinit KPageTableManager Kernel::s_page_table_manager;
|
||||||
KMemoryBlockSlabManager Kernel::s_app_memory_block_manager;
|
constinit KMemoryBlockSlabManager Kernel::s_app_memory_block_manager;
|
||||||
KMemoryBlockSlabManager Kernel::s_sys_memory_block_manager;
|
constinit KMemoryBlockSlabManager Kernel::s_sys_memory_block_manager;
|
||||||
KBlockInfoManager Kernel::s_block_info_manager;
|
constinit KBlockInfoManager Kernel::s_block_info_manager;
|
||||||
KSupervisorPageTable Kernel::s_supervisor_page_table;
|
constinit KSupervisorPageTable Kernel::s_supervisor_page_table;
|
||||||
KSynchronization Kernel::s_synchronization;
|
constinit KSynchronization Kernel::s_synchronization;
|
||||||
KUnsafeMemory Kernel::s_unsafe_memory;
|
constinit KUnsafeMemory Kernel::s_unsafe_memory;
|
||||||
KWorkerTaskManager Kernel::s_worker_task_managers[KWorkerTaskManager::WorkerType_Count];
|
constinit KWorkerTaskManager Kernel::s_worker_task_managers[KWorkerTaskManager::WorkerType_Count];
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
/* TODO: C++20 constinit */ std::array<KThread, cpu::NumCores> g_main_threads;
|
constinit std::array<KThread, cpu::NumCores> g_main_threads;
|
||||||
/* TODO: C++20 constinit */ std::array<KThread, cpu::NumCores> g_idle_threads;
|
constinit std::array<KThread, cpu::NumCores> g_idle_threads;
|
||||||
}
|
}
|
||||||
|
|
||||||
KThread &Kernel::GetMainThread(s32 core_id) { return g_main_threads[core_id]; }
|
KThread &Kernel::GetMainThread(s32 core_id) { return g_main_threads[core_id]; }
|
||||||
|
|
|
@ -19,21 +19,25 @@
|
||||||
namespace ams::mitm {
|
namespace ams::mitm {
|
||||||
|
|
||||||
/* TODO: C++20 Concepts will make this a lot less stupid. */
|
/* TODO: C++20 Concepts will make this a lot less stupid. */
|
||||||
class ModuleBase {};
|
template<typename T>
|
||||||
|
concept IsModule = requires(T, void *arg) {
|
||||||
|
{ T::ThreadPriority } -> std::convertible_to<s32>;
|
||||||
|
{ T::StackSize } -> std::convertible_to<size_t>;
|
||||||
|
{ T::Stack } -> std::convertible_to<void *>;
|
||||||
|
{ T::ThreadFunction(arg) } -> std::same_as<void>;
|
||||||
|
};
|
||||||
|
|
||||||
#define DEFINE_MITM_MODULE_CLASS(ss, prio) class MitmModule : public ::ams::mitm::ModuleBase { \
|
#define DEFINE_MITM_MODULE_CLASS(ss, prio) class MitmModule { \
|
||||||
public: \
|
public: \
|
||||||
static constexpr s32 ThreadPriority = prio; \
|
static constexpr s32 ThreadPriority = prio; \
|
||||||
static constexpr size_t StackSize = ss; \
|
static constexpr size_t StackSize = ss; \
|
||||||
alignas(os::ThreadStackAlignment) static inline u8 Stack[StackSize]; \
|
alignas(os::ThreadStackAlignment) static inline u8 Stack[StackSize]; \
|
||||||
public: \
|
public: \
|
||||||
static void ThreadFunction(void *); \
|
static void ThreadFunction(void *); \
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class M>
|
template<class M> requires IsModule<M>
|
||||||
struct ModuleTraits {
|
struct ModuleTraits {
|
||||||
static_assert(std::is_base_of<ModuleBase, M>::value, "Mitm Modules must inherit from ams::mitm::Module");
|
|
||||||
|
|
||||||
static constexpr void *Stack = &M::Stack[0];
|
static constexpr void *Stack = &M::Stack[0];
|
||||||
static constexpr size_t StackSize = M::StackSize;
|
static constexpr size_t StackSize = M::StackSize;
|
||||||
|
|
||||||
|
|
|
@ -54,7 +54,7 @@ namespace ams::mitm {
|
||||||
.main = Traits::ThreadFunction,
|
.main = Traits::ThreadFunction,
|
||||||
.stack_mem = Traits::Stack,
|
.stack_mem = Traits::Stack,
|
||||||
.priority = Traits::ThreadPriority,
|
.priority = Traits::ThreadPriority,
|
||||||
.stack_size = Traits::StackSize,
|
.stack_size = static_cast<u32>(Traits::StackSize),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -64,7 +64,7 @@ namespace ams::pgl {
|
||||||
constexpr sm::ServiceName ShellServiceName = sm::ServiceName::Encode("pgl");
|
constexpr sm::ServiceName ShellServiceName = sm::ServiceName::Encode("pgl");
|
||||||
constexpr size_t ShellMaxSessions = 8; /* Official maximum is 8. */
|
constexpr size_t ShellMaxSessions = 8; /* Official maximum is 8. */
|
||||||
|
|
||||||
/* TODO: C++20 constinit */ pgl::srv::ShellInterface g_shell_interface;
|
constinit pgl::srv::ShellInterface g_shell_interface;
|
||||||
|
|
||||||
ALWAYS_INLINE std::shared_ptr<pgl::srv::ShellInterface> GetSharedPointerToShellInterface() {
|
ALWAYS_INLINE std::shared_ptr<pgl::srv::ShellInterface> GetSharedPointerToShellInterface() {
|
||||||
return ams::sf::ServiceObjectTraits<pgl::srv::ShellInterface>::SharedPointerHelper::GetEmptyDeleteSharedPointer(std::addressof(g_shell_interface));
|
return ams::sf::ServiceObjectTraits<pgl::srv::ShellInterface>::SharedPointerHelper::GetEmptyDeleteSharedPointer(std::addressof(g_shell_interface));
|
||||||
|
|
Loading…
Reference in a new issue