kern: refactor to use m_ for member variables
This commit is contained in:
@@ -18,47 +18,47 @@
|
||||
namespace ams::kern::arch::arm {
|
||||
|
||||
void KInterruptController::SetupInterruptLines(s32 core_id) const {
|
||||
const size_t ITLines = (core_id == 0) ? 32 * ((this->gicd->typer & 0x1F) + 1) : NumLocalInterrupts;
|
||||
const size_t ITLines = (core_id == 0) ? 32 * ((m_gicd->typer & 0x1F) + 1) : NumLocalInterrupts;
|
||||
|
||||
for (size_t i = 0; i < ITLines / 32; i++) {
|
||||
this->gicd->icenabler[i] = 0xFFFFFFFF;
|
||||
this->gicd->icpendr[i] = 0xFFFFFFFF;
|
||||
this->gicd->icactiver[i] = 0xFFFFFFFF;
|
||||
this->gicd->igroupr[i] = 0;
|
||||
m_gicd->icenabler[i] = 0xFFFFFFFF;
|
||||
m_gicd->icpendr[i] = 0xFFFFFFFF;
|
||||
m_gicd->icactiver[i] = 0xFFFFFFFF;
|
||||
m_gicd->igroupr[i] = 0;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < ITLines; i++) {
|
||||
this->gicd->ipriorityr.bytes[i] = 0xFF;
|
||||
this->gicd->itargetsr.bytes[i] = 0x00;
|
||||
m_gicd->ipriorityr.bytes[i] = 0xFF;
|
||||
m_gicd->itargetsr.bytes[i] = 0x00;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < ITLines / 16; i++) {
|
||||
this->gicd->icfgr[i] = 0x00000000;
|
||||
m_gicd->icfgr[i] = 0x00000000;
|
||||
}
|
||||
}
|
||||
|
||||
void KInterruptController::Initialize(s32 core_id) {
|
||||
/* Setup pointers to ARM mmio. */
|
||||
this->gicd = GetPointer<volatile GicDistributor >(KMemoryLayout::GetDeviceVirtualAddress(KMemoryRegionType_InterruptDistributor));
|
||||
this->gicc = GetPointer<volatile GicCpuInterface>(KMemoryLayout::GetDeviceVirtualAddress(KMemoryRegionType_InterruptCpuInterface));
|
||||
m_gicd = GetPointer<volatile GicDistributor >(KMemoryLayout::GetDeviceVirtualAddress(KMemoryRegionType_InterruptDistributor));
|
||||
m_gicc = GetPointer<volatile GicCpuInterface>(KMemoryLayout::GetDeviceVirtualAddress(KMemoryRegionType_InterruptCpuInterface));
|
||||
|
||||
/* Clear CTLRs. */
|
||||
this->gicc->ctlr = 0;
|
||||
m_gicc->ctlr = 0;
|
||||
if (core_id == 0) {
|
||||
this->gicd->ctlr = 0;
|
||||
m_gicd->ctlr = 0;
|
||||
}
|
||||
|
||||
this->gicc->pmr = 0;
|
||||
this->gicc->bpr = 7;
|
||||
m_gicc->pmr = 0;
|
||||
m_gicc->bpr = 7;
|
||||
|
||||
/* Setup all interrupt lines. */
|
||||
SetupInterruptLines(core_id);
|
||||
|
||||
/* Set CTLRs. */
|
||||
if (core_id == 0) {
|
||||
this->gicd->ctlr = 1;
|
||||
m_gicd->ctlr = 1;
|
||||
}
|
||||
this->gicc->ctlr = 1;
|
||||
m_gicc->ctlr = 1;
|
||||
|
||||
/* Set the mask for this core. */
|
||||
SetGicMask(core_id);
|
||||
@@ -70,9 +70,9 @@ namespace ams::kern::arch::arm {
|
||||
void KInterruptController::Finalize(s32 core_id) {
|
||||
/* Clear CTLRs. */
|
||||
if (core_id == 0) {
|
||||
this->gicd->ctlr = 0;
|
||||
m_gicd->ctlr = 0;
|
||||
}
|
||||
this->gicc->ctlr = 0;
|
||||
m_gicc->ctlr = 0;
|
||||
|
||||
/* Set the priority level. */
|
||||
SetPriorityLevel(PriorityLevel_High);
|
||||
@@ -85,27 +85,27 @@ namespace ams::kern::arch::arm {
|
||||
/* Save isenabler. */
|
||||
for (size_t i = 0; i < util::size(state->isenabler); ++i) {
|
||||
constexpr size_t Offset = 0;
|
||||
state->isenabler[i] = this->gicd->isenabler[i + Offset];
|
||||
this->gicd->isenabler[i + Offset] = 0xFFFFFFFF;
|
||||
state->isenabler[i] = m_gicd->isenabler[i + Offset];
|
||||
m_gicd->isenabler[i + Offset] = 0xFFFFFFFF;
|
||||
}
|
||||
|
||||
/* Save ipriorityr. */
|
||||
for (size_t i = 0; i < util::size(state->ipriorityr); ++i) {
|
||||
constexpr size_t Offset = 0;
|
||||
state->ipriorityr[i] = this->gicd->ipriorityr.words[i + Offset];
|
||||
this->gicd->ipriorityr.words[i + Offset] = 0xFFFFFFFF;
|
||||
state->ipriorityr[i] = m_gicd->ipriorityr.words[i + Offset];
|
||||
m_gicd->ipriorityr.words[i + Offset] = 0xFFFFFFFF;
|
||||
}
|
||||
|
||||
/* Save itargetsr. */
|
||||
for (size_t i = 0; i < util::size(state->itargetsr); ++i) {
|
||||
constexpr size_t Offset = 0;
|
||||
state->itargetsr[i] = this->gicd->itargetsr.words[i + Offset];
|
||||
state->itargetsr[i] = m_gicd->itargetsr.words[i + Offset];
|
||||
}
|
||||
|
||||
/* Save icfgr. */
|
||||
for (size_t i = 0; i < util::size(state->icfgr); ++i) {
|
||||
constexpr size_t Offset = 0;
|
||||
state->icfgr[i] = this->gicd->icfgr[i + Offset];
|
||||
state->icfgr[i] = m_gicd->icfgr[i + Offset];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -113,27 +113,27 @@ namespace ams::kern::arch::arm {
|
||||
/* Save isenabler. */
|
||||
for (size_t i = 0; i < util::size(state->isenabler); ++i) {
|
||||
constexpr size_t Offset = util::size(LocalState{}.isenabler);
|
||||
state->isenabler[i] = this->gicd->isenabler[i + Offset];
|
||||
this->gicd->isenabler[i + Offset] = 0xFFFFFFFF;
|
||||
state->isenabler[i] = m_gicd->isenabler[i + Offset];
|
||||
m_gicd->isenabler[i + Offset] = 0xFFFFFFFF;
|
||||
}
|
||||
|
||||
/* Save ipriorityr. */
|
||||
for (size_t i = 0; i < util::size(state->ipriorityr); ++i) {
|
||||
constexpr size_t Offset = util::size(LocalState{}.ipriorityr);
|
||||
state->ipriorityr[i] = this->gicd->ipriorityr.words[i + Offset];
|
||||
this->gicd->ipriorityr.words[i + Offset] = 0xFFFFFFFF;
|
||||
state->ipriorityr[i] = m_gicd->ipriorityr.words[i + Offset];
|
||||
m_gicd->ipriorityr.words[i + Offset] = 0xFFFFFFFF;
|
||||
}
|
||||
|
||||
/* Save itargetsr. */
|
||||
for (size_t i = 0; i < util::size(state->itargetsr); ++i) {
|
||||
constexpr size_t Offset = util::size(LocalState{}.itargetsr);
|
||||
state->itargetsr[i] = this->gicd->itargetsr.words[i + Offset];
|
||||
state->itargetsr[i] = m_gicd->itargetsr.words[i + Offset];
|
||||
}
|
||||
|
||||
/* Save icfgr. */
|
||||
for (size_t i = 0; i < util::size(state->icfgr); ++i) {
|
||||
constexpr size_t Offset = util::size(LocalState{}.icfgr);
|
||||
state->icfgr[i] = this->gicd->icfgr[i + Offset];
|
||||
state->icfgr[i] = m_gicd->icfgr[i + Offset];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -141,26 +141,26 @@ namespace ams::kern::arch::arm {
|
||||
/* Restore ipriorityr. */
|
||||
for (size_t i = 0; i < util::size(state->ipriorityr); ++i) {
|
||||
constexpr size_t Offset = 0;
|
||||
this->gicd->ipriorityr.words[i + Offset] = state->ipriorityr[i];
|
||||
m_gicd->ipriorityr.words[i + Offset] = state->ipriorityr[i];
|
||||
}
|
||||
|
||||
/* Restore itargetsr. */
|
||||
for (size_t i = 0; i < util::size(state->itargetsr); ++i) {
|
||||
constexpr size_t Offset = 0;
|
||||
this->gicd->itargetsr.words[i + Offset] = state->itargetsr[i];
|
||||
m_gicd->itargetsr.words[i + Offset] = state->itargetsr[i];
|
||||
}
|
||||
|
||||
/* Restore icfgr. */
|
||||
for (size_t i = 0; i < util::size(state->icfgr); ++i) {
|
||||
constexpr size_t Offset = 0;
|
||||
this->gicd->icfgr[i + Offset] = state->icfgr[i];
|
||||
m_gicd->icfgr[i + Offset] = state->icfgr[i];
|
||||
}
|
||||
|
||||
/* Restore isenabler. */
|
||||
for (size_t i = 0; i < util::size(state->isenabler); ++i) {
|
||||
constexpr size_t Offset = 0;
|
||||
this->gicd->icenabler[i + Offset] = 0xFFFFFFFF;
|
||||
this->gicd->isenabler[i + Offset] = state->isenabler[i];
|
||||
m_gicd->icenabler[i + Offset] = 0xFFFFFFFF;
|
||||
m_gicd->isenabler[i + Offset] = state->isenabler[i];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -168,26 +168,26 @@ namespace ams::kern::arch::arm {
|
||||
/* Restore ipriorityr. */
|
||||
for (size_t i = 0; i < util::size(state->ipriorityr); ++i) {
|
||||
constexpr size_t Offset = util::size(LocalState{}.ipriorityr);
|
||||
this->gicd->ipriorityr.words[i + Offset] = state->ipriorityr[i];
|
||||
m_gicd->ipriorityr.words[i + Offset] = state->ipriorityr[i];
|
||||
}
|
||||
|
||||
/* Restore itargetsr. */
|
||||
for (size_t i = 0; i < util::size(state->itargetsr); ++i) {
|
||||
constexpr size_t Offset = util::size(LocalState{}.itargetsr);
|
||||
this->gicd->itargetsr.words[i + Offset] = state->itargetsr[i];
|
||||
m_gicd->itargetsr.words[i + Offset] = state->itargetsr[i];
|
||||
}
|
||||
|
||||
/* Restore icfgr. */
|
||||
for (size_t i = 0; i < util::size(state->icfgr); ++i) {
|
||||
constexpr size_t Offset = util::size(LocalState{}.icfgr);
|
||||
this->gicd->icfgr[i + Offset] = state->icfgr[i];
|
||||
m_gicd->icfgr[i + Offset] = state->icfgr[i];
|
||||
}
|
||||
|
||||
/* Restore isenabler. */
|
||||
for (size_t i = 0; i < util::size(state->isenabler); ++i) {
|
||||
constexpr size_t Offset = util::size(LocalState{}.isenabler);
|
||||
this->gicd->icenabler[i + Offset] = 0xFFFFFFFF;
|
||||
this->gicd->isenabler[i + Offset] = state->isenabler[i];
|
||||
m_gicd->icenabler[i + Offset] = 0xFFFFFFFF;
|
||||
m_gicd->isenabler[i + Offset] = state->isenabler[i];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -46,38 +46,38 @@ namespace ams::kern::arch::arm64::cpu {
|
||||
private:
|
||||
static inline KLightLock s_lock;
|
||||
private:
|
||||
u64 counter;
|
||||
s32 which;
|
||||
bool done;
|
||||
u64 m_counter;
|
||||
s32 m_which;
|
||||
bool m_done;
|
||||
public:
|
||||
constexpr KPerformanceCounterInterruptHandler() : KInterruptHandler(), counter(), which(), done() { /* ... */ }
|
||||
constexpr KPerformanceCounterInterruptHandler() : KInterruptHandler(), m_counter(), m_which(), m_done() { /* ... */ }
|
||||
|
||||
static KLightLock &GetLock() { return s_lock; }
|
||||
|
||||
void Setup(s32 w) {
|
||||
this->done = false;
|
||||
this->which = w;
|
||||
m_done = false;
|
||||
m_which = w;
|
||||
}
|
||||
|
||||
void Wait() {
|
||||
while (!this->done) {
|
||||
while (!m_done) {
|
||||
cpu::Yield();
|
||||
}
|
||||
}
|
||||
|
||||
u64 GetCounter() const { return this->counter; }
|
||||
u64 GetCounter() const { return m_counter; }
|
||||
|
||||
/* Nintendo misuses this per their own API, but it's functional. */
|
||||
virtual KInterruptTask *OnInterrupt(s32 interrupt_id) override {
|
||||
MESOSPHERE_UNUSED(interrupt_id);
|
||||
|
||||
if (this->which < 0) {
|
||||
this->counter = cpu::GetCycleCounter();
|
||||
if (m_which < 0) {
|
||||
m_counter = cpu::GetCycleCounter();
|
||||
} else {
|
||||
this->counter = cpu::GetPerformanceCounter(this->which);
|
||||
m_counter = cpu::GetPerformanceCounter(m_which);
|
||||
}
|
||||
DataMemoryBarrier();
|
||||
this->done = true;
|
||||
m_done = true;
|
||||
return nullptr;
|
||||
}
|
||||
};
|
||||
@@ -93,11 +93,11 @@ namespace ams::kern::arch::arm64::cpu {
|
||||
FlushDataCache,
|
||||
};
|
||||
private:
|
||||
KLightLock lock;
|
||||
KLightLock cv_lock;
|
||||
KLightConditionVariable cv;
|
||||
std::atomic<u64> target_cores;
|
||||
volatile Operation operation;
|
||||
KLightLock m_lock;
|
||||
KLightLock m_cv_lock;
|
||||
KLightConditionVariable m_cv;
|
||||
std::atomic<u64> m_target_cores;
|
||||
volatile Operation m_operation;
|
||||
private:
|
||||
static void ThreadFunction(uintptr_t _this) {
|
||||
reinterpret_cast<KCacheHelperInterruptHandler *>(_this)->ThreadFunctionImpl();
|
||||
@@ -108,9 +108,9 @@ namespace ams::kern::arch::arm64::cpu {
|
||||
while (true) {
|
||||
/* Wait for a request to come in. */
|
||||
{
|
||||
KScopedLightLock lk(this->cv_lock);
|
||||
while ((this->target_cores & (1ul << core_id)) == 0) {
|
||||
this->cv.Wait(std::addressof(this->cv_lock));
|
||||
KScopedLightLock lk(m_cv_lock);
|
||||
while ((m_target_cores & (1ul << core_id)) == 0) {
|
||||
m_cv.Wait(std::addressof(m_cv_lock));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -119,9 +119,9 @@ namespace ams::kern::arch::arm64::cpu {
|
||||
|
||||
/* Broadcast, if there's nothing pending. */
|
||||
{
|
||||
KScopedLightLock lk(this->cv_lock);
|
||||
if (this->target_cores == 0) {
|
||||
this->cv.Broadcast();
|
||||
KScopedLightLock lk(m_cv_lock);
|
||||
if (m_target_cores == 0) {
|
||||
m_cv.Broadcast();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -129,7 +129,7 @@ namespace ams::kern::arch::arm64::cpu {
|
||||
|
||||
void ProcessOperation();
|
||||
public:
|
||||
constexpr KCacheHelperInterruptHandler() : KInterruptHandler(), lock(), cv_lock(), cv(), target_cores(), operation(Operation::Idle) { /* ... */ }
|
||||
constexpr KCacheHelperInterruptHandler() : KInterruptHandler(), m_lock(), m_cv_lock(), m_cv(), m_target_cores(), m_operation(Operation::Idle) { /* ... */ }
|
||||
|
||||
void Initialize(s32 core_id) {
|
||||
/* Reserve a thread from the system limit. */
|
||||
@@ -154,7 +154,7 @@ namespace ams::kern::arch::arm64::cpu {
|
||||
}
|
||||
|
||||
void RequestOperation(Operation op) {
|
||||
KScopedLightLock lk(this->lock);
|
||||
KScopedLightLock lk(m_lock);
|
||||
|
||||
/* Create core masks for us to use. */
|
||||
constexpr u64 AllCoresMask = (1ul << cpu::NumCores) - 1ul;
|
||||
@@ -162,48 +162,48 @@ namespace ams::kern::arch::arm64::cpu {
|
||||
|
||||
if ((op == Operation::InstructionMemoryBarrier) || (Kernel::GetState() == Kernel::State::Initializing)) {
|
||||
/* Check that there's no on-going operation. */
|
||||
MESOSPHERE_ABORT_UNLESS(this->operation == Operation::Idle);
|
||||
MESOSPHERE_ABORT_UNLESS(this->target_cores == 0);
|
||||
MESOSPHERE_ABORT_UNLESS(m_operation == Operation::Idle);
|
||||
MESOSPHERE_ABORT_UNLESS(m_target_cores == 0);
|
||||
|
||||
/* Set operation. */
|
||||
this->operation = op;
|
||||
m_operation = op;
|
||||
|
||||
/* For certain operations, we want to send an interrupt. */
|
||||
this->target_cores = other_cores_mask;
|
||||
m_target_cores = other_cores_mask;
|
||||
|
||||
const u64 target_mask = this->target_cores;
|
||||
const u64 target_mask = m_target_cores;
|
||||
DataSynchronizationBarrier();
|
||||
Kernel::GetInterruptManager().SendInterProcessorInterrupt(KInterruptName_CacheOperation, target_mask);
|
||||
|
||||
this->ProcessOperation();
|
||||
while (this->target_cores != 0) {
|
||||
while (m_target_cores != 0) {
|
||||
cpu::Yield();
|
||||
}
|
||||
|
||||
/* Go idle again. */
|
||||
this->operation = Operation::Idle;
|
||||
m_operation = Operation::Idle;
|
||||
} else {
|
||||
/* Lock condvar so that we can send and wait for acknowledgement of request. */
|
||||
KScopedLightLock cv_lk(this->cv_lock);
|
||||
KScopedLightLock cv_lk(m_cv_lock);
|
||||
|
||||
/* Check that there's no on-going operation. */
|
||||
MESOSPHERE_ABORT_UNLESS(this->operation == Operation::Idle);
|
||||
MESOSPHERE_ABORT_UNLESS(this->target_cores == 0);
|
||||
MESOSPHERE_ABORT_UNLESS(m_operation == Operation::Idle);
|
||||
MESOSPHERE_ABORT_UNLESS(m_target_cores == 0);
|
||||
|
||||
/* Set operation. */
|
||||
this->operation = op;
|
||||
m_operation = op;
|
||||
|
||||
/* Request all cores. */
|
||||
this->target_cores = AllCoresMask;
|
||||
m_target_cores = AllCoresMask;
|
||||
|
||||
/* Use the condvar. */
|
||||
this->cv.Broadcast();
|
||||
while (this->target_cores != 0) {
|
||||
this->cv.Wait(std::addressof(this->cv_lock));
|
||||
m_cv.Broadcast();
|
||||
while (m_target_cores != 0) {
|
||||
m_cv.Wait(std::addressof(m_cv_lock));
|
||||
}
|
||||
|
||||
/* Go idle again. */
|
||||
this->operation = Operation::Idle;
|
||||
m_operation = Operation::Idle;
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -283,7 +283,7 @@ namespace ams::kern::arch::arm64::cpu {
|
||||
}
|
||||
|
||||
void KCacheHelperInterruptHandler::ProcessOperation() {
|
||||
switch (this->operation) {
|
||||
switch (m_operation) {
|
||||
case Operation::Idle:
|
||||
break;
|
||||
case Operation::InstructionMemoryBarrier:
|
||||
@@ -299,7 +299,7 @@ namespace ams::kern::arch::arm64::cpu {
|
||||
break;
|
||||
}
|
||||
|
||||
this->target_cores &= ~(1ul << GetCurrentCoreId());
|
||||
m_target_cores &= ~(1ul << GetCurrentCoreId());
|
||||
}
|
||||
|
||||
ALWAYS_INLINE void SetEventLocally() {
|
||||
|
||||
@@ -22,7 +22,7 @@ namespace ams::kern::arch::arm64 {
|
||||
InitializeGlobalTimer();
|
||||
|
||||
/* Set maximum time. */
|
||||
this->maximum_time = static_cast<s64>(std::min<u64>(std::numeric_limits<s64>::max(), cpu::CounterTimerPhysicalTimerCompareValueRegisterAccessor().GetCompareValue()));
|
||||
m_maximum_time = static_cast<s64>(std::min<u64>(std::numeric_limits<s64>::max(), cpu::CounterTimerPhysicalTimerCompareValueRegisterAccessor().GetCompareValue()));
|
||||
|
||||
/* Bind the interrupt task for this core. */
|
||||
Kernel::GetInterruptManager().BindHandler(this, KInterruptName_NonSecurePhysicalTimer, GetCurrentCoreId(), KInterruptController::PriorityLevel_Timer, true, true);
|
||||
@@ -41,7 +41,7 @@ namespace ams::kern::arch::arm64 {
|
||||
|
||||
/* Disable the timer interrupt while we handle this. */
|
||||
DisableInterrupt();
|
||||
if (const s64 next_time = this->DoInterruptTaskImpl(GetTick()); 0 < next_time && next_time <= this->maximum_time) {
|
||||
if (const s64 next_time = this->DoInterruptTaskImpl(GetTick()); 0 < next_time && next_time <= m_maximum_time) {
|
||||
/* We have a next time, so we should set the time to interrupt and turn the interrupt on. */
|
||||
SetCompareValue(next_time);
|
||||
EnableInterrupt();
|
||||
|
||||
@@ -18,11 +18,11 @@
|
||||
namespace ams::kern::arch::arm64 {
|
||||
|
||||
void KInterruptManager::Initialize(s32 core_id) {
|
||||
this->interrupt_controller.Initialize(core_id);
|
||||
m_interrupt_controller.Initialize(core_id);
|
||||
}
|
||||
|
||||
void KInterruptManager::Finalize(s32 core_id) {
|
||||
this->interrupt_controller.Finalize(core_id);
|
||||
m_interrupt_controller.Finalize(core_id);
|
||||
}
|
||||
|
||||
void KInterruptManager::Save(s32 core_id) {
|
||||
@@ -34,18 +34,18 @@ namespace ams::kern::arch::arm64 {
|
||||
|
||||
/* If on core 0, save the global interrupts. */
|
||||
if (core_id == 0) {
|
||||
MESOSPHERE_ABORT_UNLESS(!this->global_state_saved);
|
||||
this->interrupt_controller.SaveGlobal(std::addressof(this->global_state));
|
||||
this->global_state_saved = true;
|
||||
MESOSPHERE_ABORT_UNLESS(!m_global_state_saved);
|
||||
m_interrupt_controller.SaveGlobal(std::addressof(m_global_state));
|
||||
m_global_state_saved = true;
|
||||
}
|
||||
|
||||
/* Ensure all cores get to this point before continuing. */
|
||||
cpu::SynchronizeAllCores();
|
||||
|
||||
/* Save all local interrupts. */
|
||||
MESOSPHERE_ABORT_UNLESS(!this->local_state_saved[core_id]);
|
||||
this->interrupt_controller.SaveCoreLocal(std::addressof(this->local_states[core_id]));
|
||||
this->local_state_saved[core_id] = true;
|
||||
MESOSPHERE_ABORT_UNLESS(!m_local_state_saved[core_id]);
|
||||
m_interrupt_controller.SaveCoreLocal(std::addressof(m_local_states[core_id]));
|
||||
m_local_state_saved[core_id] = true;
|
||||
|
||||
/* Ensure all cores get to this point before continuing. */
|
||||
cpu::SynchronizeAllCores();
|
||||
@@ -88,18 +88,18 @@ namespace ams::kern::arch::arm64 {
|
||||
cpu::SynchronizeAllCores();
|
||||
|
||||
/* Restore all local interrupts. */
|
||||
MESOSPHERE_ASSERT(this->local_state_saved[core_id]);
|
||||
this->interrupt_controller.RestoreCoreLocal(std::addressof(this->local_states[core_id]));
|
||||
this->local_state_saved[core_id] = false;
|
||||
MESOSPHERE_ASSERT(m_local_state_saved[core_id]);
|
||||
m_interrupt_controller.RestoreCoreLocal(std::addressof(m_local_states[core_id]));
|
||||
m_local_state_saved[core_id] = false;
|
||||
|
||||
/* Ensure all cores get to this point before continuing. */
|
||||
cpu::SynchronizeAllCores();
|
||||
|
||||
/* If on core 0, restore the global interrupts. */
|
||||
if (core_id == 0) {
|
||||
MESOSPHERE_ASSERT(this->global_state_saved);
|
||||
this->interrupt_controller.RestoreGlobal(std::addressof(this->global_state));
|
||||
this->global_state_saved = false;
|
||||
MESOSPHERE_ASSERT(m_global_state_saved);
|
||||
m_interrupt_controller.RestoreGlobal(std::addressof(m_global_state));
|
||||
m_global_state_saved = false;
|
||||
}
|
||||
|
||||
/* Ensure all cores get to this point before continuing. */
|
||||
@@ -108,7 +108,7 @@ namespace ams::kern::arch::arm64 {
|
||||
|
||||
bool KInterruptManager::OnHandleInterrupt() {
|
||||
/* Get the interrupt id. */
|
||||
const u32 raw_irq = this->interrupt_controller.GetIrq();
|
||||
const u32 raw_irq = m_interrupt_controller.GetIrq();
|
||||
const s32 irq = KInterruptController::ConvertRawIrq(raw_irq);
|
||||
|
||||
/* Trace the interrupt. */
|
||||
@@ -126,7 +126,7 @@ namespace ams::kern::arch::arm64 {
|
||||
if (entry.handler != nullptr) {
|
||||
/* Set manual clear needed if relevant. */
|
||||
if (entry.manually_cleared) {
|
||||
this->interrupt_controller.SetPriorityLevel(irq, KInterruptController::PriorityLevel_Low);
|
||||
m_interrupt_controller.SetPriorityLevel(irq, KInterruptController::PriorityLevel_Low);
|
||||
entry.needs_clear = true;
|
||||
}
|
||||
|
||||
@@ -143,7 +143,7 @@ namespace ams::kern::arch::arm64 {
|
||||
if (entry.handler != nullptr) {
|
||||
/* Set manual clear needed if relevant. */
|
||||
if (entry.manually_cleared) {
|
||||
this->interrupt_controller.Disable(irq);
|
||||
m_interrupt_controller.Disable(irq);
|
||||
entry.needs_clear = true;
|
||||
}
|
||||
|
||||
@@ -157,7 +157,7 @@ namespace ams::kern::arch::arm64 {
|
||||
}
|
||||
|
||||
/* Acknowledge the interrupt. */
|
||||
this->interrupt_controller.EndOfInterrupt(raw_irq);
|
||||
m_interrupt_controller.EndOfInterrupt(raw_irq);
|
||||
|
||||
/* If we found no task, then we don't need to reschedule. */
|
||||
if (task == nullptr) {
|
||||
@@ -273,16 +273,16 @@ namespace ams::kern::arch::arm64 {
|
||||
|
||||
/* Configure the interrupt as level or edge. */
|
||||
if (level) {
|
||||
this->interrupt_controller.SetLevel(irq);
|
||||
m_interrupt_controller.SetLevel(irq);
|
||||
} else {
|
||||
this->interrupt_controller.SetEdge(irq);
|
||||
m_interrupt_controller.SetEdge(irq);
|
||||
}
|
||||
|
||||
/* Configure the interrupt. */
|
||||
this->interrupt_controller.Clear(irq);
|
||||
this->interrupt_controller.SetTarget(irq, core_id);
|
||||
this->interrupt_controller.SetPriorityLevel(irq, priority);
|
||||
this->interrupt_controller.Enable(irq);
|
||||
m_interrupt_controller.Clear(irq);
|
||||
m_interrupt_controller.SetTarget(irq, core_id);
|
||||
m_interrupt_controller.SetPriorityLevel(irq, priority);
|
||||
m_interrupt_controller.Enable(irq);
|
||||
|
||||
return ResultSuccess();
|
||||
}
|
||||
@@ -303,19 +303,19 @@ namespace ams::kern::arch::arm64 {
|
||||
entry.priority = static_cast<u8>(priority);
|
||||
|
||||
/* Configure the interrupt. */
|
||||
this->interrupt_controller.Clear(irq);
|
||||
this->interrupt_controller.SetPriorityLevel(irq, priority);
|
||||
this->interrupt_controller.Enable(irq);
|
||||
m_interrupt_controller.Clear(irq);
|
||||
m_interrupt_controller.SetPriorityLevel(irq, priority);
|
||||
m_interrupt_controller.Enable(irq);
|
||||
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
Result KInterruptManager::UnbindGlobal(s32 irq) {
|
||||
for (size_t core_id = 0; core_id < cpu::NumCores; core_id++) {
|
||||
this->interrupt_controller.ClearTarget(irq, static_cast<s32>(core_id));
|
||||
m_interrupt_controller.ClearTarget(irq, static_cast<s32>(core_id));
|
||||
}
|
||||
this->interrupt_controller.SetPriorityLevel(irq, KInterruptController::PriorityLevel_Low);
|
||||
this->interrupt_controller.Disable(irq);
|
||||
m_interrupt_controller.SetPriorityLevel(irq, KInterruptController::PriorityLevel_Low);
|
||||
m_interrupt_controller.Disable(irq);
|
||||
|
||||
GetGlobalInterruptEntry(irq).handler = nullptr;
|
||||
|
||||
@@ -326,8 +326,8 @@ namespace ams::kern::arch::arm64 {
|
||||
auto &entry = this->GetLocalInterruptEntry(irq);
|
||||
R_UNLESS(entry.handler != nullptr, svc::ResultInvalidState());
|
||||
|
||||
this->interrupt_controller.SetPriorityLevel(irq, KInterruptController::PriorityLevel_Low);
|
||||
this->interrupt_controller.Disable(irq);
|
||||
m_interrupt_controller.SetPriorityLevel(irq, KInterruptController::PriorityLevel_Low);
|
||||
m_interrupt_controller.Disable(irq);
|
||||
|
||||
entry.handler = nullptr;
|
||||
|
||||
@@ -345,7 +345,7 @@ namespace ams::kern::arch::arm64 {
|
||||
|
||||
/* Clear and enable. */
|
||||
entry.needs_clear = false;
|
||||
this->interrupt_controller.Enable(irq);
|
||||
m_interrupt_controller.Enable(irq);
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
@@ -360,7 +360,7 @@ namespace ams::kern::arch::arm64 {
|
||||
|
||||
/* Clear and set priority. */
|
||||
entry.needs_clear = false;
|
||||
this->interrupt_controller.SetPriorityLevel(irq, entry.priority);
|
||||
m_interrupt_controller.SetPriorityLevel(irq, entry.priority);
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
|
||||
@@ -21,13 +21,13 @@ namespace ams::kern::arch::arm64 {
|
||||
|
||||
class AlignedMemoryBlock {
|
||||
private:
|
||||
uintptr_t before_start;
|
||||
uintptr_t before_end;
|
||||
uintptr_t after_start;
|
||||
uintptr_t after_end;
|
||||
size_t current_alignment;
|
||||
uintptr_t m_before_start;
|
||||
uintptr_t m_before_end;
|
||||
uintptr_t m_after_start;
|
||||
uintptr_t m_after_end;
|
||||
size_t m_current_alignment;
|
||||
public:
|
||||
constexpr AlignedMemoryBlock(uintptr_t start, size_t num_pages, size_t alignment) : before_start(0), before_end(0), after_start(0), after_end(0), current_alignment(0) {
|
||||
constexpr AlignedMemoryBlock(uintptr_t start, size_t num_pages, size_t alignment) : m_before_start(0), m_before_end(0), m_after_start(0), m_after_end(0), m_current_alignment(0) {
|
||||
MESOSPHERE_ASSERT(util::IsAligned(start, PageSize));
|
||||
MESOSPHERE_ASSERT(num_pages > 0);
|
||||
|
||||
@@ -38,41 +38,41 @@ namespace ams::kern::arch::arm64 {
|
||||
alignment = KPageTable::GetSmallerAlignment(alignment * PageSize) / PageSize;
|
||||
}
|
||||
|
||||
this->before_start = start_page;
|
||||
this->before_end = util::AlignUp(start_page, alignment);
|
||||
this->after_start = this->before_end;
|
||||
this->after_end = start_page + num_pages;
|
||||
this->current_alignment = alignment;
|
||||
MESOSPHERE_ASSERT(this->current_alignment > 0);
|
||||
m_before_start = start_page;
|
||||
m_before_end = util::AlignUp(start_page, alignment);
|
||||
m_after_start = m_before_end;
|
||||
m_after_end = start_page + num_pages;
|
||||
m_current_alignment = alignment;
|
||||
MESOSPHERE_ASSERT(m_current_alignment > 0);
|
||||
}
|
||||
|
||||
constexpr void SetAlignment(size_t alignment) {
|
||||
/* We can only ever decrease the granularity. */
|
||||
MESOSPHERE_ASSERT(this->current_alignment >= alignment / PageSize);
|
||||
this->current_alignment = alignment / PageSize;
|
||||
MESOSPHERE_ASSERT(m_current_alignment >= alignment / PageSize);
|
||||
m_current_alignment = alignment / PageSize;
|
||||
}
|
||||
|
||||
constexpr size_t GetAlignment() const {
|
||||
return this->current_alignment * PageSize;
|
||||
return m_current_alignment * PageSize;
|
||||
}
|
||||
|
||||
constexpr void FindBlock(uintptr_t &out, size_t &num_pages) {
|
||||
if ((this->after_end - this->after_start) >= this->current_alignment) {
|
||||
if ((m_after_end - m_after_start) >= m_current_alignment) {
|
||||
/* Select aligned memory from after block. */
|
||||
const size_t available_pages = util::AlignDown(this->after_end, this->current_alignment) - this->after_start;
|
||||
const size_t available_pages = util::AlignDown(m_after_end, m_current_alignment) - m_after_start;
|
||||
if (num_pages == 0 || available_pages < num_pages) {
|
||||
num_pages = available_pages;
|
||||
}
|
||||
out = this->after_start * PageSize;
|
||||
this->after_start += num_pages;
|
||||
} else if ((this->before_end - this->before_start) >= this->current_alignment) {
|
||||
out = m_after_start * PageSize;
|
||||
m_after_start += num_pages;
|
||||
} else if ((m_before_end - m_before_start) >= m_current_alignment) {
|
||||
/* Select aligned memory from before block. */
|
||||
const size_t available_pages = this->before_end - util::AlignUp(this->before_start, this->current_alignment);
|
||||
const size_t available_pages = m_before_end - util::AlignUp(m_before_start, m_current_alignment);
|
||||
if (num_pages == 0 || available_pages < num_pages) {
|
||||
num_pages = available_pages;
|
||||
}
|
||||
this->before_end -= num_pages;
|
||||
out = this->before_end * PageSize;
|
||||
m_before_end -= num_pages;
|
||||
out = m_before_end * PageSize;
|
||||
} else {
|
||||
/* Neither after or before can get an aligned bit of memory. */
|
||||
out = 0;
|
||||
@@ -95,32 +95,32 @@ namespace ams::kern::arch::arm64 {
|
||||
static constexpr size_t NumWords = AsidCount / BitsPerWord;
|
||||
static constexpr WordType FullWord = ~WordType(0u);
|
||||
private:
|
||||
WordType state[NumWords];
|
||||
KLightLock lock;
|
||||
u8 hint;
|
||||
WordType m_state[NumWords];
|
||||
KLightLock m_lock;
|
||||
u8 m_hint;
|
||||
private:
|
||||
constexpr bool TestImpl(u8 asid) const {
|
||||
return this->state[asid / BitsPerWord] & (1u << (asid % BitsPerWord));
|
||||
return m_state[asid / BitsPerWord] & (1u << (asid % BitsPerWord));
|
||||
}
|
||||
constexpr void ReserveImpl(u8 asid) {
|
||||
MESOSPHERE_ASSERT(!this->TestImpl(asid));
|
||||
this->state[asid / BitsPerWord] |= (1u << (asid % BitsPerWord));
|
||||
m_state[asid / BitsPerWord] |= (1u << (asid % BitsPerWord));
|
||||
}
|
||||
|
||||
constexpr void ReleaseImpl(u8 asid) {
|
||||
MESOSPHERE_ASSERT(this->TestImpl(asid));
|
||||
this->state[asid / BitsPerWord] &= ~(1u << (asid % BitsPerWord));
|
||||
m_state[asid / BitsPerWord] &= ~(1u << (asid % BitsPerWord));
|
||||
}
|
||||
|
||||
constexpr u8 FindAvailable() const {
|
||||
for (size_t i = 0; i < util::size(this->state); i++) {
|
||||
if (this->state[i] == FullWord) {
|
||||
for (size_t i = 0; i < util::size(m_state); i++) {
|
||||
if (m_state[i] == FullWord) {
|
||||
continue;
|
||||
}
|
||||
const WordType clear_bit = (this->state[i] + 1) ^ (this->state[i]);
|
||||
const WordType clear_bit = (m_state[i] + 1) ^ (m_state[i]);
|
||||
return BitsPerWord * i + BitsPerWord - 1 - ClearLeadingZero(clear_bit);
|
||||
}
|
||||
if (this->state[util::size(this->state)-1] == FullWord) {
|
||||
if (m_state[util::size(m_state)-1] == FullWord) {
|
||||
MESOSPHERE_PANIC("Unable to reserve ASID");
|
||||
}
|
||||
__builtin_unreachable();
|
||||
@@ -130,26 +130,26 @@ namespace ams::kern::arch::arm64 {
|
||||
return __builtin_clzll(value) - (BITSIZEOF(unsigned long long) - BITSIZEOF(WordType));
|
||||
}
|
||||
public:
|
||||
constexpr KPageTableAsidManager() : state(), lock(), hint() {
|
||||
constexpr KPageTableAsidManager() : m_state(), m_lock(), m_hint() {
|
||||
for (size_t i = 0; i < NumReservedAsids; i++) {
|
||||
this->ReserveImpl(ReservedAsids[i]);
|
||||
}
|
||||
}
|
||||
|
||||
u8 Reserve() {
|
||||
KScopedLightLock lk(this->lock);
|
||||
KScopedLightLock lk(m_lock);
|
||||
|
||||
if (this->TestImpl(this->hint)) {
|
||||
this->hint = this->FindAvailable();
|
||||
if (this->TestImpl(m_hint)) {
|
||||
m_hint = this->FindAvailable();
|
||||
}
|
||||
|
||||
this->ReserveImpl(this->hint);
|
||||
this->ReserveImpl(m_hint);
|
||||
|
||||
return this->hint++;
|
||||
return m_hint++;
|
||||
}
|
||||
|
||||
void Release(u8 asid) {
|
||||
KScopedLightLock lk(this->lock);
|
||||
KScopedLightLock lk(m_lock);
|
||||
this->ReleaseImpl(asid);
|
||||
}
|
||||
};
|
||||
@@ -165,15 +165,15 @@ namespace ams::kern::arch::arm64 {
|
||||
|
||||
Result KPageTable::InitializeForKernel(void *table, KVirtualAddress start, KVirtualAddress end) {
|
||||
/* Initialize basic fields. */
|
||||
this->asid = 0;
|
||||
this->manager = std::addressof(Kernel::GetPageTableManager());
|
||||
m_asid = 0;
|
||||
m_manager = std::addressof(Kernel::GetPageTableManager());
|
||||
|
||||
/* Allocate a page for ttbr. */
|
||||
const u64 asid_tag = (static_cast<u64>(this->asid) << 48ul);
|
||||
const KVirtualAddress page = this->manager->Allocate();
|
||||
const u64 asid_tag = (static_cast<u64>(m_asid) << 48ul);
|
||||
const KVirtualAddress page = m_manager->Allocate();
|
||||
MESOSPHERE_ASSERT(page != Null<KVirtualAddress>);
|
||||
cpu::ClearPageToZero(GetVoidPointer(page));
|
||||
this->ttbr = GetInteger(KPageTableBase::GetLinearMappedPhysicalAddress(page)) | asid_tag;
|
||||
m_ttbr = GetInteger(KPageTableBase::GetLinearMappedPhysicalAddress(page)) | asid_tag;
|
||||
|
||||
/* Initialize the base page table. */
|
||||
MESOSPHERE_R_ABORT_UNLESS(KPageTableBase::InitializeForKernel(true, table, start, end));
|
||||
@@ -186,17 +186,17 @@ namespace ams::kern::arch::arm64 {
|
||||
MESOSPHERE_UNUSED(id);
|
||||
|
||||
/* Get an ASID */
|
||||
this->asid = g_asid_manager.Reserve();
|
||||
auto asid_guard = SCOPE_GUARD { g_asid_manager.Release(this->asid); };
|
||||
m_asid = g_asid_manager.Reserve();
|
||||
auto asid_guard = SCOPE_GUARD { g_asid_manager.Release(m_asid); };
|
||||
|
||||
/* Set our manager. */
|
||||
this->manager = pt_manager;
|
||||
m_manager = pt_manager;
|
||||
|
||||
/* Allocate a new table, and set our ttbr value. */
|
||||
const KVirtualAddress new_table = this->manager->Allocate();
|
||||
const KVirtualAddress new_table = m_manager->Allocate();
|
||||
R_UNLESS(new_table != Null<KVirtualAddress>, svc::ResultOutOfResource());
|
||||
this->ttbr = EncodeTtbr(GetPageTablePhysicalAddress(new_table), asid);
|
||||
auto table_guard = SCOPE_GUARD { this->manager->Free(new_table); };
|
||||
m_ttbr = EncodeTtbr(GetPageTablePhysicalAddress(new_table), m_asid);
|
||||
auto table_guard = SCOPE_GUARD { m_manager->Free(new_table); };
|
||||
|
||||
/* Initialize our base table. */
|
||||
const size_t as_width = GetAddressSpaceWidth(as_type);
|
||||
@@ -308,7 +308,7 @@ namespace ams::kern::arch::arm64 {
|
||||
}
|
||||
|
||||
/* Release our asid. */
|
||||
g_asid_manager.Release(this->asid);
|
||||
g_asid_manager.Release(m_asid);
|
||||
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
@@ -18,19 +18,19 @@
|
||||
namespace ams::kern::arch::arm64 {
|
||||
|
||||
void KPageTableImpl::InitializeForKernel(void *tb, KVirtualAddress start, KVirtualAddress end) {
|
||||
this->table = static_cast<L1PageTableEntry *>(tb);
|
||||
this->is_kernel = true;
|
||||
this->num_entries = util::AlignUp(end - start, L1BlockSize) / L1BlockSize;
|
||||
m_table = static_cast<L1PageTableEntry *>(tb);
|
||||
m_is_kernel = true;
|
||||
m_num_entries = util::AlignUp(end - start, L1BlockSize) / L1BlockSize;
|
||||
}
|
||||
|
||||
void KPageTableImpl::InitializeForProcess(void *tb, KVirtualAddress start, KVirtualAddress end) {
|
||||
this->table = static_cast<L1PageTableEntry *>(tb);
|
||||
this->is_kernel = false;
|
||||
this->num_entries = util::AlignUp(end - start, L1BlockSize) / L1BlockSize;
|
||||
m_table = static_cast<L1PageTableEntry *>(tb);
|
||||
m_is_kernel = false;
|
||||
m_num_entries = util::AlignUp(end - start, L1BlockSize) / L1BlockSize;
|
||||
}
|
||||
|
||||
L1PageTableEntry *KPageTableImpl::Finalize() {
|
||||
return this->table;
|
||||
return m_table;
|
||||
}
|
||||
|
||||
bool KPageTableImpl::ExtractL3Entry(TraversalEntry *out_entry, TraversalContext *out_context, const L3PageTableEntry *l3_entry, KProcessAddress virt_addr) const {
|
||||
@@ -119,21 +119,21 @@ namespace ams::kern::arch::arm64 {
|
||||
out_entry->phys_addr = Null<KPhysicalAddress>;
|
||||
out_entry->block_size = L1BlockSize;
|
||||
out_entry->sw_reserved_bits = 0;
|
||||
out_context->l1_entry = this->table + this->num_entries;
|
||||
out_context->l1_entry = m_table + m_num_entries;
|
||||
out_context->l2_entry = nullptr;
|
||||
out_context->l3_entry = nullptr;
|
||||
|
||||
/* Validate that we can read the actual entry. */
|
||||
const size_t l0_index = GetL0Index(address);
|
||||
const size_t l1_index = GetL1Index(address);
|
||||
if (this->is_kernel) {
|
||||
if (m_is_kernel) {
|
||||
/* Kernel entries must be accessed via TTBR1. */
|
||||
if ((l0_index != MaxPageTableEntries - 1) || (l1_index < MaxPageTableEntries - this->num_entries)) {
|
||||
if ((l0_index != MaxPageTableEntries - 1) || (l1_index < MaxPageTableEntries - m_num_entries)) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
/* User entries must be accessed with TTBR0. */
|
||||
if ((l0_index != 0) || l1_index >= this->num_entries) {
|
||||
if ((l0_index != 0) || l1_index >= m_num_entries) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -212,15 +212,15 @@ namespace ams::kern::arch::arm64 {
|
||||
}
|
||||
} else {
|
||||
/* We need to update the l1 entry. */
|
||||
const size_t l1_index = context->l1_entry - this->table;
|
||||
if (l1_index < this->num_entries) {
|
||||
const size_t l1_index = context->l1_entry - m_table;
|
||||
if (l1_index < m_num_entries) {
|
||||
valid = this->ExtractL1Entry(out_entry, context, context->l1_entry, Null<KProcessAddress>);
|
||||
} else {
|
||||
/* Invalid, end traversal. */
|
||||
out_entry->phys_addr = Null<KPhysicalAddress>;
|
||||
out_entry->block_size = L1BlockSize;
|
||||
out_entry->sw_reserved_bits = 0;
|
||||
context->l1_entry = this->table + this->num_entries;
|
||||
context->l1_entry = m_table + m_num_entries;
|
||||
context->l2_entry = nullptr;
|
||||
context->l3_entry = nullptr;
|
||||
return false;
|
||||
@@ -262,14 +262,14 @@ namespace ams::kern::arch::arm64 {
|
||||
/* Validate that we can read the actual entry. */
|
||||
const size_t l0_index = GetL0Index(address);
|
||||
const size_t l1_index = GetL1Index(address);
|
||||
if (this->is_kernel) {
|
||||
if (m_is_kernel) {
|
||||
/* Kernel entries must be accessed via TTBR1. */
|
||||
if ((l0_index != MaxPageTableEntries - 1) || (l1_index < MaxPageTableEntries - this->num_entries)) {
|
||||
if ((l0_index != MaxPageTableEntries - 1) || (l1_index < MaxPageTableEntries - m_num_entries)) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
/* User entries must be accessed with TTBR0. */
|
||||
if ((l0_index != 0) || l1_index >= this->num_entries) {
|
||||
if ((l0_index != 0) || l1_index >= m_num_entries) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -322,14 +322,14 @@ namespace ams::kern::arch::arm64 {
|
||||
/* Validate that we can read the actual entry. */
|
||||
const size_t l0_index = GetL0Index(cur);
|
||||
const size_t l1_index = GetL1Index(cur);
|
||||
if (this->is_kernel) {
|
||||
if (m_is_kernel) {
|
||||
/* Kernel entries must be accessed via TTBR1. */
|
||||
if ((l0_index != MaxPageTableEntries - 1) || (l1_index < MaxPageTableEntries - this->num_entries)) {
|
||||
if ((l0_index != MaxPageTableEntries - 1) || (l1_index < MaxPageTableEntries - m_num_entries)) {
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
/* User entries must be accessed with TTBR0. */
|
||||
if ((l0_index != 0) || l1_index >= this->num_entries) {
|
||||
if ((l0_index != 0) || l1_index >= m_num_entries) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -482,8 +482,8 @@ namespace ams::kern::arch::arm64 {
|
||||
#if defined(MESOSPHERE_BUILD_FOR_DEBUGGING)
|
||||
{
|
||||
++num_tables;
|
||||
for (size_t l1_index = 0; l1_index < this->num_entries; ++l1_index) {
|
||||
auto &l1_entry = this->table[l1_index];
|
||||
for (size_t l1_index = 0; l1_index < m_num_entries; ++l1_index) {
|
||||
auto &l1_entry = m_table[l1_index];
|
||||
if (l1_entry.IsTable()) {
|
||||
++num_tables;
|
||||
for (size_t l2_index = 0; l2_index < MaxPageTableEntries; ++l2_index) {
|
||||
|
||||
@@ -19,7 +19,7 @@ namespace ams::kern::arch::arm64 {
|
||||
|
||||
void KSupervisorPageTable::Initialize(s32 core_id) {
|
||||
/* Get the identity mapping ttbr0. */
|
||||
this->ttbr0_identity[core_id] = cpu::GetTtbr0El1();
|
||||
m_ttbr0_identity[core_id] = cpu::GetTtbr0El1();
|
||||
|
||||
/* Set sctlr_el1 */
|
||||
cpu::SystemControlRegisterAccessor().SetWxn(true).Store();
|
||||
@@ -35,7 +35,7 @@ namespace ams::kern::arch::arm64 {
|
||||
const u64 kernel_vaddr_start = 0xFFFFFF8000000000ul;
|
||||
const u64 kernel_vaddr_end = 0xFFFFFFFFFFE00000ul;
|
||||
void *table = GetVoidPointer(KPageTableBase::GetLinearMappedVirtualAddress(ttbr1));
|
||||
this->page_table.InitializeForKernel(table, kernel_vaddr_start, kernel_vaddr_end);
|
||||
m_page_table.InitializeForKernel(table, kernel_vaddr_start, kernel_vaddr_end);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -117,38 +117,38 @@ namespace ams::kern::arch::arm64 {
|
||||
/* Determine LR and SP. */
|
||||
if (is_user) {
|
||||
/* Usermode thread. */
|
||||
this->lr = reinterpret_cast<uintptr_t>(::ams::kern::arch::arm64::UserModeThreadStarter);
|
||||
this->sp = SetupStackForUserModeThreadStarter(u_pc, k_sp, u_sp, arg, is_64_bit);
|
||||
m_lr = reinterpret_cast<uintptr_t>(::ams::kern::arch::arm64::UserModeThreadStarter);
|
||||
m_sp = SetupStackForUserModeThreadStarter(u_pc, k_sp, u_sp, arg, is_64_bit);
|
||||
} else {
|
||||
/* Kernel thread. */
|
||||
MESOSPHERE_ASSERT(is_64_bit);
|
||||
|
||||
if (is_main) {
|
||||
/* Main thread. */
|
||||
this->lr = GetInteger(u_pc);
|
||||
this->sp = GetInteger(k_sp);
|
||||
m_lr = GetInteger(u_pc);
|
||||
m_sp = GetInteger(k_sp);
|
||||
} else {
|
||||
/* Generic Kernel thread. */
|
||||
this->lr = reinterpret_cast<uintptr_t>(::ams::kern::arch::arm64::SupervisorModeThreadStarter);
|
||||
this->sp = SetupStackForSupervisorModeThreadStarter(u_pc, k_sp, arg);
|
||||
m_lr = reinterpret_cast<uintptr_t>(::ams::kern::arch::arm64::SupervisorModeThreadStarter);
|
||||
m_sp = SetupStackForSupervisorModeThreadStarter(u_pc, k_sp, arg);
|
||||
}
|
||||
}
|
||||
|
||||
/* Clear callee-saved registers. */
|
||||
for (size_t i = 0; i < util::size(this->callee_saved.registers); i++) {
|
||||
this->callee_saved.registers[i] = 0;
|
||||
for (size_t i = 0; i < util::size(m_callee_saved.registers); i++) {
|
||||
m_callee_saved.registers[i] = 0;
|
||||
}
|
||||
|
||||
/* Clear FPU state. */
|
||||
this->fpcr = 0;
|
||||
this->fpsr = 0;
|
||||
this->cpacr = 0;
|
||||
for (size_t i = 0; i < util::size(this->fpu_registers); i++) {
|
||||
this->fpu_registers[i] = 0;
|
||||
m_fpcr = 0;
|
||||
m_fpsr = 0;
|
||||
m_cpacr = 0;
|
||||
for (size_t i = 0; i < util::size(m_fpu_registers); i++) {
|
||||
m_fpu_registers[i] = 0;
|
||||
}
|
||||
|
||||
/* Lock the context, if we're a main thread. */
|
||||
this->locked = is_main;
|
||||
m_locked = is_main;
|
||||
|
||||
return ResultSuccess();
|
||||
}
|
||||
@@ -159,7 +159,7 @@ namespace ams::kern::arch::arm64 {
|
||||
}
|
||||
|
||||
void KThreadContext::SetArguments(uintptr_t arg0, uintptr_t arg1) {
|
||||
u64 *stack = reinterpret_cast<u64 *>(this->sp);
|
||||
u64 *stack = reinterpret_cast<u64 *>(m_sp);
|
||||
stack[0] = arg0;
|
||||
stack[1] = arg1;
|
||||
}
|
||||
@@ -199,11 +199,11 @@ namespace ams::kern::arch::arm64 {
|
||||
void KThreadContext::SetFpuRegisters(const u128 *v, bool is_64_bit) {
|
||||
if (is_64_bit) {
|
||||
for (size_t i = 0; i < KThreadContext::NumFpuRegisters; ++i) {
|
||||
this->fpu_registers[i] = v[i];
|
||||
m_fpu_registers[i] = v[i];
|
||||
}
|
||||
} else {
|
||||
for (size_t i = 0; i < KThreadContext::NumFpuRegisters / 2; ++i) {
|
||||
this->fpu_registers[i] = v[i];
|
||||
m_fpu_registers[i] = v[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -210,10 +210,10 @@ namespace ams::kern::board::nintendo::nx {
|
||||
Bit_Readable = 31,
|
||||
};
|
||||
private:
|
||||
u32 value;
|
||||
u32 m_value;
|
||||
protected:
|
||||
constexpr ALWAYS_INLINE u32 SelectBit(Bit n) const {
|
||||
return (this->value & (1u << n));
|
||||
return (m_value & (1u << n));
|
||||
}
|
||||
|
||||
constexpr ALWAYS_INLINE bool GetBit(Bit n) const {
|
||||
@@ -231,7 +231,7 @@ namespace ams::kern::board::nintendo::nx {
|
||||
ALWAYS_INLINE void SetValue(u32 v) {
|
||||
/* Prevent re-ordering around entry modifications. */
|
||||
__asm__ __volatile__("" ::: "memory");
|
||||
this->value = v;
|
||||
m_value = v;
|
||||
__asm__ __volatile__("" ::: "memory");
|
||||
}
|
||||
public:
|
||||
@@ -246,7 +246,7 @@ namespace ams::kern::board::nintendo::nx {
|
||||
|
||||
constexpr ALWAYS_INLINE u32 GetAttributes() const { return this->SelectBit(Bit_NonSecure) | this->SelectBit(Bit_Writeable) | this->SelectBit(Bit_Readable); }
|
||||
|
||||
constexpr ALWAYS_INLINE KPhysicalAddress GetPhysicalAddress() const { return (static_cast<u64>(this->value) << DevicePageBits) & PhysicalAddressMask; }
|
||||
constexpr ALWAYS_INLINE KPhysicalAddress GetPhysicalAddress() const { return (static_cast<u64>(m_value) << DevicePageBits) & PhysicalAddressMask; }
|
||||
|
||||
ALWAYS_INLINE void Invalidate() { this->SetValue(0); }
|
||||
};
|
||||
@@ -286,36 +286,36 @@ namespace ams::kern::board::nintendo::nx {
|
||||
static constexpr size_t NumWords = AsidCount / BitsPerWord;
|
||||
static constexpr WordType FullWord = ~WordType(0u);
|
||||
private:
|
||||
WordType state[NumWords];
|
||||
KLightLock lock;
|
||||
WordType m_state[NumWords];
|
||||
KLightLock m_lock;
|
||||
private:
|
||||
constexpr void ReserveImpl(u8 asid) {
|
||||
this->state[asid / BitsPerWord] |= (1u << (asid % BitsPerWord));
|
||||
m_state[asid / BitsPerWord] |= (1u << (asid % BitsPerWord));
|
||||
}
|
||||
|
||||
constexpr void ReleaseImpl(u8 asid) {
|
||||
this->state[asid / BitsPerWord] &= ~(1u << (asid % BitsPerWord));
|
||||
m_state[asid / BitsPerWord] &= ~(1u << (asid % BitsPerWord));
|
||||
}
|
||||
|
||||
static constexpr ALWAYS_INLINE WordType ClearLeadingZero(WordType value) {
|
||||
return __builtin_clzll(value) - (BITSIZEOF(unsigned long long) - BITSIZEOF(WordType));
|
||||
}
|
||||
public:
|
||||
constexpr KDeviceAsidManager() : state(), lock() {
|
||||
constexpr KDeviceAsidManager() : m_state(), m_lock() {
|
||||
for (size_t i = 0; i < NumReservedAsids; i++) {
|
||||
this->ReserveImpl(ReservedAsids[i]);
|
||||
}
|
||||
}
|
||||
|
||||
Result Reserve(u8 *out, size_t num_desired) {
|
||||
KScopedLightLock lk(this->lock);
|
||||
KScopedLightLock lk(m_lock);
|
||||
MESOSPHERE_ASSERT(num_desired > 0);
|
||||
|
||||
size_t num_reserved = 0;
|
||||
for (size_t i = 0; i < NumWords; i++) {
|
||||
while (this->state[i] != FullWord) {
|
||||
const WordType clear_bit = (this->state[i] + 1) ^ (this->state[i]);
|
||||
this->state[i] |= clear_bit;
|
||||
while (m_state[i] != FullWord) {
|
||||
const WordType clear_bit = (m_state[i] + 1) ^ (m_state[i]);
|
||||
m_state[i] |= clear_bit;
|
||||
out[num_reserved++] = static_cast<u8>(BitsPerWord * i + BitsPerWord - 1 - ClearLeadingZero(clear_bit));
|
||||
R_SUCCEED_IF(num_reserved == num_desired);
|
||||
}
|
||||
@@ -329,7 +329,7 @@ namespace ams::kern::board::nintendo::nx {
|
||||
}
|
||||
|
||||
void Release(u8 asid) {
|
||||
KScopedLightLock lk(this->lock);
|
||||
KScopedLightLock lk(m_lock);
|
||||
this->ReleaseImpl(asid);
|
||||
}
|
||||
};
|
||||
@@ -776,14 +776,14 @@ namespace ams::kern::board::nintendo::nx {
|
||||
/* Clear the tables. */
|
||||
static_assert(TableCount == (1ul << DeviceVirtualAddressBits) / DeviceRegionSize);
|
||||
for (size_t i = 0; i < TableCount; ++i) {
|
||||
this->tables[i] = Null<KVirtualAddress>;
|
||||
m_tables[i] = Null<KVirtualAddress>;
|
||||
}
|
||||
|
||||
/* Ensure that we clean up the tables on failure. */
|
||||
auto table_guard = SCOPE_GUARD {
|
||||
for (size_t i = start_index; i <= end_index; ++i) {
|
||||
if (this->tables[i] != Null<KVirtualAddress> && ptm.Close(this->tables[i], 1)) {
|
||||
ptm.Free(this->tables[i]);
|
||||
if (m_tables[i] != Null<KVirtualAddress> && ptm.Close(m_tables[i], 1)) {
|
||||
ptm.Free(m_tables[i]);
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -797,32 +797,32 @@ namespace ams::kern::board::nintendo::nx {
|
||||
|
||||
ptm.Open(table_vaddr, 1);
|
||||
cpu::StoreDataCache(GetVoidPointer(table_vaddr), PageDirectorySize);
|
||||
this->tables[i] = table_vaddr;
|
||||
m_tables[i] = table_vaddr;
|
||||
}
|
||||
|
||||
/* Clear asids. */
|
||||
for (size_t i = 0; i < TableCount; ++i) {
|
||||
this->table_asids[i] = g_reserved_asid;
|
||||
m_table_asids[i] = g_reserved_asid;
|
||||
}
|
||||
|
||||
/* Reserve asids for the tables. */
|
||||
R_TRY(g_asid_manager.Reserve(std::addressof(this->table_asids[start_index]), end_index - start_index + 1));
|
||||
R_TRY(g_asid_manager.Reserve(std::addressof(m_table_asids[start_index]), end_index - start_index + 1));
|
||||
|
||||
/* Associate tables with asids. */
|
||||
for (size_t i = start_index; i <= end_index; ++i) {
|
||||
SetTable(this->table_asids[i], GetPageTablePhysicalAddress(this->tables[i]));
|
||||
SetTable(m_table_asids[i], GetPageTablePhysicalAddress(m_tables[i]));
|
||||
}
|
||||
|
||||
/* Set member variables. */
|
||||
this->attached_device = 0;
|
||||
this->attached_value = (1u << 31) | this->table_asids[0];
|
||||
this->detached_value = (1u << 31) | g_reserved_asid;
|
||||
m_attached_device = 0;
|
||||
m_attached_value = (1u << 31) | m_table_asids[0];
|
||||
m_detached_value = (1u << 31) | g_reserved_asid;
|
||||
|
||||
this->hs_attached_value = (1u << 31);
|
||||
this->hs_detached_value = (1u << 31);
|
||||
m_hs_attached_value = (1u << 31);
|
||||
m_hs_detached_value = (1u << 31);
|
||||
for (size_t i = 0; i < TableCount; ++i) {
|
||||
this->hs_attached_value |= (this->table_asids[i] << (i * BITSIZEOF(u8)));
|
||||
this->hs_detached_value |= (g_reserved_asid << (i * BITSIZEOF(u8)));
|
||||
m_hs_attached_value |= (m_table_asids[i] << (i * BITSIZEOF(u8)));
|
||||
m_hs_detached_value |= (g_reserved_asid << (i * BITSIZEOF(u8)));
|
||||
}
|
||||
|
||||
/* We succeeded. */
|
||||
@@ -839,8 +839,8 @@ namespace ams::kern::board::nintendo::nx {
|
||||
KScopedLightLock lk(g_lock);
|
||||
for (size_t i = 0; i < ams::svc::DeviceName_Count; ++i) {
|
||||
const auto device_name = static_cast<ams::svc::DeviceName>(i);
|
||||
if ((this->attached_device & (1ul << device_name)) != 0) {
|
||||
WriteMcRegister(GetDeviceAsidRegisterOffset(device_name), IsHsSupported(device_name) ? this->hs_detached_value : this->detached_value);
|
||||
if ((m_attached_device & (1ul << device_name)) != 0) {
|
||||
WriteMcRegister(GetDeviceAsidRegisterOffset(device_name), IsHsSupported(device_name) ? m_hs_detached_value : m_detached_value);
|
||||
SmmuSynchronizationBarrier();
|
||||
}
|
||||
}
|
||||
@@ -851,12 +851,12 @@ namespace ams::kern::board::nintendo::nx {
|
||||
|
||||
/* Release all asids. */
|
||||
for (size_t i = 0; i < TableCount; ++i) {
|
||||
if (this->table_asids[i] != g_reserved_asid) {
|
||||
if (m_table_asids[i] != g_reserved_asid) {
|
||||
/* Set the table to the reserved table. */
|
||||
SetTable(this->table_asids[i], g_reserved_table_phys_addr);
|
||||
SetTable(m_table_asids[i], g_reserved_table_phys_addr);
|
||||
|
||||
/* Close the table. */
|
||||
const KVirtualAddress table_vaddr = this->tables[i];
|
||||
const KVirtualAddress table_vaddr = m_tables[i];
|
||||
MESOSPHERE_ASSERT(ptm.GetRefCount(table_vaddr) == 1);
|
||||
MESOSPHERE_ABORT_UNLESS(ptm.Close(table_vaddr, 1));
|
||||
|
||||
@@ -864,7 +864,7 @@ namespace ams::kern::board::nintendo::nx {
|
||||
ptm.Free(table_vaddr);
|
||||
|
||||
/* Release the asid. */
|
||||
g_asid_manager.Release(this->table_asids[i]);
|
||||
g_asid_manager.Release(m_table_asids[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -875,7 +875,7 @@ namespace ams::kern::board::nintendo::nx {
|
||||
R_UNLESS(device_name < ams::svc::DeviceName_Count, svc::ResultNotFound());
|
||||
|
||||
/* Check that the device isn't already attached. */
|
||||
R_UNLESS((this->attached_device & (1ul << device_name)) == 0, svc::ResultBusy());
|
||||
R_UNLESS((m_attached_device & (1ul << device_name)) == 0, svc::ResultBusy());
|
||||
|
||||
/* Validate that the space is allowed for the device. */
|
||||
const size_t end_index = (space_address + space_size - 1) / DeviceRegionSize;
|
||||
@@ -889,8 +889,8 @@ namespace ams::kern::board::nintendo::nx {
|
||||
R_UNLESS(reg_offset >= 0, svc::ResultNotFound());
|
||||
|
||||
/* Determine the old/new values. */
|
||||
const u32 old_val = IsHsSupported(device_name) ? this->hs_detached_value : this->detached_value;
|
||||
const u32 new_val = IsHsSupported(device_name) ? this->hs_attached_value : this->attached_value;
|
||||
const u32 old_val = IsHsSupported(device_name) ? m_hs_detached_value : m_detached_value;
|
||||
const u32 new_val = IsHsSupported(device_name) ? m_hs_attached_value : m_attached_value;
|
||||
|
||||
/* Attach the device. */
|
||||
{
|
||||
@@ -912,7 +912,7 @@ namespace ams::kern::board::nintendo::nx {
|
||||
}
|
||||
|
||||
/* Mark the device as attached. */
|
||||
this->attached_device |= (1ul << device_name);
|
||||
m_attached_device |= (1ul << device_name);
|
||||
|
||||
return ResultSuccess();
|
||||
}
|
||||
@@ -923,15 +923,15 @@ namespace ams::kern::board::nintendo::nx {
|
||||
R_UNLESS(device_name < ams::svc::DeviceName_Count, svc::ResultNotFound());
|
||||
|
||||
/* Check that the device is already attached. */
|
||||
R_UNLESS((this->attached_device & (1ul << device_name)) != 0, svc::ResultInvalidState());
|
||||
R_UNLESS((m_attached_device & (1ul << device_name)) != 0, svc::ResultInvalidState());
|
||||
|
||||
/* Get the device asid register offset. */
|
||||
const int reg_offset = GetDeviceAsidRegisterOffset(device_name);
|
||||
R_UNLESS(reg_offset >= 0, svc::ResultNotFound());
|
||||
|
||||
/* Determine the old/new values. */
|
||||
const u32 old_val = IsHsSupported(device_name) ? this->hs_attached_value : this->attached_value;
|
||||
const u32 new_val = IsHsSupported(device_name) ? this->hs_detached_value : this->detached_value;
|
||||
const u32 old_val = IsHsSupported(device_name) ? m_hs_attached_value : m_attached_value;
|
||||
const u32 new_val = IsHsSupported(device_name) ? m_hs_detached_value : m_detached_value;
|
||||
|
||||
/* When not building for debug, the old value might be unused. */
|
||||
AMS_UNUSED(old_val);
|
||||
@@ -952,7 +952,7 @@ namespace ams::kern::board::nintendo::nx {
|
||||
}
|
||||
|
||||
/* Mark the device as detached. */
|
||||
this->attached_device &= ~(1ul << device_name);
|
||||
m_attached_device &= ~(1ul << device_name);
|
||||
|
||||
return ResultSuccess();
|
||||
}
|
||||
@@ -968,7 +968,7 @@ namespace ams::kern::board::nintendo::nx {
|
||||
const size_t l1_index = (address % DeviceRegionSize) / DeviceLargePageSize;
|
||||
const size_t l2_index = (address % DeviceLargePageSize) / DevicePageSize;
|
||||
|
||||
const PageDirectoryEntry *l1 = GetPointer<PageDirectoryEntry>(this->tables[l0_index]);
|
||||
const PageDirectoryEntry *l1 = GetPointer<PageDirectoryEntry>(m_tables[l0_index]);
|
||||
if (l1 == nullptr || !l1[l1_index].IsValid()) {
|
||||
const size_t remaining_in_entry = (PageTableSize / sizeof(PageTableEntry)) - l2_index;
|
||||
const size_t map_count = std::min<size_t>(remaining_in_entry, remaining / DevicePageSize);
|
||||
@@ -1023,7 +1023,7 @@ namespace ams::kern::board::nintendo::nx {
|
||||
const size_t l2_index = (address % DeviceLargePageSize) / DevicePageSize;
|
||||
|
||||
/* Get and validate l1. */
|
||||
PageDirectoryEntry *l1 = GetPointer<PageDirectoryEntry>(this->tables[l0_index]);
|
||||
PageDirectoryEntry *l1 = GetPointer<PageDirectoryEntry>(m_tables[l0_index]);
|
||||
MESOSPHERE_ASSERT(l1 != nullptr);
|
||||
|
||||
/* Setup an l1 table/entry, if needed. */
|
||||
@@ -1039,7 +1039,7 @@ namespace ams::kern::board::nintendo::nx {
|
||||
|
||||
/* Synchronize. */
|
||||
InvalidatePtc(GetPageTablePhysicalAddress(KVirtualAddress(std::addressof(l1[l1_index]))));
|
||||
InvalidateTlbSection(this->table_asids[l0_index], address);
|
||||
InvalidateTlbSection(m_table_asids[l0_index], address);
|
||||
SmmuSynchronizationBarrier();
|
||||
|
||||
/* Open references to the pages. */
|
||||
@@ -1066,7 +1066,7 @@ namespace ams::kern::board::nintendo::nx {
|
||||
|
||||
/* Synchronize. */
|
||||
InvalidatePtc(GetPageTablePhysicalAddress(KVirtualAddress(std::addressof(l1[l1_index]))));
|
||||
InvalidateTlbSection(this->table_asids[l0_index], address);
|
||||
InvalidateTlbSection(m_table_asids[l0_index], address);
|
||||
SmmuSynchronizationBarrier();
|
||||
|
||||
/* Increment the page table count. */
|
||||
@@ -1100,7 +1100,7 @@ namespace ams::kern::board::nintendo::nx {
|
||||
}
|
||||
|
||||
/* Synchronize. */
|
||||
InvalidateTlbSection(this->table_asids[l0_index], address);
|
||||
InvalidateTlbSection(m_table_asids[l0_index], address);
|
||||
SmmuSynchronizationBarrier();
|
||||
|
||||
/* Open references to the pages. */
|
||||
@@ -1181,7 +1181,7 @@ namespace ams::kern::board::nintendo::nx {
|
||||
const size_t l2_index = (address % DeviceLargePageSize) / DevicePageSize;
|
||||
|
||||
/* Get and validate l1. */
|
||||
PageDirectoryEntry *l1 = GetPointer<PageDirectoryEntry>(this->tables[l0_index]);
|
||||
PageDirectoryEntry *l1 = GetPointer<PageDirectoryEntry>(m_tables[l0_index]);
|
||||
|
||||
/* Check if there's nothing mapped at l1. */
|
||||
if (l1 == nullptr || !l1[l1_index].IsValid()) {
|
||||
@@ -1242,7 +1242,7 @@ namespace ams::kern::board::nintendo::nx {
|
||||
|
||||
/* Synchronize. */
|
||||
InvalidatePtc(GetPageTablePhysicalAddress(KVirtualAddress(std::addressof(l1[l1_index]))));
|
||||
InvalidateTlbSection(this->table_asids[l0_index], address);
|
||||
InvalidateTlbSection(m_table_asids[l0_index], address);
|
||||
SmmuSynchronizationBarrier();
|
||||
|
||||
/* We invalidated the tlb. */
|
||||
@@ -1254,7 +1254,7 @@ namespace ams::kern::board::nintendo::nx {
|
||||
|
||||
/* Invalidate the tlb if we haven't already. */
|
||||
if (!invalidated_tlb) {
|
||||
InvalidateTlbSection(this->table_asids[l0_index], address);
|
||||
InvalidateTlbSection(m_table_asids[l0_index], address);
|
||||
SmmuSynchronizationBarrier();
|
||||
}
|
||||
|
||||
@@ -1275,7 +1275,7 @@ namespace ams::kern::board::nintendo::nx {
|
||||
|
||||
/* Synchronize. */
|
||||
InvalidatePtc(GetPageTablePhysicalAddress(KVirtualAddress(std::addressof(l1[l1_index]))));
|
||||
InvalidateTlbSection(this->table_asids[l0_index], address);
|
||||
InvalidateTlbSection(m_table_asids[l0_index], address);
|
||||
SmmuSynchronizationBarrier();
|
||||
|
||||
/* Close references. */
|
||||
@@ -1305,7 +1305,7 @@ namespace ams::kern::board::nintendo::nx {
|
||||
const size_t l2_index = (address % DeviceLargePageSize) / DevicePageSize;
|
||||
|
||||
/* Get and validate l1. */
|
||||
const PageDirectoryEntry *l1 = GetPointer<PageDirectoryEntry>(this->tables[l0_index]);
|
||||
const PageDirectoryEntry *l1 = GetPointer<PageDirectoryEntry>(m_tables[l0_index]);
|
||||
R_UNLESS(l1 != nullptr, svc::ResultInvalidCurrentMemory());
|
||||
R_UNLESS(l1[l1_index].IsValid(), svc::ResultInvalidCurrentMemory());
|
||||
|
||||
|
||||
@@ -51,15 +51,15 @@ namespace ams::kern {
|
||||
{
|
||||
KScopedSchedulerLock sl;
|
||||
|
||||
auto it = this->tree.nfind_light({ addr, -1 });
|
||||
while ((it != this->tree.end()) && (count <= 0 || num_waiters < count) && (it->GetAddressArbiterKey() == addr)) {
|
||||
auto it = m_tree.nfind_light({ addr, -1 });
|
||||
while ((it != m_tree.end()) && (count <= 0 || num_waiters < count) && (it->GetAddressArbiterKey() == addr)) {
|
||||
KThread *target_thread = std::addressof(*it);
|
||||
target_thread->SetSyncedObject(nullptr, ResultSuccess());
|
||||
|
||||
AMS_ASSERT(target_thread->IsWaitingForAddressArbiter());
|
||||
target_thread->Wakeup();
|
||||
|
||||
it = this->tree.erase(it);
|
||||
it = m_tree.erase(it);
|
||||
target_thread->ClearAddressArbiter();
|
||||
++num_waiters;
|
||||
}
|
||||
@@ -78,15 +78,15 @@ namespace ams::kern {
|
||||
R_UNLESS(UpdateIfEqual(std::addressof(user_value), addr, value, value + 1), svc::ResultInvalidCurrentMemory());
|
||||
R_UNLESS(user_value == value, svc::ResultInvalidState());
|
||||
|
||||
auto it = this->tree.nfind_light({ addr, -1 });
|
||||
while ((it != this->tree.end()) && (count <= 0 || num_waiters < count) && (it->GetAddressArbiterKey() == addr)) {
|
||||
auto it = m_tree.nfind_light({ addr, -1 });
|
||||
while ((it != m_tree.end()) && (count <= 0 || num_waiters < count) && (it->GetAddressArbiterKey() == addr)) {
|
||||
KThread *target_thread = std::addressof(*it);
|
||||
target_thread->SetSyncedObject(nullptr, ResultSuccess());
|
||||
|
||||
AMS_ASSERT(target_thread->IsWaitingForAddressArbiter());
|
||||
target_thread->Wakeup();
|
||||
|
||||
it = this->tree.erase(it);
|
||||
it = m_tree.erase(it);
|
||||
target_thread->ClearAddressArbiter();
|
||||
++num_waiters;
|
||||
}
|
||||
@@ -100,21 +100,21 @@ namespace ams::kern {
|
||||
{
|
||||
KScopedSchedulerLock sl;
|
||||
|
||||
auto it = this->tree.nfind_light({ addr, -1 });
|
||||
auto it = m_tree.nfind_light({ addr, -1 });
|
||||
/* Determine the updated value. */
|
||||
s32 new_value;
|
||||
if (GetTargetFirmware() >= TargetFirmware_7_0_0) {
|
||||
if (count <= 0) {
|
||||
if ((it != this->tree.end()) && (it->GetAddressArbiterKey() == addr)) {
|
||||
if ((it != m_tree.end()) && (it->GetAddressArbiterKey() == addr)) {
|
||||
new_value = value - 2;
|
||||
} else {
|
||||
new_value = value + 1;
|
||||
}
|
||||
} else {
|
||||
if ((it != this->tree.end()) && (it->GetAddressArbiterKey() == addr)) {
|
||||
if ((it != m_tree.end()) && (it->GetAddressArbiterKey() == addr)) {
|
||||
auto tmp_it = it;
|
||||
s32 tmp_num_waiters = 0;
|
||||
while ((++tmp_it != this->tree.end()) && (tmp_it->GetAddressArbiterKey() == addr)) {
|
||||
while ((++tmp_it != m_tree.end()) && (tmp_it->GetAddressArbiterKey() == addr)) {
|
||||
if ((tmp_num_waiters++) >= count) {
|
||||
break;
|
||||
}
|
||||
@@ -131,7 +131,7 @@ namespace ams::kern {
|
||||
}
|
||||
} else {
|
||||
if (count <= 0) {
|
||||
if ((it != this->tree.end()) && (it->GetAddressArbiterKey() == addr)) {
|
||||
if ((it != m_tree.end()) && (it->GetAddressArbiterKey() == addr)) {
|
||||
new_value = value - 1;
|
||||
} else {
|
||||
new_value = value + 1;
|
||||
@@ -139,7 +139,7 @@ namespace ams::kern {
|
||||
} else {
|
||||
auto tmp_it = it;
|
||||
s32 tmp_num_waiters = 0;
|
||||
while ((tmp_it != this->tree.end()) && (tmp_it->GetAddressArbiterKey() == addr) && (tmp_num_waiters < count + 1)) {
|
||||
while ((tmp_it != m_tree.end()) && (tmp_it->GetAddressArbiterKey() == addr) && (tmp_num_waiters < count + 1)) {
|
||||
++tmp_num_waiters;
|
||||
++tmp_it;
|
||||
}
|
||||
@@ -166,14 +166,14 @@ namespace ams::kern {
|
||||
R_UNLESS(succeeded, svc::ResultInvalidCurrentMemory());
|
||||
R_UNLESS(user_value == value, svc::ResultInvalidState());
|
||||
|
||||
while ((it != this->tree.end()) && (count <= 0 || num_waiters < count) && (it->GetAddressArbiterKey() == addr)) {
|
||||
while ((it != m_tree.end()) && (count <= 0 || num_waiters < count) && (it->GetAddressArbiterKey() == addr)) {
|
||||
KThread *target_thread = std::addressof(*it);
|
||||
target_thread->SetSyncedObject(nullptr, ResultSuccess());
|
||||
|
||||
AMS_ASSERT(target_thread->IsWaitingForAddressArbiter());
|
||||
target_thread->Wakeup();
|
||||
|
||||
it = this->tree.erase(it);
|
||||
it = m_tree.erase(it);
|
||||
target_thread->ClearAddressArbiter();
|
||||
++num_waiters;
|
||||
}
|
||||
@@ -225,8 +225,8 @@ namespace ams::kern {
|
||||
}
|
||||
|
||||
/* Set the arbiter. */
|
||||
cur_thread->SetAddressArbiter(std::addressof(this->tree), addr);
|
||||
this->tree.insert(*cur_thread);
|
||||
cur_thread->SetAddressArbiter(std::addressof(m_tree), addr);
|
||||
m_tree.insert(*cur_thread);
|
||||
cur_thread->SetState(KThread::ThreadState_Waiting);
|
||||
}
|
||||
|
||||
@@ -240,7 +240,7 @@ namespace ams::kern {
|
||||
KScopedSchedulerLock sl;
|
||||
|
||||
if (cur_thread->IsWaitingForAddressArbiter()) {
|
||||
this->tree.erase(this->tree.iterator_to(*cur_thread));
|
||||
m_tree.erase(m_tree.iterator_to(*cur_thread));
|
||||
cur_thread->ClearAddressArbiter();
|
||||
}
|
||||
}
|
||||
@@ -287,8 +287,8 @@ namespace ams::kern {
|
||||
}
|
||||
|
||||
/* Set the arbiter. */
|
||||
cur_thread->SetAddressArbiter(std::addressof(this->tree), addr);
|
||||
this->tree.insert(*cur_thread);
|
||||
cur_thread->SetAddressArbiter(std::addressof(m_tree), addr);
|
||||
m_tree.insert(*cur_thread);
|
||||
cur_thread->SetState(KThread::ThreadState_Waiting);
|
||||
}
|
||||
|
||||
@@ -302,7 +302,7 @@ namespace ams::kern {
|
||||
KScopedSchedulerLock sl;
|
||||
|
||||
if (cur_thread->IsWaitingForAddressArbiter()) {
|
||||
this->tree.erase(this->tree.iterator_to(*cur_thread));
|
||||
m_tree.erase(m_tree.iterator_to(*cur_thread));
|
||||
cur_thread->ClearAddressArbiter();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
namespace ams::kern {
|
||||
|
||||
KAutoObject *KAutoObject::Create(KAutoObject *obj) {
|
||||
obj->ref_count = 1;
|
||||
obj->m_ref_count = 1;
|
||||
return obj;
|
||||
}
|
||||
|
||||
|
||||
@@ -21,27 +21,27 @@ namespace ams::kern {
|
||||
void KAutoObjectWithListContainer::Register(KAutoObjectWithList *obj) {
|
||||
MESOSPHERE_ASSERT_THIS();
|
||||
|
||||
KScopedLightLock lk(this->lock);
|
||||
KScopedLightLock lk(m_lock);
|
||||
|
||||
this->object_list.insert(*obj);
|
||||
m_object_list.insert(*obj);
|
||||
}
|
||||
|
||||
void KAutoObjectWithListContainer::Unregister(KAutoObjectWithList *obj) {
|
||||
MESOSPHERE_ASSERT_THIS();
|
||||
|
||||
KScopedLightLock lk(this->lock);
|
||||
KScopedLightLock lk(m_lock);
|
||||
|
||||
this->object_list.erase(this->object_list.iterator_to(*obj));
|
||||
m_object_list.erase(m_object_list.iterator_to(*obj));
|
||||
}
|
||||
|
||||
size_t KAutoObjectWithListContainer::GetOwnedCount(KProcess *owner) {
|
||||
MESOSPHERE_ASSERT_THIS();
|
||||
|
||||
KScopedLightLock lk(this->lock);
|
||||
KScopedLightLock lk(m_lock);
|
||||
|
||||
size_t count = 0;
|
||||
|
||||
for (auto &obj : this->object_list) {
|
||||
for (auto &obj : m_object_list) {
|
||||
if (obj.GetOwner() == owner) {
|
||||
count++;
|
||||
}
|
||||
|
||||
@@ -22,15 +22,15 @@ namespace ams::kern {
|
||||
/* Most fields have already been cleared by our constructor. */
|
||||
|
||||
/* Initial processes may run on all cores. */
|
||||
this->core_mask = (1ul << cpu::NumCores) - 1;
|
||||
m_core_mask = (1ul << cpu::NumCores) - 1;
|
||||
|
||||
/* Initial processes may use any user priority they like. */
|
||||
this->priority_mask = ~0xFul;
|
||||
m_priority_mask = ~0xFul;
|
||||
|
||||
/* Here, Nintendo sets the kernel version to the current kernel version. */
|
||||
/* We will follow suit and set the version to the highest supported kernel version. */
|
||||
this->intended_kernel_version.Set<KernelVersion::MajorVersion>(ams::svc::SupportedKernelMajorVersion);
|
||||
this->intended_kernel_version.Set<KernelVersion::MinorVersion>(ams::svc::SupportedKernelMinorVersion);
|
||||
m_intended_kernel_version.Set<KernelVersion::MajorVersion>(ams::svc::SupportedKernelMajorVersion);
|
||||
m_intended_kernel_version.Set<KernelVersion::MinorVersion>(ams::svc::SupportedKernelMinorVersion);
|
||||
|
||||
/* Parse the capabilities array. */
|
||||
return this->SetCapabilities(caps, num_caps, page_table);
|
||||
@@ -46,8 +46,8 @@ namespace ams::kern {
|
||||
|
||||
Result KCapabilities::SetCorePriorityCapability(const util::BitPack32 cap) {
|
||||
/* We can't set core/priority if we've already set them. */
|
||||
R_UNLESS(this->core_mask == 0, svc::ResultInvalidArgument());
|
||||
R_UNLESS(this->priority_mask == 0, svc::ResultInvalidArgument());
|
||||
R_UNLESS(m_core_mask == 0, svc::ResultInvalidArgument());
|
||||
R_UNLESS(m_priority_mask == 0, svc::ResultInvalidArgument());
|
||||
|
||||
/* Validate the core/priority. */
|
||||
const auto min_core = cap.Get<CorePriority::MinimumCoreId>();
|
||||
@@ -64,18 +64,18 @@ namespace ams::kern {
|
||||
|
||||
/* Set core mask. */
|
||||
for (auto core_id = min_core; core_id <= max_core; core_id++) {
|
||||
this->core_mask |= (1ul << core_id);
|
||||
m_core_mask |= (1ul << core_id);
|
||||
}
|
||||
MESOSPHERE_ASSERT((this->core_mask & ((1ul << cpu::NumCores) - 1)) == this->core_mask);
|
||||
MESOSPHERE_ASSERT((m_core_mask & ((1ul << cpu::NumCores) - 1)) == m_core_mask);
|
||||
|
||||
/* Set priority mask. */
|
||||
for (auto prio = min_prio; prio <= max_prio; prio++) {
|
||||
this->priority_mask |= (1ul << prio);
|
||||
m_priority_mask |= (1ul << prio);
|
||||
}
|
||||
|
||||
/* We must have some core/priority we can use. */
|
||||
R_UNLESS(this->core_mask != 0, svc::ResultInvalidArgument());
|
||||
R_UNLESS(this->priority_mask != 0, svc::ResultInvalidArgument());
|
||||
R_UNLESS(m_core_mask != 0, svc::ResultInvalidArgument());
|
||||
R_UNLESS(m_priority_mask != 0, svc::ResultInvalidArgument());
|
||||
|
||||
return ResultSuccess();
|
||||
}
|
||||
@@ -186,17 +186,17 @@ namespace ams::kern {
|
||||
/* Validate. */
|
||||
R_UNLESS(cap.Get<ProgramType::Reserved>() == 0, svc::ResultReservedUsed());
|
||||
|
||||
this->program_type = cap.Get<ProgramType::Type>();
|
||||
m_program_type = cap.Get<ProgramType::Type>();
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
Result KCapabilities::SetKernelVersionCapability(const util::BitPack32 cap) {
|
||||
/* Ensure we haven't set our version before. */
|
||||
R_UNLESS(this->intended_kernel_version.Get<KernelVersion::MajorVersion>() == 0, svc::ResultInvalidArgument());
|
||||
R_UNLESS(m_intended_kernel_version.Get<KernelVersion::MajorVersion>() == 0, svc::ResultInvalidArgument());
|
||||
|
||||
/* Set, ensure that we set a valid version. */
|
||||
this->intended_kernel_version = cap;
|
||||
R_UNLESS(this->intended_kernel_version.Get<KernelVersion::MajorVersion>() != 0, svc::ResultInvalidArgument());
|
||||
m_intended_kernel_version = cap;
|
||||
R_UNLESS(m_intended_kernel_version.Get<KernelVersion::MajorVersion>() != 0, svc::ResultInvalidArgument());
|
||||
|
||||
return ResultSuccess();
|
||||
}
|
||||
@@ -205,7 +205,7 @@ namespace ams::kern {
|
||||
/* Validate. */
|
||||
R_UNLESS(cap.Get<HandleTable::Reserved>() == 0, svc::ResultReservedUsed());
|
||||
|
||||
this->handle_table_size = cap.Get<HandleTable::Size>();
|
||||
m_handle_table_size = cap.Get<HandleTable::Size>();
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
@@ -213,8 +213,8 @@ namespace ams::kern {
|
||||
/* Validate. */
|
||||
R_UNLESS(cap.Get<DebugFlags::Reserved>() == 0, svc::ResultReservedUsed());
|
||||
|
||||
this->debug_capabilities.Set<DebugFlags::AllowDebug>(cap.Get<DebugFlags::AllowDebug>());
|
||||
this->debug_capabilities.Set<DebugFlags::ForceDebug>(cap.Get<DebugFlags::ForceDebug>());
|
||||
m_debug_capabilities.Set<DebugFlags::AllowDebug>(cap.Get<DebugFlags::AllowDebug>());
|
||||
m_debug_capabilities.Set<DebugFlags::ForceDebug>(cap.Get<DebugFlags::ForceDebug>());
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
|
||||
@@ -19,17 +19,17 @@ namespace ams::kern {
|
||||
|
||||
void KClientPort::Initialize(KPort *parent, s32 max_sessions) {
|
||||
/* Set member variables. */
|
||||
this->num_sessions = 0;
|
||||
this->peak_sessions = 0;
|
||||
this->parent = parent;
|
||||
this->max_sessions = max_sessions;
|
||||
m_num_sessions = 0;
|
||||
m_peak_sessions = 0;
|
||||
m_parent = parent;
|
||||
m_max_sessions = max_sessions;
|
||||
}
|
||||
|
||||
void KClientPort::OnSessionFinalized() {
|
||||
KScopedSchedulerLock sl;
|
||||
|
||||
const auto prev = this->num_sessions--;
|
||||
if (prev == this->max_sessions) {
|
||||
const auto prev = m_num_sessions--;
|
||||
if (prev == m_max_sessions) {
|
||||
this->NotifyAvailable();
|
||||
}
|
||||
}
|
||||
@@ -44,15 +44,15 @@ namespace ams::kern {
|
||||
|
||||
void KClientPort::Destroy() {
|
||||
/* Note with our parent that we're closed. */
|
||||
this->parent->OnClientClosed();
|
||||
m_parent->OnClientClosed();
|
||||
|
||||
/* Close our reference to our parent. */
|
||||
this->parent->Close();
|
||||
m_parent->Close();
|
||||
}
|
||||
|
||||
bool KClientPort::IsSignaled() const {
|
||||
MESOSPHERE_ASSERT_THIS();
|
||||
return this->num_sessions < this->max_sessions;
|
||||
return m_num_sessions < m_max_sessions;
|
||||
}
|
||||
|
||||
Result KClientPort::CreateSession(KClientSession **out) {
|
||||
@@ -67,23 +67,23 @@ namespace ams::kern {
|
||||
/* Atomically increment the number of sessions. */
|
||||
s32 new_sessions;
|
||||
{
|
||||
const auto max = this->max_sessions;
|
||||
auto cur_sessions = this->num_sessions.load(std::memory_order_acquire);
|
||||
const auto max = m_max_sessions;
|
||||
auto cur_sessions = m_num_sessions.load(std::memory_order_acquire);
|
||||
do {
|
||||
R_UNLESS(cur_sessions < max, svc::ResultOutOfSessions());
|
||||
new_sessions = cur_sessions + 1;
|
||||
} while (!this->num_sessions.compare_exchange_weak(cur_sessions, new_sessions, std::memory_order_relaxed));
|
||||
} while (!m_num_sessions.compare_exchange_weak(cur_sessions, new_sessions, std::memory_order_relaxed));
|
||||
|
||||
}
|
||||
|
||||
/* Atomically update the peak session tracking. */
|
||||
{
|
||||
auto peak = this->peak_sessions.load(std::memory_order_acquire);
|
||||
auto peak = m_peak_sessions.load(std::memory_order_acquire);
|
||||
do {
|
||||
if (peak >= new_sessions) {
|
||||
break;
|
||||
}
|
||||
} while (!this->peak_sessions.compare_exchange_weak(peak, new_sessions, std::memory_order_relaxed));
|
||||
} while (!m_peak_sessions.compare_exchange_weak(peak, new_sessions, std::memory_order_relaxed));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -91,8 +91,8 @@ namespace ams::kern {
|
||||
KSession *session = KSession::Create();
|
||||
if (session == nullptr) {
|
||||
/* Decrement the session count. */
|
||||
const auto prev = this->num_sessions--;
|
||||
if (prev == this->max_sessions) {
|
||||
const auto prev = m_num_sessions--;
|
||||
if (prev == m_max_sessions) {
|
||||
this->NotifyAvailable();
|
||||
}
|
||||
|
||||
@@ -100,7 +100,7 @@ namespace ams::kern {
|
||||
}
|
||||
|
||||
/* Initialize the session. */
|
||||
session->Initialize(this, this->parent->GetName());
|
||||
session->Initialize(this, m_parent->GetName());
|
||||
|
||||
/* Commit the session reservation. */
|
||||
session_reservation.Commit();
|
||||
@@ -113,7 +113,7 @@ namespace ams::kern {
|
||||
};
|
||||
|
||||
/* Enqueue the session with our parent. */
|
||||
R_TRY(this->parent->EnqueueSession(std::addressof(session->GetServerSession())));
|
||||
R_TRY(m_parent->EnqueueSession(std::addressof(session->GetServerSession())));
|
||||
|
||||
/* We succeeded, so set the output. */
|
||||
session_guard.Cancel();
|
||||
@@ -133,23 +133,23 @@ namespace ams::kern {
|
||||
/* Atomically increment the number of sessions. */
|
||||
s32 new_sessions;
|
||||
{
|
||||
const auto max = this->max_sessions;
|
||||
auto cur_sessions = this->num_sessions.load(std::memory_order_acquire);
|
||||
const auto max = m_max_sessions;
|
||||
auto cur_sessions = m_num_sessions.load(std::memory_order_acquire);
|
||||
do {
|
||||
R_UNLESS(cur_sessions < max, svc::ResultOutOfSessions());
|
||||
new_sessions = cur_sessions + 1;
|
||||
} while (!this->num_sessions.compare_exchange_weak(cur_sessions, new_sessions, std::memory_order_relaxed));
|
||||
} while (!m_num_sessions.compare_exchange_weak(cur_sessions, new_sessions, std::memory_order_relaxed));
|
||||
|
||||
}
|
||||
|
||||
/* Atomically update the peak session tracking. */
|
||||
{
|
||||
auto peak = this->peak_sessions.load(std::memory_order_acquire);
|
||||
auto peak = m_peak_sessions.load(std::memory_order_acquire);
|
||||
do {
|
||||
if (peak >= new_sessions) {
|
||||
break;
|
||||
}
|
||||
} while (!this->peak_sessions.compare_exchange_weak(peak, new_sessions, std::memory_order_relaxed));
|
||||
} while (!m_peak_sessions.compare_exchange_weak(peak, new_sessions, std::memory_order_relaxed));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -157,8 +157,8 @@ namespace ams::kern {
|
||||
KLightSession *session = KLightSession::Create();
|
||||
if (session == nullptr) {
|
||||
/* Decrement the session count. */
|
||||
const auto prev = this->num_sessions--;
|
||||
if (prev == this->max_sessions) {
|
||||
const auto prev = m_num_sessions--;
|
||||
if (prev == m_max_sessions) {
|
||||
this->NotifyAvailable();
|
||||
}
|
||||
|
||||
@@ -166,7 +166,7 @@ namespace ams::kern {
|
||||
}
|
||||
|
||||
/* Initialize the session. */
|
||||
session->Initialize(this, this->parent->GetName());
|
||||
session->Initialize(this, m_parent->GetName());
|
||||
|
||||
/* Commit the session reservation. */
|
||||
session_reservation.Commit();
|
||||
@@ -179,7 +179,7 @@ namespace ams::kern {
|
||||
};
|
||||
|
||||
/* Enqueue the session with our parent. */
|
||||
R_TRY(this->parent->EnqueueSession(std::addressof(session->GetServerSession())));
|
||||
R_TRY(m_parent->EnqueueSession(std::addressof(session->GetServerSession())));
|
||||
|
||||
/* We succeeded, so set the output. */
|
||||
session_guard.Cancel();
|
||||
|
||||
@@ -20,8 +20,8 @@ namespace ams::kern {
|
||||
void KClientSession::Destroy() {
|
||||
MESOSPHERE_ASSERT_THIS();
|
||||
|
||||
this->parent->OnClientClosed();
|
||||
this->parent->Close();
|
||||
m_parent->OnClientClosed();
|
||||
m_parent->Close();
|
||||
}
|
||||
|
||||
void KClientSession::OnServerClosed() {
|
||||
@@ -45,7 +45,7 @@ namespace ams::kern {
|
||||
|
||||
GetCurrentThread().SetSyncedObject(nullptr, ResultSuccess());
|
||||
|
||||
R_TRY(this->parent->OnRequest(request));
|
||||
R_TRY(m_parent->OnRequest(request));
|
||||
}
|
||||
|
||||
/* Get the result. */
|
||||
@@ -68,7 +68,7 @@ namespace ams::kern {
|
||||
{
|
||||
KScopedSchedulerLock sl;
|
||||
|
||||
R_TRY(this->parent->OnRequest(request));
|
||||
R_TRY(m_parent->OnRequest(request));
|
||||
}
|
||||
|
||||
return ResultSuccess();
|
||||
|
||||
@@ -21,31 +21,31 @@ namespace ams::kern {
|
||||
MESOSPHERE_ASSERT_THIS();
|
||||
|
||||
/* Set members. */
|
||||
this->owner = GetCurrentProcessPointer();
|
||||
m_owner = GetCurrentProcessPointer();
|
||||
|
||||
/* Initialize the page group. */
|
||||
auto &page_table = this->owner->GetPageTable();
|
||||
new (GetPointer(this->page_group)) KPageGroup(page_table.GetBlockInfoManager());
|
||||
auto &page_table = m_owner->GetPageTable();
|
||||
new (GetPointer(m_page_group)) KPageGroup(page_table.GetBlockInfoManager());
|
||||
|
||||
/* Ensure that our page group's state is valid on exit. */
|
||||
auto pg_guard = SCOPE_GUARD { GetReference(this->page_group).~KPageGroup(); };
|
||||
auto pg_guard = SCOPE_GUARD { GetReference(m_page_group).~KPageGroup(); };
|
||||
|
||||
/* Lock the memory. */
|
||||
R_TRY(page_table.LockForCodeMemory(GetPointer(this->page_group), addr, size));
|
||||
R_TRY(page_table.LockForCodeMemory(GetPointer(m_page_group), addr, size));
|
||||
|
||||
/* Clear the memory. */
|
||||
for (const auto &block : GetReference(this->page_group)) {
|
||||
for (const auto &block : GetReference(m_page_group)) {
|
||||
/* Clear and store cache. */
|
||||
std::memset(GetVoidPointer(block.GetAddress()), 0xFF, block.GetSize());
|
||||
cpu::StoreDataCache(GetVoidPointer(block.GetAddress()), block.GetSize());
|
||||
}
|
||||
|
||||
/* Set remaining tracking members. */
|
||||
this->owner->Open();
|
||||
this->address = addr;
|
||||
this->is_initialized = true;
|
||||
this->is_owner_mapped = false;
|
||||
this->is_mapped = false;
|
||||
m_owner->Open();
|
||||
m_address = addr;
|
||||
m_is_initialized = true;
|
||||
m_is_owner_mapped = false;
|
||||
m_is_mapped = false;
|
||||
|
||||
/* We succeeded. */
|
||||
pg_guard.Cancel();
|
||||
@@ -56,17 +56,17 @@ namespace ams::kern {
|
||||
MESOSPHERE_ASSERT_THIS();
|
||||
|
||||
/* Unlock. */
|
||||
if (!this->is_mapped && !this->is_owner_mapped) {
|
||||
const size_t size = GetReference(this->page_group).GetNumPages() * PageSize;
|
||||
MESOSPHERE_R_ABORT_UNLESS(this->owner->GetPageTable().UnlockForCodeMemory(this->address, size, GetReference(this->page_group)));
|
||||
if (!m_is_mapped && !m_is_owner_mapped) {
|
||||
const size_t size = GetReference(m_page_group).GetNumPages() * PageSize;
|
||||
MESOSPHERE_R_ABORT_UNLESS(m_owner->GetPageTable().UnlockForCodeMemory(m_address, size, GetReference(m_page_group)));
|
||||
}
|
||||
|
||||
/* Close the page group. */
|
||||
GetReference(this->page_group).Close();
|
||||
GetReference(this->page_group).Finalize();
|
||||
GetReference(m_page_group).Close();
|
||||
GetReference(m_page_group).Finalize();
|
||||
|
||||
/* Close our reference to our owner. */
|
||||
this->owner->Close();
|
||||
m_owner->Close();
|
||||
|
||||
/* Perform inherited finalization. */
|
||||
KAutoObjectWithSlabHeapAndContainer<KCodeMemory, KAutoObjectWithList>::Finalize();
|
||||
@@ -76,19 +76,19 @@ namespace ams::kern {
|
||||
MESOSPHERE_ASSERT_THIS();
|
||||
|
||||
/* Validate the size. */
|
||||
R_UNLESS(GetReference(this->page_group).GetNumPages() == util::DivideUp(size, PageSize), svc::ResultInvalidSize());
|
||||
R_UNLESS(GetReference(m_page_group).GetNumPages() == util::DivideUp(size, PageSize), svc::ResultInvalidSize());
|
||||
|
||||
/* Lock ourselves. */
|
||||
KScopedLightLock lk(this->lock);
|
||||
KScopedLightLock lk(m_lock);
|
||||
|
||||
/* Ensure we're not already mapped. */
|
||||
R_UNLESS(!this->is_mapped, svc::ResultInvalidState());
|
||||
R_UNLESS(!m_is_mapped, svc::ResultInvalidState());
|
||||
|
||||
/* Map the memory. */
|
||||
R_TRY(GetCurrentProcess().GetPageTable().MapPageGroup(address, GetReference(this->page_group), KMemoryState_CodeOut, KMemoryPermission_UserReadWrite));
|
||||
R_TRY(GetCurrentProcess().GetPageTable().MapPageGroup(address, GetReference(m_page_group), KMemoryState_CodeOut, KMemoryPermission_UserReadWrite));
|
||||
|
||||
/* Mark ourselves as mapped. */
|
||||
this->is_mapped = true;
|
||||
m_is_mapped = true;
|
||||
|
||||
return ResultSuccess();
|
||||
}
|
||||
@@ -97,17 +97,17 @@ namespace ams::kern {
|
||||
MESOSPHERE_ASSERT_THIS();
|
||||
|
||||
/* Validate the size. */
|
||||
R_UNLESS(GetReference(this->page_group).GetNumPages() == util::DivideUp(size, PageSize), svc::ResultInvalidSize());
|
||||
R_UNLESS(GetReference(m_page_group).GetNumPages() == util::DivideUp(size, PageSize), svc::ResultInvalidSize());
|
||||
|
||||
/* Lock ourselves. */
|
||||
KScopedLightLock lk(this->lock);
|
||||
KScopedLightLock lk(m_lock);
|
||||
|
||||
/* Unmap the memory. */
|
||||
R_TRY(GetCurrentProcess().GetPageTable().UnmapPageGroup(address, GetReference(this->page_group), KMemoryState_CodeOut));
|
||||
R_TRY(GetCurrentProcess().GetPageTable().UnmapPageGroup(address, GetReference(m_page_group), KMemoryState_CodeOut));
|
||||
|
||||
/* Mark ourselves as unmapped. */
|
||||
MESOSPHERE_ASSERT(this->is_mapped);
|
||||
this->is_mapped = false;
|
||||
MESOSPHERE_ASSERT(m_is_mapped);
|
||||
m_is_mapped = false;
|
||||
|
||||
return ResultSuccess();
|
||||
}
|
||||
@@ -116,13 +116,13 @@ namespace ams::kern {
|
||||
MESOSPHERE_ASSERT_THIS();
|
||||
|
||||
/* Validate the size. */
|
||||
R_UNLESS(GetReference(this->page_group).GetNumPages() == util::DivideUp(size, PageSize), svc::ResultInvalidSize());
|
||||
R_UNLESS(GetReference(m_page_group).GetNumPages() == util::DivideUp(size, PageSize), svc::ResultInvalidSize());
|
||||
|
||||
/* Lock ourselves. */
|
||||
KScopedLightLock lk(this->lock);
|
||||
KScopedLightLock lk(m_lock);
|
||||
|
||||
/* Ensure we're not already mapped. */
|
||||
R_UNLESS(!this->is_owner_mapped, svc::ResultInvalidState());
|
||||
R_UNLESS(!m_is_owner_mapped, svc::ResultInvalidState());
|
||||
|
||||
/* Convert the memory permission. */
|
||||
KMemoryPermission k_perm;
|
||||
@@ -133,10 +133,10 @@ namespace ams::kern {
|
||||
}
|
||||
|
||||
/* Map the memory. */
|
||||
R_TRY(this->owner->GetPageTable().MapPageGroup(address, GetReference(this->page_group), KMemoryState_GeneratedCode, k_perm));
|
||||
R_TRY(m_owner->GetPageTable().MapPageGroup(address, GetReference(m_page_group), KMemoryState_GeneratedCode, k_perm));
|
||||
|
||||
/* Mark ourselves as mapped. */
|
||||
this->is_owner_mapped = true;
|
||||
m_is_owner_mapped = true;
|
||||
|
||||
return ResultSuccess();
|
||||
}
|
||||
@@ -145,17 +145,17 @@ namespace ams::kern {
|
||||
MESOSPHERE_ASSERT_THIS();
|
||||
|
||||
/* Validate the size. */
|
||||
R_UNLESS(GetReference(this->page_group).GetNumPages() == util::DivideUp(size, PageSize), svc::ResultInvalidSize());
|
||||
R_UNLESS(GetReference(m_page_group).GetNumPages() == util::DivideUp(size, PageSize), svc::ResultInvalidSize());
|
||||
|
||||
/* Lock ourselves. */
|
||||
KScopedLightLock lk(this->lock);
|
||||
KScopedLightLock lk(m_lock);
|
||||
|
||||
/* Unmap the memory. */
|
||||
R_TRY(this->owner->GetPageTable().UnmapPageGroup(address, GetReference(this->page_group), KMemoryState_GeneratedCode));
|
||||
R_TRY(m_owner->GetPageTable().UnmapPageGroup(address, GetReference(m_page_group), KMemoryState_GeneratedCode));
|
||||
|
||||
/* Mark ourselves as unmapped. */
|
||||
MESOSPHERE_ASSERT(this->is_owner_mapped);
|
||||
this->is_owner_mapped = false;
|
||||
MESOSPHERE_ASSERT(m_is_owner_mapped);
|
||||
m_is_owner_mapped = false;
|
||||
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
@@ -178,8 +178,8 @@ namespace ams::kern {
|
||||
{
|
||||
KScopedSchedulerLock sl;
|
||||
|
||||
auto it = this->tree.nfind_light({ cv_key, -1 });
|
||||
while ((it != this->tree.end()) && (count <= 0 || num_waiters < count) && (it->GetConditionVariableKey() == cv_key)) {
|
||||
auto it = m_tree.nfind_light({ cv_key, -1 });
|
||||
while ((it != m_tree.end()) && (count <= 0 || num_waiters < count) && (it->GetConditionVariableKey() == cv_key)) {
|
||||
KThread *target_thread = std::addressof(*it);
|
||||
|
||||
if (KThread *thread = this->SignalImpl(target_thread); thread != nullptr) {
|
||||
@@ -190,13 +190,13 @@ namespace ams::kern {
|
||||
}
|
||||
}
|
||||
|
||||
it = this->tree.erase(it);
|
||||
it = m_tree.erase(it);
|
||||
target_thread->ClearConditionVariable();
|
||||
++num_waiters;
|
||||
}
|
||||
|
||||
/* If we have no waiters, clear the has waiter flag. */
|
||||
if (it == this->tree.end() || it->GetConditionVariableKey() != cv_key) {
|
||||
if (it == m_tree.end() || it->GetConditionVariableKey() != cv_key) {
|
||||
const u32 has_waiter_flag = 0;
|
||||
WriteToUser(cv_key, std::addressof(has_waiter_flag));
|
||||
}
|
||||
@@ -266,8 +266,8 @@ namespace ams::kern {
|
||||
|
||||
/* Update condition variable tracking. */
|
||||
{
|
||||
cur_thread->SetConditionVariable(std::addressof(this->tree), addr, key, value);
|
||||
this->tree.insert(*cur_thread);
|
||||
cur_thread->SetConditionVariable(std::addressof(m_tree), addr, key, value);
|
||||
m_tree.insert(*cur_thread);
|
||||
}
|
||||
|
||||
/* If the timeout is non-zero, set the thread as waiting. */
|
||||
@@ -290,7 +290,7 @@ namespace ams::kern {
|
||||
}
|
||||
|
||||
if (cur_thread->IsWaitingForConditionVariable()) {
|
||||
this->tree.erase(this->tree.iterator_to(*cur_thread));
|
||||
m_tree.erase(m_tree.iterator_to(*cur_thread));
|
||||
cur_thread->ClearConditionVariable();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,28 +27,28 @@ namespace ams::kern {
|
||||
|
||||
void KDebugBase::Initialize() {
|
||||
/* Clear the process and continue flags. */
|
||||
this->process = nullptr;
|
||||
this->continue_flags = 0;
|
||||
m_process = nullptr;
|
||||
m_continue_flags = 0;
|
||||
}
|
||||
|
||||
bool KDebugBase::Is64Bit() const {
|
||||
MESOSPHERE_ASSERT(this->lock.IsLockedByCurrentThread());
|
||||
MESOSPHERE_ASSERT(this->process != nullptr);
|
||||
return this->process->Is64Bit();
|
||||
MESOSPHERE_ASSERT(m_lock.IsLockedByCurrentThread());
|
||||
MESOSPHERE_ASSERT(m_process != nullptr);
|
||||
return m_process->Is64Bit();
|
||||
}
|
||||
|
||||
|
||||
Result KDebugBase::QueryMemoryInfo(ams::svc::MemoryInfo *out_memory_info, ams::svc::PageInfo *out_page_info, KProcessAddress address) {
|
||||
/* Lock ourselves. */
|
||||
KScopedLightLock lk(this->lock);
|
||||
KScopedLightLock lk(m_lock);
|
||||
|
||||
/* Check that we have a valid process. */
|
||||
R_UNLESS(this->process != nullptr, svc::ResultProcessTerminated());
|
||||
R_UNLESS(!this->process->IsTerminated(), svc::ResultProcessTerminated());
|
||||
R_UNLESS(m_process != nullptr, svc::ResultProcessTerminated());
|
||||
R_UNLESS(!m_process->IsTerminated(), svc::ResultProcessTerminated());
|
||||
|
||||
/* Query the mapping's info. */
|
||||
KMemoryInfo info;
|
||||
R_TRY(process->GetPageTable().QueryInfo(std::addressof(info), out_page_info, address));
|
||||
R_TRY(m_process->GetPageTable().QueryInfo(std::addressof(info), out_page_info, address));
|
||||
|
||||
/* Write output. */
|
||||
*out_memory_info = info.GetSvcMemoryInfo();
|
||||
@@ -57,15 +57,15 @@ namespace ams::kern {
|
||||
|
||||
Result KDebugBase::ReadMemory(KProcessAddress buffer, KProcessAddress address, size_t size) {
|
||||
/* Lock ourselves. */
|
||||
KScopedLightLock lk(this->lock);
|
||||
KScopedLightLock lk(m_lock);
|
||||
|
||||
/* Check that we have a valid process. */
|
||||
R_UNLESS(this->process != nullptr, svc::ResultProcessTerminated());
|
||||
R_UNLESS(!this->process->IsTerminated(), svc::ResultProcessTerminated());
|
||||
R_UNLESS(m_process != nullptr, svc::ResultProcessTerminated());
|
||||
R_UNLESS(!m_process->IsTerminated(), svc::ResultProcessTerminated());
|
||||
|
||||
/* Get the page tables. */
|
||||
KProcessPageTable &debugger_pt = GetCurrentProcess().GetPageTable();
|
||||
KProcessPageTable &target_pt = this->process->GetPageTable();
|
||||
KProcessPageTable &target_pt = m_process->GetPageTable();
|
||||
|
||||
/* Verify that the regions are in range. */
|
||||
R_UNLESS(target_pt.Contains(address, size), svc::ResultInvalidCurrentMemory());
|
||||
@@ -150,15 +150,15 @@ namespace ams::kern {
|
||||
|
||||
Result KDebugBase::WriteMemory(KProcessAddress buffer, KProcessAddress address, size_t size) {
|
||||
/* Lock ourselves. */
|
||||
KScopedLightLock lk(this->lock);
|
||||
KScopedLightLock lk(m_lock);
|
||||
|
||||
/* Check that we have a valid process. */
|
||||
R_UNLESS(this->process != nullptr, svc::ResultProcessTerminated());
|
||||
R_UNLESS(!this->process->IsTerminated(), svc::ResultProcessTerminated());
|
||||
R_UNLESS(m_process != nullptr, svc::ResultProcessTerminated());
|
||||
R_UNLESS(!m_process->IsTerminated(), svc::ResultProcessTerminated());
|
||||
|
||||
/* Get the page tables. */
|
||||
KProcessPageTable &debugger_pt = GetCurrentProcess().GetPageTable();
|
||||
KProcessPageTable &target_pt = this->process->GetPageTable();
|
||||
KProcessPageTable &target_pt = m_process->GetPageTable();
|
||||
|
||||
/* Verify that the regions are in range. */
|
||||
R_UNLESS(target_pt.Contains(address, size), svc::ResultInvalidCurrentMemory());
|
||||
@@ -280,7 +280,7 @@ namespace ams::kern {
|
||||
/* Lock both ourselves, the target process, and the scheduler. */
|
||||
KScopedLightLock state_lk(target->GetStateLock());
|
||||
KScopedLightLock list_lk(target->GetListLock());
|
||||
KScopedLightLock this_lk(this->lock);
|
||||
KScopedLightLock this_lk(m_lock);
|
||||
KScopedSchedulerLock sl;
|
||||
|
||||
/* Check that the process isn't already being debugged. */
|
||||
@@ -305,19 +305,19 @@ namespace ams::kern {
|
||||
}
|
||||
|
||||
/* Set our process member, and open a reference to the target. */
|
||||
this->process = target;
|
||||
this->process->Open();
|
||||
m_process = target;
|
||||
m_process->Open();
|
||||
|
||||
/* Set ourselves as the process's attached object. */
|
||||
this->old_process_state = this->process->SetDebugObject(this);
|
||||
m_old_process_state = m_process->SetDebugObject(this);
|
||||
|
||||
/* Send an event for our attaching to the process. */
|
||||
this->PushDebugEvent(ams::svc::DebugEvent_CreateProcess);
|
||||
|
||||
/* Send events for attaching to each thread in the process. */
|
||||
{
|
||||
auto end = this->process->GetThreadList().end();
|
||||
for (auto it = this->process->GetThreadList().begin(); it != end; ++it) {
|
||||
auto end = m_process->GetThreadList().end();
|
||||
for (auto it = m_process->GetThreadList().begin(); it != end; ++it) {
|
||||
/* Request that we suspend the thread. */
|
||||
it->RequestSuspend(KThread::SuspendType_Debug);
|
||||
|
||||
@@ -333,7 +333,7 @@ namespace ams::kern {
|
||||
}
|
||||
|
||||
/* Send the process's jit debug info, if relevant. */
|
||||
if (KEventInfo *jit_info = this->process->GetJitDebugInfo(); jit_info != nullptr) {
|
||||
if (KEventInfo *jit_info = m_process->GetJitDebugInfo(); jit_info != nullptr) {
|
||||
this->EnqueueDebugEventInfo(jit_info);
|
||||
}
|
||||
|
||||
@@ -356,12 +356,12 @@ namespace ams::kern {
|
||||
/* Lock both ourselves, the target process, and the scheduler. */
|
||||
KScopedLightLock state_lk(target->GetStateLock());
|
||||
KScopedLightLock list_lk(target->GetListLock());
|
||||
KScopedLightLock this_lk(this->lock);
|
||||
KScopedLightLock this_lk(m_lock);
|
||||
KScopedSchedulerLock sl;
|
||||
|
||||
/* Check that we're still attached to the process, and that it's not terminated. */
|
||||
/* NOTE: Here Nintendo only checks that this->process is not nullptr. */
|
||||
R_UNLESS(this->process == target.GetPointerUnsafe(), svc::ResultProcessTerminated());
|
||||
R_UNLESS(m_process == target.GetPointerUnsafe(), svc::ResultProcessTerminated());
|
||||
R_UNLESS(!target->IsTerminated(), svc::ResultProcessTerminated());
|
||||
|
||||
/* Get the currently active threads. */
|
||||
@@ -418,12 +418,12 @@ namespace ams::kern {
|
||||
/* Lock both ourselves and the target process. */
|
||||
KScopedLightLock state_lk(target->GetStateLock());
|
||||
KScopedLightLock list_lk(target->GetListLock());
|
||||
KScopedLightLock this_lk(this->lock);
|
||||
KScopedLightLock this_lk(m_lock);
|
||||
|
||||
/* Check that we still have our process. */
|
||||
if (this->process != nullptr) {
|
||||
if (m_process != nullptr) {
|
||||
/* Check that our process is the one we got earlier. */
|
||||
MESOSPHERE_ASSERT(this->process == target.GetPointerUnsafe());
|
||||
MESOSPHERE_ASSERT(m_process == target.GetPointerUnsafe());
|
||||
|
||||
/* Lock the scheduler. */
|
||||
KScopedSchedulerLock sl;
|
||||
@@ -450,10 +450,10 @@ namespace ams::kern {
|
||||
|
||||
/* Detach from the process. */
|
||||
target->ClearDebugObject(new_state);
|
||||
this->process = nullptr;
|
||||
m_process = nullptr;
|
||||
|
||||
/* Clear our continue flags. */
|
||||
this->continue_flags = 0;
|
||||
m_continue_flags = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -468,7 +468,7 @@ namespace ams::kern {
|
||||
|
||||
Result KDebugBase::GetThreadContext(ams::svc::ThreadContext *out, u64 thread_id, u32 context_flags) {
|
||||
/* Lock ourselves. */
|
||||
KScopedLightLock lk(this->lock);
|
||||
KScopedLightLock lk(m_lock);
|
||||
|
||||
/* Get the thread from its id. */
|
||||
KThread *thread = KThread::GetThreadFromId(thread_id);
|
||||
@@ -476,7 +476,7 @@ namespace ams::kern {
|
||||
ON_SCOPE_EXIT { thread->Close(); };
|
||||
|
||||
/* Verify that the thread is owned by our process. */
|
||||
R_UNLESS(this->process == thread->GetOwnerProcess(), svc::ResultInvalidId());
|
||||
R_UNLESS(m_process == thread->GetOwnerProcess(), svc::ResultInvalidId());
|
||||
|
||||
/* Verify that the thread isn't terminated. */
|
||||
R_UNLESS(thread->GetState() != KThread::ThreadState_Terminated, svc::ResultTerminationRequested());
|
||||
@@ -515,7 +515,7 @@ namespace ams::kern {
|
||||
|
||||
Result KDebugBase::SetThreadContext(const ams::svc::ThreadContext &ctx, u64 thread_id, u32 context_flags) {
|
||||
/* Lock ourselves. */
|
||||
KScopedLightLock lk(this->lock);
|
||||
KScopedLightLock lk(m_lock);
|
||||
|
||||
/* Get the thread from its id. */
|
||||
KThread *thread = KThread::GetThreadFromId(thread_id);
|
||||
@@ -523,7 +523,7 @@ namespace ams::kern {
|
||||
ON_SCOPE_EXIT { thread->Close(); };
|
||||
|
||||
/* Verify that the thread is owned by our process. */
|
||||
R_UNLESS(this->process == thread->GetOwnerProcess(), svc::ResultInvalidId());
|
||||
R_UNLESS(m_process == thread->GetOwnerProcess(), svc::ResultInvalidId());
|
||||
|
||||
/* Verify that the thread isn't terminated. */
|
||||
R_UNLESS(thread->GetState() != KThread::ThreadState_Terminated, svc::ResultTerminationRequested());
|
||||
@@ -575,29 +575,29 @@ namespace ams::kern {
|
||||
/* Lock both ourselves, the target process, and the scheduler. */
|
||||
KScopedLightLock state_lk(target->GetStateLock());
|
||||
KScopedLightLock list_lk(target->GetListLock());
|
||||
KScopedLightLock this_lk(this->lock);
|
||||
KScopedLightLock this_lk(m_lock);
|
||||
KScopedSchedulerLock sl;
|
||||
|
||||
/* Check that we're still attached to the process, and that it's not terminated. */
|
||||
R_UNLESS(this->process == target.GetPointerUnsafe(), svc::ResultProcessTerminated());
|
||||
R_UNLESS(m_process == target.GetPointerUnsafe(), svc::ResultProcessTerminated());
|
||||
R_UNLESS(!target->IsTerminated(), svc::ResultProcessTerminated());
|
||||
|
||||
/* Check that we have no pending events. */
|
||||
R_UNLESS(this->event_info_list.empty(), svc::ResultBusy());
|
||||
R_UNLESS(m_event_info_list.empty(), svc::ResultBusy());
|
||||
|
||||
/* Clear the target's JIT debug info. */
|
||||
target->ClearJitDebugInfo();
|
||||
|
||||
/* Set our continue flags. */
|
||||
this->continue_flags = flags;
|
||||
m_continue_flags = flags;
|
||||
|
||||
/* Iterate over threads, continuing them as we should. */
|
||||
bool has_debug_break_thread = false;
|
||||
{
|
||||
/* Parse our flags. */
|
||||
const bool exception_handled = (this->continue_flags & ams::svc::ContinueFlag_ExceptionHandled) != 0;
|
||||
const bool continue_all = (this->continue_flags & ams::svc::ContinueFlag_ContinueAll) != 0;
|
||||
const bool continue_others = (this->continue_flags & ams::svc::ContinueFlag_ContinueOthers) != 0;
|
||||
const bool exception_handled = (m_continue_flags & ams::svc::ContinueFlag_ExceptionHandled) != 0;
|
||||
const bool continue_all = (m_continue_flags & ams::svc::ContinueFlag_ContinueAll) != 0;
|
||||
const bool continue_others = (m_continue_flags & ams::svc::ContinueFlag_ContinueOthers) != 0;
|
||||
|
||||
/* Update each thread. */
|
||||
auto end = target->GetThreadList().end();
|
||||
@@ -786,15 +786,15 @@ namespace ams::kern {
|
||||
KScopedSchedulerLock sl;
|
||||
|
||||
/* Push the event to the back of the list. */
|
||||
this->event_info_list.push_back(*info);
|
||||
m_event_info_list.push_back(*info);
|
||||
}
|
||||
|
||||
|
||||
KScopedAutoObject<KProcess> KDebugBase::GetProcess() {
|
||||
/* Lock ourselves. */
|
||||
KScopedLightLock lk(this->lock);
|
||||
KScopedLightLock lk(m_lock);
|
||||
|
||||
return this->process;
|
||||
return m_process;
|
||||
}
|
||||
|
||||
template<typename T> requires (std::same_as<T, ams::svc::lp64::DebugEventInfo> || std::same_as<T, ams::svc::ilp32::DebugEventInfo>)
|
||||
@@ -809,11 +809,11 @@ namespace ams::kern {
|
||||
KScopedSchedulerLock sl;
|
||||
|
||||
/* Check that we have an event to dequeue. */
|
||||
R_UNLESS(!this->event_info_list.empty(), svc::ResultNoEvent());
|
||||
R_UNLESS(!m_event_info_list.empty(), svc::ResultNoEvent());
|
||||
|
||||
/* Pop the event from the front of the queue. */
|
||||
info = std::addressof(this->event_info_list.front());
|
||||
this->event_info_list.pop_front();
|
||||
info = std::addressof(m_event_info_list.front());
|
||||
m_event_info_list.pop_front();
|
||||
}
|
||||
MESOSPHERE_ASSERT(info != nullptr);
|
||||
|
||||
@@ -932,16 +932,16 @@ namespace ams::kern {
|
||||
/* Lock both ourselves and the target process. */
|
||||
KScopedLightLock state_lk(process->GetStateLock());
|
||||
KScopedLightLock list_lk(process->GetListLock());
|
||||
KScopedLightLock this_lk(this->lock);
|
||||
KScopedLightLock this_lk(m_lock);
|
||||
|
||||
/* Ensure we finalize exactly once. */
|
||||
if (this->process != nullptr) {
|
||||
MESOSPHERE_ASSERT(this->process == process.GetPointerUnsafe());
|
||||
if (m_process != nullptr) {
|
||||
MESOSPHERE_ASSERT(m_process == process.GetPointerUnsafe());
|
||||
{
|
||||
KScopedSchedulerLock sl;
|
||||
|
||||
/* Detach ourselves from the process. */
|
||||
process->ClearDebugObject(this->old_process_state);
|
||||
process->ClearDebugObject(m_old_process_state);
|
||||
|
||||
/* Release all threads. */
|
||||
const bool resume = (process->GetState() != KProcess::State_Crashed);
|
||||
@@ -959,7 +959,7 @@ namespace ams::kern {
|
||||
}
|
||||
|
||||
/* Clear our process. */
|
||||
this->process = nullptr;
|
||||
m_process = nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -970,9 +970,9 @@ namespace ams::kern {
|
||||
{
|
||||
KScopedSchedulerLock sl;
|
||||
|
||||
while (!this->event_info_list.empty()) {
|
||||
KEventInfo *info = std::addressof(this->event_info_list.front());
|
||||
this->event_info_list.pop_front();
|
||||
while (!m_event_info_list.empty()) {
|
||||
KEventInfo *info = std::addressof(m_event_info_list.front());
|
||||
m_event_info_list.pop_front();
|
||||
KEventInfo::Free(info);
|
||||
}
|
||||
}
|
||||
@@ -981,7 +981,7 @@ namespace ams::kern {
|
||||
bool KDebugBase::IsSignaled() const {
|
||||
KScopedSchedulerLock sl;
|
||||
|
||||
return (!this->event_info_list.empty()) || this->process == nullptr || this->process->IsTerminated();
|
||||
return (!m_event_info_list.empty()) || m_process == nullptr || m_process->IsTerminated();
|
||||
}
|
||||
|
||||
Result KDebugBase::ProcessDebugEvent(ams::svc::DebugEvent event, uintptr_t param0, uintptr_t param1, uintptr_t param2, uintptr_t param3, uintptr_t param4) {
|
||||
@@ -1007,7 +1007,7 @@ namespace ams::kern {
|
||||
R_SUCCEED_IF(debug == nullptr);
|
||||
|
||||
/* If the event is an exception and we don't have exception events enabled, we can't handle the event. */
|
||||
if (event == ams::svc::DebugEvent_Exception && (debug->continue_flags & ams::svc::ContinueFlag_EnableExceptionEvent) == 0) {
|
||||
if (event == ams::svc::DebugEvent_Exception && (debug->m_continue_flags & ams::svc::ContinueFlag_EnableExceptionEvent) == 0) {
|
||||
GetCurrentThread().SetDebugExceptionResult(ResultSuccess());
|
||||
return svc::ResultNotHandled();
|
||||
}
|
||||
|
||||
@@ -28,12 +28,12 @@ namespace ams::kern {
|
||||
MESOSPHERE_ASSERT_THIS();
|
||||
|
||||
/* Initialize the device page table. */
|
||||
R_TRY(this->table.Initialize(address, size));
|
||||
R_TRY(m_table.Initialize(address, size));
|
||||
|
||||
/* Set member variables. */
|
||||
this->space_address = address;
|
||||
this->space_size = size;
|
||||
this->is_initialized = true;
|
||||
m_space_address = address;
|
||||
m_space_size = size;
|
||||
m_is_initialized = true;
|
||||
|
||||
return ResultSuccess();
|
||||
}
|
||||
@@ -42,7 +42,7 @@ namespace ams::kern {
|
||||
MESOSPHERE_ASSERT_THIS();
|
||||
|
||||
/* Finalize the table. */
|
||||
this->table.Finalize();
|
||||
m_table.Finalize();
|
||||
|
||||
/* Finalize base. */
|
||||
KAutoObjectWithSlabHeapAndContainer<KDeviceAddressSpace, KAutoObjectWithList>::Finalize();
|
||||
@@ -50,26 +50,26 @@ namespace ams::kern {
|
||||
|
||||
Result KDeviceAddressSpace::Attach(ams::svc::DeviceName device_name) {
|
||||
/* Lock the address space. */
|
||||
KScopedLightLock lk(this->lock);
|
||||
KScopedLightLock lk(m_lock);
|
||||
|
||||
/* Attach. */
|
||||
return this->table.Attach(device_name, this->space_address, this->space_size);
|
||||
return m_table.Attach(device_name, m_space_address, m_space_size);
|
||||
}
|
||||
|
||||
Result KDeviceAddressSpace::Detach(ams::svc::DeviceName device_name) {
|
||||
/* Lock the address space. */
|
||||
KScopedLightLock lk(this->lock);
|
||||
KScopedLightLock lk(m_lock);
|
||||
|
||||
/* Detach. */
|
||||
return this->table.Detach(device_name);
|
||||
return m_table.Detach(device_name);
|
||||
}
|
||||
|
||||
Result KDeviceAddressSpace::Map(size_t *out_mapped_size, KProcessPageTable *page_table, KProcessAddress process_address, size_t size, u64 device_address, ams::svc::MemoryPermission device_perm, bool is_aligned, bool refresh_mappings) {
|
||||
/* Check that the address falls within the space. */
|
||||
R_UNLESS((this->space_address <= device_address && device_address + size - 1 <= this->space_address + this->space_size - 1), svc::ResultInvalidCurrentMemory());
|
||||
R_UNLESS((m_space_address <= device_address && device_address + size - 1 <= m_space_address + m_space_size - 1), svc::ResultInvalidCurrentMemory());
|
||||
|
||||
/* Lock the address space. */
|
||||
KScopedLightLock lk(this->lock);
|
||||
KScopedLightLock lk(m_lock);
|
||||
|
||||
/* Lock the pages. */
|
||||
KPageGroup pg(page_table->GetBlockInfoManager());
|
||||
@@ -87,11 +87,11 @@ namespace ams::kern {
|
||||
auto mapped_size_guard = SCOPE_GUARD { *out_mapped_size = 0; };
|
||||
|
||||
/* Perform the mapping. */
|
||||
R_TRY(this->table.Map(out_mapped_size, pg, device_address, device_perm, refresh_mappings));
|
||||
R_TRY(m_table.Map(out_mapped_size, pg, device_address, device_perm, refresh_mappings));
|
||||
|
||||
/* Ensure that we unmap the pages if we fail to update the protections. */
|
||||
/* NOTE: Nintendo does not check the result of this unmap call. */
|
||||
auto map_guard = SCOPE_GUARD { this->table.Unmap(device_address, *out_mapped_size); };
|
||||
auto map_guard = SCOPE_GUARD { m_table.Unmap(device_address, *out_mapped_size); };
|
||||
|
||||
/* Update the protections in accordance with how much we mapped. */
|
||||
R_TRY(page_table->UnlockForDeviceAddressSpacePartialMap(process_address, size, *out_mapped_size));
|
||||
@@ -108,10 +108,10 @@ namespace ams::kern {
|
||||
|
||||
Result KDeviceAddressSpace::Unmap(KProcessPageTable *page_table, KProcessAddress process_address, size_t size, u64 device_address) {
|
||||
/* Check that the address falls within the space. */
|
||||
R_UNLESS((this->space_address <= device_address && device_address + size - 1 <= this->space_address + this->space_size - 1), svc::ResultInvalidCurrentMemory());
|
||||
R_UNLESS((m_space_address <= device_address && device_address + size - 1 <= m_space_address + m_space_size - 1), svc::ResultInvalidCurrentMemory());
|
||||
|
||||
/* Lock the address space. */
|
||||
KScopedLightLock lk(this->lock);
|
||||
KScopedLightLock lk(m_lock);
|
||||
|
||||
/* Make and open a page group for the unmapped region. */
|
||||
KPageGroup pg(page_table->GetBlockInfoManager());
|
||||
@@ -125,7 +125,7 @@ namespace ams::kern {
|
||||
auto unlock_guard = SCOPE_GUARD { page_table->UnlockForDeviceAddressSpacePartialMap(process_address, size, size); };
|
||||
|
||||
/* Unmap. */
|
||||
R_TRY(this->table.Unmap(pg, device_address));
|
||||
R_TRY(m_table.Unmap(pg, device_address));
|
||||
|
||||
unlock_guard.Cancel();
|
||||
}
|
||||
|
||||
@@ -27,19 +27,19 @@ namespace ams::kern {
|
||||
this->Open();
|
||||
|
||||
/* Create our sub events. */
|
||||
KAutoObject::Create(std::addressof(this->readable_event));
|
||||
KAutoObject::Create(std::addressof(this->writable_event));
|
||||
KAutoObject::Create(std::addressof(m_readable_event));
|
||||
KAutoObject::Create(std::addressof(m_writable_event));
|
||||
|
||||
/* Initialize our sub sessions. */
|
||||
this->readable_event.Initialize(this);
|
||||
this->writable_event.Initialize(this);
|
||||
m_readable_event.Initialize(this);
|
||||
m_writable_event.Initialize(this);
|
||||
|
||||
/* Set our owner process. */
|
||||
this->owner = GetCurrentProcessPointer();
|
||||
this->owner->Open();
|
||||
m_owner = GetCurrentProcessPointer();
|
||||
m_owner->Open();
|
||||
|
||||
/* Mark initialized. */
|
||||
this->initialized = true;
|
||||
m_initialized = true;
|
||||
}
|
||||
|
||||
void KEvent::Finalize() {
|
||||
|
||||
@@ -25,10 +25,10 @@ namespace ams::kern {
|
||||
u16 saved_table_size = 0;
|
||||
{
|
||||
KScopedDisableDispatch dd;
|
||||
KScopedSpinLock lk(this->lock);
|
||||
KScopedSpinLock lk(m_lock);
|
||||
|
||||
std::swap(this->table, saved_table);
|
||||
std::swap(this->table_size, saved_table_size);
|
||||
std::swap(m_table, saved_table);
|
||||
std::swap(m_table_size, saved_table_size);
|
||||
}
|
||||
|
||||
/* Close and free all entries. */
|
||||
@@ -61,7 +61,7 @@ namespace ams::kern {
|
||||
KAutoObject *obj = nullptr;
|
||||
{
|
||||
KScopedDisableDispatch dd;
|
||||
KScopedSpinLock lk(this->lock);
|
||||
KScopedSpinLock lk(m_lock);
|
||||
|
||||
if (Entry *entry = this->FindEntry(handle); entry != nullptr) {
|
||||
obj = entry->GetObject();
|
||||
@@ -79,10 +79,10 @@ namespace ams::kern {
|
||||
Result KHandleTable::Add(ams::svc::Handle *out_handle, KAutoObject *obj, u16 type) {
|
||||
MESOSPHERE_ASSERT_THIS();
|
||||
KScopedDisableDispatch dd;
|
||||
KScopedSpinLock lk(this->lock);
|
||||
KScopedSpinLock lk(m_lock);
|
||||
|
||||
/* Never exceed our capacity. */
|
||||
R_UNLESS(this->count < this->table_size, svc::ResultOutOfHandles());
|
||||
R_UNLESS(m_count < m_table_size, svc::ResultOutOfHandles());
|
||||
|
||||
/* Allocate entry, set output handle. */
|
||||
{
|
||||
@@ -99,10 +99,10 @@ namespace ams::kern {
|
||||
Result KHandleTable::Reserve(ams::svc::Handle *out_handle) {
|
||||
MESOSPHERE_ASSERT_THIS();
|
||||
KScopedDisableDispatch dd;
|
||||
KScopedSpinLock lk(this->lock);
|
||||
KScopedSpinLock lk(m_lock);
|
||||
|
||||
/* Never exceed our capacity. */
|
||||
R_UNLESS(this->count < this->table_size, svc::ResultOutOfHandles());
|
||||
R_UNLESS(m_count < m_table_size, svc::ResultOutOfHandles());
|
||||
|
||||
*out_handle = EncodeHandle(this->GetEntryIndex(this->AllocateEntry()), this->AllocateLinearId());
|
||||
return ResultSuccess();
|
||||
@@ -111,7 +111,7 @@ namespace ams::kern {
|
||||
void KHandleTable::Unreserve(ams::svc::Handle handle) {
|
||||
MESOSPHERE_ASSERT_THIS();
|
||||
KScopedDisableDispatch dd;
|
||||
KScopedSpinLock lk(this->lock);
|
||||
KScopedSpinLock lk(m_lock);
|
||||
|
||||
/* Unpack the handle. */
|
||||
const auto handle_pack = GetHandleBitPack(handle);
|
||||
@@ -120,11 +120,11 @@ namespace ams::kern {
|
||||
const auto reserved = handle_pack.Get<HandleReserved>();
|
||||
MESOSPHERE_ASSERT(reserved == 0);
|
||||
MESOSPHERE_ASSERT(linear_id != 0);
|
||||
MESOSPHERE_ASSERT(index < this->table_size);
|
||||
MESOSPHERE_ASSERT(index < m_table_size);
|
||||
|
||||
/* Free the entry. */
|
||||
/* NOTE: This code does not check the linear id. */
|
||||
Entry *entry = std::addressof(this->table[index]);
|
||||
Entry *entry = std::addressof(m_table[index]);
|
||||
MESOSPHERE_ASSERT(entry->GetObject() == nullptr);
|
||||
|
||||
this->FreeEntry(entry);
|
||||
@@ -133,7 +133,7 @@ namespace ams::kern {
|
||||
void KHandleTable::Register(ams::svc::Handle handle, KAutoObject *obj, u16 type) {
|
||||
MESOSPHERE_ASSERT_THIS();
|
||||
KScopedDisableDispatch dd;
|
||||
KScopedSpinLock lk(this->lock);
|
||||
KScopedSpinLock lk(m_lock);
|
||||
|
||||
/* Unpack the handle. */
|
||||
const auto handle_pack = GetHandleBitPack(handle);
|
||||
@@ -142,10 +142,10 @@ namespace ams::kern {
|
||||
const auto reserved = handle_pack.Get<HandleReserved>();
|
||||
MESOSPHERE_ASSERT(reserved == 0);
|
||||
MESOSPHERE_ASSERT(linear_id != 0);
|
||||
MESOSPHERE_ASSERT(index < this->table_size);
|
||||
MESOSPHERE_ASSERT(index < m_table_size);
|
||||
|
||||
/* Set the entry. */
|
||||
Entry *entry = std::addressof(this->table[index]);
|
||||
Entry *entry = std::addressof(m_table[index]);
|
||||
MESOSPHERE_ASSERT(entry->GetObject() == nullptr);
|
||||
|
||||
entry->SetUsed(obj, linear_id, type);
|
||||
|
||||
@@ -77,14 +77,14 @@ namespace ams::kern {
|
||||
|
||||
Result KInitialProcessReader::MakeCreateProcessParameter(ams::svc::CreateProcessParameter *out, bool enable_aslr) const {
|
||||
/* Get and validate addresses/sizes. */
|
||||
const uintptr_t rx_address = this->kip_header->GetRxAddress();
|
||||
const size_t rx_size = this->kip_header->GetRxSize();
|
||||
const uintptr_t ro_address = this->kip_header->GetRoAddress();
|
||||
const size_t ro_size = this->kip_header->GetRoSize();
|
||||
const uintptr_t rw_address = this->kip_header->GetRwAddress();
|
||||
const size_t rw_size = this->kip_header->GetRwSize();
|
||||
const uintptr_t bss_address = this->kip_header->GetBssAddress();
|
||||
const size_t bss_size = this->kip_header->GetBssSize();
|
||||
const uintptr_t rx_address = m_kip_header->GetRxAddress();
|
||||
const size_t rx_size = m_kip_header->GetRxSize();
|
||||
const uintptr_t ro_address = m_kip_header->GetRoAddress();
|
||||
const size_t ro_size = m_kip_header->GetRoSize();
|
||||
const uintptr_t rw_address = m_kip_header->GetRwAddress();
|
||||
const size_t rw_size = m_kip_header->GetRwSize();
|
||||
const uintptr_t bss_address = m_kip_header->GetBssAddress();
|
||||
const size_t bss_size = m_kip_header->GetBssSize();
|
||||
R_UNLESS(util::IsAligned(rx_address, PageSize), svc::ResultInvalidAddress());
|
||||
R_UNLESS(util::IsAligned(ro_address, PageSize), svc::ResultInvalidAddress());
|
||||
R_UNLESS(util::IsAligned(rw_address, PageSize), svc::ResultInvalidAddress());
|
||||
@@ -115,13 +115,13 @@ namespace ams::kern {
|
||||
/* Set fields in parameter. */
|
||||
out->code_address = map_start + start_address;
|
||||
out->code_num_pages = util::AlignUp(end_address - start_address, PageSize) / PageSize;
|
||||
out->program_id = this->kip_header->GetProgramId();
|
||||
out->version = this->kip_header->GetVersion();
|
||||
out->program_id = m_kip_header->GetProgramId();
|
||||
out->version = m_kip_header->GetVersion();
|
||||
out->flags = 0;
|
||||
MESOSPHERE_ABORT_UNLESS((out->code_address / PageSize) + out->code_num_pages <= (map_end / PageSize));
|
||||
|
||||
/* Copy name field. */
|
||||
this->kip_header->GetName(out->name, sizeof(out->name));
|
||||
m_kip_header->GetName(out->name, sizeof(out->name));
|
||||
|
||||
/* Apply ASLR, if needed. */
|
||||
if (enable_aslr) {
|
||||
@@ -151,34 +151,34 @@ namespace ams::kern {
|
||||
std::memset(GetVoidPointer(address), 0, params.code_num_pages * PageSize);
|
||||
|
||||
/* Prepare to layout the data. */
|
||||
const KProcessAddress rx_address = address + this->kip_header->GetRxAddress();
|
||||
const KProcessAddress ro_address = address + this->kip_header->GetRoAddress();
|
||||
const KProcessAddress rw_address = address + this->kip_header->GetRwAddress();
|
||||
const u8 *rx_binary = reinterpret_cast<const u8 *>(this->kip_header + 1);
|
||||
const u8 *ro_binary = rx_binary + this->kip_header->GetRxCompressedSize();
|
||||
const u8 *rw_binary = ro_binary + this->kip_header->GetRoCompressedSize();
|
||||
const KProcessAddress rx_address = address + m_kip_header->GetRxAddress();
|
||||
const KProcessAddress ro_address = address + m_kip_header->GetRoAddress();
|
||||
const KProcessAddress rw_address = address + m_kip_header->GetRwAddress();
|
||||
const u8 *rx_binary = reinterpret_cast<const u8 *>(m_kip_header + 1);
|
||||
const u8 *ro_binary = rx_binary + m_kip_header->GetRxCompressedSize();
|
||||
const u8 *rw_binary = ro_binary + m_kip_header->GetRoCompressedSize();
|
||||
|
||||
/* Copy text. */
|
||||
if (util::AlignUp(this->kip_header->GetRxSize(), PageSize)) {
|
||||
std::memcpy(GetVoidPointer(rx_address), rx_binary, this->kip_header->GetRxCompressedSize());
|
||||
if (this->kip_header->IsRxCompressed()) {
|
||||
BlzUncompress(GetVoidPointer(rx_address + this->kip_header->GetRxCompressedSize()));
|
||||
if (util::AlignUp(m_kip_header->GetRxSize(), PageSize)) {
|
||||
std::memcpy(GetVoidPointer(rx_address), rx_binary, m_kip_header->GetRxCompressedSize());
|
||||
if (m_kip_header->IsRxCompressed()) {
|
||||
BlzUncompress(GetVoidPointer(rx_address + m_kip_header->GetRxCompressedSize()));
|
||||
}
|
||||
}
|
||||
|
||||
/* Copy rodata. */
|
||||
if (util::AlignUp(this->kip_header->GetRoSize(), PageSize)) {
|
||||
std::memcpy(GetVoidPointer(ro_address), ro_binary, this->kip_header->GetRoCompressedSize());
|
||||
if (this->kip_header->IsRoCompressed()) {
|
||||
BlzUncompress(GetVoidPointer(ro_address + this->kip_header->GetRoCompressedSize()));
|
||||
if (util::AlignUp(m_kip_header->GetRoSize(), PageSize)) {
|
||||
std::memcpy(GetVoidPointer(ro_address), ro_binary, m_kip_header->GetRoCompressedSize());
|
||||
if (m_kip_header->IsRoCompressed()) {
|
||||
BlzUncompress(GetVoidPointer(ro_address + m_kip_header->GetRoCompressedSize()));
|
||||
}
|
||||
}
|
||||
|
||||
/* Copy rwdata. */
|
||||
if (util::AlignUp(this->kip_header->GetRwSize(), PageSize)) {
|
||||
std::memcpy(GetVoidPointer(rw_address), rw_binary, this->kip_header->GetRwCompressedSize());
|
||||
if (this->kip_header->IsRwCompressed()) {
|
||||
BlzUncompress(GetVoidPointer(rw_address + this->kip_header->GetRwCompressedSize()));
|
||||
if (util::AlignUp(m_kip_header->GetRwSize(), PageSize)) {
|
||||
std::memcpy(GetVoidPointer(rw_address), rw_binary, m_kip_header->GetRwCompressedSize());
|
||||
if (m_kip_header->IsRwCompressed()) {
|
||||
BlzUncompress(GetVoidPointer(rw_address + m_kip_header->GetRwCompressedSize()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -192,27 +192,27 @@ namespace ams::kern {
|
||||
}
|
||||
|
||||
Result KInitialProcessReader::SetMemoryPermissions(KProcessPageTable &page_table, const ams::svc::CreateProcessParameter ¶ms) const {
|
||||
const size_t rx_size = this->kip_header->GetRxSize();
|
||||
const size_t ro_size = this->kip_header->GetRoSize();
|
||||
const size_t rw_size = this->kip_header->GetRwSize();
|
||||
const size_t bss_size = this->kip_header->GetBssSize();
|
||||
const size_t rx_size = m_kip_header->GetRxSize();
|
||||
const size_t ro_size = m_kip_header->GetRoSize();
|
||||
const size_t rw_size = m_kip_header->GetRwSize();
|
||||
const size_t bss_size = m_kip_header->GetBssSize();
|
||||
|
||||
/* Set R-X pages. */
|
||||
if (rx_size) {
|
||||
const uintptr_t start = this->kip_header->GetRxAddress() + params.code_address;
|
||||
const uintptr_t start = m_kip_header->GetRxAddress() + params.code_address;
|
||||
R_TRY(page_table.SetProcessMemoryPermission(start, util::AlignUp(rx_size, PageSize), ams::svc::MemoryPermission_ReadExecute));
|
||||
}
|
||||
|
||||
/* Set R-- pages. */
|
||||
if (ro_size) {
|
||||
const uintptr_t start = this->kip_header->GetRoAddress() + params.code_address;
|
||||
const uintptr_t start = m_kip_header->GetRoAddress() + params.code_address;
|
||||
R_TRY(page_table.SetProcessMemoryPermission(start, util::AlignUp(ro_size, PageSize), ams::svc::MemoryPermission_Read));
|
||||
}
|
||||
|
||||
/* Set RW- pages. */
|
||||
if (rw_size || bss_size) {
|
||||
const uintptr_t start = (rw_size ? this->kip_header->GetRwAddress() : this->kip_header->GetBssAddress()) + params.code_address;
|
||||
const uintptr_t end = (bss_size ? this->kip_header->GetBssAddress() + bss_size : this->kip_header->GetRwAddress() + rw_size) + params.code_address;
|
||||
const uintptr_t start = (rw_size ? m_kip_header->GetRwAddress() : m_kip_header->GetBssAddress()) + params.code_address;
|
||||
const uintptr_t end = (bss_size ? m_kip_header->GetBssAddress() + bss_size : m_kip_header->GetRwAddress() + rw_size) + params.code_address;
|
||||
R_TRY(page_table.SetProcessMemoryPermission(start, util::AlignUp(end - start, PageSize), ams::svc::MemoryPermission_ReadWrite));
|
||||
}
|
||||
|
||||
|
||||
@@ -28,23 +28,23 @@ namespace ams::kern {
|
||||
MESOSPHERE_ASSERT_THIS();
|
||||
|
||||
/* Set interrupt id. */
|
||||
this->interrupt_id = interrupt_name;
|
||||
m_interrupt_id = interrupt_name;
|
||||
|
||||
/* Initialize readable event base. */
|
||||
KReadableEvent::Initialize(nullptr);
|
||||
|
||||
/* Try to register the task. */
|
||||
R_TRY(KInterruptEventTask::Register(this->interrupt_id, type == ams::svc::InterruptType_Level, this));
|
||||
R_TRY(KInterruptEventTask::Register(m_interrupt_id, type == ams::svc::InterruptType_Level, this));
|
||||
|
||||
/* Mark initialized. */
|
||||
this->is_initialized = true;
|
||||
m_is_initialized = true;
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
void KInterruptEvent::Finalize() {
|
||||
MESOSPHERE_ASSERT_THIS();
|
||||
|
||||
g_interrupt_event_task_table[this->interrupt_id]->Unregister(this->interrupt_id);
|
||||
g_interrupt_event_task_table[m_interrupt_id]->Unregister(m_interrupt_id);
|
||||
|
||||
/* Perform inherited finalization. */
|
||||
KAutoObjectWithSlabHeapAndContainer<KInterruptEvent, KReadableEvent>::Finalize();
|
||||
@@ -54,13 +54,13 @@ namespace ams::kern {
|
||||
MESOSPHERE_ASSERT_THIS();
|
||||
|
||||
/* Lock the task. */
|
||||
KScopedLightLock lk(g_interrupt_event_task_table[this->interrupt_id]->GetLock());
|
||||
KScopedLightLock lk(g_interrupt_event_task_table[m_interrupt_id]->GetLock());
|
||||
|
||||
/* Clear the event. */
|
||||
R_TRY(KReadableEvent::Reset());
|
||||
|
||||
/* Clear the interrupt. */
|
||||
Kernel::GetInterruptManager().ClearInterrupt(this->interrupt_id);
|
||||
Kernel::GetInterruptManager().ClearInterrupt(m_interrupt_id);
|
||||
|
||||
return ResultSuccess();
|
||||
}
|
||||
@@ -78,7 +78,7 @@ namespace ams::kern {
|
||||
KInterruptEventTask *task = g_interrupt_event_task_table[interrupt_id];
|
||||
if (task != nullptr) {
|
||||
/* Check that there's not already an event for this task. */
|
||||
R_UNLESS(task->event == nullptr, svc::ResultBusy());
|
||||
R_UNLESS(task->m_event == nullptr, svc::ResultBusy());
|
||||
} else {
|
||||
/* Allocate a new task. */
|
||||
task = KInterruptEventTask::Allocate();
|
||||
@@ -93,13 +93,13 @@ namespace ams::kern {
|
||||
/* Register/bind the interrupt task. */
|
||||
{
|
||||
/* Acqquire exclusive access to the task. */
|
||||
KScopedLightLock tlk(task->lock);
|
||||
KScopedLightLock tlk(task->m_lock);
|
||||
|
||||
/* Bind the interrupt handler. */
|
||||
R_TRY(Kernel::GetInterruptManager().BindHandler(task, interrupt_id, GetCurrentCoreId(), KInterruptController::PriorityLevel_High, true, level));
|
||||
|
||||
/* Set the event. */
|
||||
task->event = event;
|
||||
task->m_event = event;
|
||||
}
|
||||
|
||||
/* If we allocated, set the event in the table. */
|
||||
@@ -119,14 +119,14 @@ namespace ams::kern {
|
||||
KScopedLightLock lk(g_interrupt_event_lock);
|
||||
|
||||
/* Lock the task. */
|
||||
KScopedLightLock tlk(this->lock);
|
||||
KScopedLightLock tlk(m_lock);
|
||||
|
||||
/* Ensure we can unregister. */
|
||||
MESOSPHERE_ABORT_UNLESS(g_interrupt_event_task_table[interrupt_id] == this);
|
||||
MESOSPHERE_ABORT_UNLESS(this->event != nullptr);
|
||||
MESOSPHERE_ABORT_UNLESS(m_event != nullptr);
|
||||
|
||||
/* Unbind the interrupt. */
|
||||
this->event = nullptr;
|
||||
m_event = nullptr;
|
||||
Kernel::GetInterruptManager().UnbindHandler(interrupt_id, GetCurrentCoreId());
|
||||
}
|
||||
|
||||
@@ -140,10 +140,10 @@ namespace ams::kern {
|
||||
MESOSPHERE_ASSERT_THIS();
|
||||
|
||||
/* Lock the task table. */
|
||||
KScopedLightLock lk(this->lock);
|
||||
KScopedLightLock lk(m_lock);
|
||||
|
||||
if (this->event != nullptr) {
|
||||
this->event->Signal();
|
||||
if (m_event != nullptr) {
|
||||
m_event->Signal();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,18 +18,18 @@
|
||||
namespace ams::kern {
|
||||
|
||||
void KInterruptTaskManager::TaskQueue::Enqueue(KInterruptTask *task) {
|
||||
MESOSPHERE_ASSERT(task != this->head);
|
||||
MESOSPHERE_ASSERT(task != this->tail);
|
||||
MESOSPHERE_ASSERT(task != m_head);
|
||||
MESOSPHERE_ASSERT(task != m_tail);
|
||||
MESOSPHERE_AUDIT(task->GetNextTask() == nullptr);
|
||||
|
||||
/* Insert the task into the queue. */
|
||||
if (this->tail != nullptr) {
|
||||
this->tail->SetNextTask(task);
|
||||
if (m_tail != nullptr) {
|
||||
m_tail->SetNextTask(task);
|
||||
} else {
|
||||
this->head = task;
|
||||
m_head = task;
|
||||
}
|
||||
|
||||
this->tail = task;
|
||||
m_tail = task;
|
||||
|
||||
/* Set the next task for auditing. */
|
||||
#if defined (MESOSPHERE_BUILD_FOR_AUDITING)
|
||||
@@ -38,18 +38,18 @@ namespace ams::kern {
|
||||
}
|
||||
|
||||
void KInterruptTaskManager::TaskQueue::Dequeue() {
|
||||
MESOSPHERE_ASSERT(this->head != nullptr);
|
||||
MESOSPHERE_ASSERT(this->tail != nullptr);
|
||||
MESOSPHERE_AUDIT(this->tail->GetNextTask() == GetDummyInterruptTask());
|
||||
MESOSPHERE_ASSERT(m_head != nullptr);
|
||||
MESOSPHERE_ASSERT(m_tail != nullptr);
|
||||
MESOSPHERE_AUDIT(m_tail->GetNextTask() == GetDummyInterruptTask());
|
||||
|
||||
/* Pop the task from the front of the queue. */
|
||||
KInterruptTask *old_head = this->head;
|
||||
KInterruptTask *old_head = m_head;
|
||||
|
||||
if (this->head == this->tail) {
|
||||
this->head = nullptr;
|
||||
this->tail = nullptr;
|
||||
if (m_head == m_tail) {
|
||||
m_head = nullptr;
|
||||
m_tail = nullptr;
|
||||
} else {
|
||||
this->head = this->head->GetNextTask();
|
||||
m_head = m_head->GetNextTask();
|
||||
}
|
||||
|
||||
#if defined (MESOSPHERE_BUILD_FOR_AUDITING)
|
||||
@@ -72,13 +72,13 @@ namespace ams::kern {
|
||||
{
|
||||
KScopedInterruptDisable di;
|
||||
|
||||
task = this->task_queue.GetHead();
|
||||
task = m_task_queue.GetHead();
|
||||
if (task == nullptr) {
|
||||
this->thread->SetState(KThread::ThreadState_Waiting);
|
||||
m_thread->SetState(KThread::ThreadState_Waiting);
|
||||
continue;
|
||||
}
|
||||
|
||||
this->task_queue.Dequeue();
|
||||
m_task_queue.Dequeue();
|
||||
}
|
||||
|
||||
/* Do the task. */
|
||||
@@ -91,20 +91,20 @@ namespace ams::kern {
|
||||
MESOSPHERE_ABORT_UNLESS(Kernel::GetSystemResourceLimit().Reserve(ams::svc::LimitableResource_ThreadCountMax, 1));
|
||||
|
||||
/* Create and initialize the thread. */
|
||||
this->thread = KThread::Create();
|
||||
MESOSPHERE_ABORT_UNLESS(this->thread != nullptr);
|
||||
MESOSPHERE_R_ABORT_UNLESS(KThread::InitializeHighPriorityThread(this->thread, ThreadFunction, reinterpret_cast<uintptr_t>(this)));
|
||||
KThread::Register(this->thread);
|
||||
m_thread = KThread::Create();
|
||||
MESOSPHERE_ABORT_UNLESS(m_thread != nullptr);
|
||||
MESOSPHERE_R_ABORT_UNLESS(KThread::InitializeHighPriorityThread(m_thread, ThreadFunction, reinterpret_cast<uintptr_t>(this)));
|
||||
KThread::Register(m_thread);
|
||||
|
||||
/* Run the thread. */
|
||||
this->thread->Run();
|
||||
m_thread->Run();
|
||||
}
|
||||
|
||||
void KInterruptTaskManager::EnqueueTask(KInterruptTask *task) {
|
||||
MESOSPHERE_ASSERT(!KInterruptManager::AreInterruptsEnabled());
|
||||
|
||||
/* Enqueue the task and signal the scheduler. */
|
||||
this->task_queue.Enqueue(task);
|
||||
m_task_queue.Enqueue(task);
|
||||
Kernel::GetScheduler().SetInterruptTaskRunnable();
|
||||
}
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@ namespace ams::kern {
|
||||
void KLightClientSession::Destroy() {
|
||||
MESOSPHERE_ASSERT_THIS();
|
||||
|
||||
this->parent->OnClientClosed();
|
||||
m_parent->OnClientClosed();
|
||||
}
|
||||
|
||||
void KLightClientSession::OnServerClosed() {
|
||||
@@ -42,7 +42,7 @@ namespace ams::kern {
|
||||
|
||||
cur_thread->SetSyncedObject(nullptr, ResultSuccess());
|
||||
|
||||
R_TRY(this->parent->OnRequest(cur_thread));
|
||||
R_TRY(m_parent->OnRequest(cur_thread));
|
||||
}
|
||||
|
||||
/* Get the result. */
|
||||
|
||||
@@ -25,13 +25,13 @@ namespace ams::kern {
|
||||
KScopedSchedulerLock sl;
|
||||
|
||||
/* Ensure we actually have locking to do. */
|
||||
if (AMS_UNLIKELY(this->tag.load(std::memory_order_relaxed) != _owner)) {
|
||||
if (AMS_UNLIKELY(m_tag.load(std::memory_order_relaxed) != _owner)) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Add the current thread as a waiter on the owner. */
|
||||
KThread *owner_thread = reinterpret_cast<KThread *>(_owner & ~1ul);
|
||||
cur_thread->SetAddressKey(reinterpret_cast<uintptr_t>(std::addressof(this->tag)));
|
||||
cur_thread->SetAddressKey(reinterpret_cast<uintptr_t>(std::addressof(m_tag)));
|
||||
owner_thread->AddWaiter(cur_thread);
|
||||
|
||||
/* Set thread states. */
|
||||
@@ -66,7 +66,7 @@ namespace ams::kern {
|
||||
|
||||
/* Get the next owner. */
|
||||
s32 num_waiters = 0;
|
||||
KThread *next_owner = owner_thread->RemoveWaiterByKey(std::addressof(num_waiters), reinterpret_cast<uintptr_t>(std::addressof(this->tag)));
|
||||
KThread *next_owner = owner_thread->RemoveWaiterByKey(std::addressof(num_waiters), reinterpret_cast<uintptr_t>(std::addressof(m_tag)));
|
||||
|
||||
/* Pass the lock to the next owner. */
|
||||
uintptr_t next_tag = 0;
|
||||
@@ -93,7 +93,7 @@ namespace ams::kern {
|
||||
}
|
||||
|
||||
/* Write the new tag value. */
|
||||
this->tag.store(next_tag);
|
||||
m_tag.store(next_tag);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@ namespace ams::kern {
|
||||
|
||||
this->CleanupRequests();
|
||||
|
||||
this->parent->OnServerClosed();
|
||||
m_parent->OnServerClosed();
|
||||
}
|
||||
|
||||
void KLightServerSession::OnClientClosed() {
|
||||
@@ -36,14 +36,14 @@ namespace ams::kern {
|
||||
MESOSPHERE_ASSERT(KScheduler::IsSchedulerLockedByCurrentThread());
|
||||
|
||||
/* Check that the server isn't closed. */
|
||||
R_UNLESS(!this->parent->IsServerClosed(), svc::ResultSessionClosed());
|
||||
R_UNLESS(!m_parent->IsServerClosed(), svc::ResultSessionClosed());
|
||||
|
||||
/* Try to sleep the thread. */
|
||||
R_UNLESS(this->request_queue.SleepThread(request_thread), svc::ResultTerminationRequested());
|
||||
R_UNLESS(m_request_queue.SleepThread(request_thread), svc::ResultTerminationRequested());
|
||||
|
||||
/* If we don't have a current request, wake up a server thread to handle it. */
|
||||
if (this->current_request == nullptr) {
|
||||
this->server_queue.WakeupFrontThread();
|
||||
if (m_current_request == nullptr) {
|
||||
m_server_queue.WakeupFrontThread();
|
||||
}
|
||||
|
||||
return ResultSuccess();
|
||||
@@ -62,27 +62,27 @@ namespace ams::kern {
|
||||
KScopedSchedulerLock sl;
|
||||
|
||||
/* Check that we're open. */
|
||||
R_UNLESS(!this->parent->IsClientClosed(), svc::ResultSessionClosed());
|
||||
R_UNLESS(!this->parent->IsServerClosed(), svc::ResultSessionClosed());
|
||||
R_UNLESS(!m_parent->IsClientClosed(), svc::ResultSessionClosed());
|
||||
R_UNLESS(!m_parent->IsServerClosed(), svc::ResultSessionClosed());
|
||||
|
||||
/* Check that we have a request to reply to. */
|
||||
R_UNLESS(this->current_request != nullptr, svc::ResultInvalidState());
|
||||
R_UNLESS(m_current_request != nullptr, svc::ResultInvalidState());
|
||||
|
||||
/* Check that the server thread is correct. */
|
||||
R_UNLESS(this->server_thread == server_thread, svc::ResultInvalidState());
|
||||
R_UNLESS(m_server_thread == server_thread, svc::ResultInvalidState());
|
||||
|
||||
/* If we can reply, do so. */
|
||||
if (!this->current_request->IsTerminationRequested()) {
|
||||
MESOSPHERE_ASSERT(this->current_request->GetState() == KThread::ThreadState_Waiting);
|
||||
MESOSPHERE_ASSERT(this->request_queue.begin() != this->request_queue.end() && this->current_request == std::addressof(*this->request_queue.begin()));
|
||||
std::memcpy(this->current_request->GetLightSessionData(), server_thread->GetLightSessionData(), KLightSession::DataSize);
|
||||
this->request_queue.WakeupThread(this->current_request);
|
||||
if (!m_current_request->IsTerminationRequested()) {
|
||||
MESOSPHERE_ASSERT(m_current_request->GetState() == KThread::ThreadState_Waiting);
|
||||
MESOSPHERE_ASSERT(m_request_queue.begin() != m_request_queue.end() && m_current_request == std::addressof(*m_request_queue.begin()));
|
||||
std::memcpy(m_current_request->GetLightSessionData(), server_thread->GetLightSessionData(), KLightSession::DataSize);
|
||||
m_request_queue.WakeupThread(m_current_request);
|
||||
}
|
||||
|
||||
/* Clear our current request. */
|
||||
cur_request = this->current_request;
|
||||
this->current_request = nullptr;
|
||||
this->server_thread = nullptr;
|
||||
cur_request = m_current_request;
|
||||
m_current_request = nullptr;
|
||||
m_server_thread = nullptr;
|
||||
}
|
||||
|
||||
/* Close the current request, if we had one. */
|
||||
@@ -96,8 +96,8 @@ namespace ams::kern {
|
||||
KScopedSchedulerLock sl;
|
||||
|
||||
/* Check that we aren't already receiving. */
|
||||
R_UNLESS(this->server_queue.IsEmpty(), svc::ResultInvalidState());
|
||||
R_UNLESS(this->server_thread == nullptr, svc::ResultInvalidState());
|
||||
R_UNLESS(m_server_queue.IsEmpty(), svc::ResultInvalidState());
|
||||
R_UNLESS(m_server_thread == nullptr, svc::ResultInvalidState());
|
||||
|
||||
/* If we cancelled in a previous loop, clear cancel state. */
|
||||
if (set_cancellable) {
|
||||
@@ -106,22 +106,22 @@ namespace ams::kern {
|
||||
}
|
||||
|
||||
/* Check that we're open. */
|
||||
R_UNLESS(!this->parent->IsClientClosed(), svc::ResultSessionClosed());
|
||||
R_UNLESS(!this->parent->IsServerClosed(), svc::ResultSessionClosed());
|
||||
R_UNLESS(!m_parent->IsClientClosed(), svc::ResultSessionClosed());
|
||||
R_UNLESS(!m_parent->IsServerClosed(), svc::ResultSessionClosed());
|
||||
|
||||
/* If we have a request available, use it. */
|
||||
if (this->current_request == nullptr && !this->request_queue.IsEmpty()) {
|
||||
this->current_request = std::addressof(*this->request_queue.begin());
|
||||
this->current_request->Open();
|
||||
this->server_thread = server_thread;
|
||||
if (m_current_request == nullptr && !m_request_queue.IsEmpty()) {
|
||||
m_current_request = std::addressof(*m_request_queue.begin());
|
||||
m_current_request->Open();
|
||||
m_server_thread = server_thread;
|
||||
break;
|
||||
} else {
|
||||
/* Otherwise, wait for a request to come in. */
|
||||
R_UNLESS(this->server_queue.SleepThread(server_thread), svc::ResultTerminationRequested());
|
||||
R_UNLESS(m_server_queue.SleepThread(server_thread), svc::ResultTerminationRequested());
|
||||
|
||||
/* Check if we were cancelled. */
|
||||
if (server_thread->IsWaitCancelled()) {
|
||||
this->server_queue.WakeupThread(server_thread);
|
||||
m_server_queue.WakeupThread(server_thread);
|
||||
server_thread->ClearWaitCancelled();
|
||||
return svc::ResultCancelled();
|
||||
}
|
||||
@@ -133,7 +133,7 @@ namespace ams::kern {
|
||||
}
|
||||
|
||||
/* Copy the client data. */
|
||||
std::memcpy(server_thread->GetLightSessionData(), this->current_request->GetLightSessionData(), KLightSession::DataSize);
|
||||
std::memcpy(server_thread->GetLightSessionData(), m_current_request->GetLightSessionData(), KLightSession::DataSize);
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
@@ -144,30 +144,30 @@ namespace ams::kern {
|
||||
KScopedSchedulerLock sl;
|
||||
|
||||
/* Handle the current request. */
|
||||
if (this->current_request != nullptr) {
|
||||
if (m_current_request != nullptr) {
|
||||
/* Reply to the current request. */
|
||||
if (!this->current_request->IsTerminationRequested()) {
|
||||
MESOSPHERE_ASSERT(this->current_request->GetState() == KThread::ThreadState_Waiting);
|
||||
MESOSPHERE_ASSERT(this->request_queue.begin() != this->request_queue.end() && this->current_request == std::addressof(*this->request_queue.begin()));
|
||||
this->request_queue.WakeupThread(this->current_request);
|
||||
this->current_request->SetSyncedObject(nullptr, svc::ResultSessionClosed());
|
||||
if (!m_current_request->IsTerminationRequested()) {
|
||||
MESOSPHERE_ASSERT(m_current_request->GetState() == KThread::ThreadState_Waiting);
|
||||
MESOSPHERE_ASSERT(m_request_queue.begin() != m_request_queue.end() && m_current_request == std::addressof(*m_request_queue.begin()));
|
||||
m_request_queue.WakeupThread(m_current_request);
|
||||
m_current_request->SetSyncedObject(nullptr, svc::ResultSessionClosed());
|
||||
}
|
||||
|
||||
/* Clear our current request. */
|
||||
cur_request = this->current_request;
|
||||
this->current_request = nullptr;
|
||||
this->server_thread = nullptr;
|
||||
cur_request = m_current_request;
|
||||
m_current_request = nullptr;
|
||||
m_server_thread = nullptr;
|
||||
}
|
||||
|
||||
/* Reply to all other requests. */
|
||||
while (!this->request_queue.IsEmpty()) {
|
||||
KThread *client_thread = this->request_queue.WakeupFrontThread();
|
||||
while (!m_request_queue.IsEmpty()) {
|
||||
KThread *client_thread = m_request_queue.WakeupFrontThread();
|
||||
client_thread->SetSyncedObject(nullptr, svc::ResultSessionClosed());
|
||||
}
|
||||
|
||||
/* Wake up all server threads. */
|
||||
while (!this->server_queue.IsEmpty()) {
|
||||
this->server_queue.WakeupFrontThread();
|
||||
while (!m_server_queue.IsEmpty()) {
|
||||
m_server_queue.WakeupFrontThread();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -27,44 +27,44 @@ namespace ams::kern {
|
||||
this->Open();
|
||||
|
||||
/* Create our sub sessions. */
|
||||
KAutoObject::Create(std::addressof(this->server));
|
||||
KAutoObject::Create(std::addressof(this->client));
|
||||
KAutoObject::Create(std::addressof(m_server));
|
||||
KAutoObject::Create(std::addressof(m_client));
|
||||
|
||||
/* Initialize our sub sessions. */
|
||||
this->server.Initialize(this);
|
||||
this->client.Initialize(this);
|
||||
m_server.Initialize(this);
|
||||
m_client.Initialize(this);
|
||||
|
||||
/* Set state and name. */
|
||||
this->state = State::Normal;
|
||||
this->name = name;
|
||||
m_state = State::Normal;
|
||||
m_name = name;
|
||||
|
||||
/* Set our owner process. */
|
||||
this->process = GetCurrentProcessPointer();
|
||||
this->process->Open();
|
||||
m_process = GetCurrentProcessPointer();
|
||||
m_process->Open();
|
||||
|
||||
/* Set our port. */
|
||||
this->port = client_port;
|
||||
if (this->port != nullptr) {
|
||||
this->port->Open();
|
||||
m_port = client_port;
|
||||
if (m_port != nullptr) {
|
||||
m_port->Open();
|
||||
}
|
||||
|
||||
/* Mark initialized. */
|
||||
this->initialized = true;
|
||||
m_initialized = true;
|
||||
}
|
||||
|
||||
void KLightSession::Finalize() {
|
||||
if (this->port != nullptr) {
|
||||
this->port->OnSessionFinalized();
|
||||
this->port->Close();
|
||||
if (m_port != nullptr) {
|
||||
m_port->OnSessionFinalized();
|
||||
m_port->Close();
|
||||
}
|
||||
}
|
||||
|
||||
void KLightSession::OnServerClosed() {
|
||||
MESOSPHERE_ASSERT_THIS();
|
||||
|
||||
if (this->state == State::Normal) {
|
||||
this->state = State::ServerClosed;
|
||||
this->client.OnServerClosed();
|
||||
if (m_state == State::Normal) {
|
||||
m_state = State::ServerClosed;
|
||||
m_client.OnServerClosed();
|
||||
}
|
||||
|
||||
this->Close();
|
||||
@@ -73,9 +73,9 @@ namespace ams::kern {
|
||||
void KLightSession::OnClientClosed() {
|
||||
MESOSPHERE_ASSERT_THIS();
|
||||
|
||||
if (this->state == State::Normal) {
|
||||
this->state = State::ClientClosed;
|
||||
this->server.OnClientClosed();
|
||||
if (m_state == State::Normal) {
|
||||
m_state = State::ClientClosed;
|
||||
m_server.OnClientClosed();
|
||||
}
|
||||
|
||||
this->Close();
|
||||
|
||||
@@ -53,10 +53,10 @@ namespace ams::kern {
|
||||
}
|
||||
|
||||
constexpr const char *GetMemoryPermissionString(const KMemoryInfo &info) {
|
||||
if (info.state == KMemoryState_Free) {
|
||||
if (info.m_state == KMemoryState_Free) {
|
||||
return " ";
|
||||
} else {
|
||||
switch (info.perm) {
|
||||
switch (info.m_perm) {
|
||||
case KMemoryPermission_UserReadExecute:
|
||||
return "r-x";
|
||||
case KMemoryPermission_UserRead:
|
||||
@@ -70,18 +70,18 @@ namespace ams::kern {
|
||||
}
|
||||
|
||||
void DumpMemoryInfo(const KMemoryInfo &info) {
|
||||
const char *state = GetMemoryStateName(info.state);
|
||||
const char *state = GetMemoryStateName(info.m_state);
|
||||
const char *perm = GetMemoryPermissionString(info);
|
||||
const uintptr_t start = info.GetAddress();
|
||||
const uintptr_t end = info.GetLastAddress();
|
||||
const size_t kb = info.GetSize() / 1_KB;
|
||||
|
||||
const char l = (info.attribute & KMemoryAttribute_Locked) ? 'L' : '-';
|
||||
const char i = (info.attribute & KMemoryAttribute_IpcLocked) ? 'I' : '-';
|
||||
const char d = (info.attribute & KMemoryAttribute_DeviceShared) ? 'D' : '-';
|
||||
const char u = (info.attribute & KMemoryAttribute_Uncached) ? 'U' : '-';
|
||||
const char l = (info.m_attribute & KMemoryAttribute_Locked) ? 'L' : '-';
|
||||
const char i = (info.m_attribute & KMemoryAttribute_IpcLocked) ? 'I' : '-';
|
||||
const char d = (info.m_attribute & KMemoryAttribute_DeviceShared) ? 'D' : '-';
|
||||
const char u = (info.m_attribute & KMemoryAttribute_Uncached) ? 'U' : '-';
|
||||
|
||||
MESOSPHERE_LOG("0x%10lx - 0x%10lx (%9zu KB) %s %s %c%c%c%c [%d, %d]\n", start, end, kb, perm, state, l, i, d, u, info.ipc_lock_count, info.device_use_count);
|
||||
MESOSPHERE_LOG("0x%10lx - 0x%10lx (%9zu KB) %s %s %c%c%c%c [%d, %d]\n", start, end, kb, perm, state, l, i, d, u, info.m_ipc_lock_count, info.m_device_use_count);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -92,40 +92,40 @@ namespace ams::kern {
|
||||
R_UNLESS(start_block != nullptr, svc::ResultOutOfResource());
|
||||
|
||||
/* Set our start and end. */
|
||||
this->start_address = st;
|
||||
this->end_address = nd;
|
||||
MESOSPHERE_ASSERT(util::IsAligned(GetInteger(this->start_address), PageSize));
|
||||
MESOSPHERE_ASSERT(util::IsAligned(GetInteger(this->end_address), PageSize));
|
||||
m_start_address = st;
|
||||
m_end_address = nd;
|
||||
MESOSPHERE_ASSERT(util::IsAligned(GetInteger(m_start_address), PageSize));
|
||||
MESOSPHERE_ASSERT(util::IsAligned(GetInteger(m_end_address), PageSize));
|
||||
|
||||
/* Initialize and insert the block. */
|
||||
start_block->Initialize(this->start_address, (this->end_address - this->start_address) / PageSize, KMemoryState_Free, KMemoryPermission_None, KMemoryAttribute_None);
|
||||
this->memory_block_tree.insert(*start_block);
|
||||
start_block->Initialize(m_start_address, (m_end_address - m_start_address) / PageSize, KMemoryState_Free, KMemoryPermission_None, KMemoryAttribute_None);
|
||||
m_memory_block_tree.insert(*start_block);
|
||||
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
void KMemoryBlockManager::Finalize(KMemoryBlockSlabManager *slab_manager) {
|
||||
/* Erase every block until we have none left. */
|
||||
auto it = this->memory_block_tree.begin();
|
||||
while (it != this->memory_block_tree.end()) {
|
||||
auto it = m_memory_block_tree.begin();
|
||||
while (it != m_memory_block_tree.end()) {
|
||||
KMemoryBlock *block = std::addressof(*it);
|
||||
it = this->memory_block_tree.erase(it);
|
||||
it = m_memory_block_tree.erase(it);
|
||||
slab_manager->Free(block);
|
||||
}
|
||||
|
||||
MESOSPHERE_ASSERT(this->memory_block_tree.empty());
|
||||
MESOSPHERE_ASSERT(m_memory_block_tree.empty());
|
||||
}
|
||||
|
||||
KProcessAddress KMemoryBlockManager::FindFreeArea(KProcessAddress region_start, size_t region_num_pages, size_t num_pages, size_t alignment, size_t offset, size_t guard_pages) const {
|
||||
if (num_pages > 0) {
|
||||
const KProcessAddress region_end = region_start + region_num_pages * PageSize;
|
||||
const KProcessAddress region_last = region_end - 1;
|
||||
for (const_iterator it = this->FindIterator(region_start); it != this->memory_block_tree.cend(); it++) {
|
||||
for (const_iterator it = this->FindIterator(region_start); it != m_memory_block_tree.cend(); it++) {
|
||||
const KMemoryInfo info = it->GetMemoryInfo();
|
||||
if (region_last < info.GetAddress()) {
|
||||
break;
|
||||
}
|
||||
if (info.state != KMemoryState_Free) {
|
||||
if (info.m_state != KMemoryState_Free) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -150,20 +150,20 @@ namespace ams::kern {
|
||||
void KMemoryBlockManager::CoalesceForUpdate(KMemoryBlockManagerUpdateAllocator *allocator, KProcessAddress address, size_t num_pages) {
|
||||
/* Find the iterator now that we've updated. */
|
||||
iterator it = this->FindIterator(address);
|
||||
if (address != this->start_address) {
|
||||
if (address != m_start_address) {
|
||||
it--;
|
||||
}
|
||||
|
||||
/* Coalesce blocks that we can. */
|
||||
while (true) {
|
||||
iterator prev = it++;
|
||||
if (it == this->memory_block_tree.end()) {
|
||||
if (it == m_memory_block_tree.end()) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (prev->CanMergeWith(*it)) {
|
||||
KMemoryBlock *block = std::addressof(*it);
|
||||
this->memory_block_tree.erase(it);
|
||||
m_memory_block_tree.erase(it);
|
||||
prev->Add(*block);
|
||||
allocator->Free(block);
|
||||
it = prev;
|
||||
@@ -203,7 +203,7 @@ namespace ams::kern {
|
||||
KMemoryBlock *new_block = allocator->Allocate();
|
||||
|
||||
it->Split(new_block, cur_address);
|
||||
it = this->memory_block_tree.insert(*new_block);
|
||||
it = m_memory_block_tree.insert(*new_block);
|
||||
it++;
|
||||
|
||||
cur_info = it->GetMemoryInfo();
|
||||
@@ -215,7 +215,7 @@ namespace ams::kern {
|
||||
KMemoryBlock *new_block = allocator->Allocate();
|
||||
|
||||
it->Split(new_block, cur_address + remaining_size);
|
||||
it = this->memory_block_tree.insert(*new_block);
|
||||
it = m_memory_block_tree.insert(*new_block);
|
||||
|
||||
cur_info = it->GetMemoryInfo();
|
||||
}
|
||||
@@ -250,7 +250,7 @@ namespace ams::kern {
|
||||
KMemoryBlock *new_block = allocator->Allocate();
|
||||
|
||||
it->Split(new_block, cur_address);
|
||||
it = this->memory_block_tree.insert(*new_block);
|
||||
it = m_memory_block_tree.insert(*new_block);
|
||||
it++;
|
||||
|
||||
cur_info = it->GetMemoryInfo();
|
||||
@@ -262,7 +262,7 @@ namespace ams::kern {
|
||||
KMemoryBlock *new_block = allocator->Allocate();
|
||||
|
||||
it->Split(new_block, cur_address + remaining_size);
|
||||
it = this->memory_block_tree.insert(*new_block);
|
||||
it = m_memory_block_tree.insert(*new_block);
|
||||
|
||||
cur_info = it->GetMemoryInfo();
|
||||
}
|
||||
@@ -303,11 +303,11 @@ namespace ams::kern {
|
||||
KMemoryInfo cur_info = it->GetMemoryInfo();
|
||||
|
||||
/* If we need to, create a new block before and insert it. */
|
||||
if (cur_info.address != GetInteger(cur_address)) {
|
||||
if (cur_info.m_address != GetInteger(cur_address)) {
|
||||
KMemoryBlock *new_block = allocator->Allocate();
|
||||
|
||||
it->Split(new_block, cur_address);
|
||||
it = this->memory_block_tree.insert(*new_block);
|
||||
it = m_memory_block_tree.insert(*new_block);
|
||||
it++;
|
||||
|
||||
cur_info = it->GetMemoryInfo();
|
||||
@@ -319,7 +319,7 @@ namespace ams::kern {
|
||||
KMemoryBlock *new_block = allocator->Allocate();
|
||||
|
||||
it->Split(new_block, cur_address + remaining_size);
|
||||
it = this->memory_block_tree.insert(*new_block);
|
||||
it = m_memory_block_tree.insert(*new_block);
|
||||
|
||||
cur_info = it->GetMemoryInfo();
|
||||
}
|
||||
@@ -340,9 +340,9 @@ namespace ams::kern {
|
||||
auto dump_guard = SCOPE_GUARD { this->DumpBlocks(); };
|
||||
|
||||
/* Loop over every block, ensuring that we are sorted and coalesced. */
|
||||
auto it = this->memory_block_tree.cbegin();
|
||||
auto it = m_memory_block_tree.cbegin();
|
||||
auto prev = it++;
|
||||
while (it != this->memory_block_tree.cend()) {
|
||||
while (it != m_memory_block_tree.cend()) {
|
||||
const KMemoryInfo prev_info = prev->GetMemoryInfo();
|
||||
const KMemoryInfo cur_info = it->GetMemoryInfo();
|
||||
|
||||
@@ -357,12 +357,12 @@ namespace ams::kern {
|
||||
}
|
||||
|
||||
/* If the block is ipc locked, it must have a count. */
|
||||
if ((cur_info.attribute & KMemoryAttribute_IpcLocked) != 0 && cur_info.ipc_lock_count == 0) {
|
||||
if ((cur_info.m_attribute & KMemoryAttribute_IpcLocked) != 0 && cur_info.m_ipc_lock_count == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/* If the block is device shared, it must have a count. */
|
||||
if ((cur_info.attribute & KMemoryAttribute_DeviceShared) != 0 && cur_info.device_use_count == 0) {
|
||||
if ((cur_info.m_attribute & KMemoryAttribute_DeviceShared) != 0 && cur_info.m_device_use_count == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -371,15 +371,15 @@ namespace ams::kern {
|
||||
}
|
||||
|
||||
/* Our loop will miss checking the last block, potentially, so check it. */
|
||||
if (prev != this->memory_block_tree.cend()) {
|
||||
if (prev != m_memory_block_tree.cend()) {
|
||||
const KMemoryInfo prev_info = prev->GetMemoryInfo();
|
||||
/* If the block is ipc locked, it must have a count. */
|
||||
if ((prev_info.attribute & KMemoryAttribute_IpcLocked) != 0 && prev_info.ipc_lock_count == 0) {
|
||||
if ((prev_info.m_attribute & KMemoryAttribute_IpcLocked) != 0 && prev_info.m_ipc_lock_count == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/* If the block is device shared, it must have a count. */
|
||||
if ((prev_info.attribute & KMemoryAttribute_DeviceShared) != 0 && prev_info.device_use_count == 0) {
|
||||
if ((prev_info.m_attribute & KMemoryAttribute_DeviceShared) != 0 && prev_info.m_device_use_count == 0) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -391,7 +391,7 @@ namespace ams::kern {
|
||||
|
||||
void KMemoryBlockManager::DumpBlocks() const {
|
||||
/* Dump each block. */
|
||||
for (const auto &block : this->memory_block_tree) {
|
||||
for (const auto &block : m_memory_block_tree) {
|
||||
DumpMemoryInfo(block.GetMemoryInfo());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,7 +41,7 @@ namespace ams::kern {
|
||||
std::memset(GetVoidPointer(management_region), 0, management_region_size);
|
||||
|
||||
/* Traverse the virtual memory layout tree, initializing each manager as appropriate. */
|
||||
while (this->num_managers != MaxManagerCount) {
|
||||
while (m_num_managers != MaxManagerCount) {
|
||||
/* Locate the region that should initialize the current manager. */
|
||||
uintptr_t region_address = 0;
|
||||
size_t region_size = 0;
|
||||
@@ -53,7 +53,7 @@ namespace ams::kern {
|
||||
}
|
||||
|
||||
/* We want to initialize the managers in order. */
|
||||
if (it.GetAttributes() != this->num_managers) {
|
||||
if (it.GetAttributes() != m_num_managers) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -82,21 +82,21 @@ namespace ams::kern {
|
||||
}
|
||||
|
||||
/* Initialize a new manager for the region. */
|
||||
Impl *manager = std::addressof(this->managers[this->num_managers++]);
|
||||
MESOSPHERE_ABORT_UNLESS(this->num_managers <= util::size(this->managers));
|
||||
Impl *manager = std::addressof(m_managers[m_num_managers++]);
|
||||
MESOSPHERE_ABORT_UNLESS(m_num_managers <= util::size(m_managers));
|
||||
|
||||
const size_t cur_size = manager->Initialize(region_address, region_size, management_region, management_region_end, region_pool);
|
||||
management_region += cur_size;
|
||||
MESOSPHERE_ABORT_UNLESS(management_region <= management_region_end);
|
||||
|
||||
/* Insert the manager into the pool list. */
|
||||
if (this->pool_managers_tail[region_pool] == nullptr) {
|
||||
this->pool_managers_head[region_pool] = manager;
|
||||
if (m_pool_managers_tail[region_pool] == nullptr) {
|
||||
m_pool_managers_head[region_pool] = manager;
|
||||
} else {
|
||||
this->pool_managers_tail[region_pool]->SetNext(manager);
|
||||
manager->SetPrev(this->pool_managers_tail[region_pool]);
|
||||
m_pool_managers_tail[region_pool]->SetNext(manager);
|
||||
manager->SetPrev(m_pool_managers_tail[region_pool]);
|
||||
}
|
||||
this->pool_managers_tail[region_pool] = manager;
|
||||
m_pool_managers_tail[region_pool] = manager;
|
||||
}
|
||||
|
||||
/* Free each region to its corresponding heap. */
|
||||
@@ -106,26 +106,26 @@ namespace ams::kern {
|
||||
MESOSPHERE_ABORT_UNLESS(it.GetEndAddress() != 0);
|
||||
|
||||
/* Free the memory to the heap. */
|
||||
this->managers[it.GetAttributes()].Free(it.GetAddress(), it.GetSize() / PageSize);
|
||||
m_managers[it.GetAttributes()].Free(it.GetAddress(), it.GetSize() / PageSize);
|
||||
}
|
||||
}
|
||||
|
||||
/* Update the used size for all managers. */
|
||||
for (size_t i = 0; i < this->num_managers; ++i) {
|
||||
this->managers[i].UpdateUsedHeapSize();
|
||||
for (size_t i = 0; i < m_num_managers; ++i) {
|
||||
m_managers[i].UpdateUsedHeapSize();
|
||||
}
|
||||
}
|
||||
|
||||
Result KMemoryManager::InitializeOptimizedMemory(u64 process_id, Pool pool) {
|
||||
/* Lock the pool. */
|
||||
KScopedLightLock lk(this->pool_locks[pool]);
|
||||
KScopedLightLock lk(m_pool_locks[pool]);
|
||||
|
||||
/* Check that we don't already have an optimized process. */
|
||||
R_UNLESS(!this->has_optimized_process[pool], svc::ResultBusy());
|
||||
R_UNLESS(!m_has_optimized_process[pool], svc::ResultBusy());
|
||||
|
||||
/* Set the optimized process id. */
|
||||
this->optimized_process_ids[pool] = process_id;
|
||||
this->has_optimized_process[pool] = true;
|
||||
m_optimized_process_ids[pool] = process_id;
|
||||
m_has_optimized_process[pool] = true;
|
||||
|
||||
/* Clear the management area for the optimized process. */
|
||||
for (auto *manager = this->GetFirstManager(pool, Direction_FromFront); manager != nullptr; manager = this->GetNextManager(manager, Direction_FromFront)) {
|
||||
@@ -137,11 +137,11 @@ namespace ams::kern {
|
||||
|
||||
void KMemoryManager::FinalizeOptimizedMemory(u64 process_id, Pool pool) {
|
||||
/* Lock the pool. */
|
||||
KScopedLightLock lk(this->pool_locks[pool]);
|
||||
KScopedLightLock lk(m_pool_locks[pool]);
|
||||
|
||||
/* If the process was optimized, clear it. */
|
||||
if (this->has_optimized_process[pool] && this->optimized_process_ids[pool] == process_id) {
|
||||
this->has_optimized_process[pool] = false;
|
||||
if (m_has_optimized_process[pool] && m_optimized_process_ids[pool] == process_id) {
|
||||
m_has_optimized_process[pool] = false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -154,7 +154,7 @@ namespace ams::kern {
|
||||
|
||||
/* Lock the pool that we're allocating from. */
|
||||
const auto [pool, dir] = DecodeOption(option);
|
||||
KScopedLightLock lk(this->pool_locks[pool]);
|
||||
KScopedLightLock lk(m_pool_locks[pool]);
|
||||
|
||||
/* Choose a heap based on our page size request. */
|
||||
const s32 heap_index = KPageHeap::GetAlignedBlockIndex(num_pages, align_pages);
|
||||
@@ -181,7 +181,7 @@ namespace ams::kern {
|
||||
}
|
||||
|
||||
/* Maintain the optimized memory bitmap, if we should. */
|
||||
if (this->has_optimized_process[pool]) {
|
||||
if (m_has_optimized_process[pool]) {
|
||||
chosen_manager->TrackUnoptimizedAllocation(allocated_block, num_pages);
|
||||
}
|
||||
|
||||
@@ -251,10 +251,10 @@ namespace ams::kern {
|
||||
|
||||
/* Lock the pool that we're allocating from. */
|
||||
const auto [pool, dir] = DecodeOption(option);
|
||||
KScopedLightLock lk(this->pool_locks[pool]);
|
||||
KScopedLightLock lk(m_pool_locks[pool]);
|
||||
|
||||
/* Allocate the page group. */
|
||||
R_TRY(this->AllocatePageGroupImpl(out, num_pages, pool, dir, this->has_optimized_process[pool], true));
|
||||
R_TRY(this->AllocatePageGroupImpl(out, num_pages, pool, dir, m_has_optimized_process[pool], true));
|
||||
|
||||
/* Open the first reference to the pages. */
|
||||
for (const auto &block : *out) {
|
||||
@@ -288,11 +288,11 @@ namespace ams::kern {
|
||||
bool optimized;
|
||||
{
|
||||
/* Lock the pool that we're allocating from. */
|
||||
KScopedLightLock lk(this->pool_locks[pool]);
|
||||
KScopedLightLock lk(m_pool_locks[pool]);
|
||||
|
||||
/* Check if we have an optimized process. */
|
||||
const bool has_optimized = this->has_optimized_process[pool];
|
||||
const bool is_optimized = this->optimized_process_ids[pool] == process_id;
|
||||
const bool has_optimized = m_has_optimized_process[pool];
|
||||
const bool is_optimized = m_optimized_process_ids[pool] == process_id;
|
||||
|
||||
/* Allocate the page group. */
|
||||
R_TRY(this->AllocatePageGroupImpl(out, num_pages, pool, dir, has_optimized && !is_optimized, false));
|
||||
@@ -361,7 +361,7 @@ namespace ams::kern {
|
||||
auto &manager = this->GetManager(cur_address);
|
||||
|
||||
/* Lock the pool for the manager. */
|
||||
KScopedLightLock lk(this->pool_locks[manager.GetPool()]);
|
||||
KScopedLightLock lk(m_pool_locks[manager.GetPool()]);
|
||||
|
||||
/* Track some or all of the current pages. */
|
||||
const size_t cur_pages = std::min(remaining_pages, manager.GetPageOffsetToEnd(cur_address));
|
||||
@@ -395,13 +395,13 @@ namespace ams::kern {
|
||||
MESOSPHERE_ABORT_UNLESS(util::IsAligned(total_management_size, PageSize));
|
||||
|
||||
/* Setup region. */
|
||||
this->pool = p;
|
||||
this->management_region = management;
|
||||
this->page_reference_counts = GetPointer<RefCount>(management + optimize_map_size);
|
||||
MESOSPHERE_ABORT_UNLESS(util::IsAligned(GetInteger(this->management_region), PageSize));
|
||||
m_pool = p;
|
||||
m_management_region = management;
|
||||
m_page_reference_counts = GetPointer<RefCount>(management + optimize_map_size);
|
||||
MESOSPHERE_ABORT_UNLESS(util::IsAligned(GetInteger(m_management_region), PageSize));
|
||||
|
||||
/* Initialize the manager's KPageHeap. */
|
||||
this->heap.Initialize(address, size, management + manager_size, page_heap_size);
|
||||
m_heap.Initialize(address, size, management + manager_size, page_heap_size);
|
||||
|
||||
return total_management_size;
|
||||
}
|
||||
@@ -412,7 +412,7 @@ namespace ams::kern {
|
||||
const size_t last = offset + num_pages - 1;
|
||||
|
||||
/* Track. */
|
||||
u64 *optimize_map = GetPointer<u64>(this->management_region);
|
||||
u64 *optimize_map = GetPointer<u64>(m_management_region);
|
||||
while (offset <= last) {
|
||||
/* Mark the page as not being optimized-allocated. */
|
||||
optimize_map[offset / BITSIZEOF(u64)] &= ~(u64(1) << (offset % BITSIZEOF(u64)));
|
||||
@@ -427,7 +427,7 @@ namespace ams::kern {
|
||||
const size_t last = offset + num_pages - 1;
|
||||
|
||||
/* Track. */
|
||||
u64 *optimize_map = GetPointer<u64>(this->management_region);
|
||||
u64 *optimize_map = GetPointer<u64>(m_management_region);
|
||||
while (offset <= last) {
|
||||
/* Mark the page as being optimized-allocated. */
|
||||
optimize_map[offset / BITSIZEOF(u64)] |= (u64(1) << (offset % BITSIZEOF(u64)));
|
||||
@@ -445,7 +445,7 @@ namespace ams::kern {
|
||||
const size_t last = offset + num_pages - 1;
|
||||
|
||||
/* Process. */
|
||||
u64 *optimize_map = GetPointer<u64>(this->management_region);
|
||||
u64 *optimize_map = GetPointer<u64>(m_management_region);
|
||||
while (offset <= last) {
|
||||
/* Check if the page has been optimized-allocated before. */
|
||||
if ((optimize_map[offset / BITSIZEOF(u64)] & (u64(1) << (offset % BITSIZEOF(u64)))) == 0) {
|
||||
@@ -453,7 +453,7 @@ namespace ams::kern {
|
||||
any_new = true;
|
||||
|
||||
/* Fill the page. */
|
||||
std::memset(GetVoidPointer(this->heap.GetAddress() + offset * PageSize), fill_pattern, PageSize);
|
||||
std::memset(GetVoidPointer(m_heap.GetAddress() + offset * PageSize), fill_pattern, PageSize);
|
||||
}
|
||||
|
||||
offset++;
|
||||
|
||||
@@ -26,16 +26,16 @@ namespace ams::kern {
|
||||
|
||||
void KObjectName::Initialize(KAutoObject *obj, const char *name) {
|
||||
/* Set member variables. */
|
||||
this->object = obj;
|
||||
std::strncpy(this->name, name, sizeof(this->name));
|
||||
this->name[sizeof(this->name) - 1] = '\x00';
|
||||
m_object = obj;
|
||||
std::strncpy(m_name, name, sizeof(m_name));
|
||||
m_name[sizeof(m_name) - 1] = '\x00';
|
||||
|
||||
/* Open a reference to the object we hold. */
|
||||
this->object->Open();
|
||||
m_object->Open();
|
||||
}
|
||||
|
||||
bool KObjectName::MatchesName(const char *name) const {
|
||||
return std::strncmp(this->name, name, sizeof(this->name)) == 0;
|
||||
return std::strncmp(m_name, name, sizeof(m_name)) == 0;
|
||||
}
|
||||
|
||||
Result KObjectName::NewFromName(KAutoObject *obj, const char *name) {
|
||||
|
||||
@@ -18,11 +18,11 @@
|
||||
namespace ams::kern {
|
||||
|
||||
void KPageGroup::Finalize() {
|
||||
auto it = this->block_list.begin();
|
||||
while (it != this->block_list.end()) {
|
||||
auto it = m_block_list.begin();
|
||||
while (it != m_block_list.end()) {
|
||||
KBlockInfo *info = std::addressof(*it);
|
||||
it = this->block_list.erase(it);
|
||||
this->manager->Free(info);
|
||||
it = m_block_list.erase(it);
|
||||
m_manager->Free(info);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -44,18 +44,18 @@ namespace ams::kern {
|
||||
MESOSPHERE_ASSERT(addr < addr + num_pages * PageSize);
|
||||
|
||||
/* Try to just append to the last block. */
|
||||
if (!this->block_list.empty()) {
|
||||
auto it = --(this->block_list.end());
|
||||
if (!m_block_list.empty()) {
|
||||
auto it = --(m_block_list.end());
|
||||
R_SUCCEED_IF(it->TryConcatenate(addr, num_pages));
|
||||
}
|
||||
|
||||
/* Allocate a new block. */
|
||||
KBlockInfo *new_block = this->manager->Allocate();
|
||||
KBlockInfo *new_block = m_manager->Allocate();
|
||||
R_UNLESS(new_block != nullptr, svc::ResultOutOfResource());
|
||||
|
||||
/* Initialize the block. */
|
||||
new_block->Initialize(addr, num_pages);
|
||||
this->block_list.push_back(*new_block);
|
||||
m_block_list.push_back(*new_block);
|
||||
|
||||
return ResultSuccess();
|
||||
}
|
||||
@@ -77,10 +77,10 @@ namespace ams::kern {
|
||||
}
|
||||
|
||||
bool KPageGroup::IsEquivalentTo(const KPageGroup &rhs) const {
|
||||
auto lit = this->block_list.cbegin();
|
||||
auto rit = rhs.block_list.cbegin();
|
||||
auto lend = this->block_list.cend();
|
||||
auto rend = rhs.block_list.cend();
|
||||
auto lit = m_block_list.cbegin();
|
||||
auto rit = rhs.m_block_list.cbegin();
|
||||
auto lend = m_block_list.cend();
|
||||
auto rend = rhs.m_block_list.cend();
|
||||
|
||||
while (lit != lend && rit != rend) {
|
||||
if (*lit != *rit) {
|
||||
|
||||
@@ -25,16 +25,16 @@ namespace ams::kern {
|
||||
const KVirtualAddress management_end = management_address + management_size;
|
||||
|
||||
/* Set our members. */
|
||||
this->heap_address = address;
|
||||
this->heap_size = size;
|
||||
this->num_blocks = num_block_shifts;
|
||||
m_heap_address = address;
|
||||
m_heap_size = size;
|
||||
m_num_blocks = num_block_shifts;
|
||||
|
||||
/* Setup bitmaps. */
|
||||
u64 *cur_bitmap_storage = GetPointer<u64>(management_address);
|
||||
for (size_t i = 0; i < num_block_shifts; i++) {
|
||||
const size_t cur_block_shift = block_shifts[i];
|
||||
const size_t next_block_shift = (i != num_block_shifts - 1) ? block_shifts[i + 1] : 0;
|
||||
cur_bitmap_storage = this->blocks[i].Initialize(this->heap_address, this->heap_size, cur_block_shift, next_block_shift, cur_bitmap_storage);
|
||||
cur_bitmap_storage = m_blocks[i].Initialize(m_heap_address, m_heap_size, cur_block_shift, next_block_shift, cur_bitmap_storage);
|
||||
}
|
||||
|
||||
/* Ensure we didn't overextend our bounds. */
|
||||
@@ -44,19 +44,19 @@ namespace ams::kern {
|
||||
size_t KPageHeap::GetNumFreePages() const {
|
||||
size_t num_free = 0;
|
||||
|
||||
for (size_t i = 0; i < this->num_blocks; i++) {
|
||||
num_free += this->blocks[i].GetNumFreePages();
|
||||
for (size_t i = 0; i < m_num_blocks; i++) {
|
||||
num_free += m_blocks[i].GetNumFreePages();
|
||||
}
|
||||
|
||||
return num_free;
|
||||
}
|
||||
|
||||
KVirtualAddress KPageHeap::AllocateBlock(s32 index, bool random) {
|
||||
const size_t needed_size = this->blocks[index].GetSize();
|
||||
const size_t needed_size = m_blocks[index].GetSize();
|
||||
|
||||
for (s32 i = index; i < static_cast<s32>(this->num_blocks); i++) {
|
||||
if (const KVirtualAddress addr = this->blocks[i].PopBlock(random); addr != Null<KVirtualAddress>) {
|
||||
if (const size_t allocated_size = this->blocks[i].GetSize(); allocated_size > needed_size) {
|
||||
for (s32 i = index; i < static_cast<s32>(m_num_blocks); i++) {
|
||||
if (const KVirtualAddress addr = m_blocks[i].PopBlock(random); addr != Null<KVirtualAddress>) {
|
||||
if (const size_t allocated_size = m_blocks[i].GetSize(); allocated_size > needed_size) {
|
||||
this->Free(addr + needed_size, (allocated_size - needed_size) / PageSize);
|
||||
}
|
||||
return addr;
|
||||
@@ -68,7 +68,7 @@ namespace ams::kern {
|
||||
|
||||
void KPageHeap::FreeBlock(KVirtualAddress block, s32 index) {
|
||||
do {
|
||||
block = this->blocks[index++].PushBlock(block);
|
||||
block = m_blocks[index++].PushBlock(block);
|
||||
} while (block != Null<KVirtualAddress>);
|
||||
}
|
||||
|
||||
@@ -79,7 +79,7 @@ namespace ams::kern {
|
||||
}
|
||||
|
||||
/* Find the largest block size that we can free, and free as many as possible. */
|
||||
s32 big_index = static_cast<s32>(this->num_blocks) - 1;
|
||||
s32 big_index = static_cast<s32>(m_num_blocks) - 1;
|
||||
const KVirtualAddress start = addr;
|
||||
const KVirtualAddress end = addr + num_pages * PageSize;
|
||||
KVirtualAddress before_start = start;
|
||||
@@ -87,7 +87,7 @@ namespace ams::kern {
|
||||
KVirtualAddress after_start = end;
|
||||
KVirtualAddress after_end = end;
|
||||
while (big_index >= 0) {
|
||||
const size_t block_size = this->blocks[big_index].GetSize();
|
||||
const size_t block_size = m_blocks[big_index].GetSize();
|
||||
const KVirtualAddress big_start = util::AlignUp(GetInteger(start), block_size);
|
||||
const KVirtualAddress big_end = util::AlignDown(GetInteger(end), block_size);
|
||||
if (big_start < big_end) {
|
||||
@@ -105,7 +105,7 @@ namespace ams::kern {
|
||||
|
||||
/* Free space before the big blocks. */
|
||||
for (s32 i = big_index - 1; i >= 0; i--) {
|
||||
const size_t block_size = this->blocks[i].GetSize();
|
||||
const size_t block_size = m_blocks[i].GetSize();
|
||||
while (before_start + block_size <= before_end) {
|
||||
before_end -= block_size;
|
||||
this->FreeBlock(before_end, i);
|
||||
@@ -114,7 +114,7 @@ namespace ams::kern {
|
||||
|
||||
/* Free space after the big blocks. */
|
||||
for (s32 i = big_index - 1; i >= 0; i--) {
|
||||
const size_t block_size = this->blocks[i].GetSize();
|
||||
const size_t block_size = m_blocks[i].GetSize();
|
||||
while (after_start + block_size <= after_end) {
|
||||
this->FreeBlock(after_start, i);
|
||||
after_start += block_size;
|
||||
@@ -135,8 +135,8 @@ namespace ams::kern {
|
||||
void KPageHeap::DumpFreeList() const {
|
||||
MESOSPHERE_RELEASE_LOG("KPageHeap::DumpFreeList %p\n", this);
|
||||
|
||||
for (size_t i = 0; i < this->num_blocks; ++i) {
|
||||
const size_t block_size = this->blocks[i].GetSize();
|
||||
for (size_t i = 0; i < m_num_blocks; ++i) {
|
||||
const size_t block_size = m_blocks[i].GetSize();
|
||||
const char *suffix;
|
||||
size_t size;
|
||||
if (block_size >= 1_GB) {
|
||||
@@ -153,7 +153,7 @@ namespace ams::kern {
|
||||
size = block_size;
|
||||
}
|
||||
|
||||
MESOSPHERE_RELEASE_LOG(" %4zu %s block x %zu\n", size, suffix, this->blocks[i].GetNumFreeBlocks());
|
||||
MESOSPHERE_RELEASE_LOG(" %4zu %s block x %zu\n", size, suffix, m_blocks[i].GetNumFreeBlocks());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -22,15 +22,15 @@ namespace ams::kern {
|
||||
this->Open();
|
||||
|
||||
/* Create and initialize our server/client pair. */
|
||||
KAutoObject::Create(std::addressof(this->server));
|
||||
KAutoObject::Create(std::addressof(this->client));
|
||||
this->server.Initialize(this);
|
||||
this->client.Initialize(this, max_sessions);
|
||||
KAutoObject::Create(std::addressof(m_server));
|
||||
KAutoObject::Create(std::addressof(m_client));
|
||||
m_server.Initialize(this);
|
||||
m_client.Initialize(this, max_sessions);
|
||||
|
||||
/* Set our member variables. */
|
||||
this->is_light = is_light;
|
||||
this->name = name;
|
||||
this->state = State::Normal;
|
||||
m_is_light = is_light;
|
||||
m_name = name;
|
||||
m_state = State::Normal;
|
||||
}
|
||||
|
||||
void KPort::OnClientClosed() {
|
||||
@@ -38,8 +38,8 @@ namespace ams::kern {
|
||||
|
||||
KScopedSchedulerLock sl;
|
||||
|
||||
if (this->state == State::Normal) {
|
||||
this->state = State::ClientClosed;
|
||||
if (m_state == State::Normal) {
|
||||
m_state = State::ClientClosed;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -48,26 +48,26 @@ namespace ams::kern {
|
||||
|
||||
KScopedSchedulerLock sl;
|
||||
|
||||
if (this->state == State::Normal) {
|
||||
this->state = State::ServerClosed;
|
||||
if (m_state == State::Normal) {
|
||||
m_state = State::ServerClosed;
|
||||
}
|
||||
}
|
||||
|
||||
Result KPort::EnqueueSession(KServerSession *session) {
|
||||
KScopedSchedulerLock sl;
|
||||
|
||||
R_UNLESS(this->state == State::Normal, svc::ResultPortClosed());
|
||||
R_UNLESS(m_state == State::Normal, svc::ResultPortClosed());
|
||||
|
||||
this->server.EnqueueSession(session);
|
||||
m_server.EnqueueSession(session);
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
Result KPort::EnqueueSession(KLightServerSession *session) {
|
||||
KScopedSchedulerLock sl;
|
||||
|
||||
R_UNLESS(this->state == State::Normal, svc::ResultPortClosed());
|
||||
R_UNLESS(m_state == State::Normal, svc::ResultPortClosed());
|
||||
|
||||
this->server.EnqueueSession(session);
|
||||
m_server.EnqueueSession(session);
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
|
||||
@@ -79,43 +79,43 @@ namespace ams::kern {
|
||||
|
||||
void KProcess::Finalize() {
|
||||
/* Delete the process local region. */
|
||||
this->DeleteThreadLocalRegion(this->plr_address);
|
||||
this->DeleteThreadLocalRegion(m_plr_address);
|
||||
|
||||
/* Get the used memory size. */
|
||||
const size_t used_memory_size = this->GetUsedUserPhysicalMemorySize();
|
||||
|
||||
/* Finalize the page table. */
|
||||
this->page_table.Finalize();
|
||||
m_page_table.Finalize();
|
||||
|
||||
/* Free the system resource. */
|
||||
if (this->system_resource_address != Null<KVirtualAddress>) {
|
||||
if (m_system_resource_address != Null<KVirtualAddress>) {
|
||||
/* Check that we have no outstanding allocations. */
|
||||
MESOSPHERE_ABORT_UNLESS(this->memory_block_slab_manager.GetUsed() == 0);
|
||||
MESOSPHERE_ABORT_UNLESS(this->block_info_manager.GetUsed() == 0);
|
||||
MESOSPHERE_ABORT_UNLESS(this->page_table_manager.GetUsed() == 0);
|
||||
MESOSPHERE_ABORT_UNLESS(m_memory_block_slab_manager.GetUsed() == 0);
|
||||
MESOSPHERE_ABORT_UNLESS(m_block_info_manager.GetUsed() == 0);
|
||||
MESOSPHERE_ABORT_UNLESS(m_page_table_manager.GetUsed() == 0);
|
||||
|
||||
/* Free the memory. */
|
||||
KSystemControl::FreeSecureMemory(this->system_resource_address, this->system_resource_num_pages * PageSize, this->memory_pool);
|
||||
KSystemControl::FreeSecureMemory(m_system_resource_address, m_system_resource_num_pages * PageSize, m_memory_pool);
|
||||
|
||||
/* Clear our tracking variables. */
|
||||
this->system_resource_address = Null<KVirtualAddress>;
|
||||
this->system_resource_num_pages = 0;
|
||||
m_system_resource_address = Null<KVirtualAddress>;
|
||||
m_system_resource_num_pages = 0;
|
||||
|
||||
/* Finalize optimized memory. If memory wasn't optimized, this is a no-op. */
|
||||
Kernel::GetMemoryManager().FinalizeOptimizedMemory(this->GetId(), this->memory_pool);
|
||||
Kernel::GetMemoryManager().FinalizeOptimizedMemory(this->GetId(), m_memory_pool);
|
||||
}
|
||||
|
||||
/* Release memory to the resource limit. */
|
||||
if (this->resource_limit != nullptr) {
|
||||
MESOSPHERE_ABORT_UNLESS(used_memory_size >= this->memory_release_hint);
|
||||
this->resource_limit->Release(ams::svc::LimitableResource_PhysicalMemoryMax, used_memory_size, used_memory_size - this->memory_release_hint);
|
||||
this->resource_limit->Close();
|
||||
if (m_resource_limit != nullptr) {
|
||||
MESOSPHERE_ABORT_UNLESS(used_memory_size >= m_memory_release_hint);
|
||||
m_resource_limit->Release(ams::svc::LimitableResource_PhysicalMemoryMax, used_memory_size, used_memory_size - m_memory_release_hint);
|
||||
m_resource_limit->Close();
|
||||
}
|
||||
|
||||
/* Free all shared memory infos. */
|
||||
{
|
||||
auto it = this->shared_memory_list.begin();
|
||||
while (it != this->shared_memory_list.end()) {
|
||||
auto it = m_shared_memory_list.begin();
|
||||
while (it != m_shared_memory_list.end()) {
|
||||
KSharedMemoryInfo *info = std::addressof(*it);
|
||||
KSharedMemory *shmem = info->GetSharedMemory();
|
||||
|
||||
@@ -124,28 +124,28 @@ namespace ams::kern {
|
||||
}
|
||||
shmem->Close();
|
||||
|
||||
it = this->shared_memory_list.erase(it);
|
||||
it = m_shared_memory_list.erase(it);
|
||||
KSharedMemoryInfo::Free(info);
|
||||
}
|
||||
}
|
||||
|
||||
/* Close all references to our betas. */
|
||||
{
|
||||
auto it = this->beta_list.begin();
|
||||
while (it != this->beta_list.end()) {
|
||||
auto it = m_beta_list.begin();
|
||||
while (it != m_beta_list.end()) {
|
||||
KBeta *beta = std::addressof(*it);
|
||||
it = this->beta_list.erase(it);
|
||||
it = m_beta_list.erase(it);
|
||||
|
||||
beta->Close();
|
||||
}
|
||||
}
|
||||
|
||||
/* Our thread local page list must be empty at this point. */
|
||||
MESOSPHERE_ABORT_UNLESS(this->partially_used_tlp_tree.empty());
|
||||
MESOSPHERE_ABORT_UNLESS(this->fully_used_tlp_tree.empty());
|
||||
MESOSPHERE_ABORT_UNLESS(m_partially_used_tlp_tree.empty());
|
||||
MESOSPHERE_ABORT_UNLESS(m_fully_used_tlp_tree.empty());
|
||||
|
||||
/* Log that we finalized for debug. */
|
||||
MESOSPHERE_LOG("KProcess::Finalize() pid=%ld name=%-12s\n", this->process_id, this->name);
|
||||
MESOSPHERE_LOG("KProcess::Finalize() pid=%ld name=%-12s\n", m_process_id, m_name);
|
||||
|
||||
/* Perform inherited finalization. */
|
||||
KAutoObjectWithSlabHeapAndContainer<KProcess, KSynchronizationObject>::Finalize();
|
||||
@@ -153,40 +153,40 @@ namespace ams::kern {
|
||||
|
||||
Result KProcess::Initialize(const ams::svc::CreateProcessParameter ¶ms) {
|
||||
/* Validate that the intended kernel version is high enough for us to support. */
|
||||
R_UNLESS(this->capabilities.GetIntendedKernelVersion() >= ams::svc::RequiredKernelVersion, svc::ResultInvalidCombination());
|
||||
R_UNLESS(m_capabilities.GetIntendedKernelVersion() >= ams::svc::RequiredKernelVersion, svc::ResultInvalidCombination());
|
||||
|
||||
/* Validate that the intended kernel version isn't too high for us to support. */
|
||||
R_UNLESS(this->capabilities.GetIntendedKernelVersion() <= ams::svc::SupportedKernelVersion, svc::ResultInvalidCombination());
|
||||
R_UNLESS(m_capabilities.GetIntendedKernelVersion() <= ams::svc::SupportedKernelVersion, svc::ResultInvalidCombination());
|
||||
|
||||
/* Create and clear the process local region. */
|
||||
R_TRY(this->CreateThreadLocalRegion(std::addressof(this->plr_address)));
|
||||
this->plr_heap_address = this->GetThreadLocalRegionPointer(this->plr_address);
|
||||
std::memset(this->plr_heap_address, 0, ams::svc::ThreadLocalRegionSize);
|
||||
R_TRY(this->CreateThreadLocalRegion(std::addressof(m_plr_address)));
|
||||
m_plr_heap_address = this->GetThreadLocalRegionPointer(m_plr_address);
|
||||
std::memset(m_plr_heap_address, 0, ams::svc::ThreadLocalRegionSize);
|
||||
|
||||
/* Copy in the name from parameters. */
|
||||
static_assert(sizeof(params.name) < sizeof(this->name));
|
||||
std::memcpy(this->name, params.name, sizeof(params.name));
|
||||
this->name[sizeof(params.name)] = 0;
|
||||
static_assert(sizeof(params.name) < sizeof(m_name));
|
||||
std::memcpy(m_name, params.name, sizeof(params.name));
|
||||
m_name[sizeof(params.name)] = 0;
|
||||
|
||||
/* Set misc fields. */
|
||||
this->state = State_Created;
|
||||
this->main_thread_stack_size = 0;
|
||||
this->creation_time = KHardwareTimer::GetTick();
|
||||
this->used_kernel_memory_size = 0;
|
||||
this->ideal_core_id = 0;
|
||||
this->flags = params.flags;
|
||||
this->version = params.version;
|
||||
this->program_id = params.program_id;
|
||||
this->code_address = params.code_address;
|
||||
this->code_size = params.code_num_pages * PageSize;
|
||||
this->is_application = (params.flags & ams::svc::CreateProcessFlag_IsApplication);
|
||||
this->is_jit_debug = false;
|
||||
m_state = State_Created;
|
||||
m_main_thread_stack_size = 0;
|
||||
m_creation_time = KHardwareTimer::GetTick();
|
||||
m_used_kernel_memory_size = 0;
|
||||
m_ideal_core_id = 0;
|
||||
m_flags = params.flags;
|
||||
m_version = params.version;
|
||||
m_program_id = params.program_id;
|
||||
m_code_address = params.code_address;
|
||||
m_code_size = params.code_num_pages * PageSize;
|
||||
m_is_application = (params.flags & ams::svc::CreateProcessFlag_IsApplication);
|
||||
m_is_jit_debug = false;
|
||||
|
||||
/* Set thread fields. */
|
||||
for (size_t i = 0; i < cpu::NumCores; i++) {
|
||||
this->running_threads[i] = nullptr;
|
||||
this->running_thread_idle_counts[i] = 0;
|
||||
this->pinned_threads[i] = nullptr;
|
||||
m_running_threads[i] = nullptr;
|
||||
m_running_thread_idle_counts[i] = 0;
|
||||
m_pinned_threads[i] = nullptr;
|
||||
}
|
||||
|
||||
/* Set max memory based on address space type. */
|
||||
@@ -194,36 +194,36 @@ namespace ams::kern {
|
||||
case ams::svc::CreateProcessFlag_AddressSpace32Bit:
|
||||
case ams::svc::CreateProcessFlag_AddressSpace64BitDeprecated:
|
||||
case ams::svc::CreateProcessFlag_AddressSpace64Bit:
|
||||
this->max_process_memory = this->page_table.GetHeapRegionSize();
|
||||
m_max_process_memory = m_page_table.GetHeapRegionSize();
|
||||
break;
|
||||
case ams::svc::CreateProcessFlag_AddressSpace32BitWithoutAlias:
|
||||
this->max_process_memory = this->page_table.GetHeapRegionSize() + this->page_table.GetAliasRegionSize();
|
||||
m_max_process_memory = m_page_table.GetHeapRegionSize() + m_page_table.GetAliasRegionSize();
|
||||
break;
|
||||
MESOSPHERE_UNREACHABLE_DEFAULT_CASE();
|
||||
}
|
||||
|
||||
/* Generate random entropy. */
|
||||
KSystemControl::GenerateRandomBytes(this->entropy, sizeof(this->entropy));
|
||||
KSystemControl::GenerateRandomBytes(m_entropy, sizeof(m_entropy));
|
||||
|
||||
/* Clear remaining fields. */
|
||||
this->num_threads = 0;
|
||||
this->peak_num_threads = 0;
|
||||
this->num_created_threads = 0;
|
||||
this->num_process_switches = 0;
|
||||
this->num_thread_switches = 0;
|
||||
this->num_fpu_switches = 0;
|
||||
this->num_supervisor_calls = 0;
|
||||
this->num_ipc_messages = 0;
|
||||
m_num_threads = 0;
|
||||
m_peak_num_threads = 0;
|
||||
m_num_created_threads = 0;
|
||||
m_num_process_switches = 0;
|
||||
m_num_thread_switches = 0;
|
||||
m_num_fpu_switches = 0;
|
||||
m_num_supervisor_calls = 0;
|
||||
m_num_ipc_messages = 0;
|
||||
|
||||
this->is_signaled = false;
|
||||
this->attached_object = nullptr;
|
||||
this->exception_thread = nullptr;
|
||||
this->is_suspended = false;
|
||||
this->memory_release_hint = 0;
|
||||
this->schedule_count = 0;
|
||||
m_is_signaled = false;
|
||||
m_attached_object = nullptr;
|
||||
m_exception_thread = nullptr;
|
||||
m_is_suspended = false;
|
||||
m_memory_release_hint = 0;
|
||||
m_schedule_count = 0;
|
||||
|
||||
/* We're initialized! */
|
||||
this->is_initialized = true;
|
||||
m_is_initialized = true;
|
||||
|
||||
return ResultSuccess();
|
||||
}
|
||||
@@ -234,10 +234,10 @@ namespace ams::kern {
|
||||
MESOSPHERE_ABORT_UNLESS((params.code_num_pages * PageSize) / PageSize == static_cast<size_t>(params.code_num_pages));
|
||||
|
||||
/* Set members. */
|
||||
this->memory_pool = pool;
|
||||
this->resource_limit = res_limit;
|
||||
this->system_resource_address = Null<KVirtualAddress>;
|
||||
this->system_resource_num_pages = 0;
|
||||
m_memory_pool = pool;
|
||||
m_resource_limit = res_limit;
|
||||
m_system_resource_address = Null<KVirtualAddress>;
|
||||
m_system_resource_num_pages = 0;
|
||||
|
||||
/* Setup page table. */
|
||||
/* NOTE: Nintendo passes process ID despite not having set it yet. */
|
||||
@@ -250,29 +250,29 @@ namespace ams::kern {
|
||||
auto *mem_block_manager = std::addressof(is_app ? Kernel::GetApplicationMemoryBlockManager() : Kernel::GetSystemMemoryBlockManager());
|
||||
auto *block_info_manager = std::addressof(Kernel::GetBlockInfoManager());
|
||||
auto *pt_manager = std::addressof(Kernel::GetPageTableManager());
|
||||
R_TRY(this->page_table.Initialize(this->process_id, as_type, enable_aslr, enable_das_merge, !enable_aslr, pool, params.code_address, params.code_num_pages * PageSize, mem_block_manager, block_info_manager, pt_manager));
|
||||
R_TRY(m_page_table.Initialize(m_process_id, as_type, enable_aslr, enable_das_merge, !enable_aslr, pool, params.code_address, params.code_num_pages * PageSize, mem_block_manager, block_info_manager, pt_manager));
|
||||
}
|
||||
auto pt_guard = SCOPE_GUARD { this->page_table.Finalize(); };
|
||||
auto pt_guard = SCOPE_GUARD { m_page_table.Finalize(); };
|
||||
|
||||
/* Ensure we can insert the code region. */
|
||||
R_UNLESS(this->page_table.CanContain(params.code_address, params.code_num_pages * PageSize, KMemoryState_Code), svc::ResultInvalidMemoryRegion());
|
||||
R_UNLESS(m_page_table.CanContain(params.code_address, params.code_num_pages * PageSize, KMemoryState_Code), svc::ResultInvalidMemoryRegion());
|
||||
|
||||
/* Map the code region. */
|
||||
R_TRY(this->page_table.MapPageGroup(params.code_address, pg, KMemoryState_Code, KMemoryPermission_KernelRead));
|
||||
R_TRY(m_page_table.MapPageGroup(params.code_address, pg, KMemoryState_Code, KMemoryPermission_KernelRead));
|
||||
|
||||
/* Initialize capabilities. */
|
||||
R_TRY(this->capabilities.Initialize(caps, num_caps, std::addressof(this->page_table)));
|
||||
R_TRY(m_capabilities.Initialize(caps, num_caps, std::addressof(m_page_table)));
|
||||
|
||||
/* Initialize the process id. */
|
||||
this->process_id = g_initial_process_id++;
|
||||
MESOSPHERE_ABORT_UNLESS(InitialProcessIdMin <= this->process_id);
|
||||
MESOSPHERE_ABORT_UNLESS(this->process_id <= InitialProcessIdMax);
|
||||
m_process_id = g_initial_process_id++;
|
||||
MESOSPHERE_ABORT_UNLESS(InitialProcessIdMin <= m_process_id);
|
||||
MESOSPHERE_ABORT_UNLESS(m_process_id <= InitialProcessIdMax);
|
||||
|
||||
/* Initialize the rest of the process. */
|
||||
R_TRY(this->Initialize(params));
|
||||
|
||||
/* Open a reference to the resource limit. */
|
||||
this->resource_limit->Open();
|
||||
m_resource_limit->Open();
|
||||
|
||||
/* We succeeded! */
|
||||
pt_guard.Cancel();
|
||||
@@ -284,8 +284,8 @@ namespace ams::kern {
|
||||
MESOSPHERE_ASSERT(res_limit != nullptr);
|
||||
|
||||
/* Set pool and resource limit. */
|
||||
this->memory_pool = pool;
|
||||
this->resource_limit = res_limit;
|
||||
m_memory_pool = pool;
|
||||
m_resource_limit = res_limit;
|
||||
|
||||
/* Get the memory sizes. */
|
||||
const size_t code_num_pages = params.code_num_pages;
|
||||
@@ -302,27 +302,27 @@ namespace ams::kern {
|
||||
KBlockInfoManager *block_info_manager;
|
||||
KPageTableManager *pt_manager;
|
||||
|
||||
this->system_resource_address = Null<KVirtualAddress>;
|
||||
this->system_resource_num_pages = 0;
|
||||
m_system_resource_address = Null<KVirtualAddress>;
|
||||
m_system_resource_num_pages = 0;
|
||||
|
||||
if (system_resource_num_pages != 0) {
|
||||
/* Allocate secure memory. */
|
||||
R_TRY(KSystemControl::AllocateSecureMemory(std::addressof(this->system_resource_address), system_resource_size, pool));
|
||||
R_TRY(KSystemControl::AllocateSecureMemory(std::addressof(m_system_resource_address), system_resource_size, pool));
|
||||
|
||||
/* Set the number of system resource pages. */
|
||||
MESOSPHERE_ASSERT(this->system_resource_address != Null<KVirtualAddress>);
|
||||
this->system_resource_num_pages = system_resource_num_pages;
|
||||
MESOSPHERE_ASSERT(m_system_resource_address != Null<KVirtualAddress>);
|
||||
m_system_resource_num_pages = system_resource_num_pages;
|
||||
|
||||
/* Initialize managers. */
|
||||
const size_t rc_size = util::AlignUp(KPageTableManager::CalculateReferenceCountSize(system_resource_size), PageSize);
|
||||
this->dynamic_page_manager.Initialize(this->system_resource_address + rc_size, system_resource_size - rc_size);
|
||||
this->page_table_manager.Initialize(std::addressof(this->dynamic_page_manager), GetPointer<KPageTableManager::RefCount>(this->system_resource_address));
|
||||
this->memory_block_slab_manager.Initialize(std::addressof(this->dynamic_page_manager));
|
||||
this->block_info_manager.Initialize(std::addressof(this->dynamic_page_manager));
|
||||
m_dynamic_page_manager.Initialize(m_system_resource_address + rc_size, system_resource_size - rc_size);
|
||||
m_page_table_manager.Initialize(std::addressof(m_dynamic_page_manager), GetPointer<KPageTableManager::RefCount>(m_system_resource_address));
|
||||
m_memory_block_slab_manager.Initialize(std::addressof(m_dynamic_page_manager));
|
||||
m_block_info_manager.Initialize(std::addressof(m_dynamic_page_manager));
|
||||
|
||||
mem_block_manager = std::addressof(this->memory_block_slab_manager);
|
||||
block_info_manager = std::addressof(this->block_info_manager);
|
||||
pt_manager = std::addressof(this->page_table_manager);
|
||||
mem_block_manager = std::addressof(m_memory_block_slab_manager);
|
||||
block_info_manager = std::addressof(m_block_info_manager);
|
||||
pt_manager = std::addressof(m_page_table_manager);
|
||||
} else {
|
||||
const bool is_app = (params.flags & ams::svc::CreateProcessFlag_IsApplication);
|
||||
mem_block_manager = std::addressof(is_app ? Kernel::GetApplicationMemoryBlockManager() : Kernel::GetSystemMemoryBlockManager());
|
||||
@@ -332,18 +332,18 @@ namespace ams::kern {
|
||||
|
||||
/* Ensure we don't leak any secure memory we allocated. */
|
||||
auto sys_resource_guard = SCOPE_GUARD {
|
||||
if (this->system_resource_address != Null<KVirtualAddress>) {
|
||||
if (m_system_resource_address != Null<KVirtualAddress>) {
|
||||
/* Check that we have no outstanding allocations. */
|
||||
MESOSPHERE_ABORT_UNLESS(this->memory_block_slab_manager.GetUsed() == 0);
|
||||
MESOSPHERE_ABORT_UNLESS(this->block_info_manager.GetUsed() == 0);
|
||||
MESOSPHERE_ABORT_UNLESS(this->page_table_manager.GetUsed() == 0);
|
||||
MESOSPHERE_ABORT_UNLESS(m_memory_block_slab_manager.GetUsed() == 0);
|
||||
MESOSPHERE_ABORT_UNLESS(m_block_info_manager.GetUsed() == 0);
|
||||
MESOSPHERE_ABORT_UNLESS(m_page_table_manager.GetUsed() == 0);
|
||||
|
||||
/* Free the memory. */
|
||||
KSystemControl::FreeSecureMemory(this->system_resource_address, system_resource_size, pool);
|
||||
KSystemControl::FreeSecureMemory(m_system_resource_address, system_resource_size, pool);
|
||||
|
||||
/* Clear our tracking variables. */
|
||||
this->system_resource_address = Null<KVirtualAddress>;
|
||||
this->system_resource_num_pages = 0;
|
||||
m_system_resource_address = Null<KVirtualAddress>;
|
||||
m_system_resource_num_pages = 0;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -354,34 +354,34 @@ namespace ams::kern {
|
||||
const auto as_type = static_cast<ams::svc::CreateProcessFlag>(params.flags & ams::svc::CreateProcessFlag_AddressSpaceMask);
|
||||
const bool enable_aslr = (params.flags & ams::svc::CreateProcessFlag_EnableAslr) != 0;
|
||||
const bool enable_das_merge = (params.flags & ams::svc::CreateProcessFlag_DisableDeviceAddressSpaceMerge) == 0;
|
||||
R_TRY(this->page_table.Initialize(this->process_id, as_type, enable_aslr, enable_das_merge, !enable_aslr, pool, params.code_address, code_size, mem_block_manager, block_info_manager, pt_manager));
|
||||
R_TRY(m_page_table.Initialize(m_process_id, as_type, enable_aslr, enable_das_merge, !enable_aslr, pool, params.code_address, code_size, mem_block_manager, block_info_manager, pt_manager));
|
||||
}
|
||||
auto pt_guard = SCOPE_GUARD { this->page_table.Finalize(); };
|
||||
auto pt_guard = SCOPE_GUARD { m_page_table.Finalize(); };
|
||||
|
||||
/* Ensure we can insert the code region. */
|
||||
R_UNLESS(this->page_table.CanContain(params.code_address, code_size, KMemoryState_Code), svc::ResultInvalidMemoryRegion());
|
||||
R_UNLESS(m_page_table.CanContain(params.code_address, code_size, KMemoryState_Code), svc::ResultInvalidMemoryRegion());
|
||||
|
||||
/* Map the code region. */
|
||||
R_TRY(this->page_table.MapPages(params.code_address, code_num_pages, KMemoryState_Code, static_cast<KMemoryPermission>(KMemoryPermission_KernelRead | KMemoryPermission_NotMapped)));
|
||||
R_TRY(m_page_table.MapPages(params.code_address, code_num_pages, KMemoryState_Code, static_cast<KMemoryPermission>(KMemoryPermission_KernelRead | KMemoryPermission_NotMapped)));
|
||||
|
||||
/* Initialize capabilities. */
|
||||
R_TRY(this->capabilities.Initialize(user_caps, num_caps, std::addressof(this->page_table)));
|
||||
R_TRY(m_capabilities.Initialize(user_caps, num_caps, std::addressof(m_page_table)));
|
||||
|
||||
/* Initialize the process id. */
|
||||
this->process_id = g_process_id++;
|
||||
MESOSPHERE_ABORT_UNLESS(ProcessIdMin <= this->process_id);
|
||||
MESOSPHERE_ABORT_UNLESS(this->process_id <= ProcessIdMax);
|
||||
m_process_id = g_process_id++;
|
||||
MESOSPHERE_ABORT_UNLESS(ProcessIdMin <= m_process_id);
|
||||
MESOSPHERE_ABORT_UNLESS(m_process_id <= ProcessIdMax);
|
||||
|
||||
/* If we should optimize memory allocations, do so. */
|
||||
if (this->system_resource_address != Null<KVirtualAddress> && (params.flags & ams::svc::CreateProcessFlag_OptimizeMemoryAllocation) != 0) {
|
||||
R_TRY(Kernel::GetMemoryManager().InitializeOptimizedMemory(this->process_id, pool));
|
||||
if (m_system_resource_address != Null<KVirtualAddress> && (params.flags & ams::svc::CreateProcessFlag_OptimizeMemoryAllocation) != 0) {
|
||||
R_TRY(Kernel::GetMemoryManager().InitializeOptimizedMemory(m_process_id, pool));
|
||||
}
|
||||
|
||||
/* Initialize the rest of the process. */
|
||||
R_TRY(this->Initialize(params));
|
||||
|
||||
/* Open a reference to the resource limit. */
|
||||
this->resource_limit->Open();
|
||||
m_resource_limit->Open();
|
||||
|
||||
/* We succeeded, so commit our memory reservation and cancel our guards. */
|
||||
sys_resource_guard.Cancel();
|
||||
@@ -407,14 +407,14 @@ namespace ams::kern {
|
||||
TerminateChildren(this, GetCurrentThreadPointer());
|
||||
|
||||
/* Finalize the handle tahble. */
|
||||
this->handle_table.Finalize();
|
||||
m_handle_table.Finalize();
|
||||
}
|
||||
|
||||
void KProcess::FinishTermination() {
|
||||
/* Release resource limit hint. */
|
||||
if (this->resource_limit != nullptr) {
|
||||
this->memory_release_hint = this->GetUsedUserPhysicalMemorySize();
|
||||
this->resource_limit->Release(ams::svc::LimitableResource_PhysicalMemoryMax, 0, this->memory_release_hint);
|
||||
if (m_resource_limit != nullptr) {
|
||||
m_memory_release_hint = this->GetUsedUserPhysicalMemorySize();
|
||||
m_resource_limit->Release(ams::svc::LimitableResource_PhysicalMemoryMax, 0, m_memory_release_hint);
|
||||
}
|
||||
|
||||
/* Change state. */
|
||||
@@ -433,14 +433,14 @@ namespace ams::kern {
|
||||
/* Determine whether we need to start terminating */
|
||||
bool needs_terminate = false;
|
||||
{
|
||||
KScopedLightLock lk(this->state_lock);
|
||||
KScopedLightLock lk(m_state_lock);
|
||||
KScopedSchedulerLock sl;
|
||||
|
||||
MESOSPHERE_ASSERT(this->state != State_Created);
|
||||
MESOSPHERE_ASSERT(this->state != State_CreatedAttached);
|
||||
MESOSPHERE_ASSERT(this->state != State_Crashed);
|
||||
MESOSPHERE_ASSERT(this->state != State_Terminated);
|
||||
if (this->state == State_Running || this->state == State_RunningAttached || this->state == State_DebugBreak) {
|
||||
MESOSPHERE_ASSERT(m_state != State_Created);
|
||||
MESOSPHERE_ASSERT(m_state != State_CreatedAttached);
|
||||
MESOSPHERE_ASSERT(m_state != State_Crashed);
|
||||
MESOSPHERE_ASSERT(m_state != State_Terminated);
|
||||
if (m_state == State_Running || m_state == State_RunningAttached || m_state == State_DebugBreak) {
|
||||
this->ChangeState(State_Terminating);
|
||||
needs_terminate = true;
|
||||
}
|
||||
@@ -451,7 +451,7 @@ namespace ams::kern {
|
||||
this->StartTermination();
|
||||
|
||||
/* Note for debug that we're exiting the process. */
|
||||
MESOSPHERE_LOG("KProcess::Exit() pid=%ld name=%-12s\n", this->process_id, this->name);
|
||||
MESOSPHERE_LOG("KProcess::Exit() pid=%ld name=%-12s\n", m_process_id, m_name);
|
||||
|
||||
/* Register the process as a work task. */
|
||||
KWorkerTaskManager::AddTask(KWorkerTaskManager::WorkerType_Exit, this);
|
||||
@@ -468,15 +468,15 @@ namespace ams::kern {
|
||||
/* Determine whether we need to start terminating */
|
||||
bool needs_terminate = false;
|
||||
{
|
||||
KScopedLightLock lk(this->state_lock);
|
||||
KScopedLightLock lk(m_state_lock);
|
||||
|
||||
/* Check whether we're allowed to terminate. */
|
||||
R_UNLESS(this->state != State_Created, svc::ResultInvalidState());
|
||||
R_UNLESS(this->state != State_CreatedAttached, svc::ResultInvalidState());
|
||||
R_UNLESS(m_state != State_Created, svc::ResultInvalidState());
|
||||
R_UNLESS(m_state != State_CreatedAttached, svc::ResultInvalidState());
|
||||
|
||||
KScopedSchedulerLock sl;
|
||||
|
||||
if (this->state == State_Running || this->state == State_RunningAttached || this->state == State_Crashed || this->state == State_DebugBreak) {
|
||||
if (m_state == State_Running || m_state == State_RunningAttached || m_state == State_Crashed || m_state == State_DebugBreak) {
|
||||
this->ChangeState(State_Terminating);
|
||||
needs_terminate = true;
|
||||
}
|
||||
@@ -488,7 +488,7 @@ namespace ams::kern {
|
||||
this->StartTermination();
|
||||
|
||||
/* Note for debug that we're terminating the process. */
|
||||
MESOSPHERE_LOG("KProcess::Terminate() pid=%ld name=%-12s\n", this->process_id, this->name);
|
||||
MESOSPHERE_LOG("KProcess::Terminate() pid=%ld name=%-12s\n", m_process_id, m_name);
|
||||
|
||||
/* Call the debug callback. */
|
||||
KDebug::OnTerminateProcess(this);
|
||||
@@ -502,14 +502,14 @@ namespace ams::kern {
|
||||
|
||||
Result KProcess::AddSharedMemory(KSharedMemory *shmem, KProcessAddress address, size_t size) {
|
||||
/* Lock ourselves, to prevent concurrent access. */
|
||||
KScopedLightLock lk(this->state_lock);
|
||||
KScopedLightLock lk(m_state_lock);
|
||||
|
||||
/* Address and size parameters aren't used. */
|
||||
MESOSPHERE_UNUSED(address, size);
|
||||
|
||||
/* Try to find an existing info for the memory. */
|
||||
KSharedMemoryInfo *info = nullptr;
|
||||
for (auto it = this->shared_memory_list.begin(); it != this->shared_memory_list.end(); ++it) {
|
||||
for (auto it = m_shared_memory_list.begin(); it != m_shared_memory_list.end(); ++it) {
|
||||
if (it->GetSharedMemory() == shmem) {
|
||||
info = std::addressof(*it);
|
||||
break;
|
||||
@@ -524,7 +524,7 @@ namespace ams::kern {
|
||||
|
||||
/* Initialize the info and add it to our list. */
|
||||
info->Initialize(shmem);
|
||||
this->shared_memory_list.push_back(*info);
|
||||
m_shared_memory_list.push_back(*info);
|
||||
}
|
||||
|
||||
/* Open a reference to the shared memory and its info. */
|
||||
@@ -536,15 +536,15 @@ namespace ams::kern {
|
||||
|
||||
void KProcess::RemoveSharedMemory(KSharedMemory *shmem, KProcessAddress address, size_t size) {
|
||||
/* Lock ourselves, to prevent concurrent access. */
|
||||
KScopedLightLock lk(this->state_lock);
|
||||
KScopedLightLock lk(m_state_lock);
|
||||
|
||||
/* Address and size parameters aren't used. */
|
||||
MESOSPHERE_UNUSED(address, size);
|
||||
|
||||
/* Find an existing info for the memory. */
|
||||
KSharedMemoryInfo *info = nullptr;
|
||||
auto it = this->shared_memory_list.begin();
|
||||
for (/* ... */; it != this->shared_memory_list.end(); ++it) {
|
||||
auto it = m_shared_memory_list.begin();
|
||||
for (/* ... */; it != m_shared_memory_list.end(); ++it) {
|
||||
if (it->GetSharedMemory() == shmem) {
|
||||
info = std::addressof(*it);
|
||||
break;
|
||||
@@ -554,7 +554,7 @@ namespace ams::kern {
|
||||
|
||||
/* Close a reference to the info and its memory. */
|
||||
if (info->Close()) {
|
||||
this->shared_memory_list.erase(it);
|
||||
m_shared_memory_list.erase(it);
|
||||
KSharedMemoryInfo::Free(info);
|
||||
}
|
||||
|
||||
@@ -569,14 +569,14 @@ namespace ams::kern {
|
||||
{
|
||||
KScopedSchedulerLock sl;
|
||||
|
||||
if (auto it = this->partially_used_tlp_tree.begin(); it != partially_used_tlp_tree.end()) {
|
||||
if (auto it = m_partially_used_tlp_tree.begin(); it != m_partially_used_tlp_tree.end()) {
|
||||
tlr = it->Reserve();
|
||||
MESOSPHERE_ABORT_UNLESS(tlr != Null<KProcessAddress>);
|
||||
|
||||
if (it->IsAllUsed()) {
|
||||
tlp = std::addressof(*it);
|
||||
this->partially_used_tlp_tree.erase(it);
|
||||
this->fully_used_tlp_tree.insert(*tlp);
|
||||
m_partially_used_tlp_tree.erase(it);
|
||||
m_fully_used_tlp_tree.insert(*tlp);
|
||||
}
|
||||
|
||||
*out = tlr;
|
||||
@@ -600,9 +600,9 @@ namespace ams::kern {
|
||||
{
|
||||
KScopedSchedulerLock sl;
|
||||
if (tlp->IsAllUsed()) {
|
||||
this->fully_used_tlp_tree.insert(*tlp);
|
||||
m_fully_used_tlp_tree.insert(*tlp);
|
||||
} else {
|
||||
this->partially_used_tlp_tree.insert(*tlp);
|
||||
m_partially_used_tlp_tree.insert(*tlp);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -620,22 +620,22 @@ namespace ams::kern {
|
||||
KScopedSchedulerLock sl;
|
||||
|
||||
/* Try to find the page in the partially used list. */
|
||||
auto it = this->partially_used_tlp_tree.find(KThreadLocalPage(util::AlignDown(GetInteger(addr), PageSize)));
|
||||
if (it == this->partially_used_tlp_tree.end()) {
|
||||
auto it = m_partially_used_tlp_tree.find(KThreadLocalPage(util::AlignDown(GetInteger(addr), PageSize)));
|
||||
if (it == m_partially_used_tlp_tree.end()) {
|
||||
/* If we don't find it, it has to be in the fully used list. */
|
||||
it = this->fully_used_tlp_tree.find(KThreadLocalPage(util::AlignDown(GetInteger(addr), PageSize)));
|
||||
R_UNLESS(it != this->fully_used_tlp_tree.end(), svc::ResultInvalidAddress());
|
||||
it = m_fully_used_tlp_tree.find(KThreadLocalPage(util::AlignDown(GetInteger(addr), PageSize)));
|
||||
R_UNLESS(it != m_fully_used_tlp_tree.end(), svc::ResultInvalidAddress());
|
||||
|
||||
/* Release the region. */
|
||||
it->Release(addr);
|
||||
|
||||
/* Move the page out of the fully used list. */
|
||||
KThreadLocalPage *tlp = std::addressof(*it);
|
||||
this->fully_used_tlp_tree.erase(it);
|
||||
m_fully_used_tlp_tree.erase(it);
|
||||
if (tlp->IsAllFree()) {
|
||||
page_to_free = tlp;
|
||||
} else {
|
||||
this->partially_used_tlp_tree.insert(*tlp);
|
||||
m_partially_used_tlp_tree.insert(*tlp);
|
||||
}
|
||||
} else {
|
||||
/* Release the region. */
|
||||
@@ -644,7 +644,7 @@ namespace ams::kern {
|
||||
/* Handle the all-free case. */
|
||||
KThreadLocalPage *tlp = std::addressof(*it);
|
||||
if (tlp->IsAllFree()) {
|
||||
this->partially_used_tlp_tree.erase(it);
|
||||
m_partially_used_tlp_tree.erase(it);
|
||||
page_to_free = tlp;
|
||||
}
|
||||
}
|
||||
@@ -664,9 +664,9 @@ namespace ams::kern {
|
||||
KThreadLocalPage *tlp = nullptr;
|
||||
{
|
||||
KScopedSchedulerLock sl;
|
||||
if (auto it = this->partially_used_tlp_tree.find(KThreadLocalPage(util::AlignDown(GetInteger(addr), PageSize))); it != this->partially_used_tlp_tree.end()) {
|
||||
if (auto it = m_partially_used_tlp_tree.find(KThreadLocalPage(util::AlignDown(GetInteger(addr), PageSize))); it != m_partially_used_tlp_tree.end()) {
|
||||
tlp = std::addressof(*it);
|
||||
} else if (auto it = this->fully_used_tlp_tree.find(KThreadLocalPage(util::AlignDown(GetInteger(addr), PageSize))); it != this->fully_used_tlp_tree.end()) {
|
||||
} else if (auto it = m_fully_used_tlp_tree.find(KThreadLocalPage(util::AlignDown(GetInteger(addr), PageSize))); it != m_fully_used_tlp_tree.end()) {
|
||||
tlp = std::addressof(*it);
|
||||
} else {
|
||||
return nullptr;
|
||||
@@ -704,18 +704,18 @@ namespace ams::kern {
|
||||
}
|
||||
|
||||
void KProcess::IncrementThreadCount() {
|
||||
MESOSPHERE_ASSERT(this->num_threads >= 0);
|
||||
++this->num_created_threads;
|
||||
MESOSPHERE_ASSERT(m_num_threads >= 0);
|
||||
++m_num_created_threads;
|
||||
|
||||
if (const auto count = ++this->num_threads; count > this->peak_num_threads) {
|
||||
this->peak_num_threads = count;
|
||||
if (const auto count = ++m_num_threads; count > m_peak_num_threads) {
|
||||
m_peak_num_threads = count;
|
||||
}
|
||||
}
|
||||
|
||||
void KProcess::DecrementThreadCount() {
|
||||
MESOSPHERE_ASSERT(this->num_threads > 0);
|
||||
MESOSPHERE_ASSERT(m_num_threads > 0);
|
||||
|
||||
if (const auto count = --this->num_threads; count == 0) {
|
||||
if (const auto count = --m_num_threads; count == 0) {
|
||||
this->Terminate();
|
||||
}
|
||||
}
|
||||
@@ -726,8 +726,8 @@ namespace ams::kern {
|
||||
MESOSPHERE_ASSERT(this == cur_thread->GetOwnerProcess());
|
||||
|
||||
/* Try to claim the exception thread. */
|
||||
if (this->exception_thread != cur_thread) {
|
||||
const uintptr_t address_key = reinterpret_cast<uintptr_t>(std::addressof(this->exception_thread));
|
||||
if (m_exception_thread != cur_thread) {
|
||||
const uintptr_t address_key = reinterpret_cast<uintptr_t>(std::addressof(m_exception_thread));
|
||||
while (true) {
|
||||
{
|
||||
KScopedSchedulerLock sl;
|
||||
@@ -738,14 +738,14 @@ namespace ams::kern {
|
||||
}
|
||||
|
||||
/* If we have no exception thread, we succeeded. */
|
||||
if (this->exception_thread == nullptr) {
|
||||
this->exception_thread = cur_thread;
|
||||
if (m_exception_thread == nullptr) {
|
||||
m_exception_thread = cur_thread;
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Otherwise, wait for us to not have an exception thread. */
|
||||
cur_thread->SetAddressKey(address_key);
|
||||
this->exception_thread->AddWaiter(cur_thread);
|
||||
m_exception_thread->AddWaiter(cur_thread);
|
||||
if (cur_thread->GetState() == KThread::ThreadState_Runnable) {
|
||||
cur_thread->SetState(KThread::ThreadState_Waiting);
|
||||
} else {
|
||||
@@ -774,12 +774,12 @@ namespace ams::kern {
|
||||
bool KProcess::ReleaseUserException(KThread *thread) {
|
||||
KScopedSchedulerLock sl;
|
||||
|
||||
if (this->exception_thread == thread) {
|
||||
this->exception_thread = nullptr;
|
||||
if (m_exception_thread == thread) {
|
||||
m_exception_thread = nullptr;
|
||||
|
||||
/* Remove waiter thread. */
|
||||
s32 num_waiters;
|
||||
KThread *next = thread->RemoveWaiterByKey(std::addressof(num_waiters), reinterpret_cast<uintptr_t>(std::addressof(this->exception_thread)));
|
||||
KThread *next = thread->RemoveWaiterByKey(std::addressof(num_waiters), reinterpret_cast<uintptr_t>(std::addressof(m_exception_thread)));
|
||||
if (next != nullptr) {
|
||||
if (next->GetState() == KThread::ThreadState_Waiting) {
|
||||
next->SetState(KThread::ThreadState_Runnable);
|
||||
@@ -795,30 +795,30 @@ namespace ams::kern {
|
||||
}
|
||||
|
||||
void KProcess::RegisterThread(KThread *thread) {
|
||||
KScopedLightLock lk(this->list_lock);
|
||||
KScopedLightLock lk(m_list_lock);
|
||||
|
||||
this->thread_list.push_back(*thread);
|
||||
m_thread_list.push_back(*thread);
|
||||
}
|
||||
|
||||
void KProcess::UnregisterThread(KThread *thread) {
|
||||
KScopedLightLock lk(this->list_lock);
|
||||
KScopedLightLock lk(m_list_lock);
|
||||
|
||||
this->thread_list.erase(this->thread_list.iterator_to(*thread));
|
||||
m_thread_list.erase(m_thread_list.iterator_to(*thread));
|
||||
}
|
||||
|
||||
size_t KProcess::GetUsedUserPhysicalMemorySize() const {
|
||||
const size_t norm_size = this->page_table.GetNormalMemorySize();
|
||||
const size_t other_size = this->code_size + this->main_thread_stack_size;
|
||||
const size_t sec_size = KSystemControl::CalculateRequiredSecureMemorySize(this->system_resource_num_pages * PageSize, this->memory_pool);
|
||||
const size_t norm_size = m_page_table.GetNormalMemorySize();
|
||||
const size_t other_size = m_code_size + m_main_thread_stack_size;
|
||||
const size_t sec_size = KSystemControl::CalculateRequiredSecureMemorySize(m_system_resource_num_pages * PageSize, m_memory_pool);
|
||||
|
||||
return norm_size + other_size + sec_size;
|
||||
}
|
||||
|
||||
size_t KProcess::GetTotalUserPhysicalMemorySize() const {
|
||||
/* Get the amount of free and used size. */
|
||||
const size_t free_size = this->resource_limit->GetFreeValue(ams::svc::LimitableResource_PhysicalMemoryMax);
|
||||
const size_t free_size = m_resource_limit->GetFreeValue(ams::svc::LimitableResource_PhysicalMemoryMax);
|
||||
const size_t used_size = this->GetUsedNonSystemUserPhysicalMemorySize();
|
||||
const size_t max_size = this->max_process_memory;
|
||||
const size_t max_size = m_max_process_memory;
|
||||
|
||||
if (used_size + free_size > max_size) {
|
||||
return max_size;
|
||||
@@ -828,18 +828,18 @@ namespace ams::kern {
|
||||
}
|
||||
|
||||
size_t KProcess::GetUsedNonSystemUserPhysicalMemorySize() const {
|
||||
const size_t norm_size = this->page_table.GetNormalMemorySize();
|
||||
const size_t other_size = this->code_size + this->main_thread_stack_size;
|
||||
const size_t norm_size = m_page_table.GetNormalMemorySize();
|
||||
const size_t other_size = m_code_size + m_main_thread_stack_size;
|
||||
|
||||
return norm_size + other_size;
|
||||
}
|
||||
|
||||
size_t KProcess::GetTotalNonSystemUserPhysicalMemorySize() const {
|
||||
/* Get the amount of free and used size. */
|
||||
const size_t free_size = this->resource_limit->GetFreeValue(ams::svc::LimitableResource_PhysicalMemoryMax);
|
||||
const size_t free_size = m_resource_limit->GetFreeValue(ams::svc::LimitableResource_PhysicalMemoryMax);
|
||||
const size_t used_size = this->GetUsedUserPhysicalMemorySize();
|
||||
const size_t sec_size = KSystemControl::CalculateRequiredSecureMemorySize(this->system_resource_num_pages * PageSize, this->memory_pool);
|
||||
const size_t max_size = this->max_process_memory;
|
||||
const size_t sec_size = KSystemControl::CalculateRequiredSecureMemorySize(m_system_resource_num_pages * PageSize, m_memory_pool);
|
||||
const size_t max_size = m_max_process_memory;
|
||||
|
||||
if (used_size + free_size > max_size) {
|
||||
return max_size - sec_size;
|
||||
@@ -852,10 +852,10 @@ namespace ams::kern {
|
||||
MESOSPHERE_ASSERT_THIS();
|
||||
|
||||
/* Lock ourselves, to prevent concurrent access. */
|
||||
KScopedLightLock lk(this->state_lock);
|
||||
KScopedLightLock lk(m_state_lock);
|
||||
|
||||
/* Validate that we're in a state where we can initialize. */
|
||||
const auto state = this->state;
|
||||
const auto state = m_state;
|
||||
R_UNLESS(state == State_Created || state == State_CreatedAttached, svc::ResultInvalidState());
|
||||
|
||||
/* Place a tentative reservation of a thread for this process. */
|
||||
@@ -863,12 +863,12 @@ namespace ams::kern {
|
||||
R_UNLESS(thread_reservation.Succeeded(), svc::ResultLimitReached());
|
||||
|
||||
/* Ensure that we haven't already allocated stack. */
|
||||
MESOSPHERE_ABORT_UNLESS(this->main_thread_stack_size == 0);
|
||||
MESOSPHERE_ABORT_UNLESS(m_main_thread_stack_size == 0);
|
||||
|
||||
/* Ensure that we're allocating a valid stack. */
|
||||
stack_size = util::AlignUp(stack_size, PageSize);
|
||||
R_UNLESS(stack_size + this->code_size <= this->max_process_memory, svc::ResultOutOfMemory());
|
||||
R_UNLESS(stack_size + this->code_size >= this->code_size, svc::ResultOutOfMemory());
|
||||
R_UNLESS(stack_size + m_code_size <= m_max_process_memory, svc::ResultOutOfMemory());
|
||||
R_UNLESS(stack_size + m_code_size >= m_code_size, svc::ResultOutOfMemory());
|
||||
|
||||
/* Place a tentative reservation of memory for our new stack. */
|
||||
KScopedResourceReservation mem_reservation(this, ams::svc::LimitableResource_PhysicalMemoryMax, stack_size);
|
||||
@@ -878,26 +878,26 @@ namespace ams::kern {
|
||||
KProcessAddress stack_top = Null<KProcessAddress>;
|
||||
if (stack_size) {
|
||||
KProcessAddress stack_bottom;
|
||||
R_TRY(this->page_table.MapPages(std::addressof(stack_bottom), stack_size / PageSize, KMemoryState_Stack, KMemoryPermission_UserReadWrite));
|
||||
R_TRY(m_page_table.MapPages(std::addressof(stack_bottom), stack_size / PageSize, KMemoryState_Stack, KMemoryPermission_UserReadWrite));
|
||||
|
||||
stack_top = stack_bottom + stack_size;
|
||||
this->main_thread_stack_size = stack_size;
|
||||
m_main_thread_stack_size = stack_size;
|
||||
}
|
||||
|
||||
/* Ensure our stack is safe to clean up on exit. */
|
||||
auto stack_guard = SCOPE_GUARD {
|
||||
if (this->main_thread_stack_size) {
|
||||
MESOSPHERE_R_ABORT_UNLESS(this->page_table.UnmapPages(stack_top - this->main_thread_stack_size, this->main_thread_stack_size / PageSize, KMemoryState_Stack));
|
||||
this->main_thread_stack_size = 0;
|
||||
if (m_main_thread_stack_size) {
|
||||
MESOSPHERE_R_ABORT_UNLESS(m_page_table.UnmapPages(stack_top - m_main_thread_stack_size, m_main_thread_stack_size / PageSize, KMemoryState_Stack));
|
||||
m_main_thread_stack_size = 0;
|
||||
}
|
||||
};
|
||||
|
||||
/* Set our maximum heap size. */
|
||||
R_TRY(this->page_table.SetMaxHeapSize(this->max_process_memory - (this->main_thread_stack_size + this->code_size)));
|
||||
R_TRY(m_page_table.SetMaxHeapSize(m_max_process_memory - (m_main_thread_stack_size + m_code_size)));
|
||||
|
||||
/* Initialize our handle table. */
|
||||
R_TRY(this->handle_table.Initialize(this->capabilities.GetHandleTableSize()));
|
||||
auto ht_guard = SCOPE_GUARD { this->handle_table.Finalize(); };
|
||||
R_TRY(m_handle_table.Initialize(m_capabilities.GetHandleTableSize()));
|
||||
auto ht_guard = SCOPE_GUARD { m_handle_table.Finalize(); };
|
||||
|
||||
/* Create a new thread for the process. */
|
||||
KThread *main_thread = KThread::Create();
|
||||
@@ -905,7 +905,7 @@ namespace ams::kern {
|
||||
auto thread_guard = SCOPE_GUARD { main_thread->Close(); };
|
||||
|
||||
/* Initialize the thread. */
|
||||
R_TRY(KThread::InitializeUserThread(main_thread, reinterpret_cast<KThreadFunction>(GetVoidPointer(this->GetEntryPoint())), 0, stack_top, priority, this->ideal_core_id, this));
|
||||
R_TRY(KThread::InitializeUserThread(main_thread, reinterpret_cast<KThreadFunction>(GetVoidPointer(this->GetEntryPoint())), 0, stack_top, priority, m_ideal_core_id, this));
|
||||
|
||||
/* Register the thread, and commit our reservation. */
|
||||
KThread::Register(main_thread);
|
||||
@@ -913,7 +913,7 @@ namespace ams::kern {
|
||||
|
||||
/* Add the thread to our handle table. */
|
||||
ams::svc::Handle thread_handle;
|
||||
R_TRY(this->handle_table.Add(std::addressof(thread_handle), main_thread));
|
||||
R_TRY(m_handle_table.Add(std::addressof(thread_handle), main_thread));
|
||||
|
||||
/* Set the thread arguments. */
|
||||
main_thread->GetContext().SetArguments(0, thread_handle);
|
||||
@@ -933,7 +933,7 @@ namespace ams::kern {
|
||||
mem_reservation.Commit();
|
||||
|
||||
/* Note for debug that we're running a new process. */
|
||||
MESOSPHERE_LOG("KProcess::Run() pid=%ld name=%-12s thread=%ld affinity=0x%lx ideal_core=%d active_core=%d\n", this->process_id, this->name, main_thread->GetId(), main_thread->GetVirtualAffinityMask(), main_thread->GetIdealVirtualCore(), main_thread->GetActiveCore());
|
||||
MESOSPHERE_LOG("KProcess::Run() pid=%ld name=%-12s thread=%ld affinity=0x%lx ideal_core=%d active_core=%d\n", m_process_id, m_name, main_thread->GetId(), main_thread->GetVirtualAffinityMask(), main_thread->GetIdealVirtualCore(), main_thread->GetActiveCore());
|
||||
|
||||
return ResultSuccess();
|
||||
}
|
||||
@@ -942,32 +942,32 @@ namespace ams::kern {
|
||||
MESOSPHERE_ASSERT_THIS();
|
||||
|
||||
/* Lock the process and the scheduler. */
|
||||
KScopedLightLock lk(this->state_lock);
|
||||
KScopedLightLock lk(m_state_lock);
|
||||
KScopedSchedulerLock sl;
|
||||
|
||||
/* Validate that we're in a state that we can reset. */
|
||||
R_UNLESS(this->state != State_Terminated, svc::ResultInvalidState());
|
||||
R_UNLESS(this->is_signaled, svc::ResultInvalidState());
|
||||
R_UNLESS(m_state != State_Terminated, svc::ResultInvalidState());
|
||||
R_UNLESS(m_is_signaled, svc::ResultInvalidState());
|
||||
|
||||
/* Clear signaled. */
|
||||
this->is_signaled = false;
|
||||
m_is_signaled = false;
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
Result KProcess::SetActivity(ams::svc::ProcessActivity activity) {
|
||||
/* Lock ourselves and the scheduler. */
|
||||
KScopedLightLock lk(this->state_lock);
|
||||
KScopedLightLock list_lk(this->list_lock);
|
||||
KScopedLightLock lk(m_state_lock);
|
||||
KScopedLightLock list_lk(m_list_lock);
|
||||
KScopedSchedulerLock sl;
|
||||
|
||||
/* Validate our state. */
|
||||
R_UNLESS(this->state != State_Terminating, svc::ResultInvalidState());
|
||||
R_UNLESS(this->state != State_Terminated, svc::ResultInvalidState());
|
||||
R_UNLESS(m_state != State_Terminating, svc::ResultInvalidState());
|
||||
R_UNLESS(m_state != State_Terminated, svc::ResultInvalidState());
|
||||
|
||||
/* Either pause or resume. */
|
||||
if (activity == ams::svc::ProcessActivity_Paused) {
|
||||
/* Verify that we're not suspended. */
|
||||
R_UNLESS(!this->is_suspended, svc::ResultInvalidState());
|
||||
R_UNLESS(!m_is_suspended, svc::ResultInvalidState());
|
||||
|
||||
/* Suspend all threads. */
|
||||
auto end = this->GetThreadList().end();
|
||||
@@ -981,7 +981,7 @@ namespace ams::kern {
|
||||
MESOSPHERE_ASSERT(activity == ams::svc::ProcessActivity_Runnable);
|
||||
|
||||
/* Verify that we're suspended. */
|
||||
R_UNLESS(this->is_suspended, svc::ResultInvalidState());
|
||||
R_UNLESS(m_is_suspended, svc::ResultInvalidState());
|
||||
|
||||
/* Resume all threads. */
|
||||
auto end = this->GetThreadList().end();
|
||||
@@ -1028,7 +1028,7 @@ namespace ams::kern {
|
||||
|
||||
Result KProcess::GetThreadList(s32 *out_num_threads, ams::kern::svc::KUserPointer<u64 *> out_thread_ids, s32 max_out_count) {
|
||||
/* Lock the list. */
|
||||
KScopedLightLock lk(this->list_lock);
|
||||
KScopedLightLock lk(m_list_lock);
|
||||
|
||||
/* Iterate over the list. */
|
||||
s32 count = 0;
|
||||
@@ -1059,17 +1059,17 @@ namespace ams::kern {
|
||||
MESOSPHERE_ASSERT(debug_object != nullptr);
|
||||
|
||||
/* Cache our state to return it to the debug object. */
|
||||
const auto old_state = this->state;
|
||||
const auto old_state = m_state;
|
||||
|
||||
/* Set the object. */
|
||||
this->attached_object = debug_object;
|
||||
m_attached_object = debug_object;
|
||||
|
||||
/* Check that our state is valid for attach. */
|
||||
MESOSPHERE_ASSERT(this->state == State_Created || this->state == State_Running || this->state == State_Crashed);
|
||||
MESOSPHERE_ASSERT(m_state == State_Created || m_state == State_Running || m_state == State_Crashed);
|
||||
|
||||
/* Update our state. */
|
||||
if (this->state != State_DebugBreak) {
|
||||
if (this->state == State_Created) {
|
||||
if (m_state != State_DebugBreak) {
|
||||
if (m_state == State_Created) {
|
||||
this->ChangeState(State_CreatedAttached);
|
||||
} else {
|
||||
this->ChangeState(State_DebugBreak);
|
||||
@@ -1084,15 +1084,15 @@ namespace ams::kern {
|
||||
MESOSPHERE_ASSERT(KScheduler::IsSchedulerLockedByCurrentThread());
|
||||
|
||||
/* Clear the attached object. */
|
||||
this->attached_object = nullptr;
|
||||
m_attached_object = nullptr;
|
||||
|
||||
/* Validate that the process is in an attached state. */
|
||||
MESOSPHERE_ASSERT(this->state == State_CreatedAttached || this->state == State_RunningAttached || this->state == State_DebugBreak || this->state == State_Terminating || this->state == State_Terminated);
|
||||
MESOSPHERE_ASSERT(m_state == State_CreatedAttached || m_state == State_RunningAttached || m_state == State_DebugBreak || m_state == State_Terminating || m_state == State_Terminated);
|
||||
|
||||
/* Change the state appropriately. */
|
||||
if (this->state == State_CreatedAttached) {
|
||||
if (m_state == State_CreatedAttached) {
|
||||
this->ChangeState(State_Created);
|
||||
} else if (this->state == State_RunningAttached || this->state == State_DebugBreak) {
|
||||
} else if (m_state == State_RunningAttached || m_state == State_DebugBreak) {
|
||||
/* Disallow transition back to created from running. */
|
||||
if (old_state == State_Created) {
|
||||
old_state = State_Running;
|
||||
@@ -1107,20 +1107,20 @@ namespace ams::kern {
|
||||
MESOSPHERE_ASSERT(this == GetCurrentProcessPointer());
|
||||
|
||||
/* If we aren't allowed to enter jit debug, don't. */
|
||||
if ((this->flags & ams::svc::CreateProcessFlag_EnableDebug) == 0) {
|
||||
if ((m_flags & ams::svc::CreateProcessFlag_EnableDebug) == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/* We're the current process, so we should be some kind of running. */
|
||||
MESOSPHERE_ASSERT(this->state != State_Created);
|
||||
MESOSPHERE_ASSERT(this->state != State_CreatedAttached);
|
||||
MESOSPHERE_ASSERT(this->state != State_Terminated);
|
||||
MESOSPHERE_ASSERT(m_state != State_Created);
|
||||
MESOSPHERE_ASSERT(m_state != State_CreatedAttached);
|
||||
MESOSPHERE_ASSERT(m_state != State_Terminated);
|
||||
|
||||
/* Try to enter JIT debug. */
|
||||
while (true) {
|
||||
/* Lock ourselves and the scheduler. */
|
||||
KScopedLightLock lk(this->state_lock);
|
||||
KScopedLightLock list_lk(this->list_lock);
|
||||
KScopedLightLock lk(m_state_lock);
|
||||
KScopedLightLock list_lk(m_list_lock);
|
||||
KScopedSchedulerLock sl;
|
||||
|
||||
/* If we're attached to a debugger, we're necessarily in debug. */
|
||||
@@ -1134,12 +1134,12 @@ namespace ams::kern {
|
||||
}
|
||||
|
||||
/* We're not attached to debugger, so check that. */
|
||||
MESOSPHERE_ASSERT(this->state != State_RunningAttached);
|
||||
MESOSPHERE_ASSERT(this->state != State_DebugBreak);
|
||||
MESOSPHERE_ASSERT(m_state != State_RunningAttached);
|
||||
MESOSPHERE_ASSERT(m_state != State_DebugBreak);
|
||||
|
||||
/* If we're terminating, we can't enter debug. */
|
||||
if (this->state != State_Running && this->state != State_Crashed) {
|
||||
MESOSPHERE_ASSERT(this->state == State_Terminating);
|
||||
if (m_state != State_Running && m_state != State_Crashed) {
|
||||
MESOSPHERE_ASSERT(m_state == State_Terminating);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1160,14 +1160,14 @@ namespace ams::kern {
|
||||
this->ChangeState(State_Crashed);
|
||||
|
||||
/* Enter jit debug. */
|
||||
this->is_jit_debug = true;
|
||||
this->jit_debug_event_type = event;
|
||||
this->jit_debug_exception_type = exception;
|
||||
this->jit_debug_params[0] = param1;
|
||||
this->jit_debug_params[1] = param2;
|
||||
this->jit_debug_params[2] = param3;
|
||||
this->jit_debug_params[3] = param4;
|
||||
this->jit_debug_thread_id = GetCurrentThread().GetId();
|
||||
m_is_jit_debug = true;
|
||||
m_jit_debug_event_type = event;
|
||||
m_jit_debug_exception_type = exception;
|
||||
m_jit_debug_params[0] = param1;
|
||||
m_jit_debug_params[1] = param2;
|
||||
m_jit_debug_params[2] = param3;
|
||||
m_jit_debug_params[3] = param4;
|
||||
m_jit_debug_thread_id = GetCurrentThread().GetId();
|
||||
|
||||
/* Exit our retry loop. */
|
||||
break;
|
||||
@@ -1177,7 +1177,7 @@ namespace ams::kern {
|
||||
{
|
||||
KScopedSchedulerLock sl;
|
||||
|
||||
if (this->state == State_Running || this->state == State_RunningAttached || this->state == State_Crashed || this->state == State_DebugBreak) {
|
||||
if (m_state == State_Running || m_state == State_RunningAttached || m_state == State_Crashed || m_state == State_DebugBreak) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -1189,8 +1189,8 @@ namespace ams::kern {
|
||||
MESOSPHERE_ASSERT_THIS();
|
||||
MESOSPHERE_ASSERT(KScheduler::IsSchedulerLockedByCurrentThread());
|
||||
|
||||
if (this->is_jit_debug) {
|
||||
return KDebugBase::CreateDebugEvent(this->jit_debug_event_type, this->jit_debug_exception_type, this->jit_debug_params[0], this->jit_debug_params[1], this->jit_debug_params[2], this->jit_debug_params[3], this->jit_debug_thread_id);
|
||||
if (m_is_jit_debug) {
|
||||
return KDebugBase::CreateDebugEvent(m_jit_debug_event_type, m_jit_debug_exception_type, m_jit_debug_params[0], m_jit_debug_params[1], m_jit_debug_params[2], m_jit_debug_params[3], m_jit_debug_thread_id);
|
||||
} else {
|
||||
return nullptr;
|
||||
}
|
||||
@@ -1200,7 +1200,7 @@ namespace ams::kern {
|
||||
MESOSPHERE_ASSERT_THIS();
|
||||
MESOSPHERE_ASSERT(KScheduler::IsSchedulerLockedByCurrentThread());
|
||||
|
||||
this->is_jit_debug = false;
|
||||
m_is_jit_debug = false;
|
||||
}
|
||||
|
||||
KProcess *KProcess::GetProcessFromId(u64 process_id) {
|
||||
|
||||
@@ -21,13 +21,13 @@ namespace ams::kern {
|
||||
MESOSPHERE_ASSERT_THIS();
|
||||
MESOSPHERE_ASSERT(KScheduler::IsSchedulerLockedByCurrentThread());
|
||||
|
||||
return this->is_signaled;
|
||||
return m_is_signaled;
|
||||
}
|
||||
|
||||
void KReadableEvent::Destroy() {
|
||||
MESOSPHERE_ASSERT_THIS();
|
||||
if (this->parent_event) {
|
||||
this->parent_event->Close();
|
||||
if (m_parent) {
|
||||
m_parent->Close();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,8 +36,8 @@ namespace ams::kern {
|
||||
|
||||
KScopedSchedulerLock lk;
|
||||
|
||||
if (!this->is_signaled) {
|
||||
this->is_signaled = true;
|
||||
if (!m_is_signaled) {
|
||||
m_is_signaled = true;
|
||||
this->NotifyAvailable();
|
||||
}
|
||||
|
||||
@@ -57,9 +57,9 @@ namespace ams::kern {
|
||||
|
||||
KScopedSchedulerLock lk;
|
||||
|
||||
R_UNLESS(this->is_signaled, svc::ResultInvalidState());
|
||||
R_UNLESS(m_is_signaled, svc::ResultInvalidState());
|
||||
|
||||
this->is_signaled = false;
|
||||
m_is_signaled = false;
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
|
||||
@@ -27,12 +27,12 @@ namespace ams::kern {
|
||||
/* 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. */
|
||||
/*
|
||||
this->waiter_count = 0;
|
||||
for (size_t i = 0; i < util::size(this->limit_values); i++) {
|
||||
this->limit_values[i] = 0;
|
||||
this->current_values[i] = 0;
|
||||
this->current_hints[i] = 0;
|
||||
this->peak_values[i] = 0;
|
||||
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;
|
||||
}
|
||||
*/
|
||||
}
|
||||
@@ -46,11 +46,11 @@ namespace ams::kern {
|
||||
|
||||
s64 value;
|
||||
{
|
||||
KScopedLightLock lk(this->lock);
|
||||
value = this->limit_values[which];
|
||||
KScopedLightLock lk(m_lock);
|
||||
value = m_limit_values[which];
|
||||
MESOSPHERE_ASSERT(value >= 0);
|
||||
MESOSPHERE_ASSERT(this->current_values[which] <= this->limit_values[which]);
|
||||
MESOSPHERE_ASSERT(this->current_hints[which] <= this->current_values[which]);
|
||||
MESOSPHERE_ASSERT(m_current_values[which] <= m_limit_values[which]);
|
||||
MESOSPHERE_ASSERT(m_current_hints[which] <= m_current_values[which]);
|
||||
}
|
||||
|
||||
return value;
|
||||
@@ -61,11 +61,11 @@ namespace ams::kern {
|
||||
|
||||
s64 value;
|
||||
{
|
||||
KScopedLightLock lk(this->lock);
|
||||
value = this->current_values[which];
|
||||
KScopedLightLock lk(m_lock);
|
||||
value = m_current_values[which];
|
||||
MESOSPHERE_ASSERT(value >= 0);
|
||||
MESOSPHERE_ASSERT(this->current_values[which] <= this->limit_values[which]);
|
||||
MESOSPHERE_ASSERT(this->current_hints[which] <= this->current_values[which]);
|
||||
MESOSPHERE_ASSERT(m_current_values[which] <= m_limit_values[which]);
|
||||
MESOSPHERE_ASSERT(m_current_hints[which] <= m_current_values[which]);
|
||||
}
|
||||
|
||||
return value;
|
||||
@@ -76,11 +76,11 @@ namespace ams::kern {
|
||||
|
||||
s64 value;
|
||||
{
|
||||
KScopedLightLock lk(this->lock);
|
||||
value = this->peak_values[which];
|
||||
KScopedLightLock lk(m_lock);
|
||||
value = m_peak_values[which];
|
||||
MESOSPHERE_ASSERT(value >= 0);
|
||||
MESOSPHERE_ASSERT(this->current_values[which] <= this->limit_values[which]);
|
||||
MESOSPHERE_ASSERT(this->current_hints[which] <= this->current_values[which]);
|
||||
MESOSPHERE_ASSERT(m_current_values[which] <= m_limit_values[which]);
|
||||
MESOSPHERE_ASSERT(m_current_hints[which] <= m_current_values[which]);
|
||||
}
|
||||
|
||||
return value;
|
||||
@@ -91,11 +91,11 @@ namespace ams::kern {
|
||||
|
||||
s64 value;
|
||||
{
|
||||
KScopedLightLock lk(this->lock);
|
||||
MESOSPHERE_ASSERT(this->current_values[which] >= 0);
|
||||
MESOSPHERE_ASSERT(this->current_values[which] <= this->limit_values[which]);
|
||||
MESOSPHERE_ASSERT(this->current_hints[which] <= this->current_values[which]);
|
||||
value = this->limit_values[which] - this->current_values[which];
|
||||
KScopedLightLock lk(m_lock);
|
||||
MESOSPHERE_ASSERT(m_current_values[which] >= 0);
|
||||
MESOSPHERE_ASSERT(m_current_values[which] <= m_limit_values[which]);
|
||||
MESOSPHERE_ASSERT(m_current_hints[which] <= m_current_values[which]);
|
||||
value = m_limit_values[which] - m_current_values[which];
|
||||
}
|
||||
|
||||
return value;
|
||||
@@ -104,10 +104,10 @@ namespace ams::kern {
|
||||
Result KResourceLimit::SetLimitValue(ams::svc::LimitableResource which, s64 value) {
|
||||
MESOSPHERE_ASSERT_THIS();
|
||||
|
||||
KScopedLightLock lk(this->lock);
|
||||
R_UNLESS(this->current_values[which] <= value, svc::ResultInvalidState());
|
||||
KScopedLightLock lk(m_lock);
|
||||
R_UNLESS(m_current_values[which] <= value, svc::ResultInvalidState());
|
||||
|
||||
this->limit_values[which] = value;
|
||||
m_limit_values[which] = value;
|
||||
|
||||
return ResultSuccess();
|
||||
}
|
||||
@@ -120,34 +120,34 @@ namespace ams::kern {
|
||||
MESOSPHERE_ASSERT_THIS();
|
||||
MESOSPHERE_ASSERT(value >= 0);
|
||||
|
||||
KScopedLightLock lk(this->lock);
|
||||
KScopedLightLock lk(m_lock);
|
||||
|
||||
MESOSPHERE_ASSERT(this->current_hints[which] <= this->current_values[which]);
|
||||
if (this->current_hints[which] >= this->limit_values[which]) {
|
||||
MESOSPHERE_ASSERT(m_current_hints[which] <= m_current_values[which]);
|
||||
if (m_current_hints[which] >= m_limit_values[which]) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Loop until we reserve or run out of time. */
|
||||
while (true) {
|
||||
MESOSPHERE_ASSERT(this->current_values[which] <= this->limit_values[which]);
|
||||
MESOSPHERE_ASSERT(this->current_hints[which] <= this->current_values[which]);
|
||||
MESOSPHERE_ASSERT(m_current_values[which] <= m_limit_values[which]);
|
||||
MESOSPHERE_ASSERT(m_current_hints[which] <= m_current_values[which]);
|
||||
|
||||
/* If we would overflow, don't allow to succeed. */
|
||||
if (this->current_values[which] + value <= this->current_values[which]) {
|
||||
if (m_current_values[which] + value <= m_current_values[which]) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (this->current_values[which] + value <= this->limit_values[which]) {
|
||||
this->current_values[which] += value;
|
||||
this->current_hints[which] += value;
|
||||
this->peak_values[which] = std::max(this->peak_values[which], this->current_values[which]);
|
||||
if (m_current_values[which] + value <= m_limit_values[which]) {
|
||||
m_current_values[which] += value;
|
||||
m_current_hints[which] += value;
|
||||
m_peak_values[which] = std::max(m_peak_values[which], m_current_values[which]);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (this->current_hints[which] + value <= this->limit_values[which] && (timeout < 0 || KHardwareTimer::GetTick() < timeout)) {
|
||||
this->waiter_count++;
|
||||
this->cond_var.Wait(&this->lock, timeout);
|
||||
this->waiter_count--;
|
||||
if (m_current_hints[which] + value <= m_limit_values[which] && (timeout < 0 || KHardwareTimer::GetTick() < timeout)) {
|
||||
m_waiter_count++;
|
||||
m_cond_var.Wait(&m_lock, timeout);
|
||||
m_waiter_count--;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
@@ -165,17 +165,17 @@ namespace ams::kern {
|
||||
MESOSPHERE_ASSERT(value >= 0);
|
||||
MESOSPHERE_ASSERT(hint >= 0);
|
||||
|
||||
KScopedLightLock lk(this->lock);
|
||||
MESOSPHERE_ASSERT(this->current_values[which] <= this->limit_values[which]);
|
||||
MESOSPHERE_ASSERT(this->current_hints[which] <= this->current_values[which]);
|
||||
MESOSPHERE_ASSERT(value <= this->current_values[which]);
|
||||
MESOSPHERE_ASSERT(hint <= this->current_hints[which]);
|
||||
KScopedLightLock lk(m_lock);
|
||||
MESOSPHERE_ASSERT(m_current_values[which] <= m_limit_values[which]);
|
||||
MESOSPHERE_ASSERT(m_current_hints[which] <= m_current_values[which]);
|
||||
MESOSPHERE_ASSERT(value <= m_current_values[which]);
|
||||
MESOSPHERE_ASSERT(hint <= m_current_hints[which]);
|
||||
|
||||
this->current_values[which] -= value;
|
||||
this->current_hints[which] -= hint;
|
||||
m_current_values[which] -= value;
|
||||
m_current_hints[which] -= hint;
|
||||
|
||||
if (this->waiter_count != 0) {
|
||||
this->cond_var.Broadcast();
|
||||
if (m_waiter_count != 0) {
|
||||
m_cond_var.Broadcast();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -53,9 +53,9 @@ namespace ams::kern {
|
||||
|
||||
void KScheduler::Initialize(KThread *idle_thread) {
|
||||
/* Set core ID and idle thread. */
|
||||
this->core_id = GetCurrentCoreId();
|
||||
this->idle_thread = idle_thread;
|
||||
this->state.idle_thread_stack = this->idle_thread->GetStackTop();
|
||||
m_core_id = GetCurrentCoreId();
|
||||
m_idle_thread = idle_thread;
|
||||
m_state.idle_thread_stack = m_idle_thread->GetStackTop();
|
||||
|
||||
/* Insert the main thread into the priority queue. */
|
||||
{
|
||||
@@ -65,48 +65,48 @@ namespace ams::kern {
|
||||
}
|
||||
|
||||
/* Bind interrupt handler. */
|
||||
Kernel::GetInterruptManager().BindHandler(GetSchedulerInterruptTask(), KInterruptName_Scheduler, this->core_id, KInterruptController::PriorityLevel_Scheduler, false, false);
|
||||
Kernel::GetInterruptManager().BindHandler(GetSchedulerInterruptTask(), KInterruptName_Scheduler, m_core_id, KInterruptController::PriorityLevel_Scheduler, false, false);
|
||||
|
||||
/* Set the current thread. */
|
||||
this->current_thread = GetCurrentThreadPointer();
|
||||
m_current_thread = GetCurrentThreadPointer();
|
||||
}
|
||||
|
||||
void KScheduler::Activate() {
|
||||
MESOSPHERE_ASSERT(GetCurrentThread().GetDisableDispatchCount() == 1);
|
||||
|
||||
this->state.should_count_idle = KTargetSystem::IsDebugMode();
|
||||
this->is_active = true;
|
||||
m_state.should_count_idle = KTargetSystem::IsDebugMode();
|
||||
m_is_active = true;
|
||||
RescheduleCurrentCore();
|
||||
}
|
||||
|
||||
void KScheduler::RescheduleOtherCores(u64 cores_needing_scheduling) {
|
||||
if (const u64 core_mask = cores_needing_scheduling & ~(1ul << this->core_id); core_mask != 0) {
|
||||
if (const u64 core_mask = cores_needing_scheduling & ~(1ul << m_core_id); core_mask != 0) {
|
||||
cpu::DataSynchronizationBarrier();
|
||||
Kernel::GetInterruptManager().SendInterProcessorInterrupt(KInterruptName_Scheduler, core_mask);
|
||||
}
|
||||
}
|
||||
|
||||
u64 KScheduler::UpdateHighestPriorityThread(KThread *highest_thread) {
|
||||
if (KThread *prev_highest_thread = this->state.highest_priority_thread; AMS_LIKELY(prev_highest_thread != highest_thread)) {
|
||||
if (KThread *prev_highest_thread = m_state.highest_priority_thread; AMS_LIKELY(prev_highest_thread != highest_thread)) {
|
||||
if (AMS_LIKELY(prev_highest_thread != nullptr)) {
|
||||
IncrementScheduledCount(prev_highest_thread);
|
||||
prev_highest_thread->SetLastScheduledTick(KHardwareTimer::GetTick());
|
||||
}
|
||||
if (this->state.should_count_idle) {
|
||||
if (m_state.should_count_idle) {
|
||||
if (AMS_LIKELY(highest_thread != nullptr)) {
|
||||
if (KProcess *process = highest_thread->GetOwnerProcess(); process != nullptr) {
|
||||
process->SetRunningThread(this->core_id, highest_thread, this->state.idle_count);
|
||||
process->SetRunningThread(m_core_id, highest_thread, m_state.idle_count);
|
||||
}
|
||||
} else {
|
||||
this->state.idle_count++;
|
||||
m_state.idle_count++;
|
||||
}
|
||||
}
|
||||
|
||||
MESOSPHERE_KTRACE_SCHEDULE_UPDATE(this->core_id, (prev_highest_thread != nullptr ? prev_highest_thread : this->idle_thread), (highest_thread != nullptr ? highest_thread : this->idle_thread));
|
||||
MESOSPHERE_KTRACE_SCHEDULE_UPDATE(m_core_id, (prev_highest_thread != nullptr ? prev_highest_thread : m_idle_thread), (highest_thread != nullptr ? highest_thread : m_idle_thread));
|
||||
|
||||
this->state.highest_priority_thread = highest_thread;
|
||||
this->state.needs_scheduling = true;
|
||||
return (1ul << this->core_id);
|
||||
m_state.highest_priority_thread = highest_thread;
|
||||
m_state.needs_scheduling = true;
|
||||
return (1ul << m_core_id);
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
@@ -227,7 +227,7 @@ namespace ams::kern {
|
||||
|
||||
/* We never want to schedule a null thread, so use the idle thread if we don't have a next. */
|
||||
if (next_thread == nullptr) {
|
||||
next_thread = this->idle_thread;
|
||||
next_thread = m_idle_thread;
|
||||
}
|
||||
|
||||
/* If we're not actually switching thread, there's nothing to do. */
|
||||
@@ -239,31 +239,31 @@ namespace ams::kern {
|
||||
MESOSPHERE_ASSERT(next_thread->GetDisableDispatchCount() == 1);
|
||||
|
||||
/* Update the CPU time tracking variables. */
|
||||
const s64 prev_tick = this->last_context_switch_time;
|
||||
const s64 prev_tick = m_last_context_switch_time;
|
||||
const s64 cur_tick = KHardwareTimer::GetTick();
|
||||
const s64 tick_diff = cur_tick - prev_tick;
|
||||
cur_thread->AddCpuTime(this->core_id, tick_diff);
|
||||
cur_thread->AddCpuTime(m_core_id, tick_diff);
|
||||
if (cur_process != nullptr) {
|
||||
cur_process->AddCpuTime(tick_diff);
|
||||
}
|
||||
this->last_context_switch_time = cur_tick;
|
||||
m_last_context_switch_time = cur_tick;
|
||||
|
||||
/* Update our previous thread. */
|
||||
if (cur_process != nullptr) {
|
||||
/* NOTE: Combining this into AMS_LIKELY(!... && ...) triggers an internal compiler error: Segmentation fault in GCC 9.2.0. */
|
||||
if (AMS_LIKELY(!cur_thread->IsTerminationRequested()) && AMS_LIKELY(cur_thread->GetActiveCore() == this->core_id)) {
|
||||
this->prev_thread = cur_thread;
|
||||
if (AMS_LIKELY(!cur_thread->IsTerminationRequested()) && AMS_LIKELY(cur_thread->GetActiveCore() == m_core_id)) {
|
||||
m_prev_thread = cur_thread;
|
||||
} else {
|
||||
this->prev_thread = nullptr;
|
||||
m_prev_thread = nullptr;
|
||||
}
|
||||
} else if (cur_thread == this->idle_thread) {
|
||||
this->prev_thread = nullptr;
|
||||
} else if (cur_thread == m_idle_thread) {
|
||||
m_prev_thread = nullptr;
|
||||
}
|
||||
|
||||
MESOSPHERE_KTRACE_THREAD_SWITCH(next_thread);
|
||||
|
||||
if (next_thread->GetCurrentCore() != this->core_id) {
|
||||
next_thread->SetCurrentCore(this->core_id);
|
||||
if (next_thread->GetCurrentCore() != m_core_id) {
|
||||
next_thread->SetCurrentCore(m_core_id);
|
||||
}
|
||||
|
||||
/* Switch the current process, if we're switching processes. */
|
||||
@@ -273,7 +273,7 @@ namespace ams::kern {
|
||||
|
||||
/* Set the new thread. */
|
||||
SetCurrentThread(next_thread);
|
||||
this->current_thread = next_thread;
|
||||
m_current_thread = next_thread;
|
||||
|
||||
/* Set the new Thread Local region. */
|
||||
cpu::SwitchThreadLocalRegion(GetInteger(next_thread->GetThreadLocalRegionAddress()));
|
||||
@@ -283,7 +283,7 @@ namespace ams::kern {
|
||||
MESOSPHERE_ASSERT(IsSchedulerLockedByCurrentThread());
|
||||
for (size_t i = 0; i < cpu::NumCores; ++i) {
|
||||
/* Get an atomic reference to the core scheduler's previous thread. */
|
||||
std::atomic_ref<KThread *> prev_thread(Kernel::GetScheduler(static_cast<s32>(i)).prev_thread);
|
||||
std::atomic_ref<KThread *> prev_thread(Kernel::GetScheduler(static_cast<s32>(i)).m_prev_thread);
|
||||
static_assert(std::atomic_ref<KThread *>::is_always_lock_free);
|
||||
|
||||
/* Atomically clear the previous thread if it's our target. */
|
||||
@@ -496,7 +496,7 @@ namespace ams::kern {
|
||||
/* Check if the suggested thread is the thread running on its core. */
|
||||
const s32 suggested_core = suggested->GetActiveCore();
|
||||
|
||||
if (KThread *running_on_suggested_core = (suggested_core >= 0) ? Kernel::GetScheduler(suggested_core).state.highest_priority_thread : nullptr; running_on_suggested_core != suggested) {
|
||||
if (KThread *running_on_suggested_core = (suggested_core >= 0) ? Kernel::GetScheduler(suggested_core).m_state.highest_priority_thread : nullptr; running_on_suggested_core != suggested) {
|
||||
/* If the current thread's priority is higher than our suggestion's we prefer the next thread to the suggestion. */
|
||||
/* We also prefer the next thread when the current thread's priority is equal to the suggestions, but the next thread has been waiting longer. */
|
||||
if ((suggested->GetPriority() > cur_thread.GetPriority()) ||
|
||||
|
||||
@@ -19,7 +19,7 @@ namespace ams::kern {
|
||||
|
||||
void KServerPort::Initialize(KPort *parent) {
|
||||
/* Set member variables. */
|
||||
this->parent = parent;
|
||||
m_parent = parent;
|
||||
}
|
||||
|
||||
bool KServerPort::IsLight() const {
|
||||
@@ -29,9 +29,9 @@ namespace ams::kern {
|
||||
void KServerPort::CleanupSessions() {
|
||||
/* Ensure our preconditions are met. */
|
||||
if (this->IsLight()) {
|
||||
MESOSPHERE_ASSERT(this->session_list.empty());
|
||||
MESOSPHERE_ASSERT(m_session_list.empty());
|
||||
} else {
|
||||
MESOSPHERE_ASSERT(this->light_session_list.empty());
|
||||
MESOSPHERE_ASSERT(m_light_session_list.empty());
|
||||
}
|
||||
|
||||
/* Cleanup the session list. */
|
||||
@@ -40,9 +40,9 @@ namespace ams::kern {
|
||||
KServerSession *session = nullptr;
|
||||
{
|
||||
KScopedSchedulerLock sl;
|
||||
while (!this->session_list.empty()) {
|
||||
session = std::addressof(this->session_list.front());
|
||||
this->session_list.pop_front();
|
||||
while (!m_session_list.empty()) {
|
||||
session = std::addressof(m_session_list.front());
|
||||
m_session_list.pop_front();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -60,9 +60,9 @@ namespace ams::kern {
|
||||
KLightServerSession *session = nullptr;
|
||||
{
|
||||
KScopedSchedulerLock sl;
|
||||
while (!this->light_session_list.empty()) {
|
||||
session = std::addressof(this->light_session_list.front());
|
||||
this->light_session_list.pop_front();
|
||||
while (!m_light_session_list.empty()) {
|
||||
session = std::addressof(m_light_session_list.front());
|
||||
m_light_session_list.pop_front();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -77,21 +77,21 @@ namespace ams::kern {
|
||||
|
||||
void KServerPort::Destroy() {
|
||||
/* Note with our parent that we're closed. */
|
||||
this->parent->OnClientClosed();
|
||||
m_parent->OnClientClosed();
|
||||
|
||||
/* Perform necessary cleanup of our session lists. */
|
||||
this->CleanupSessions();
|
||||
|
||||
/* Close our reference to our parent. */
|
||||
this->parent->Close();
|
||||
m_parent->Close();
|
||||
}
|
||||
|
||||
bool KServerPort::IsSignaled() const {
|
||||
MESOSPHERE_ASSERT_THIS();
|
||||
if (this->IsLight()) {
|
||||
return !this->light_session_list.empty();
|
||||
return !m_light_session_list.empty();
|
||||
} else {
|
||||
return !this->session_list.empty();
|
||||
return !m_session_list.empty();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -102,8 +102,8 @@ namespace ams::kern {
|
||||
KScopedSchedulerLock sl;
|
||||
|
||||
/* Add the session to our queue. */
|
||||
this->session_list.push_back(*session);
|
||||
if (this->session_list.size() == 1) {
|
||||
m_session_list.push_back(*session);
|
||||
if (m_session_list.size() == 1) {
|
||||
this->NotifyAvailable();
|
||||
}
|
||||
}
|
||||
@@ -115,8 +115,8 @@ namespace ams::kern {
|
||||
KScopedSchedulerLock sl;
|
||||
|
||||
/* Add the session to our queue. */
|
||||
this->light_session_list.push_back(*session);
|
||||
if (this->light_session_list.size() == 1) {
|
||||
m_light_session_list.push_back(*session);
|
||||
if (m_light_session_list.size() == 1) {
|
||||
this->NotifyAvailable();
|
||||
}
|
||||
}
|
||||
@@ -128,12 +128,12 @@ namespace ams::kern {
|
||||
KScopedSchedulerLock sl;
|
||||
|
||||
/* Return the first session in the list. */
|
||||
if (this->session_list.empty()) {
|
||||
if (m_session_list.empty()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
KServerSession *session = std::addressof(this->session_list.front());
|
||||
this->session_list.pop_front();
|
||||
KServerSession *session = std::addressof(m_session_list.front());
|
||||
m_session_list.pop_front();
|
||||
return session;
|
||||
}
|
||||
|
||||
@@ -144,12 +144,12 @@ namespace ams::kern {
|
||||
KScopedSchedulerLock sl;
|
||||
|
||||
/* Return the first session in the list. */
|
||||
if (this->light_session_list.empty()) {
|
||||
if (m_light_session_list.empty()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
KLightServerSession *session = std::addressof(this->light_session_list.front());
|
||||
this->light_session_list.pop_front();
|
||||
KLightServerSession *session = std::addressof(m_light_session_list.front());
|
||||
m_light_session_list.pop_front();
|
||||
return session;
|
||||
}
|
||||
|
||||
|
||||
@@ -32,10 +32,10 @@ namespace ams::kern {
|
||||
|
||||
class ReceiveList {
|
||||
private:
|
||||
u32 data[ipc::MessageBuffer::MessageHeader::ReceiveListCountType_CountMax * ipc::MessageBuffer::ReceiveListEntry::GetDataSize() / sizeof(u32)];
|
||||
s32 recv_list_count;
|
||||
uintptr_t msg_buffer_end;
|
||||
uintptr_t msg_buffer_space_end;
|
||||
u32 m_data[ipc::MessageBuffer::MessageHeader::ReceiveListCountType_CountMax * ipc::MessageBuffer::ReceiveListEntry::GetDataSize() / sizeof(u32)];
|
||||
s32 m_recv_list_count;
|
||||
uintptr_t m_msg_buffer_end;
|
||||
uintptr_t m_msg_buffer_space_end;
|
||||
public:
|
||||
static constexpr int GetEntryCount(const ipc::MessageBuffer::MessageHeader &header) {
|
||||
const auto count = header.GetReceiveListCount();
|
||||
@@ -52,9 +52,9 @@ namespace ams::kern {
|
||||
}
|
||||
public:
|
||||
ReceiveList(const u32 *dst_msg, uintptr_t dst_address, const KProcessPageTable &dst_page_table, const ipc::MessageBuffer::MessageHeader &dst_header, const ipc::MessageBuffer::SpecialHeader &dst_special_header, size_t msg_size, size_t out_offset, s32 dst_recv_list_idx, bool is_tls) {
|
||||
this->recv_list_count = dst_header.GetReceiveListCount();
|
||||
this->msg_buffer_end = dst_address + sizeof(u32) * out_offset;
|
||||
this->msg_buffer_space_end = dst_address + msg_size;
|
||||
m_recv_list_count = dst_header.GetReceiveListCount();
|
||||
m_msg_buffer_end = dst_address + sizeof(u32) * out_offset;
|
||||
m_msg_buffer_space_end = dst_address + msg_size;
|
||||
|
||||
/* NOTE: Nintendo calculates the receive list index here using the special header. */
|
||||
/* We pre-calculate it in the caller, and pass it as a parameter. */
|
||||
@@ -64,7 +64,7 @@ namespace ams::kern {
|
||||
const auto entry_count = GetEntryCount(dst_header);
|
||||
|
||||
if (is_tls) {
|
||||
__builtin_memcpy(this->data, recv_list, entry_count * ipc::MessageBuffer::ReceiveListEntry::GetDataSize());
|
||||
__builtin_memcpy(m_data, recv_list, entry_count * ipc::MessageBuffer::ReceiveListEntry::GetDataSize());
|
||||
} else {
|
||||
uintptr_t page_addr = util::AlignDown(dst_address, PageSize);
|
||||
uintptr_t cur_addr = dst_address + dst_recv_list_idx * sizeof(u32);
|
||||
@@ -76,18 +76,18 @@ namespace ams::kern {
|
||||
recv_list = GetPointer<u32>(KPageTable::GetHeapVirtualAddress(phys_addr));
|
||||
page_addr = util::AlignDown(cur_addr, PageSize);
|
||||
}
|
||||
this->data[i] = *(recv_list++);
|
||||
m_data[i] = *(recv_list++);
|
||||
cur_addr += sizeof(u32);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
constexpr bool IsIndex() const {
|
||||
return this->recv_list_count > ipc::MessageBuffer::MessageHeader::ReceiveListCountType_CountOffset;
|
||||
return m_recv_list_count > ipc::MessageBuffer::MessageHeader::ReceiveListCountType_CountOffset;
|
||||
}
|
||||
|
||||
void GetBuffer(uintptr_t &out, size_t size, int &key) const {
|
||||
switch (this->recv_list_count) {
|
||||
switch (m_recv_list_count) {
|
||||
case ipc::MessageBuffer::MessageHeader::ReceiveListCountType_None:
|
||||
{
|
||||
out = 0;
|
||||
@@ -95,11 +95,11 @@ namespace ams::kern {
|
||||
break;
|
||||
case ipc::MessageBuffer::MessageHeader::ReceiveListCountType_ToMessageBuffer:
|
||||
{
|
||||
const uintptr_t buf = util::AlignUp(this->msg_buffer_end + key, PointerTransferBufferAlignment);
|
||||
const uintptr_t buf = util::AlignUp(m_msg_buffer_end + key, PointerTransferBufferAlignment);
|
||||
|
||||
if ((buf < buf + size) && (buf + size <= this->msg_buffer_space_end)) {
|
||||
if ((buf < buf + size) && (buf + size <= m_msg_buffer_space_end)) {
|
||||
out = buf;
|
||||
key = buf + size - this->msg_buffer_end;
|
||||
key = buf + size - m_msg_buffer_end;
|
||||
} else {
|
||||
out = 0;
|
||||
}
|
||||
@@ -107,7 +107,7 @@ namespace ams::kern {
|
||||
break;
|
||||
case ipc::MessageBuffer::MessageHeader::ReceiveListCountType_ToSingleBuffer:
|
||||
{
|
||||
const ipc::MessageBuffer::ReceiveListEntry entry(this->data[0], this->data[1]);
|
||||
const ipc::MessageBuffer::ReceiveListEntry entry(m_data[0], m_data[1]);
|
||||
const uintptr_t buf = util::AlignUp(entry.GetAddress() + key, PointerTransferBufferAlignment);
|
||||
|
||||
const uintptr_t entry_addr = entry.GetAddress();
|
||||
@@ -123,8 +123,8 @@ namespace ams::kern {
|
||||
break;
|
||||
default:
|
||||
{
|
||||
if (key < this->recv_list_count - ipc::MessageBuffer::MessageHeader::ReceiveListCountType_CountOffset) {
|
||||
const ipc::MessageBuffer::ReceiveListEntry entry(this->data[2 * key + 0], this->data[2 * key + 1]);
|
||||
if (key < m_recv_list_count - ipc::MessageBuffer::MessageHeader::ReceiveListCountType_CountOffset) {
|
||||
const ipc::MessageBuffer::ReceiveListEntry entry(m_data[2 * key + 0], m_data[2 * key + 1]);
|
||||
|
||||
const uintptr_t entry_addr = entry.GetAddress();
|
||||
const size_t entry_size = entry.GetSize();
|
||||
@@ -953,18 +953,18 @@ namespace ams::kern {
|
||||
void KServerSession::Destroy() {
|
||||
MESOSPHERE_ASSERT_THIS();
|
||||
|
||||
this->parent->OnServerClosed();
|
||||
m_parent->OnServerClosed();
|
||||
|
||||
this->CleanupRequests();
|
||||
|
||||
this->parent->Close();
|
||||
m_parent->Close();
|
||||
}
|
||||
|
||||
Result KServerSession::ReceiveRequest(uintptr_t server_message, uintptr_t server_buffer_size, KPhysicalAddress server_message_paddr) {
|
||||
MESOSPHERE_ASSERT_THIS();
|
||||
|
||||
/* Lock the session. */
|
||||
KScopedLightLock lk(this->lock);
|
||||
KScopedLightLock lk(m_lock);
|
||||
|
||||
/* Get the request and client thread. */
|
||||
KSessionRequest *request;
|
||||
@@ -973,17 +973,17 @@ namespace ams::kern {
|
||||
KScopedSchedulerLock sl;
|
||||
|
||||
/* Ensure that we can service the request. */
|
||||
R_UNLESS(!this->parent->IsClientClosed(), svc::ResultSessionClosed());
|
||||
R_UNLESS(!m_parent->IsClientClosed(), svc::ResultSessionClosed());
|
||||
|
||||
/* Ensure we aren't already servicing a request. */
|
||||
R_UNLESS(this->current_request == nullptr, svc::ResultNotFound());
|
||||
R_UNLESS(m_current_request == nullptr, svc::ResultNotFound());
|
||||
|
||||
/* Ensure we have a request to service. */
|
||||
R_UNLESS(!this->request_list.empty(), svc::ResultNotFound());
|
||||
R_UNLESS(!m_request_list.empty(), svc::ResultNotFound());
|
||||
|
||||
/* Pop the first request from the list. */
|
||||
request = std::addressof(this->request_list.front());
|
||||
this->request_list.pop_front();
|
||||
request = std::addressof(m_request_list.front());
|
||||
m_request_list.pop_front();
|
||||
|
||||
/* Get the thread for the request. */
|
||||
client_thread = KScopedAutoObject<KThread>(request->GetThread());
|
||||
@@ -991,7 +991,7 @@ namespace ams::kern {
|
||||
}
|
||||
|
||||
/* Set the request as our current. */
|
||||
this->current_request = request;
|
||||
m_current_request = request;
|
||||
|
||||
/* Get the client address. */
|
||||
uintptr_t client_message = request->GetAddress();
|
||||
@@ -1009,9 +1009,9 @@ namespace ams::kern {
|
||||
/* Clear the current request. */
|
||||
{
|
||||
KScopedSchedulerLock sl;
|
||||
MESOSPHERE_ASSERT(this->current_request == request);
|
||||
this->current_request = nullptr;
|
||||
if (!this->request_list.empty()) {
|
||||
MESOSPHERE_ASSERT(m_current_request == request);
|
||||
m_current_request = nullptr;
|
||||
if (!m_request_list.empty()) {
|
||||
this->NotifyAvailable();
|
||||
}
|
||||
}
|
||||
@@ -1063,7 +1063,7 @@ namespace ams::kern {
|
||||
MESOSPHERE_ASSERT_THIS();
|
||||
|
||||
/* Lock the session. */
|
||||
KScopedLightLock lk(this->lock);
|
||||
KScopedLightLock lk(m_lock);
|
||||
|
||||
/* Get the request. */
|
||||
KSessionRequest *request;
|
||||
@@ -1071,12 +1071,12 @@ namespace ams::kern {
|
||||
KScopedSchedulerLock sl;
|
||||
|
||||
/* Get the current request. */
|
||||
request = this->current_request;
|
||||
request = m_current_request;
|
||||
R_UNLESS(request != nullptr, svc::ResultInvalidState());
|
||||
|
||||
/* Clear the current request, since we're processing it. */
|
||||
this->current_request = nullptr;
|
||||
if (!this->request_list.empty()) {
|
||||
m_current_request = nullptr;
|
||||
if (!m_request_list.empty()) {
|
||||
this->NotifyAvailable();
|
||||
}
|
||||
}
|
||||
@@ -1091,7 +1091,7 @@ namespace ams::kern {
|
||||
KWritableEvent *event = request->GetEvent();
|
||||
|
||||
/* Check whether we're closed. */
|
||||
const bool closed = (client_thread == nullptr || this->parent->IsClientClosed());
|
||||
const bool closed = (client_thread == nullptr || m_parent->IsClientClosed());
|
||||
|
||||
Result result;
|
||||
if (!closed) {
|
||||
@@ -1160,7 +1160,7 @@ namespace ams::kern {
|
||||
MESOSPHERE_ASSERT(KScheduler::IsSchedulerLockedByCurrentThread());
|
||||
|
||||
/* Ensure that we can handle new requests. */
|
||||
R_UNLESS(!this->parent->IsServerClosed(), svc::ResultSessionClosed());
|
||||
R_UNLESS(!m_parent->IsServerClosed(), svc::ResultSessionClosed());
|
||||
|
||||
/* If there's no event, this is synchronous, so we should check for thread termination. */
|
||||
if (request->GetEvent() == nullptr) {
|
||||
@@ -1170,11 +1170,11 @@ namespace ams::kern {
|
||||
}
|
||||
|
||||
/* Get whether we're empty. */
|
||||
const bool was_empty = this->request_list.empty();
|
||||
const bool was_empty = m_request_list.empty();
|
||||
|
||||
/* Add the request to the list. */
|
||||
request->Open();
|
||||
this->request_list.push_back(*request);
|
||||
m_request_list.push_back(*request);
|
||||
|
||||
/* If we were empty, signal. */
|
||||
if (was_empty) {
|
||||
@@ -1189,12 +1189,12 @@ namespace ams::kern {
|
||||
MESOSPHERE_ASSERT(KScheduler::IsSchedulerLockedByCurrentThread());
|
||||
|
||||
/* If the client is closed, we're always signaled. */
|
||||
if (this->parent->IsClientClosed()) {
|
||||
if (m_parent->IsClientClosed()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Otherwise, we're signaled if we have a request and aren't handling one. */
|
||||
return !this->request_list.empty() && this->current_request == nullptr;
|
||||
return !m_request_list.empty() && m_current_request == nullptr;
|
||||
}
|
||||
|
||||
bool KServerSession::IsSignaled() const {
|
||||
@@ -1207,7 +1207,7 @@ namespace ams::kern {
|
||||
void KServerSession::CleanupRequests() {
|
||||
MESOSPHERE_ASSERT_THIS();
|
||||
|
||||
KScopedLightLock lk(this->lock);
|
||||
KScopedLightLock lk(m_lock);
|
||||
|
||||
/* Clean up any pending requests. */
|
||||
while (true) {
|
||||
@@ -1216,14 +1216,14 @@ namespace ams::kern {
|
||||
{
|
||||
KScopedSchedulerLock sl;
|
||||
|
||||
if (this->current_request) {
|
||||
if (m_current_request) {
|
||||
/* Choose the current request if we have one. */
|
||||
request = this->current_request;
|
||||
this->current_request = nullptr;
|
||||
} else if (!this->request_list.empty()) {
|
||||
request = m_current_request;
|
||||
m_current_request = nullptr;
|
||||
} else if (!m_request_list.empty()) {
|
||||
/* Pop the request from the front of the list. */
|
||||
request = std::addressof(this->request_list.front());
|
||||
this->request_list.pop_front();
|
||||
request = std::addressof(m_request_list.front());
|
||||
m_request_list.pop_front();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1275,7 +1275,7 @@ namespace ams::kern {
|
||||
void KServerSession::OnClientClosed() {
|
||||
MESOSPHERE_ASSERT_THIS();
|
||||
|
||||
KScopedLightLock lk(this->lock);
|
||||
KScopedLightLock lk(m_lock);
|
||||
|
||||
/* Handle any pending requests. */
|
||||
KSessionRequest *prev_request = nullptr;
|
||||
@@ -1291,9 +1291,9 @@ namespace ams::kern {
|
||||
{
|
||||
KScopedSchedulerLock sl;
|
||||
|
||||
if (this->current_request != nullptr && this->current_request != prev_request) {
|
||||
if (m_current_request != nullptr && m_current_request != prev_request) {
|
||||
/* Set the request, open a reference as we process it. */
|
||||
request = this->current_request;
|
||||
request = m_current_request;
|
||||
request->Open();
|
||||
cur_request = true;
|
||||
|
||||
@@ -1308,10 +1308,10 @@ namespace ams::kern {
|
||||
terminate = true;
|
||||
}
|
||||
prev_request = request;
|
||||
} else if (!this->request_list.empty()) {
|
||||
} else if (!m_request_list.empty()) {
|
||||
/* Pop the request from the front of the list. */
|
||||
request = std::addressof(this->request_list.front());
|
||||
this->request_list.pop_front();
|
||||
request = std::addressof(m_request_list.front());
|
||||
m_request_list.pop_front();
|
||||
|
||||
/* Get thread and event for the request. */
|
||||
thread = request->GetThread();
|
||||
@@ -1370,25 +1370,25 @@ namespace ams::kern {
|
||||
void KServerSession::Dump() {
|
||||
MESOSPHERE_ASSERT_THIS();
|
||||
|
||||
KScopedLightLock lk(this->lock);
|
||||
KScopedLightLock lk(m_lock);
|
||||
{
|
||||
KScopedSchedulerLock sl;
|
||||
MESOSPHERE_RELEASE_LOG("Dump Session %p\n", this);
|
||||
|
||||
/* Dump current request. */
|
||||
bool has_request = false;
|
||||
if (this->current_request != nullptr) {
|
||||
KThread *thread = this->current_request->GetThread();
|
||||
if (m_current_request != nullptr) {
|
||||
KThread *thread = m_current_request->GetThread();
|
||||
const s32 thread_id = thread != nullptr ? static_cast<s32>(thread->GetId()) : -1;
|
||||
MESOSPHERE_RELEASE_LOG(" CurrentReq %p Thread=%p ID=%d\n", this->current_request, thread, thread_id);
|
||||
MESOSPHERE_RELEASE_LOG(" CurrentReq %p Thread=%p ID=%d\n", m_current_request, thread, thread_id);
|
||||
has_request = true;
|
||||
}
|
||||
|
||||
/* Dump all rqeuests in list. */
|
||||
for (auto it = this->request_list.begin(); it != this->request_list.end(); ++it) {
|
||||
for (auto it = m_request_list.begin(); it != m_request_list.end(); ++it) {
|
||||
KThread *thread = it->GetThread();
|
||||
const s32 thread_id = thread != nullptr ? static_cast<s32>(thread->GetId()) : -1;
|
||||
MESOSPHERE_RELEASE_LOG(" Req %p Thread=%p ID=%d\n", this->current_request, thread, thread_id);
|
||||
MESOSPHERE_RELEASE_LOG(" Req %p Thread=%p ID=%d\n", m_current_request, thread, thread_id);
|
||||
has_request = true;
|
||||
}
|
||||
|
||||
|
||||
@@ -27,53 +27,53 @@ namespace ams::kern {
|
||||
this->Open();
|
||||
|
||||
/* Create our sub sessions. */
|
||||
KAutoObject::Create(std::addressof(this->server));
|
||||
KAutoObject::Create(std::addressof(this->client));
|
||||
KAutoObject::Create(std::addressof(m_server));
|
||||
KAutoObject::Create(std::addressof(m_client));
|
||||
|
||||
/* Initialize our sub sessions. */
|
||||
this->server.Initialize(this);
|
||||
this->client.Initialize(this);
|
||||
m_server.Initialize(this);
|
||||
m_client.Initialize(this);
|
||||
|
||||
/* Set state and name. */
|
||||
this->state = State::Normal;
|
||||
this->name = name;
|
||||
m_state = State::Normal;
|
||||
m_name = name;
|
||||
|
||||
/* Set our owner process. */
|
||||
this->process = GetCurrentProcessPointer();
|
||||
this->process->Open();
|
||||
m_process = GetCurrentProcessPointer();
|
||||
m_process->Open();
|
||||
|
||||
/* Set our port. */
|
||||
this->port = client_port;
|
||||
if (this->port != nullptr) {
|
||||
this->port->Open();
|
||||
m_port = client_port;
|
||||
if (m_port != nullptr) {
|
||||
m_port->Open();
|
||||
}
|
||||
|
||||
/* Mark initialized. */
|
||||
this->initialized = true;
|
||||
m_initialized = true;
|
||||
}
|
||||
|
||||
void KSession::Finalize() {
|
||||
if (this->port != nullptr) {
|
||||
this->port->OnSessionFinalized();
|
||||
this->port->Close();
|
||||
if (m_port != nullptr) {
|
||||
m_port->OnSessionFinalized();
|
||||
m_port->Close();
|
||||
}
|
||||
}
|
||||
|
||||
void KSession::OnServerClosed() {
|
||||
MESOSPHERE_ASSERT_THIS();
|
||||
|
||||
if (this->state == State::Normal) {
|
||||
this->state = State::ServerClosed;
|
||||
this->client.OnServerClosed();
|
||||
if (m_state == State::Normal) {
|
||||
m_state = State::ServerClosed;
|
||||
m_client.OnServerClosed();
|
||||
}
|
||||
}
|
||||
|
||||
void KSession::OnClientClosed() {
|
||||
MESOSPHERE_ASSERT_THIS();
|
||||
|
||||
if (this->state == State::Normal) {
|
||||
this->state = State::ClientClosed;
|
||||
this->server.OnClientClosed();
|
||||
if (m_state == State::Normal) {
|
||||
m_state = State::ClientClosed;
|
||||
m_server.OnClientClosed();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -24,17 +24,17 @@ namespace ams::kern {
|
||||
/* Get the mapping. */
|
||||
Mapping *mapping;
|
||||
if (index < NumStaticMappings) {
|
||||
mapping = std::addressof(this->static_mappings[index]);
|
||||
mapping = std::addressof(m_static_mappings[index]);
|
||||
} else {
|
||||
/* Allocate a page for the extra mappings. */
|
||||
if (this->mappings == nullptr) {
|
||||
if (m_mappings == nullptr) {
|
||||
KPageBuffer *page_buffer = KPageBuffer::Allocate();
|
||||
R_UNLESS(page_buffer != nullptr, svc::ResultOutOfMemory());
|
||||
|
||||
this->mappings = reinterpret_cast<Mapping *>(page_buffer);
|
||||
m_mappings = reinterpret_cast<Mapping *>(page_buffer);
|
||||
}
|
||||
|
||||
mapping = std::addressof(this->mappings[index - NumStaticMappings]);
|
||||
mapping = std::addressof(m_mappings[index - NumStaticMappings]);
|
||||
}
|
||||
|
||||
/* Set the mapping. */
|
||||
@@ -44,24 +44,24 @@ namespace ams::kern {
|
||||
}
|
||||
|
||||
Result KSessionRequest::SessionMappings::PushSend(KProcessAddress client, KProcessAddress server, size_t size, KMemoryState state) {
|
||||
MESOSPHERE_ASSERT(this->num_recv == 0);
|
||||
MESOSPHERE_ASSERT(this->num_exch == 0);
|
||||
return this->PushMap(client, server, size, state, this->num_send++);
|
||||
MESOSPHERE_ASSERT(m_num_recv == 0);
|
||||
MESOSPHERE_ASSERT(m_num_exch == 0);
|
||||
return this->PushMap(client, server, size, state, m_num_send++);
|
||||
}
|
||||
|
||||
Result KSessionRequest::SessionMappings::PushReceive(KProcessAddress client, KProcessAddress server, size_t size, KMemoryState state) {
|
||||
MESOSPHERE_ASSERT(this->num_exch == 0);
|
||||
return this->PushMap(client, server, size, state, this->num_send + this->num_recv++);
|
||||
MESOSPHERE_ASSERT(m_num_exch == 0);
|
||||
return this->PushMap(client, server, size, state, m_num_send + m_num_recv++);
|
||||
}
|
||||
|
||||
Result KSessionRequest::SessionMappings::PushExchange(KProcessAddress client, KProcessAddress server, size_t size, KMemoryState state) {
|
||||
return this->PushMap(client, server, size, state, this->num_send + this->num_recv + this->num_exch++);
|
||||
return this->PushMap(client, server, size, state, m_num_send + m_num_recv + m_num_exch++);
|
||||
}
|
||||
|
||||
void KSessionRequest::SessionMappings::Finalize() {
|
||||
if (this->mappings) {
|
||||
KPageBuffer::Free(reinterpret_cast<KPageBuffer *>(this->mappings));
|
||||
this->mappings = nullptr;
|
||||
if (m_mappings) {
|
||||
KPageBuffer::Free(reinterpret_cast<KPageBuffer *>(m_mappings));
|
||||
m_mappings = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -21,9 +21,9 @@ namespace ams::kern {
|
||||
MESOSPHERE_ASSERT_THIS();
|
||||
|
||||
/* Set members. */
|
||||
this->owner_process_id = owner->GetId();
|
||||
this->owner_perm = own_perm;
|
||||
this->remote_perm = rem_perm;
|
||||
m_owner_process_id = owner->GetId();
|
||||
m_owner_perm = own_perm;
|
||||
m_remote_perm = rem_perm;
|
||||
|
||||
/* Get the number of pages. */
|
||||
const size_t num_pages = util::DivideUp(size, PageSize);
|
||||
@@ -37,20 +37,20 @@ namespace ams::kern {
|
||||
R_UNLESS(memory_reservation.Succeeded(), svc::ResultLimitReached());
|
||||
|
||||
/* Allocate the memory. */
|
||||
R_TRY(Kernel::GetMemoryManager().AllocateAndOpen(std::addressof(this->page_group), num_pages, owner->GetAllocateOption()));
|
||||
R_TRY(Kernel::GetMemoryManager().AllocateAndOpen(std::addressof(m_page_group), num_pages, owner->GetAllocateOption()));
|
||||
|
||||
/* Commit our reservation. */
|
||||
memory_reservation.Commit();
|
||||
|
||||
/* Set our resource limit. */
|
||||
this->resource_limit = reslimit;
|
||||
this->resource_limit->Open();
|
||||
m_resource_limit = reslimit;
|
||||
m_resource_limit->Open();
|
||||
|
||||
/* Mark initialized. */
|
||||
this->is_initialized = true;
|
||||
m_is_initialized = true;
|
||||
|
||||
/* Clear all pages in the memory. */
|
||||
for (const auto &block : this->page_group) {
|
||||
for (const auto &block : m_page_group) {
|
||||
std::memset(GetVoidPointer(block.GetAddress()), 0, block.GetSize());
|
||||
}
|
||||
|
||||
@@ -61,16 +61,16 @@ namespace ams::kern {
|
||||
MESOSPHERE_ASSERT_THIS();
|
||||
|
||||
/* Get the number of pages. */
|
||||
const size_t num_pages = this->page_group.GetNumPages();
|
||||
const size_t num_pages = m_page_group.GetNumPages();
|
||||
const size_t size = num_pages * PageSize;
|
||||
|
||||
/* Close and finalize the page group. */
|
||||
this->page_group.Close();
|
||||
this->page_group.Finalize();
|
||||
m_page_group.Close();
|
||||
m_page_group.Finalize();
|
||||
|
||||
/* Release the memory reservation. */
|
||||
this->resource_limit->Release(ams::svc::LimitableResource_PhysicalMemoryMax, size);
|
||||
this->resource_limit->Close();
|
||||
m_resource_limit->Release(ams::svc::LimitableResource_PhysicalMemoryMax, size);
|
||||
m_resource_limit->Close();
|
||||
|
||||
/* Perform inherited finalization. */
|
||||
KAutoObjectWithSlabHeapAndContainer<KSharedMemory, KAutoObjectWithList>::Finalize();
|
||||
@@ -80,10 +80,10 @@ namespace ams::kern {
|
||||
MESOSPHERE_ASSERT_THIS();
|
||||
|
||||
/* Validate the size. */
|
||||
R_UNLESS(this->page_group.GetNumPages() == util::DivideUp(size, PageSize), svc::ResultInvalidSize());
|
||||
R_UNLESS(m_page_group.GetNumPages() == util::DivideUp(size, PageSize), svc::ResultInvalidSize());
|
||||
|
||||
/* Validate the permission. */
|
||||
const ams::svc::MemoryPermission test_perm = (process->GetId() == this->owner_process_id) ? this->owner_perm : this->remote_perm;
|
||||
const ams::svc::MemoryPermission test_perm = (process->GetId() == m_owner_process_id) ? m_owner_perm : m_remote_perm;
|
||||
if (test_perm == ams::svc::MemoryPermission_DontCare) {
|
||||
MESOSPHERE_ASSERT(map_perm == ams::svc::MemoryPermission_Read || map_perm == ams::svc::MemoryPermission_ReadWrite);
|
||||
} else {
|
||||
@@ -91,7 +91,7 @@ namespace ams::kern {
|
||||
}
|
||||
|
||||
/* Map the memory. */
|
||||
return table->MapPageGroup(address, this->page_group, KMemoryState_Shared, ConvertToKMemoryPermission(map_perm));
|
||||
return table->MapPageGroup(address, m_page_group, KMemoryState_Shared, ConvertToKMemoryPermission(map_perm));
|
||||
}
|
||||
|
||||
Result KSharedMemory::Unmap(KProcessPageTable *table, KProcessAddress address, size_t size, KProcess *process) {
|
||||
@@ -99,10 +99,10 @@ namespace ams::kern {
|
||||
MESOSPHERE_UNUSED(process);
|
||||
|
||||
/* Validate the size. */
|
||||
R_UNLESS(this->page_group.GetNumPages() == util::DivideUp(size, PageSize), svc::ResultInvalidSize());
|
||||
R_UNLESS(m_page_group.GetNumPages() == util::DivideUp(size, PageSize), svc::ResultInvalidSize());
|
||||
|
||||
/* Unmap the memory. */
|
||||
return table->UnmapPageGroup(address, this->page_group, KMemoryState_Shared);
|
||||
return table->UnmapPageGroup(address, m_page_group, KMemoryState_Shared);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -25,7 +25,7 @@ namespace ams::kern {
|
||||
{
|
||||
KScopedSchedulerLock sl;
|
||||
|
||||
for (auto *cur_node = this->thread_list_root; cur_node != nullptr; cur_node = cur_node->next) {
|
||||
for (auto *cur_node = m_thread_list_head; cur_node != nullptr; cur_node = cur_node->next) {
|
||||
KThread *thread = cur_node->thread;
|
||||
MESOSPHERE_LOG("KSynchronizationObject::Finalize(%p) with %p (id=%ld) waiting.\n", this, thread, thread->GetId());
|
||||
}
|
||||
@@ -83,13 +83,13 @@ namespace ams::kern {
|
||||
thread_nodes[i].thread = thread;
|
||||
thread_nodes[i].next = nullptr;
|
||||
|
||||
if (objects[i]->thread_list_tail == nullptr) {
|
||||
objects[i]->thread_list_head = std::addressof(thread_nodes[i]);
|
||||
if (objects[i]->m_thread_list_tail == nullptr) {
|
||||
objects[i]->m_thread_list_head = std::addressof(thread_nodes[i]);
|
||||
} else {
|
||||
objects[i]->thread_list_tail->next = std::addressof(thread_nodes[i]);
|
||||
objects[i]->m_thread_list_tail->next = std::addressof(thread_nodes[i]);
|
||||
}
|
||||
|
||||
objects[i]->thread_list_tail = std::addressof(thread_nodes[i]);
|
||||
objects[i]->m_thread_list_tail = std::addressof(thread_nodes[i]);
|
||||
}
|
||||
|
||||
/* Mark the thread as waiting. */
|
||||
@@ -118,7 +118,7 @@ namespace ams::kern {
|
||||
|
||||
for (auto i = 0; i < num_objects; ++i) {
|
||||
/* Unlink the object from the list. */
|
||||
ThreadListNode *prev_ptr = reinterpret_cast<ThreadListNode *>(std::addressof(objects[i]->thread_list_head));
|
||||
ThreadListNode *prev_ptr = reinterpret_cast<ThreadListNode *>(std::addressof(objects[i]->m_thread_list_head));
|
||||
ThreadListNode *prev_val = nullptr;
|
||||
ThreadListNode *prev, *tail_prev;
|
||||
|
||||
@@ -129,8 +129,8 @@ namespace ams::kern {
|
||||
prev_val = prev_ptr;
|
||||
} while (prev_ptr != std::addressof(thread_nodes[i]));
|
||||
|
||||
if (objects[i]->thread_list_tail == std::addressof(thread_nodes[i])) {
|
||||
objects[i]->thread_list_tail = tail_prev;
|
||||
if (objects[i]->m_thread_list_tail == std::addressof(thread_nodes[i])) {
|
||||
objects[i]->m_thread_list_tail = tail_prev;
|
||||
}
|
||||
|
||||
prev->next = thread_nodes[i].next;
|
||||
@@ -157,7 +157,7 @@ namespace ams::kern {
|
||||
}
|
||||
|
||||
/* Iterate over each thread. */
|
||||
for (auto *cur_node = this->thread_list_head; cur_node != nullptr; cur_node = cur_node->next) {
|
||||
for (auto *cur_node = m_thread_list_head; cur_node != nullptr; cur_node = cur_node->next) {
|
||||
KThread *thread = cur_node->thread;
|
||||
if (thread->GetState() == KThread::ThreadState_Waiting) {
|
||||
thread->SetSyncedObject(this, result);
|
||||
@@ -176,7 +176,7 @@ namespace ams::kern {
|
||||
|
||||
MESOSPHERE_RELEASE_LOG("Threads waiting on %p:\n", this);
|
||||
|
||||
for (auto *cur_node = this->thread_list_head; cur_node != nullptr; cur_node = cur_node->next) {
|
||||
for (auto *cur_node = m_thread_list_head; cur_node != nullptr; cur_node = cur_node->next) {
|
||||
KThread *thread = cur_node->thread;
|
||||
|
||||
if (KProcess *process = thread->GetOwnerProcess(); process != nullptr) {
|
||||
@@ -187,7 +187,7 @@ namespace ams::kern {
|
||||
}
|
||||
|
||||
/* If we didn't have any waiters, print so. */
|
||||
if (this->thread_list_head == nullptr) {
|
||||
if (m_thread_list_head == nullptr) {
|
||||
MESOSPHERE_RELEASE_LOG(" None\n");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -60,7 +60,7 @@ namespace ams::kern {
|
||||
MESOSPHERE_ASSERT(0 <= phys_core && phys_core < static_cast<s32>(cpu::NumCores));
|
||||
|
||||
/* First, clear the TLS address. */
|
||||
this->tls_address = Null<KProcessAddress>;
|
||||
m_tls_address = Null<KProcessAddress>;
|
||||
|
||||
const uintptr_t kern_stack_top_address = reinterpret_cast<uintptr_t>(kern_stack_top);
|
||||
|
||||
@@ -94,73 +94,73 @@ namespace ams::kern {
|
||||
}
|
||||
|
||||
/* Set the ideal core ID and affinity mask. */
|
||||
this->virtual_ideal_core_id = virt_core;
|
||||
this->physical_ideal_core_id = phys_core;
|
||||
this->virtual_affinity_mask = (static_cast<u64>(1) << virt_core);
|
||||
this->physical_affinity_mask.SetAffinity(phys_core, true);
|
||||
m_virtual_ideal_core_id = virt_core;
|
||||
m_physical_ideal_core_id = phys_core;
|
||||
m_virtual_affinity_mask = (static_cast<u64>(1) << virt_core);
|
||||
m_physical_affinity_mask.SetAffinity(phys_core, true);
|
||||
|
||||
/* Set the thread state. */
|
||||
this->thread_state = (type == ThreadType_Main) ? ThreadState_Runnable : ThreadState_Initialized;
|
||||
m_thread_state = (type == ThreadType_Main) ? ThreadState_Runnable : ThreadState_Initialized;
|
||||
|
||||
/* Set TLS address and TLS heap address. */
|
||||
/* NOTE: Nintendo wrote TLS address above already, but official code really does write tls address twice. */
|
||||
this->tls_address = 0;
|
||||
this->tls_heap_address = 0;
|
||||
m_tls_address = 0;
|
||||
m_tls_heap_address = 0;
|
||||
|
||||
/* Set parent and condvar tree. */
|
||||
this->parent = nullptr;
|
||||
this->condvar_tree = nullptr;
|
||||
m_parent = nullptr;
|
||||
m_condvar_tree = nullptr;
|
||||
|
||||
/* Set sync booleans. */
|
||||
this->signaled = false;
|
||||
this->termination_requested = false;
|
||||
this->wait_cancelled = false;
|
||||
this->cancellable = false;
|
||||
m_signaled = false;
|
||||
m_termination_requested = false;
|
||||
m_wait_cancelled = false;
|
||||
m_cancellable = false;
|
||||
|
||||
/* Set core ID and wait result. */
|
||||
this->core_id = phys_core;
|
||||
this->wait_result = svc::ResultNoSynchronizationObject();
|
||||
m_core_id = phys_core;
|
||||
m_wait_result = svc::ResultNoSynchronizationObject();
|
||||
|
||||
/* Set the stack top. */
|
||||
this->kernel_stack_top = kern_stack_top;
|
||||
m_kernel_stack_top = kern_stack_top;
|
||||
|
||||
/* Set priorities. */
|
||||
this->priority = prio;
|
||||
this->base_priority = prio;
|
||||
m_priority = prio;
|
||||
m_base_priority = prio;
|
||||
|
||||
/* Set sync object and waiting lock to null. */
|
||||
this->synced_object = nullptr;
|
||||
this->waiting_lock = nullptr;
|
||||
m_synced_object = nullptr;
|
||||
m_waiting_lock = nullptr;
|
||||
|
||||
/* Initialize sleeping queue. */
|
||||
this->sleeping_queue = nullptr;
|
||||
m_sleeping_queue = nullptr;
|
||||
|
||||
/* Set suspend flags. */
|
||||
this->suspend_request_flags = 0;
|
||||
this->suspend_allowed_flags = ThreadState_SuspendFlagMask;
|
||||
m_suspend_request_flags = 0;
|
||||
m_suspend_allowed_flags = ThreadState_SuspendFlagMask;
|
||||
|
||||
/* We're neither debug attached, nor are we nesting our priority inheritance. */
|
||||
this->debug_attached = false;
|
||||
this->priority_inheritance_count = 0;
|
||||
m_debug_attached = false;
|
||||
m_priority_inheritance_count = 0;
|
||||
|
||||
/* We haven't been scheduled, and we have done no light IPC. */
|
||||
this->schedule_count = -1;
|
||||
this->last_scheduled_tick = 0;
|
||||
this->light_ipc_data = nullptr;
|
||||
m_schedule_count = -1;
|
||||
m_last_scheduled_tick = 0;
|
||||
m_light_ipc_data = nullptr;
|
||||
|
||||
/* We're not waiting for a lock, and we haven't disabled migration. */
|
||||
this->lock_owner = nullptr;
|
||||
this->num_core_migration_disables = 0;
|
||||
m_lock_owner = nullptr;
|
||||
m_num_core_migration_disables = 0;
|
||||
|
||||
/* We have no waiters, but we do have an entrypoint. */
|
||||
this->num_kernel_waiters = 0;
|
||||
m_num_kernel_waiters = 0;
|
||||
|
||||
/* Set our current core id. */
|
||||
this->current_core_id = phys_core;
|
||||
m_current_core_id = phys_core;
|
||||
|
||||
/* We haven't released our resource limit hint, and we've spent no time on the cpu. */
|
||||
this->resource_limit_release_hint = 0;
|
||||
this->cpu_time = 0;
|
||||
m_resource_limit_release_hint = 0;
|
||||
m_cpu_time = 0;
|
||||
|
||||
/* Setup our kernel stack. */
|
||||
if (type != ThreadType_Main) {
|
||||
@@ -172,45 +172,45 @@ namespace ams::kern {
|
||||
|
||||
/* Setup the TLS, if needed. */
|
||||
if (type == ThreadType_User) {
|
||||
R_TRY(owner->CreateThreadLocalRegion(std::addressof(this->tls_address)));
|
||||
this->tls_heap_address = owner->GetThreadLocalRegionPointer(this->tls_address);
|
||||
std::memset(this->tls_heap_address, 0, ams::svc::ThreadLocalRegionSize);
|
||||
R_TRY(owner->CreateThreadLocalRegion(std::addressof(m_tls_address)));
|
||||
m_tls_heap_address = owner->GetThreadLocalRegionPointer(m_tls_address);
|
||||
std::memset(m_tls_heap_address, 0, ams::svc::ThreadLocalRegionSize);
|
||||
}
|
||||
|
||||
/* Set parent, if relevant. */
|
||||
if (owner != nullptr) {
|
||||
this->parent = owner;
|
||||
this->parent->Open();
|
||||
this->parent->IncrementThreadCount();
|
||||
m_parent = owner;
|
||||
m_parent->Open();
|
||||
m_parent->IncrementThreadCount();
|
||||
}
|
||||
|
||||
/* Initialize thread context. */
|
||||
constexpr bool IsDefault64Bit = sizeof(uintptr_t) == sizeof(u64);
|
||||
const bool is_64_bit = this->parent ? this->parent->Is64Bit() : IsDefault64Bit;
|
||||
const bool is_64_bit = m_parent ? m_parent->Is64Bit() : IsDefault64Bit;
|
||||
const bool is_user = (type == ThreadType_User);
|
||||
const bool is_main = (type == ThreadType_Main);
|
||||
this->thread_context.Initialize(reinterpret_cast<uintptr_t>(func), reinterpret_cast<uintptr_t>(this->GetStackTop()), GetInteger(user_stack_top), arg, is_user, is_64_bit, is_main);
|
||||
m_thread_context.Initialize(reinterpret_cast<uintptr_t>(func), reinterpret_cast<uintptr_t>(this->GetStackTop()), GetInteger(user_stack_top), arg, is_user, is_64_bit, is_main);
|
||||
|
||||
/* Setup the stack parameters. */
|
||||
StackParameters &sp = this->GetStackParameters();
|
||||
if (this->parent != nullptr) {
|
||||
this->parent->CopySvcPermissionsTo(sp);
|
||||
if (m_parent != nullptr) {
|
||||
m_parent->CopySvcPermissionsTo(sp);
|
||||
}
|
||||
sp.context = std::addressof(this->thread_context);
|
||||
sp.context = std::addressof(m_thread_context);
|
||||
sp.cur_thread = this;
|
||||
sp.disable_count = 1;
|
||||
this->SetInExceptionHandler();
|
||||
|
||||
/* Set thread ID. */
|
||||
this->thread_id = s_next_thread_id++;
|
||||
m_thread_id = s_next_thread_id++;
|
||||
|
||||
/* We initialized! */
|
||||
this->initialized = true;
|
||||
m_initialized = true;
|
||||
|
||||
/* Register ourselves with our parent process. */
|
||||
if (this->parent != nullptr) {
|
||||
this->parent->RegisterThread(this);
|
||||
if (this->parent->IsSuspended()) {
|
||||
if (m_parent != nullptr) {
|
||||
m_parent->RegisterThread(this);
|
||||
if (m_parent->IsSuspended()) {
|
||||
this->RequestSuspend(SuspendType_Process);
|
||||
}
|
||||
}
|
||||
@@ -276,42 +276,42 @@ namespace ams::kern {
|
||||
MESOSPHERE_ASSERT_THIS();
|
||||
|
||||
/* If the thread has an owner process, unregister it. */
|
||||
if (this->parent != nullptr) {
|
||||
this->parent->UnregisterThread(this);
|
||||
if (m_parent != nullptr) {
|
||||
m_parent->UnregisterThread(this);
|
||||
}
|
||||
|
||||
/* If the thread has a local region, delete it. */
|
||||
if (this->tls_address != Null<KProcessAddress>) {
|
||||
MESOSPHERE_R_ABORT_UNLESS(this->parent->DeleteThreadLocalRegion(this->tls_address));
|
||||
if (m_tls_address != Null<KProcessAddress>) {
|
||||
MESOSPHERE_R_ABORT_UNLESS(m_parent->DeleteThreadLocalRegion(m_tls_address));
|
||||
}
|
||||
|
||||
/* Release any waiters. */
|
||||
{
|
||||
MESOSPHERE_ASSERT(this->lock_owner == nullptr);
|
||||
MESOSPHERE_ASSERT(m_lock_owner == nullptr);
|
||||
KScopedSchedulerLock sl;
|
||||
|
||||
auto it = this->waiter_list.begin();
|
||||
while (it != this->waiter_list.end()) {
|
||||
auto it = m_waiter_list.begin();
|
||||
while (it != m_waiter_list.end()) {
|
||||
/* The thread shouldn't be a kernel waiter. */
|
||||
MESOSPHERE_ASSERT(!IsKernelAddressKey(it->GetAddressKey()));
|
||||
it->SetLockOwner(nullptr);
|
||||
it->SetSyncedObject(nullptr, svc::ResultInvalidState());
|
||||
it->Wakeup();
|
||||
it = this->waiter_list.erase(it);
|
||||
it = m_waiter_list.erase(it);
|
||||
}
|
||||
}
|
||||
|
||||
/* Finalize the thread context. */
|
||||
this->thread_context.Finalize();
|
||||
m_thread_context.Finalize();
|
||||
|
||||
/* Cleanup the kernel stack. */
|
||||
if (this->kernel_stack_top != nullptr) {
|
||||
CleanupKernelStack(reinterpret_cast<uintptr_t>(this->kernel_stack_top));
|
||||
if (m_kernel_stack_top != nullptr) {
|
||||
CleanupKernelStack(reinterpret_cast<uintptr_t>(m_kernel_stack_top));
|
||||
}
|
||||
|
||||
/* Decrement the parent process's thread count. */
|
||||
if (this->parent != nullptr) {
|
||||
this->parent->DecrementThreadCount();
|
||||
if (m_parent != nullptr) {
|
||||
m_parent->DecrementThreadCount();
|
||||
}
|
||||
|
||||
/* Perform inherited finalization. */
|
||||
@@ -319,7 +319,7 @@ namespace ams::kern {
|
||||
}
|
||||
|
||||
bool KThread::IsSignaled() const {
|
||||
return this->signaled;
|
||||
return m_signaled;
|
||||
}
|
||||
|
||||
void KThread::Wakeup() {
|
||||
@@ -327,8 +327,8 @@ namespace ams::kern {
|
||||
KScopedSchedulerLock sl;
|
||||
|
||||
if (this->GetState() == ThreadState_Waiting) {
|
||||
if (this->sleeping_queue != nullptr) {
|
||||
this->sleeping_queue->WakeupThread(this);
|
||||
if (m_sleeping_queue != nullptr) {
|
||||
m_sleeping_queue->WakeupThread(this);
|
||||
} else {
|
||||
this->SetState(ThreadState_Runnable);
|
||||
}
|
||||
@@ -347,10 +347,10 @@ namespace ams::kern {
|
||||
MESOSPHERE_ASSERT(KScheduler::IsSchedulerLockedByCurrentThread());
|
||||
|
||||
/* Release user exception and unpin, if relevant. */
|
||||
if (this->parent != nullptr) {
|
||||
this->parent->ReleaseUserException(this);
|
||||
if (this->parent->GetPinnedThread(GetCurrentCoreId()) == this) {
|
||||
this->parent->UnpinCurrentThread();
|
||||
if (m_parent != nullptr) {
|
||||
m_parent->ReleaseUserException(this);
|
||||
if (m_parent->GetPinnedThread(GetCurrentCoreId()) == this) {
|
||||
m_parent->UnpinCurrentThread();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -358,12 +358,12 @@ namespace ams::kern {
|
||||
this->SetState(KThread::ThreadState_Terminated);
|
||||
|
||||
/* Clear the thread's status as running in parent. */
|
||||
if (this->parent != nullptr) {
|
||||
this->parent->ClearRunningThread(this);
|
||||
if (m_parent != nullptr) {
|
||||
m_parent->ClearRunningThread(this);
|
||||
}
|
||||
|
||||
/* Signal. */
|
||||
this->signaled = true;
|
||||
m_signaled = true;
|
||||
this->NotifyAvailable();
|
||||
|
||||
/* Call the on thread termination handler. */
|
||||
@@ -380,7 +380,7 @@ namespace ams::kern {
|
||||
MESOSPHERE_ASSERT_THIS();
|
||||
|
||||
/* Ensure that the thread is not executing on any core. */
|
||||
if (this->parent != nullptr) {
|
||||
if (m_parent != nullptr) {
|
||||
for (size_t i = 0; i < cpu::NumCores; ++i) {
|
||||
KThread *core_thread;
|
||||
do {
|
||||
@@ -406,43 +406,43 @@ namespace ams::kern {
|
||||
this->GetStackParameters().is_pinned = true;
|
||||
|
||||
/* Disable core migration. */
|
||||
MESOSPHERE_ASSERT(this->num_core_migration_disables == 0);
|
||||
MESOSPHERE_ASSERT(m_num_core_migration_disables == 0);
|
||||
{
|
||||
++this->num_core_migration_disables;
|
||||
++m_num_core_migration_disables;
|
||||
|
||||
/* Save our ideal state to restore when we're unpinned. */
|
||||
this->original_physical_ideal_core_id = this->physical_ideal_core_id;
|
||||
this->original_physical_affinity_mask = this->physical_affinity_mask;
|
||||
m_original_physical_ideal_core_id = m_physical_ideal_core_id;
|
||||
m_original_physical_affinity_mask = m_physical_affinity_mask;
|
||||
|
||||
/* Bind ourselves to this core. */
|
||||
const s32 active_core = this->GetActiveCore();
|
||||
const s32 current_core = GetCurrentCoreId();
|
||||
|
||||
this->SetActiveCore(current_core);
|
||||
this->physical_ideal_core_id = current_core;
|
||||
this->physical_affinity_mask.SetAffinityMask(1ul << current_core);
|
||||
m_physical_ideal_core_id = current_core;
|
||||
m_physical_affinity_mask.SetAffinityMask(1ul << current_core);
|
||||
|
||||
if (active_core != current_core || this->physical_affinity_mask.GetAffinityMask() != this->original_physical_affinity_mask.GetAffinityMask()) {
|
||||
KScheduler::OnThreadAffinityMaskChanged(this, this->original_physical_affinity_mask, active_core);
|
||||
if (active_core != current_core || m_physical_affinity_mask.GetAffinityMask() != m_original_physical_affinity_mask.GetAffinityMask()) {
|
||||
KScheduler::OnThreadAffinityMaskChanged(this, m_original_physical_affinity_mask, active_core);
|
||||
}
|
||||
}
|
||||
|
||||
/* Disallow performing thread suspension. */
|
||||
{
|
||||
/* Update our allow flags. */
|
||||
this->suspend_allowed_flags &= ~(1 << (SuspendType_Thread + ThreadState_SuspendShift));
|
||||
m_suspend_allowed_flags &= ~(1 << (SuspendType_Thread + ThreadState_SuspendShift));
|
||||
|
||||
/* Update our state. */
|
||||
const ThreadState old_state = this->thread_state;
|
||||
this->thread_state = static_cast<ThreadState>(this->GetSuspendFlags() | (old_state & ThreadState_Mask));
|
||||
if (this->thread_state != old_state) {
|
||||
const ThreadState old_state = m_thread_state;
|
||||
m_thread_state = static_cast<ThreadState>(this->GetSuspendFlags() | (old_state & ThreadState_Mask));
|
||||
if (m_thread_state != old_state) {
|
||||
KScheduler::OnThreadStateChanged(this, old_state);
|
||||
}
|
||||
}
|
||||
|
||||
/* Update our SVC access permissions. */
|
||||
MESOSPHERE_ASSERT(this->parent != nullptr);
|
||||
this->parent->CopyPinnedSvcPermissionsTo(this->GetStackParameters());
|
||||
MESOSPHERE_ASSERT(m_parent != nullptr);
|
||||
m_parent->CopyPinnedSvcPermissionsTo(this->GetStackParameters());
|
||||
}
|
||||
|
||||
void KThread::Unpin() {
|
||||
@@ -453,24 +453,24 @@ namespace ams::kern {
|
||||
this->GetStackParameters().is_pinned = false;
|
||||
|
||||
/* Enable core migration. */
|
||||
MESOSPHERE_ASSERT(this->num_core_migration_disables == 1);
|
||||
MESOSPHERE_ASSERT(m_num_core_migration_disables == 1);
|
||||
{
|
||||
--this->num_core_migration_disables;
|
||||
--m_num_core_migration_disables;
|
||||
|
||||
/* Restore our original state. */
|
||||
const KAffinityMask old_mask = this->physical_affinity_mask;
|
||||
const KAffinityMask old_mask = m_physical_affinity_mask;
|
||||
|
||||
this->physical_ideal_core_id = this->original_physical_ideal_core_id;
|
||||
this->physical_affinity_mask = this->original_physical_affinity_mask;
|
||||
m_physical_ideal_core_id = m_original_physical_ideal_core_id;
|
||||
m_physical_affinity_mask = m_original_physical_affinity_mask;
|
||||
|
||||
if (this->physical_affinity_mask.GetAffinityMask() != old_mask.GetAffinityMask()) {
|
||||
if (m_physical_affinity_mask.GetAffinityMask() != old_mask.GetAffinityMask()) {
|
||||
const s32 active_core = this->GetActiveCore();
|
||||
|
||||
if (!this->physical_affinity_mask.GetAffinity(active_core)) {
|
||||
if (this->physical_ideal_core_id >= 0) {
|
||||
this->SetActiveCore(this->physical_ideal_core_id);
|
||||
if (!m_physical_affinity_mask.GetAffinity(active_core)) {
|
||||
if (m_physical_ideal_core_id >= 0) {
|
||||
this->SetActiveCore(m_physical_ideal_core_id);
|
||||
} else {
|
||||
this->SetActiveCore(BITSIZEOF(unsigned long long) - 1 - __builtin_clzll(this->physical_affinity_mask.GetAffinityMask()));
|
||||
this->SetActiveCore(BITSIZEOF(unsigned long long) - 1 - __builtin_clzll(m_physical_affinity_mask.GetAffinityMask()));
|
||||
}
|
||||
}
|
||||
KScheduler::OnThreadAffinityMaskChanged(this, old_mask, active_core);
|
||||
@@ -481,23 +481,23 @@ namespace ams::kern {
|
||||
{
|
||||
/* Update our allow flags. */
|
||||
if (!this->IsTerminationRequested()) {
|
||||
this->suspend_allowed_flags |= (1 << (SuspendType_Thread + ThreadState_SuspendShift));
|
||||
m_suspend_allowed_flags |= (1 << (SuspendType_Thread + ThreadState_SuspendShift));
|
||||
}
|
||||
|
||||
/* Update our state. */
|
||||
const ThreadState old_state = this->thread_state;
|
||||
this->thread_state = static_cast<ThreadState>(this->GetSuspendFlags() | (old_state & ThreadState_Mask));
|
||||
if (this->thread_state != old_state) {
|
||||
const ThreadState old_state = m_thread_state;
|
||||
m_thread_state = static_cast<ThreadState>(this->GetSuspendFlags() | (old_state & ThreadState_Mask));
|
||||
if (m_thread_state != old_state) {
|
||||
KScheduler::OnThreadStateChanged(this, old_state);
|
||||
}
|
||||
}
|
||||
|
||||
/* Update our SVC access permissions. */
|
||||
MESOSPHERE_ASSERT(this->parent != nullptr);
|
||||
this->parent->CopyUnpinnedSvcPermissionsTo(this->GetStackParameters());
|
||||
MESOSPHERE_ASSERT(m_parent != nullptr);
|
||||
m_parent->CopyUnpinnedSvcPermissionsTo(this->GetStackParameters());
|
||||
|
||||
/* Resume any threads that began waiting on us while we were pinned. */
|
||||
for (auto it = this->pinned_waiter_list.begin(); it != this->pinned_waiter_list.end(); ++it) {
|
||||
for (auto it = m_pinned_waiter_list.begin(); it != m_pinned_waiter_list.end(); ++it) {
|
||||
if (it->GetState() == ThreadState_Waiting) {
|
||||
it->SetState(ThreadState_Runnable);
|
||||
}
|
||||
@@ -509,19 +509,19 @@ namespace ams::kern {
|
||||
MESOSPHERE_ASSERT(this == GetCurrentThreadPointer());
|
||||
|
||||
KScopedSchedulerLock sl;
|
||||
MESOSPHERE_ASSERT(this->num_core_migration_disables >= 0);
|
||||
if ((this->num_core_migration_disables++) == 0) {
|
||||
MESOSPHERE_ASSERT(m_num_core_migration_disables >= 0);
|
||||
if ((m_num_core_migration_disables++) == 0) {
|
||||
/* Save our ideal state to restore when we can migrate again. */
|
||||
this->original_physical_ideal_core_id = this->physical_ideal_core_id;
|
||||
this->original_physical_affinity_mask = this->physical_affinity_mask;
|
||||
m_original_physical_ideal_core_id = m_physical_ideal_core_id;
|
||||
m_original_physical_affinity_mask = m_physical_affinity_mask;
|
||||
|
||||
/* Bind ourselves to this core. */
|
||||
const s32 active_core = this->GetActiveCore();
|
||||
this->physical_ideal_core_id = active_core;
|
||||
this->physical_affinity_mask.SetAffinityMask(1ul << active_core);
|
||||
m_physical_ideal_core_id = active_core;
|
||||
m_physical_affinity_mask.SetAffinityMask(1ul << active_core);
|
||||
|
||||
if (this->physical_affinity_mask.GetAffinityMask() != this->original_physical_affinity_mask.GetAffinityMask()) {
|
||||
KScheduler::OnThreadAffinityMaskChanged(this, this->original_physical_affinity_mask, active_core);
|
||||
if (m_physical_affinity_mask.GetAffinityMask() != m_original_physical_affinity_mask.GetAffinityMask()) {
|
||||
KScheduler::OnThreadAffinityMaskChanged(this, m_original_physical_affinity_mask, active_core);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -531,22 +531,22 @@ namespace ams::kern {
|
||||
MESOSPHERE_ASSERT(this == GetCurrentThreadPointer());
|
||||
|
||||
KScopedSchedulerLock sl;
|
||||
MESOSPHERE_ASSERT(this->num_core_migration_disables > 0);
|
||||
if ((--this->num_core_migration_disables) == 0) {
|
||||
const KAffinityMask old_mask = this->physical_affinity_mask;
|
||||
MESOSPHERE_ASSERT(m_num_core_migration_disables > 0);
|
||||
if ((--m_num_core_migration_disables) == 0) {
|
||||
const KAffinityMask old_mask = m_physical_affinity_mask;
|
||||
|
||||
/* Restore our ideals. */
|
||||
this->physical_ideal_core_id = this->original_physical_ideal_core_id;
|
||||
this->physical_affinity_mask = this->original_physical_affinity_mask;
|
||||
m_physical_ideal_core_id = m_original_physical_ideal_core_id;
|
||||
m_physical_affinity_mask = m_original_physical_affinity_mask;
|
||||
|
||||
if (this->physical_affinity_mask.GetAffinityMask() != old_mask.GetAffinityMask()) {
|
||||
if (m_physical_affinity_mask.GetAffinityMask() != old_mask.GetAffinityMask()) {
|
||||
const s32 active_core = this->GetActiveCore();
|
||||
|
||||
if (!this->physical_affinity_mask.GetAffinity(active_core)) {
|
||||
if (this->physical_ideal_core_id >= 0) {
|
||||
this->SetActiveCore(this->physical_ideal_core_id);
|
||||
if (!m_physical_affinity_mask.GetAffinity(active_core)) {
|
||||
if (m_physical_ideal_core_id >= 0) {
|
||||
this->SetActiveCore(m_physical_ideal_core_id);
|
||||
} else {
|
||||
this->SetActiveCore(BITSIZEOF(unsigned long long) - 1 - __builtin_clzll(this->physical_affinity_mask.GetAffinityMask()));
|
||||
this->SetActiveCore(BITSIZEOF(unsigned long long) - 1 - __builtin_clzll(m_physical_affinity_mask.GetAffinityMask()));
|
||||
}
|
||||
}
|
||||
KScheduler::OnThreadAffinityMaskChanged(this, old_mask, active_core);
|
||||
@@ -560,8 +560,8 @@ namespace ams::kern {
|
||||
KScopedSchedulerLock sl;
|
||||
|
||||
/* Get the virtual mask. */
|
||||
*out_ideal_core = this->virtual_ideal_core_id;
|
||||
*out_affinity_mask = this->virtual_affinity_mask;
|
||||
*out_ideal_core = m_virtual_ideal_core_id;
|
||||
*out_affinity_mask = m_virtual_affinity_mask;
|
||||
}
|
||||
|
||||
return ResultSuccess();
|
||||
@@ -571,15 +571,15 @@ namespace ams::kern {
|
||||
MESOSPHERE_ASSERT_THIS();
|
||||
{
|
||||
KScopedSchedulerLock sl;
|
||||
MESOSPHERE_ASSERT(this->num_core_migration_disables >= 0);
|
||||
MESOSPHERE_ASSERT(m_num_core_migration_disables >= 0);
|
||||
|
||||
/* Select between core mask and original core mask. */
|
||||
if (this->num_core_migration_disables == 0) {
|
||||
*out_ideal_core = this->physical_ideal_core_id;
|
||||
*out_affinity_mask = this->physical_affinity_mask.GetAffinityMask();
|
||||
if (m_num_core_migration_disables == 0) {
|
||||
*out_ideal_core = m_physical_ideal_core_id;
|
||||
*out_affinity_mask = m_physical_affinity_mask.GetAffinityMask();
|
||||
} else {
|
||||
*out_ideal_core = this->original_physical_ideal_core_id;
|
||||
*out_affinity_mask = this->original_physical_affinity_mask.GetAffinityMask();
|
||||
*out_ideal_core = m_original_physical_ideal_core_id;
|
||||
*out_affinity_mask = m_original_physical_affinity_mask.GetAffinityMask();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -588,25 +588,25 @@ namespace ams::kern {
|
||||
|
||||
Result KThread::SetCoreMask(int32_t core_id, u64 v_affinity_mask) {
|
||||
MESOSPHERE_ASSERT_THIS();
|
||||
MESOSPHERE_ASSERT(this->parent != nullptr);
|
||||
MESOSPHERE_ASSERT(m_parent != nullptr);
|
||||
MESOSPHERE_ASSERT(v_affinity_mask != 0);
|
||||
KScopedLightLock lk(this->activity_pause_lock);
|
||||
KScopedLightLock lk(m_activity_pause_lock);
|
||||
|
||||
/* Set the core mask. */
|
||||
u64 p_affinity_mask = 0;
|
||||
{
|
||||
KScopedSchedulerLock sl;
|
||||
MESOSPHERE_ASSERT(this->num_core_migration_disables >= 0);
|
||||
MESOSPHERE_ASSERT(m_num_core_migration_disables >= 0);
|
||||
|
||||
/* If the core id is no-update magic, preserve the ideal core id. */
|
||||
if (core_id == ams::svc::IdealCoreNoUpdate) {
|
||||
core_id = this->virtual_ideal_core_id;
|
||||
core_id = m_virtual_ideal_core_id;
|
||||
R_UNLESS(((1ul << core_id) & v_affinity_mask) != 0, svc::ResultInvalidCombination());
|
||||
}
|
||||
|
||||
/* Set the virtual core/affinity mask. */
|
||||
this->virtual_ideal_core_id = core_id;
|
||||
this->virtual_affinity_mask = v_affinity_mask;
|
||||
m_virtual_ideal_core_id = core_id;
|
||||
m_virtual_affinity_mask = v_affinity_mask;
|
||||
|
||||
/* Translate the virtual core to a physical core. */
|
||||
if (core_id >= 0) {
|
||||
@@ -621,26 +621,26 @@ namespace ams::kern {
|
||||
}
|
||||
|
||||
/* If we haven't disabled migration, perform an affinity change. */
|
||||
if (this->num_core_migration_disables == 0) {
|
||||
const KAffinityMask old_mask = this->physical_affinity_mask;
|
||||
if (m_num_core_migration_disables == 0) {
|
||||
const KAffinityMask old_mask = m_physical_affinity_mask;
|
||||
|
||||
/* Set our new ideals. */
|
||||
this->physical_ideal_core_id = core_id;
|
||||
this->physical_affinity_mask.SetAffinityMask(p_affinity_mask);
|
||||
m_physical_ideal_core_id = core_id;
|
||||
m_physical_affinity_mask.SetAffinityMask(p_affinity_mask);
|
||||
|
||||
if (this->physical_affinity_mask.GetAffinityMask() != old_mask.GetAffinityMask()) {
|
||||
if (m_physical_affinity_mask.GetAffinityMask() != old_mask.GetAffinityMask()) {
|
||||
const s32 active_core = this->GetActiveCore();
|
||||
|
||||
if (active_core >= 0 && !this->physical_affinity_mask.GetAffinity(active_core)) {
|
||||
const s32 new_core = this->physical_ideal_core_id >= 0 ? this->physical_ideal_core_id : BITSIZEOF(unsigned long long) - 1 - __builtin_clzll(this->physical_affinity_mask.GetAffinityMask());
|
||||
if (active_core >= 0 && !m_physical_affinity_mask.GetAffinity(active_core)) {
|
||||
const s32 new_core = m_physical_ideal_core_id >= 0 ? m_physical_ideal_core_id : BITSIZEOF(unsigned long long) - 1 - __builtin_clzll(m_physical_affinity_mask.GetAffinityMask());
|
||||
this->SetActiveCore(new_core);
|
||||
}
|
||||
KScheduler::OnThreadAffinityMaskChanged(this, old_mask, active_core);
|
||||
}
|
||||
} else {
|
||||
/* Otherwise, we edit the original affinity for restoration later. */
|
||||
this->original_physical_ideal_core_id = core_id;
|
||||
this->original_physical_affinity_mask.SetAffinityMask(p_affinity_mask);
|
||||
m_original_physical_ideal_core_id = core_id;
|
||||
m_original_physical_affinity_mask.SetAffinityMask(p_affinity_mask);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -679,7 +679,7 @@ namespace ams::kern {
|
||||
thread_is_pinned = true;
|
||||
|
||||
/* Wait until the thread isn't pinned any more. */
|
||||
this->pinned_waiter_list.push_back(GetCurrentThread());
|
||||
m_pinned_waiter_list.push_back(GetCurrentThread());
|
||||
GetCurrentThread().SetState(ThreadState_Waiting);
|
||||
} else {
|
||||
/* If the thread isn't pinned, release the scheduler lock and retry until it's not current. */
|
||||
@@ -694,7 +694,7 @@ namespace ams::kern {
|
||||
KScopedSchedulerLock sl;
|
||||
|
||||
/* Remove from the list. */
|
||||
this->pinned_waiter_list.erase(this->pinned_waiter_list.iterator_to(GetCurrentThread()));
|
||||
m_pinned_waiter_list.erase(m_pinned_waiter_list.iterator_to(GetCurrentThread()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -708,7 +708,7 @@ namespace ams::kern {
|
||||
KScopedSchedulerLock sl;
|
||||
|
||||
/* Change our base priority. */
|
||||
this->base_priority = priority;
|
||||
m_base_priority = priority;
|
||||
|
||||
/* Perform a priority restoration. */
|
||||
RestorePriority(this);
|
||||
@@ -720,9 +720,9 @@ namespace ams::kern {
|
||||
KScopedSchedulerLock sl;
|
||||
|
||||
/* Change both our priorities to the idle thread priority. */
|
||||
const s32 old_priority = this->priority;
|
||||
this->priority = IdleThreadPriority;
|
||||
this->base_priority = IdleThreadPriority;
|
||||
const s32 old_priority = m_priority;
|
||||
m_priority = IdleThreadPriority;
|
||||
m_base_priority = IdleThreadPriority;
|
||||
KScheduler::OnThreadPriorityChanged(this, old_priority);
|
||||
|
||||
return ResultSuccess();
|
||||
@@ -734,7 +734,7 @@ namespace ams::kern {
|
||||
KScopedSchedulerLock lk;
|
||||
|
||||
/* Note the request in our flags. */
|
||||
this->suspend_request_flags |= (1u << (ThreadState_SuspendShift + type));
|
||||
m_suspend_request_flags |= (1u << (ThreadState_SuspendShift + type));
|
||||
|
||||
/* Try to perform the suspend. */
|
||||
this->TrySuspend();
|
||||
@@ -746,12 +746,12 @@ namespace ams::kern {
|
||||
KScopedSchedulerLock sl;
|
||||
|
||||
/* Clear the request in our flags. */
|
||||
this->suspend_request_flags &= ~(1u << (ThreadState_SuspendShift + type));
|
||||
m_suspend_request_flags &= ~(1u << (ThreadState_SuspendShift + type));
|
||||
|
||||
/* Update our state. */
|
||||
const ThreadState old_state = this->thread_state;
|
||||
this->thread_state = static_cast<ThreadState>(this->GetSuspendFlags() | (old_state & ThreadState_Mask));
|
||||
if (this->thread_state != old_state) {
|
||||
const ThreadState old_state = m_thread_state;
|
||||
m_thread_state = static_cast<ThreadState>(this->GetSuspendFlags() | (old_state & ThreadState_Mask));
|
||||
if (m_thread_state != old_state) {
|
||||
KScheduler::OnThreadStateChanged(this, old_state);
|
||||
}
|
||||
}
|
||||
@@ -762,18 +762,18 @@ namespace ams::kern {
|
||||
KScopedSchedulerLock sl;
|
||||
|
||||
/* Check if we're waiting and cancellable. */
|
||||
if (this->GetState() == ThreadState_Waiting && this->cancellable) {
|
||||
if (this->sleeping_queue != nullptr) {
|
||||
this->sleeping_queue->WakeupThread(this);
|
||||
this->wait_cancelled = true;
|
||||
if (this->GetState() == ThreadState_Waiting && m_cancellable) {
|
||||
if (m_sleeping_queue != nullptr) {
|
||||
m_sleeping_queue->WakeupThread(this);
|
||||
m_wait_cancelled = true;
|
||||
} else {
|
||||
this->SetSyncedObject(nullptr, svc::ResultCancelled());
|
||||
this->SetState(ThreadState_Runnable);
|
||||
this->wait_cancelled = false;
|
||||
m_wait_cancelled = false;
|
||||
}
|
||||
} else {
|
||||
/* Otherwise, note that we cancelled a wait. */
|
||||
this->wait_cancelled = true;
|
||||
m_wait_cancelled = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -798,8 +798,8 @@ namespace ams::kern {
|
||||
MESOSPHERE_ASSERT(this->IsSuspendRequested());
|
||||
|
||||
/* Set our suspend flags in state. */
|
||||
const auto old_state = this->thread_state;
|
||||
this->thread_state = static_cast<ThreadState>(this->GetSuspendFlags() | (old_state & ThreadState_Mask));
|
||||
const auto old_state = m_thread_state;
|
||||
m_thread_state = static_cast<ThreadState>(this->GetSuspendFlags() | (old_state & ThreadState_Mask));
|
||||
|
||||
/* Note the state change in scheduler. */
|
||||
KScheduler::OnThreadStateChanged(this, old_state);
|
||||
@@ -810,8 +810,8 @@ namespace ams::kern {
|
||||
MESOSPHERE_ASSERT(KScheduler::IsSchedulerLockedByCurrentThread());
|
||||
|
||||
/* Clear our suspend flags in state. */
|
||||
const auto old_state = this->thread_state;
|
||||
this->thread_state = static_cast<ThreadState>(old_state & ThreadState_Mask);
|
||||
const auto old_state = m_thread_state;
|
||||
m_thread_state = static_cast<ThreadState>(old_state & ThreadState_Mask);
|
||||
|
||||
/* Note the state change in scheduler. */
|
||||
KScheduler::OnThreadStateChanged(this, old_state);
|
||||
@@ -819,10 +819,10 @@ namespace ams::kern {
|
||||
|
||||
size_t KThread::GetKernelStackUsage() const {
|
||||
MESOSPHERE_ASSERT_THIS();
|
||||
MESOSPHERE_ASSERT(this->kernel_stack_top != nullptr);
|
||||
MESOSPHERE_ASSERT(m_kernel_stack_top != nullptr);
|
||||
|
||||
#if defined(MESOSPHERE_ENABLE_KERNEL_STACK_USAGE)
|
||||
const u8 *stack = static_cast<const u8 *>(this->kernel_stack_top) - PageSize;
|
||||
const u8 *stack = static_cast<const u8 *>(m_kernel_stack_top) - PageSize;
|
||||
|
||||
size_t i;
|
||||
for (i = 0; i < PageSize; ++i) {
|
||||
@@ -839,7 +839,7 @@ namespace ams::kern {
|
||||
|
||||
Result KThread::SetActivity(ams::svc::ThreadActivity activity) {
|
||||
/* Lock ourselves. */
|
||||
KScopedLightLock lk(this->activity_pause_lock);
|
||||
KScopedLightLock lk(m_activity_pause_lock);
|
||||
|
||||
/* Set the activity. */
|
||||
{
|
||||
@@ -889,7 +889,7 @@ namespace ams::kern {
|
||||
thread_is_current = false;
|
||||
|
||||
/* Wait until the thread isn't pinned any more. */
|
||||
this->pinned_waiter_list.push_back(GetCurrentThread());
|
||||
m_pinned_waiter_list.push_back(GetCurrentThread());
|
||||
GetCurrentThread().SetState(ThreadState_Waiting);
|
||||
} else {
|
||||
/* Check if the thread is currently running. */
|
||||
@@ -911,7 +911,7 @@ namespace ams::kern {
|
||||
KScopedSchedulerLock sl;
|
||||
|
||||
/* Remove from the list. */
|
||||
this->pinned_waiter_list.erase(this->pinned_waiter_list.iterator_to(GetCurrentThread()));
|
||||
m_pinned_waiter_list.erase(m_pinned_waiter_list.iterator_to(GetCurrentThread()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -920,7 +920,7 @@ namespace ams::kern {
|
||||
|
||||
Result KThread::GetThreadContext3(ams::svc::ThreadContext *out) {
|
||||
/* Lock ourselves. */
|
||||
KScopedLightLock lk(this->activity_pause_lock);
|
||||
KScopedLightLock lk(m_activity_pause_lock);
|
||||
|
||||
/* Get the context. */
|
||||
{
|
||||
@@ -944,8 +944,8 @@ namespace ams::kern {
|
||||
MESOSPHERE_ASSERT(KScheduler::IsSchedulerLockedByCurrentThread());
|
||||
|
||||
/* Find the right spot to insert the waiter. */
|
||||
auto it = this->waiter_list.begin();
|
||||
while (it != this->waiter_list.end()) {
|
||||
auto it = m_waiter_list.begin();
|
||||
while (it != m_waiter_list.end()) {
|
||||
if (it->GetPriority() > thread->GetPriority()) {
|
||||
break;
|
||||
}
|
||||
@@ -954,11 +954,11 @@ namespace ams::kern {
|
||||
|
||||
/* Keep track of how many kernel waiters we have. */
|
||||
if (IsKernelAddressKey(thread->GetAddressKey())) {
|
||||
MESOSPHERE_ABORT_UNLESS((this->num_kernel_waiters++) >= 0);
|
||||
MESOSPHERE_ABORT_UNLESS((m_num_kernel_waiters++) >= 0);
|
||||
}
|
||||
|
||||
/* Insert the waiter. */
|
||||
this->waiter_list.insert(it, *thread);
|
||||
m_waiter_list.insert(it, *thread);
|
||||
thread->SetLockOwner(this);
|
||||
}
|
||||
|
||||
@@ -968,11 +968,11 @@ namespace ams::kern {
|
||||
|
||||
/* Keep track of how many kernel waiters we have. */
|
||||
if (IsKernelAddressKey(thread->GetAddressKey())) {
|
||||
MESOSPHERE_ABORT_UNLESS((this->num_kernel_waiters--) > 0);
|
||||
MESOSPHERE_ABORT_UNLESS((m_num_kernel_waiters--) > 0);
|
||||
}
|
||||
|
||||
/* Remove the waiter. */
|
||||
this->waiter_list.erase(this->waiter_list.iterator_to(*thread));
|
||||
m_waiter_list.erase(m_waiter_list.iterator_to(*thread));
|
||||
thread->SetLockOwner(nullptr);
|
||||
}
|
||||
|
||||
@@ -983,7 +983,7 @@ namespace ams::kern {
|
||||
/* We want to inherit priority where possible. */
|
||||
s32 new_priority = thread->GetBasePriority();
|
||||
if (thread->HasWaiters()) {
|
||||
new_priority = std::min(new_priority, thread->waiter_list.front().GetPriority());
|
||||
new_priority = std::min(new_priority, thread->m_waiter_list.front().GetPriority());
|
||||
}
|
||||
|
||||
/* If the priority we would inherit is not different from ours, don't do anything. */
|
||||
@@ -1039,16 +1039,16 @@ namespace ams::kern {
|
||||
|
||||
s32 num_waiters = 0;
|
||||
KThread *next_lock_owner = nullptr;
|
||||
auto it = this->waiter_list.begin();
|
||||
while (it != this->waiter_list.end()) {
|
||||
auto it = m_waiter_list.begin();
|
||||
while (it != m_waiter_list.end()) {
|
||||
if (it->GetAddressKey() == key) {
|
||||
KThread *thread = std::addressof(*it);
|
||||
|
||||
/* Keep track of how many kernel waiters we have. */
|
||||
if (IsKernelAddressKey(thread->GetAddressKey())) {
|
||||
MESOSPHERE_ABORT_UNLESS((this->num_kernel_waiters--) > 0);
|
||||
MESOSPHERE_ABORT_UNLESS((m_num_kernel_waiters--) > 0);
|
||||
}
|
||||
it = this->waiter_list.erase(it);
|
||||
it = m_waiter_list.erase(it);
|
||||
|
||||
/* Update the next lock owner. */
|
||||
if (next_lock_owner == nullptr) {
|
||||
@@ -1117,9 +1117,9 @@ namespace ams::kern {
|
||||
KDebug::OnExitThread(this);
|
||||
|
||||
/* Release the thread resource hint from parent. */
|
||||
if (this->parent != nullptr) {
|
||||
this->parent->ReleaseResource(ams::svc::LimitableResource_ThreadCountMax, 0, 1);
|
||||
this->resource_limit_release_hint = true;
|
||||
if (m_parent != nullptr) {
|
||||
m_parent->ReleaseResource(ams::svc::LimitableResource_ThreadCountMax, 0, 1);
|
||||
m_resource_limit_release_hint = true;
|
||||
}
|
||||
|
||||
/* Perform termination. */
|
||||
@@ -1127,7 +1127,7 @@ namespace ams::kern {
|
||||
KScopedSchedulerLock sl;
|
||||
|
||||
/* Disallow all suspension. */
|
||||
this->suspend_allowed_flags = 0;
|
||||
m_suspend_allowed_flags = 0;
|
||||
|
||||
/* Start termination. */
|
||||
this->StartTermination();
|
||||
@@ -1162,14 +1162,14 @@ namespace ams::kern {
|
||||
const bool first_request = [&] ALWAYS_INLINE_LAMBDA () -> bool {
|
||||
/* Perform an atomic compare-and-swap from false to true. */
|
||||
bool expected = false;
|
||||
return this->termination_requested.compare_exchange_strong(expected, true);
|
||||
return m_termination_requested.compare_exchange_strong(expected, true);
|
||||
}();
|
||||
|
||||
/* If this is the first request, start termination procedure. */
|
||||
if (first_request) {
|
||||
/* If the thread is in initialized state, just change state to terminated. */
|
||||
if (this->GetState() == ThreadState_Initialized) {
|
||||
this->thread_state = ThreadState_Terminated;
|
||||
m_thread_state = ThreadState_Terminated;
|
||||
return ThreadState_Terminated;
|
||||
}
|
||||
|
||||
@@ -1178,7 +1178,7 @@ namespace ams::kern {
|
||||
|
||||
/* If the thread is suspended, continue it. */
|
||||
if (this->IsSuspended()) {
|
||||
this->suspend_allowed_flags = 0;
|
||||
m_suspend_allowed_flags = 0;
|
||||
this->Continue();
|
||||
}
|
||||
|
||||
@@ -1189,7 +1189,7 @@ namespace ams::kern {
|
||||
|
||||
/* If the thread is runnable, send a termination interrupt to other cores. */
|
||||
if (this->GetState() == ThreadState_Runnable) {
|
||||
if (const u64 core_mask = this->physical_affinity_mask.GetAffinityMask() & ~(1ul << GetCurrentCoreId()); core_mask != 0) {
|
||||
if (const u64 core_mask = m_physical_affinity_mask.GetAffinityMask() & ~(1ul << GetCurrentCoreId()); core_mask != 0) {
|
||||
cpu::DataSynchronizationBarrier();
|
||||
Kernel::GetInterruptManager().SendInterProcessorInterrupt(KInterruptName_ThreadTerminate, core_mask);
|
||||
}
|
||||
@@ -1237,9 +1237,9 @@ namespace ams::kern {
|
||||
|
||||
KScopedSchedulerLock sl;
|
||||
|
||||
const ThreadState old_state = this->thread_state;
|
||||
this->thread_state = static_cast<ThreadState>((old_state & ~ThreadState_Mask) | (state & ThreadState_Mask));
|
||||
if (this->thread_state != old_state) {
|
||||
const ThreadState old_state = m_thread_state;
|
||||
m_thread_state = static_cast<ThreadState>((old_state & ~ThreadState_Mask) | (state & ThreadState_Mask));
|
||||
if (m_thread_state != old_state) {
|
||||
KScheduler::OnThreadStateChanged(this, old_state);
|
||||
}
|
||||
}
|
||||
@@ -1256,10 +1256,10 @@ namespace ams::kern {
|
||||
/* Define helper object to find the thread. */
|
||||
class IdObjectHelper : public KAutoObjectWithListContainer::ListType::value_type {
|
||||
private:
|
||||
u64 id;
|
||||
u64 m_id;
|
||||
public:
|
||||
constexpr explicit IdObjectHelper(u64 id) : id(id) { /* ... */ }
|
||||
virtual u64 GetId() const override { return this->id; }
|
||||
constexpr explicit IdObjectHelper(u64 id) : m_id(id) { /* ... */ }
|
||||
virtual u64 GetId() const override { return m_id; }
|
||||
};
|
||||
|
||||
/* Find the object with the right id. */
|
||||
|
||||
@@ -21,7 +21,7 @@ namespace ams::kern {
|
||||
MESOSPHERE_ASSERT_THIS();
|
||||
|
||||
/* Set that this process owns us. */
|
||||
this->owner = process;
|
||||
m_owner = process;
|
||||
|
||||
/* Allocate a new page. */
|
||||
KPageBuffer *page_buf = KPageBuffer::Allocate();
|
||||
@@ -29,7 +29,7 @@ namespace ams::kern {
|
||||
auto page_buf_guard = SCOPE_GUARD { KPageBuffer::Free(page_buf); };
|
||||
|
||||
/* Map the address in. */
|
||||
R_TRY(this->owner->GetPageTable().MapPages(std::addressof(this->virt_addr), 1, PageSize, page_buf->GetPhysicalAddress(), KMemoryState_ThreadLocal, KMemoryPermission_UserReadWrite));
|
||||
R_TRY(m_owner->GetPageTable().MapPages(std::addressof(m_virt_addr), 1, PageSize, page_buf->GetPhysicalAddress(), KMemoryState_ThreadLocal, KMemoryPermission_UserReadWrite));
|
||||
|
||||
/* We succeeded. */
|
||||
page_buf_guard.Cancel();
|
||||
@@ -41,10 +41,10 @@ namespace ams::kern {
|
||||
|
||||
/* Get the physical address of the page. */
|
||||
KPhysicalAddress phys_addr = Null<KPhysicalAddress>;
|
||||
MESOSPHERE_ABORT_UNLESS(this->owner->GetPageTable().GetPhysicalAddress(&phys_addr, this->GetAddress()));
|
||||
MESOSPHERE_ABORT_UNLESS(m_owner->GetPageTable().GetPhysicalAddress(&phys_addr, this->GetAddress()));
|
||||
|
||||
/* Unmap the page. */
|
||||
R_TRY(this->owner->GetPageTable().UnmapPages(this->GetAddress(), 1, KMemoryState_ThreadLocal));
|
||||
R_TRY(m_owner->GetPageTable().UnmapPages(this->GetAddress(), 1, KMemoryState_ThreadLocal));
|
||||
|
||||
/* Free the page. */
|
||||
KPageBuffer::Free(KPageBuffer::FromPhysicalAddress(phys_addr));
|
||||
@@ -54,9 +54,9 @@ namespace ams::kern {
|
||||
KProcessAddress KThreadLocalPage::Reserve() {
|
||||
MESOSPHERE_ASSERT_THIS();
|
||||
|
||||
for (size_t i = 0; i < util::size(this->is_region_free); i++) {
|
||||
if (this->is_region_free[i]) {
|
||||
this->is_region_free[i] = false;
|
||||
for (size_t i = 0; i < util::size(m_is_region_free); i++) {
|
||||
if (m_is_region_free[i]) {
|
||||
m_is_region_free[i] = false;
|
||||
return this->GetRegionAddress(i);
|
||||
}
|
||||
}
|
||||
@@ -67,14 +67,14 @@ namespace ams::kern {
|
||||
void KThreadLocalPage::Release(KProcessAddress addr) {
|
||||
MESOSPHERE_ASSERT_THIS();
|
||||
|
||||
this->is_region_free[this->GetRegionIndex(addr)] = true;
|
||||
m_is_region_free[this->GetRegionIndex(addr)] = true;
|
||||
}
|
||||
|
||||
void *KThreadLocalPage::GetPointer() const {
|
||||
MESOSPHERE_ASSERT_THIS();
|
||||
|
||||
KPhysicalAddress phys_addr;
|
||||
MESOSPHERE_ABORT_UNLESS(this->owner->GetPageTable().GetPhysicalAddress(std::addressof(phys_addr), this->GetAddress()));
|
||||
MESOSPHERE_ABORT_UNLESS(m_owner->GetPageTable().GetPhysicalAddress(std::addressof(phys_addr), this->GetAddress()));
|
||||
return static_cast<void *>(KPageBuffer::FromPhysicalAddress(phys_addr));
|
||||
}
|
||||
|
||||
|
||||
@@ -21,24 +21,24 @@ namespace ams::kern {
|
||||
MESOSPHERE_ASSERT_THIS();
|
||||
|
||||
/* Set members. */
|
||||
this->owner = GetCurrentProcessPointer();
|
||||
m_owner = GetCurrentProcessPointer();
|
||||
|
||||
/* Initialize the page group. */
|
||||
auto &page_table = this->owner->GetPageTable();
|
||||
new (GetPointer(this->page_group)) KPageGroup(page_table.GetBlockInfoManager());
|
||||
auto &page_table = m_owner->GetPageTable();
|
||||
new (GetPointer(m_page_group)) KPageGroup(page_table.GetBlockInfoManager());
|
||||
|
||||
/* Ensure that our page group's state is valid on exit. */
|
||||
auto pg_guard = SCOPE_GUARD { GetReference(this->page_group).~KPageGroup(); };
|
||||
auto pg_guard = SCOPE_GUARD { GetReference(m_page_group).~KPageGroup(); };
|
||||
|
||||
/* Lock the memory. */
|
||||
R_TRY(page_table.LockForTransferMemory(GetPointer(this->page_group), addr, size, ConvertToKMemoryPermission(own_perm)));
|
||||
R_TRY(page_table.LockForTransferMemory(GetPointer(m_page_group), addr, size, ConvertToKMemoryPermission(own_perm)));
|
||||
|
||||
/* Set remaining tracking members. */
|
||||
this->owner->Open();
|
||||
this->owner_perm = own_perm;
|
||||
this->address = addr;
|
||||
this->is_initialized = true;
|
||||
this->is_mapped = false;
|
||||
m_owner->Open();
|
||||
m_owner_perm = own_perm;
|
||||
m_address = addr;
|
||||
m_is_initialized = true;
|
||||
m_is_mapped = false;
|
||||
|
||||
/* We succeeded. */
|
||||
pg_guard.Cancel();
|
||||
@@ -49,14 +49,14 @@ namespace ams::kern {
|
||||
MESOSPHERE_ASSERT_THIS();
|
||||
|
||||
/* Unlock. */
|
||||
if (!this->is_mapped) {
|
||||
const size_t size = GetReference(this->page_group).GetNumPages() * PageSize;
|
||||
MESOSPHERE_R_ABORT_UNLESS(this->owner->GetPageTable().UnlockForTransferMemory(this->address, size, GetReference(this->page_group)));
|
||||
if (!m_is_mapped) {
|
||||
const size_t size = GetReference(m_page_group).GetNumPages() * PageSize;
|
||||
MESOSPHERE_R_ABORT_UNLESS(m_owner->GetPageTable().UnlockForTransferMemory(m_address, size, GetReference(m_page_group)));
|
||||
}
|
||||
|
||||
/* Close the page group. */
|
||||
GetReference(this->page_group).Close();
|
||||
GetReference(this->page_group).Finalize();
|
||||
GetReference(m_page_group).Close();
|
||||
GetReference(m_page_group).Finalize();
|
||||
|
||||
/* Perform inherited finalization. */
|
||||
KAutoObjectWithSlabHeapAndContainer<KTransferMemory, KAutoObjectWithList>::Finalize();
|
||||
@@ -72,23 +72,23 @@ namespace ams::kern {
|
||||
MESOSPHERE_ASSERT_THIS();
|
||||
|
||||
/* Validate the size. */
|
||||
R_UNLESS(GetReference(this->page_group).GetNumPages() == util::DivideUp(size, PageSize), svc::ResultInvalidSize());
|
||||
R_UNLESS(GetReference(m_page_group).GetNumPages() == util::DivideUp(size, PageSize), svc::ResultInvalidSize());
|
||||
|
||||
/* Validate the permission. */
|
||||
R_UNLESS(this->owner_perm == map_perm, svc::ResultInvalidState());
|
||||
R_UNLESS(m_owner_perm == map_perm, svc::ResultInvalidState());
|
||||
|
||||
/* Lock ourselves. */
|
||||
KScopedLightLock lk(this->lock);
|
||||
KScopedLightLock lk(m_lock);
|
||||
|
||||
/* Ensure we're not already mapped. */
|
||||
R_UNLESS(!this->is_mapped, svc::ResultInvalidState());
|
||||
R_UNLESS(!m_is_mapped, svc::ResultInvalidState());
|
||||
|
||||
/* Map the memory. */
|
||||
const KMemoryState state = (this->owner_perm == ams::svc::MemoryPermission_None) ? KMemoryState_Transfered : KMemoryState_SharedTransfered;
|
||||
R_TRY(GetCurrentProcess().GetPageTable().MapPageGroup(address, GetReference(this->page_group), state, KMemoryPermission_UserReadWrite));
|
||||
const KMemoryState state = (m_owner_perm == ams::svc::MemoryPermission_None) ? KMemoryState_Transfered : KMemoryState_SharedTransfered;
|
||||
R_TRY(GetCurrentProcess().GetPageTable().MapPageGroup(address, GetReference(m_page_group), state, KMemoryPermission_UserReadWrite));
|
||||
|
||||
/* Mark ourselves as mapped. */
|
||||
this->is_mapped = true;
|
||||
m_is_mapped = true;
|
||||
|
||||
return ResultSuccess();
|
||||
}
|
||||
@@ -97,18 +97,18 @@ namespace ams::kern {
|
||||
MESOSPHERE_ASSERT_THIS();
|
||||
|
||||
/* Validate the size. */
|
||||
R_UNLESS(GetReference(this->page_group).GetNumPages() == util::DivideUp(size, PageSize), svc::ResultInvalidSize());
|
||||
R_UNLESS(GetReference(m_page_group).GetNumPages() == util::DivideUp(size, PageSize), svc::ResultInvalidSize());
|
||||
|
||||
/* Lock ourselves. */
|
||||
KScopedLightLock lk(this->lock);
|
||||
KScopedLightLock lk(m_lock);
|
||||
|
||||
/* Unmap the memory. */
|
||||
const KMemoryState state = (this->owner_perm == ams::svc::MemoryPermission_None) ? KMemoryState_Transfered : KMemoryState_SharedTransfered;
|
||||
R_TRY(GetCurrentProcess().GetPageTable().UnmapPageGroup(address, GetReference(this->page_group), state));
|
||||
const KMemoryState state = (m_owner_perm == ams::svc::MemoryPermission_None) ? KMemoryState_Transfered : KMemoryState_SharedTransfered;
|
||||
R_TRY(GetCurrentProcess().GetPageTable().UnmapPageGroup(address, GetReference(m_page_group), state));
|
||||
|
||||
/* Mark ourselves as unmapped. */
|
||||
MESOSPHERE_ASSERT(this->is_mapped);
|
||||
this->is_mapped = false;
|
||||
MESOSPHERE_ASSERT(m_is_mapped);
|
||||
m_is_mapped = false;
|
||||
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@ namespace ams::kern {
|
||||
MESOSPHERE_ASSERT(KScheduler::IsSchedulerLockedByCurrentThread());
|
||||
|
||||
/* Wake up all the waiting threads. */
|
||||
for (KThread &thread : this->wait_list) {
|
||||
for (KThread &thread : m_wait_list) {
|
||||
thread.Wakeup();
|
||||
}
|
||||
}
|
||||
@@ -38,19 +38,19 @@ namespace ams::kern {
|
||||
|
||||
/* Verify that nothing else is already waiting on the object. */
|
||||
if (timeout > 0) {
|
||||
R_UNLESS(!this->timer_used, svc::ResultBusy());
|
||||
R_UNLESS(!m_timer_used, svc::ResultBusy());
|
||||
}
|
||||
|
||||
/* Check that we're not already in use. */
|
||||
if (timeout >= 0) {
|
||||
/* Verify the timer isn't already in use. */
|
||||
R_UNLESS(!this->timer_used, svc::ResultBusy());
|
||||
R_UNLESS(!m_timer_used, svc::ResultBusy());
|
||||
}
|
||||
|
||||
/* If we need to, register our timeout. */
|
||||
if (timeout > 0) {
|
||||
/* Mark that we're using the timer. */
|
||||
this->timer_used = true;
|
||||
m_timer_used = true;
|
||||
|
||||
/* Use the timer. */
|
||||
timer = std::addressof(Kernel::GetHardwareTimer());
|
||||
@@ -62,7 +62,7 @@ namespace ams::kern {
|
||||
this->OnTimer();
|
||||
} else {
|
||||
/* Otherwise, sleep until the timeout occurs. */
|
||||
this->wait_list.push_back(GetCurrentThread());
|
||||
m_wait_list.push_back(GetCurrentThread());
|
||||
cur_thread->SetState(KThread::ThreadState_Waiting);
|
||||
cur_thread->SetSyncedObject(nullptr, svc::ResultTimedOut());
|
||||
}
|
||||
@@ -74,15 +74,15 @@ namespace ams::kern {
|
||||
|
||||
/* Remove from the timer. */
|
||||
if (timeout > 0) {
|
||||
MESOSPHERE_ASSERT(this->timer_used);
|
||||
MESOSPHERE_ASSERT(m_timer_used);
|
||||
MESOSPHERE_ASSERT(timer != nullptr);
|
||||
timer->CancelTask(this);
|
||||
this->timer_used = false;
|
||||
m_timer_used = false;
|
||||
}
|
||||
|
||||
/* Remove the thread from our queue. */
|
||||
if (timeout != 0) {
|
||||
this->wait_list.erase(this->wait_list.iterator_to(GetCurrentThread()));
|
||||
m_wait_list.erase(m_wait_list.iterator_to(GetCurrentThread()));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -19,23 +19,23 @@ namespace ams::kern {
|
||||
|
||||
void KWorkerTaskManager::Initialize(WorkerType wt, s32 priority) {
|
||||
/* Set type, other members already initialized in constructor. */
|
||||
this->type = wt;
|
||||
m_type = wt;
|
||||
|
||||
/* Reserve a thread from the system limit. */
|
||||
MESOSPHERE_ABORT_UNLESS(Kernel::GetSystemResourceLimit().Reserve(ams::svc::LimitableResource_ThreadCountMax, 1));
|
||||
|
||||
/* Create a new thread. */
|
||||
this->thread = KThread::Create();
|
||||
MESOSPHERE_ABORT_UNLESS(this->thread != nullptr);
|
||||
m_thread = KThread::Create();
|
||||
MESOSPHERE_ABORT_UNLESS(m_thread != nullptr);
|
||||
|
||||
/* Launch the new thread. */
|
||||
MESOSPHERE_R_ABORT_UNLESS(KThread::InitializeKernelThread(this->thread, ThreadFunction, reinterpret_cast<uintptr_t>(this), priority, cpu::NumCores - 1));
|
||||
MESOSPHERE_R_ABORT_UNLESS(KThread::InitializeKernelThread(m_thread, ThreadFunction, reinterpret_cast<uintptr_t>(this), priority, cpu::NumCores - 1));
|
||||
|
||||
/* Register the new thread. */
|
||||
KThread::Register(this->thread);
|
||||
KThread::Register(m_thread);
|
||||
|
||||
/* Run the thread. */
|
||||
this->thread->Run();
|
||||
m_thread->Run();
|
||||
}
|
||||
|
||||
void KWorkerTaskManager::AddTask(WorkerType type, KWorkerTask *task) {
|
||||
@@ -58,12 +58,12 @@ namespace ams::kern {
|
||||
|
||||
if (task == nullptr) {
|
||||
/* If there's nothing to do, set ourselves as waiting. */
|
||||
this->active = false;
|
||||
this->thread->SetState(KThread::ThreadState_Waiting);
|
||||
m_active = false;
|
||||
m_thread->SetState(KThread::ThreadState_Waiting);
|
||||
continue;
|
||||
}
|
||||
|
||||
this->active = true;
|
||||
m_active = true;
|
||||
}
|
||||
|
||||
/* Do the task. */
|
||||
@@ -73,14 +73,14 @@ namespace ams::kern {
|
||||
|
||||
KWorkerTask *KWorkerTaskManager::GetTask() {
|
||||
MESOSPHERE_ASSERT(KScheduler::IsSchedulerLockedByCurrentThread());
|
||||
KWorkerTask *next = this->head_task;
|
||||
KWorkerTask *next = m_head_task;
|
||||
if (next) {
|
||||
/* Advance the list. */
|
||||
if (this->head_task == this->tail_task) {
|
||||
this->head_task = nullptr;
|
||||
this->tail_task = nullptr;
|
||||
if (m_head_task == m_tail_task) {
|
||||
m_head_task = nullptr;
|
||||
m_tail_task = nullptr;
|
||||
} else {
|
||||
this->head_task = this->head_task->GetNextTask();
|
||||
m_head_task = m_head_task->GetNextTask();
|
||||
}
|
||||
|
||||
/* Clear the next task's next. */
|
||||
@@ -94,16 +94,16 @@ namespace ams::kern {
|
||||
MESOSPHERE_ASSERT(task->GetNextTask() == nullptr);
|
||||
|
||||
/* Insert the task. */
|
||||
if (this->tail_task) {
|
||||
this->tail_task->SetNextTask(task);
|
||||
this->tail_task = task;
|
||||
if (m_tail_task) {
|
||||
m_tail_task->SetNextTask(task);
|
||||
m_tail_task = task;
|
||||
} else {
|
||||
this->head_task = task;
|
||||
this->tail_task = task;
|
||||
m_head_task = task;
|
||||
m_tail_task = task;
|
||||
|
||||
/* Make ourselves active if we need to. */
|
||||
if (!this->active) {
|
||||
this->thread->SetState(KThread::ThreadState_Runnable);
|
||||
if (!m_active) {
|
||||
m_thread->SetState(KThread::ThreadState_Runnable);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,22 +19,22 @@ namespace ams::kern {
|
||||
|
||||
void KWritableEvent::Initialize(KEvent *p) {
|
||||
/* Set parent, open a reference to the readable event. */
|
||||
this->parent = p;
|
||||
this->parent->GetReadableEvent().Open();
|
||||
m_parent = p;
|
||||
m_parent->GetReadableEvent().Open();
|
||||
}
|
||||
|
||||
Result KWritableEvent::Signal() {
|
||||
return this->parent->GetReadableEvent().Signal();
|
||||
return m_parent->GetReadableEvent().Signal();
|
||||
}
|
||||
|
||||
Result KWritableEvent::Clear() {
|
||||
return this->parent->GetReadableEvent().Clear();
|
||||
return m_parent->GetReadableEvent().Clear();
|
||||
}
|
||||
|
||||
void KWritableEvent::Destroy() {
|
||||
/* Close our references. */
|
||||
this->parent->GetReadableEvent().Close();
|
||||
this->parent->Close();
|
||||
m_parent->GetReadableEvent().Close();
|
||||
m_parent->Close();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user