os: implement ReadWriteLock

This commit is contained in:
Michael Scire 2020-04-13 17:07:06 -07:00
parent 6eb77e69c4
commit 97cba5e881
20 changed files with 941 additions and 66 deletions

View file

@ -23,8 +23,8 @@ namespace ams::svc::arch::arm64 {
struct ThreadLocalRegion {
u32 message_buffer[MessageBufferSize / sizeof(u32)];
u16 disable_count;
u16 preemption_state;
volatile u16 disable_count;
volatile u16 interrupt_flag;
/* TODO: How should we handle libnx vs Nintendo user thread local space? */
uintptr_t TODO[(0x200 - 0x108) / sizeof(uintptr_t)];
};

View file

@ -58,11 +58,11 @@ namespace ams::svc::ipc {
private:
util::BitPack32 header[2];
public:
constexpr ALWAYS_INLINE MessageHeader() : header({util::BitPack32(0), util::BitPack32(0)}) {
constexpr ALWAYS_INLINE MessageHeader() : header({util::BitPack32{0}, util::BitPack32{0}}) {
this->header[0].Set<Tag>(NullTag);
}
constexpr ALWAYS_INLINE MessageHeader(u16 tag, bool special, s32 ptr, s32 send, s32 recv, s32 exch, s32 raw, s32 recv_list) : header({util::BitPack32(0), util::BitPack32(0)}) {
constexpr ALWAYS_INLINE MessageHeader(u16 tag, bool special, s32 ptr, s32 send, s32 recv, s32 exch, s32 raw, s32 recv_list) : header({util::BitPack32{0}, util::BitPack32{0}}) {
this->header[0].Set<Tag>(tag);
this->header[0].Set<PointerCount>(ptr);
this->header[0].Set<SendCount>(send);
@ -74,11 +74,11 @@ namespace ams::svc::ipc {
this->header[1].Set<HasSpecialHeader>(special);
}
ALWAYS_INLINE explicit MessageHeader(const MessageBuffer &buf) : header({util::BitPack32(0), util::BitPack32(0)}) {
ALWAYS_INLINE explicit MessageHeader(const MessageBuffer &buf) : header({util::BitPack32{0}, util::BitPack32{0}}) {
buf.Get(0, this->header, util::size(this->header));
}
ALWAYS_INLINE explicit MessageHeader(const u32 *msg) : header({util::BitPack32(msg[0]), util::BitPack32(msg[1])}) { /* ... */ }
ALWAYS_INLINE explicit MessageHeader(const u32 *msg) : header({util::BitPack32{msg[0]}, util::BitPack32{msg[1]}}) { /* ... */ }
constexpr ALWAYS_INLINE u16 GetTag() const {
return this->header[0].Get<Tag>();
@ -143,13 +143,13 @@ namespace ams::svc::ipc {
util::BitPack32 header;
bool has_header;
public:
constexpr ALWAYS_INLINE explicit SpecialHeader(bool pid, s32 copy, s32 move) : header(0), has_header(true) {
constexpr ALWAYS_INLINE explicit SpecialHeader(bool pid, s32 copy, s32 move) : header{0}, has_header(true) {
this->header.Set<HasProcessId>(pid);
this->header.Set<CopyHandleCount>(copy);
this->header.Set<MoveHandleCount>(move);
}
ALWAYS_INLINE explicit SpecialHeader(const MessageBuffer &buf, const MessageHeader &hdr) : header(0), has_header(hdr.GetHasSpecialHeader()) {
ALWAYS_INLINE explicit SpecialHeader(const MessageBuffer &buf, const MessageHeader &hdr) : header{0}, has_header(hdr.GetHasSpecialHeader()) {
if (this->has_header) {
buf.Get(MessageHeader::GetDataSize() / sizeof(util::BitPack32), std::addressof(this->header), sizeof(this->header) / sizeof(util::BitPack32));
}
@ -219,9 +219,9 @@ namespace ams::svc::ipc {
private:
util::BitPack32 data[3];
public:
constexpr ALWAYS_INLINE MapAliasDescriptor() : data({util::BitPack32(0), util::BitPack32(0), util::BitPack32(0)}) { /* ... */ }
constexpr ALWAYS_INLINE MapAliasDescriptor() : data({util::BitPack32{0}, util::BitPack32{0}, util::BitPack32{0}}) { /* ... */ }
ALWAYS_INLINE MapAliasDescriptor(const void *buffer, size_t _size, Attribute attr = Attribute_Ipc) : data({util::BitPack32(0), util::BitPack32(0), util::BitPack32(0)}) {
ALWAYS_INLINE MapAliasDescriptor(const void *buffer, size_t _size, Attribute attr = Attribute_Ipc) : data({util::BitPack32{0}, util::BitPack32{0}, util::BitPack32{0}}) {
const u64 address = reinterpret_cast<u64>(buffer);
const u64 size = static_cast<u64>(_size);
this->data[0] = { static_cast<u32>(size) };
@ -233,7 +233,7 @@ namespace ams::svc::ipc {
this->data[2].Set<AddressHigh>(GetAddressHigh(address));
}
ALWAYS_INLINE MapAliasDescriptor(const MessageBuffer &buf, s32 index) : data({util::BitPack32(0), util::BitPack32(0), util::BitPack32(0)}) {
ALWAYS_INLINE MapAliasDescriptor(const MessageBuffer &buf, s32 index) : data({util::BitPack32{0}, util::BitPack32{0}, util::BitPack32{0}}) {
buf.Get(index, this->data, util::size(this->data));
}
@ -283,9 +283,9 @@ namespace ams::svc::ipc {
private:
util::BitPack32 data[2];
public:
constexpr ALWAYS_INLINE PointerDescriptor() : data({util::BitPack32(0), util::BitPack32(0)}) { /* ... */ }
constexpr ALWAYS_INLINE PointerDescriptor() : data({util::BitPack32{0}, util::BitPack32{0}}) { /* ... */ }
ALWAYS_INLINE PointerDescriptor(const void *buffer, size_t size, s32 index) : data({util::BitPack32(0), util::BitPack32(0)}) {
ALWAYS_INLINE PointerDescriptor(const void *buffer, size_t size, s32 index) : data({util::BitPack32{0}, util::BitPack32{0}}) {
const u64 address = reinterpret_cast<u64>(buffer);
this->data[0].Set<Index>(index);
@ -296,7 +296,7 @@ namespace ams::svc::ipc {
this->data[1] = { static_cast<u32>(address) };
}
ALWAYS_INLINE PointerDescriptor(const MessageBuffer &buf, s32 index) : data({util::BitPack32(0), util::BitPack32(0)}) {
ALWAYS_INLINE PointerDescriptor(const MessageBuffer &buf, s32 index) : data({util::BitPack32{0}, util::BitPack32{0}}) {
buf.Get(index, this->data, util::size(this->data));
}
@ -338,9 +338,9 @@ namespace ams::svc::ipc {
private:
util::BitPack32 data[2];
public:
constexpr ALWAYS_INLINE ReceiveListEntry() : data({util::BitPack32(0), util::BitPack32(0)}) { /* ... */ }
constexpr ALWAYS_INLINE ReceiveListEntry() : data({util::BitPack32{0}, util::BitPack32{0}}) { /* ... */ }
ALWAYS_INLINE ReceiveListEntry(const void *buffer, size_t size) : data({util::BitPack32(0), util::BitPack32(0)}) {
ALWAYS_INLINE ReceiveListEntry(const void *buffer, size_t size) : data({util::BitPack32{0}, util::BitPack32{0}}) {
const u64 address = reinterpret_cast<u64>(buffer);
this->data[0] = { static_cast<u32>(address) };
@ -349,7 +349,7 @@ namespace ams::svc::ipc {
this->data[1].Set<Size>(size);
}
ALWAYS_INLINE ReceiveListEntry(u32 a, u32 b) : data({util::BitPack32(a), util::BitPack32(b)}) { /* ... */ }
ALWAYS_INLINE ReceiveListEntry(u32 a, u32 b) : data({util::BitPack32{a}, util::BitPack32{b}}) { /* ... */ }
constexpr ALWAYS_INLINE uintptr_t GetAddress() {
const u64 address = (static_cast<u64>(this->data[1].Get<AddressHigh>()) << AddressLow::Count) | this->data[0].Get<AddressLow>();

View file

@ -23,7 +23,8 @@ namespace ams::util {
namespace impl {
template<typename IntegralStorageType>
class BitPack {
struct BitPack {
IntegralStorageType value;
private:
static_assert(std::is_integral<IntegralStorageType>::value);
static_assert(std::is_unsigned<IntegralStorageType>::value);
@ -49,16 +50,13 @@ namespace ams::util {
static constexpr size_t Next = Index + Count;
using BitPackType = BitPack<IntegralStorageType>;
static_assert(std::is_pod<BitPackType>::value);
static_assert(Mask<Index, Count> != 0);
static_assert(std::is_integral<T>::value || std::is_enum<T>::value);
static_assert(!std::is_same<T, bool>::value || Count == 1);
};
private:
IntegralStorageType value;
public:
constexpr ALWAYS_INLINE BitPack(IntegralStorageType v) : value(v) { /* ... */ }
constexpr ALWAYS_INLINE void Clear() {
constexpr IntegralStorageType Zero = IntegralStorageType(0);
this->value = Zero;
@ -86,6 +84,10 @@ namespace ams::util {
using BitPack32 = impl::BitPack<u32>;
using BitPack64 = impl::BitPack<u64>;
static_assert(std::is_pod<BitPack8>::value);
static_assert(std::is_pod<BitPack16>::value);
static_assert(std::is_pod<BitPack32>::value);
static_assert(std::is_pod<BitPack64>::value);
static_assert(std::is_trivially_destructible<BitPack8 >::value);
static_assert(std::is_trivially_destructible<BitPack16>::value);
static_assert(std::is_trivially_destructible<BitPack32>::value);