mirror of
https://github.com/Atmosphere-NX/Atmosphere.git
synced 2024-11-24 15:50:29 +01:00
KScheduler big brain strat for mdscr_el1 cfg change
This commit is contained in:
parent
e256261b80
commit
09074798cd
@ -62,8 +62,7 @@ namespace ams::kern {
|
|||||||
KThread *m_idle_thread;
|
KThread *m_idle_thread;
|
||||||
util::Atomic<KThread *> m_current_thread;
|
util::Atomic<KThread *> m_current_thread;
|
||||||
public:
|
public:
|
||||||
constexpr KScheduler() : m_state(), m_is_active(false), m_core_id(0), m_last_context_switch_time(0), m_idle_thread(nullptr), m_current_thread(nullptr)
|
constexpr KScheduler() : m_state(), m_is_active(false), m_core_id(0), m_last_context_switch_time(0), m_idle_thread(nullptr), m_current_thread(nullptr) {
|
||||||
{
|
|
||||||
m_state.needs_scheduling = true;
|
m_state.needs_scheduling = true;
|
||||||
m_state.interrupt_task_runnable = false;
|
m_state.interrupt_task_runnable = false;
|
||||||
m_state.should_count_idle = false;
|
m_state.should_count_idle = false;
|
||||||
|
@ -249,22 +249,18 @@ namespace ams::kern {
|
|||||||
|
|
||||||
#if defined(MESOSPHERE_ENABLE_HARDWARE_SINGLE_STEP)
|
#if defined(MESOSPHERE_ENABLE_HARDWARE_SINGLE_STEP)
|
||||||
/* Ensure the single-step bit in mdscr reflects the correct single-step state for the new thread. */
|
/* Ensure the single-step bit in mdscr reflects the correct single-step state for the new thread. */
|
||||||
|
/* NOTE: Per ARM docs, changing the single-step bit requires a "context synchronization event" to */
|
||||||
|
/* be sure that our new configuration takes. However, there are three types of synchronization event: */
|
||||||
|
/* Taking an exception, returning from an exception, and ISB. The single-step bit change only matters */
|
||||||
|
/* in EL0...which implies a return-from-exception has occurred since we set the bit. Thus, forcing */
|
||||||
|
/* an ISB is unnecessary, and we can modify the register safely and be confident it will affect the next */
|
||||||
|
/* userland instruction executed. */
|
||||||
cpu::MonitorDebugSystemControlRegisterAccessor().SetSoftwareStep(next_thread->IsSingleStep()).Store();
|
cpu::MonitorDebugSystemControlRegisterAccessor().SetSoftwareStep(next_thread->IsSingleStep()).Store();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Switch the current process, if we're switching processes. */
|
/* Switch the current process, if we're switching processes. */
|
||||||
if (KProcess *next_process = next_thread->GetOwnerProcess(); next_process != cur_process) {
|
if (KProcess *next_process = next_thread->GetOwnerProcess(); next_process != cur_process) {
|
||||||
KProcess::Switch(cur_process, next_process);
|
KProcess::Switch(cur_process, next_process);
|
||||||
} else {
|
|
||||||
/* The single-step bit set up above requires an instruction synchronization barrier, to ensure */
|
|
||||||
/* the state change takes before we actually perform a return which might break-to-step. */
|
|
||||||
/* KProcess::Switch performs an isb incidentally, and so when we're changing process we */
|
|
||||||
/* can piggy-back off of that isb to avoid unnecessarily emptying the pipeline twice. */
|
|
||||||
/* However, this means that when we're switching to thread in a different process, */
|
|
||||||
/* we must ensure that we still isb. In practice, gcc will deduplicate into a single isb. */
|
|
||||||
#if defined(MESOSPHERE_ENABLE_HARDWARE_SINGLE_STEP)
|
|
||||||
cpu::InstructionMemoryBarrier();
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set the new thread. */
|
/* Set the new thread. */
|
||||||
|
Loading…
Reference in New Issue
Block a user