kern: add tracing for irq/scheduling

This commit is contained in:
Michael Scire 2020-08-03 18:11:13 -07:00 committed by SciresM
parent 8e5c0a9663
commit f058536b59
6 changed files with 59 additions and 12 deletions

View File

@ -32,10 +32,17 @@ namespace ams::kern {
class KTrace {
public:
enum Type {
Type_ThreadSwitch = 1,
Type_SvcEntry0 = 3,
Type_SvcEntry1 = 4,
Type_SvcExit0 = 5,
Type_SvcExit1 = 6,
Type_Interrupt = 7,
Type_ScheduleUpdate = 11,
Type_CoreMigration = 14,
};
private:
static bool s_is_active;
@ -65,6 +72,18 @@ namespace ams::kern {
} \
})
#define MESOSPHERE_KTRACE_PUSH_RECORD(TYPE, ...) \
({ \
if constexpr (::ams::kern::IsKTraceEnabled) { \
if (::ams::kern::KTrace::IsActive()) { \
::ams::kern::KTrace::PushRecord(TYPE, ## __VA_ARGS__); \
} \
} \
})
#define MESOSPHERE_KTRACE_THREAD_SWITCH(NEXT) \
MESOSPHERE_KTRACE_PUSH_RECORD(::ams::kern::KTrace::Type_ThreadSwitch, (NEXT)->GetId())
#define MESOSPHERE_KTRACE_SVC_ENTRY(SVC_ID, PARAM0, PARAM1, PARAM2, PARAM3, PARAM4, PARAM5, PARAM6, PARAM7) \
({ \
if constexpr (::ams::kern::IsKTraceEnabled) { \
@ -84,3 +103,12 @@ namespace ams::kern {
} \
} \
})
#define MESOSPHERE_KTRACE_INTERRUPT(ID) \
MESOSPHERE_KTRACE_PUSH_RECORD(::ams::kern::KTrace::Type_Interrupt, ID)
#define MESOSPHERE_KTRACE_SCHEDULE_UPDATE(CORE, PREV, NEXT) \
MESOSPHERE_KTRACE_PUSH_RECORD(::ams::kern::KTrace::Type_ScheduleUpdate, CORE, (PREV)->GetId(), (NEXT)->GetId())
#define MESOSPHERE_KTRACE_CORE_MIGRATION(THREAD_ID, PREV, NEXT, REASON) \
MESOSPHERE_KTRACE_PUSH_RECORD(::ams::kern::KTrace::Type_CoreMigration, THREAD_ID, PREV, NEXT, REASON)

View File

@ -111,6 +111,9 @@ namespace ams::kern::arch::arm64 {
const u32 raw_irq = this->interrupt_controller.GetIrq();
const s32 irq = KInterruptController::ConvertRawIrq(raw_irq);
/* Trace the interrupt. */
MESOSPHERE_KTRACE_INTERRUPT(irq);
/* If the IRQ is spurious, we don't need to reschedule. */
if (irq < 0) {
return false;

View File

@ -86,18 +86,20 @@ _ZN3ams4kern4arch5arm6412SvcHandler64Ev:
/* If we should, trace the svc entry. */
#if defined(MESOSPHERE_BUILD_FOR_TRACING)
sub sp, sp, #0x40
sub sp, sp, #0x50
stp x0, x1, [sp, #(8 * 0)]
stp x2, x3, [sp, #(8 * 2)]
stp x4, x5, [sp, #(8 * 4)]
stp x6, x7, [sp, #(8 * 6)]
str x11, [sp, #(8 * 8)]
mov x0, sp
bl _ZN3ams4kern3svc13TraceSvcEntryEPKm
ldp x0, x1, [sp, #(8 * 0)]
ldp x2, x3, [sp, #(8 * 2)]
ldp x4, x5, [sp, #(8 * 4)]
ldp x6, x7, [sp, #(8 * 6)]
add sp, sp, #0x40
ldr x11, [sp, #(8 * 8)]
add sp, sp, #0x50
#endif
/* Invoke the SVC handler. */
@ -294,18 +296,20 @@ _ZN3ams4kern4arch5arm6412SvcHandler32Ev:
/* If we should, trace the svc entry. */
#if defined(MESOSPHERE_BUILD_FOR_TRACING)
sub sp, sp, #0x40
sub sp, sp, #0x50
stp x0, x1, [sp, #(8 * 0)]
stp x2, x3, [sp, #(8 * 2)]
stp x4, x5, [sp, #(8 * 4)]
stp x6, x7, [sp, #(8 * 6)]
str x19, [sp, #(8 * 8)]
mov x0, sp
bl _ZN3ams4kern3svc13TraceSvcEntryEPKm
ldp x0, x1, [sp, #(8 * 0)]
ldp x2, x3, [sp, #(8 * 2)]
ldp x4, x5, [sp, #(8 * 4)]
ldp x6, x7, [sp, #(8 * 6)]
add sp, sp, #0x40
ldr x19, [sp, #(8 * 8)]
add sp, sp, #0x50
#endif
/* Invoke the SVC handler. */

View File

@ -99,6 +99,8 @@ namespace ams::kern {
}
}
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));
this->state.highest_priority_thread = highest_thread;
this->state.needs_scheduling = true;
return (1ul << this->core_id);
@ -163,6 +165,7 @@ namespace ams::kern {
/* The suggested thread isn't bound to its core, so we can migrate it! */
suggested->SetActiveCore(core_id);
priority_queue.ChangeCore(suggested_core, suggested);
MESOSPHERE_KTRACE_CORE_MIGRATION(suggested->GetId(), suggested_core, core_id, 1);
top_threads[core_id] = suggested;
cores_needing_scheduling |= Kernel::GetScheduler(core_id).UpdateHighestPriorityThread(top_threads[core_id]);
break;
@ -188,6 +191,7 @@ namespace ams::kern {
/* Perform the migration. */
suggested->SetActiveCore(core_id);
priority_queue.ChangeCore(candidate_core, suggested);
MESOSPHERE_KTRACE_CORE_MIGRATION(suggested->GetId(), candidate_core, core_id, 2);
top_threads[core_id] = suggested;
cores_needing_scheduling |= Kernel::GetScheduler(core_id).UpdateHighestPriorityThread(top_threads[core_id]);
break;
@ -253,6 +257,8 @@ namespace ams::kern {
this->prev_thread = nullptr;
}
MESOSPHERE_KTRACE_THREAD_SWITCH(next_thread);
/* Switch the current process, if we're switching processes. */
if (KProcess *next_process = next_thread->GetOwnerProcess(); next_process != cur_process) {
/* MESOSPHERE_LOG("!!! PROCESS SWITCH !!! %s -> %s\n", cur_process != nullptr ? cur_process->GetName() : nullptr, next_process != nullptr ? next_process->GetName() : nullptr); */
@ -496,6 +502,7 @@ namespace ams::kern {
if (running_on_suggested_core == nullptr || running_on_suggested_core->GetPriority() >= HighestCoreMigrationAllowedPriority) {
suggested->SetActiveCore(core_id);
priority_queue.ChangeCore(suggested_core, suggested, true);
MESOSPHERE_KTRACE_CORE_MIGRATION(suggested->GetId(), suggested_core, core_id, 3);
IncrementScheduledCount(suggested);
break;
} else {
@ -549,6 +556,7 @@ namespace ams::kern {
/* Migrate the current thread to core -1. */
cur_thread.SetActiveCore(-1);
priority_queue.ChangeCore(core_id, std::addressof(cur_thread));
MESOSPHERE_KTRACE_CORE_MIGRATION(cur_thread.GetId(), core_id, -1, 4);
IncrementScheduledCount(std::addressof(cur_thread));
/* If there's nothing scheduled, we can try to perform a migration. */
@ -563,6 +571,7 @@ namespace ams::kern {
if (top_on_suggested_core == nullptr || top_on_suggested_core->GetPriority() >= HighestCoreMigrationAllowedPriority) {
suggested->SetActiveCore(core_id);
priority_queue.ChangeCore(suggested_core, suggested);
MESOSPHERE_KTRACE_CORE_MIGRATION(suggested->GetId(), suggested_core, core_id, 5);
IncrementScheduledCount(suggested);
}

View File

@ -28,8 +28,11 @@ namespace ams::kern {
void KServerPort::CleanupSessions() {
/* Ensure our preconditions are met. */
MESOSPHERE_ASSERT(this->IsLight() || this->session_list.empty());
MESOSPHERE_ASSERT(!this->IsLight() || this->light_session_list.empty());
if (this->IsLight()) {
MESOSPHERE_ASSERT(this->session_list.empty());
} else {
MESOSPHERE_ASSERT(this->light_session_list.empty());
}
/* Cleanup the session list. */
while (true) {