Loading arch/arm64/Kconfig +6 −0 Original line number Diff line number Diff line Loading @@ -344,6 +344,12 @@ config SCHED_SMT MultiThreading at a cost of slightly increased overhead in some places. If unsure say N here. config ARCH_WANTS_CTXSW_LOGGING bool "Enable logging in context switch" depends on SMP help Logs critical context switch latencies. If unsure say N here. config NR_CPUS int "Maximum number of CPUs (2-32)" range 2 32 Loading kernel/sched/core.c +53 −0 Original line number Diff line number Diff line Loading @@ -90,6 +90,30 @@ #define CREATE_TRACE_POINTS #include <trace/events/sched.h> #include <soc/qcom/watchdog.h> #define DLOG_SIZE 15000 #define MAX_CTXSW_LATENCY 1000000000 static DEFINE_PER_CPU(char[DLOG_SIZE], dbuf); static DEFINE_PER_CPU(char *, dptr); #define dlog(x...) \ do { \ unsigned long dflags; \ char *ptr, *buf; \ int dcpu; \ local_irq_save(dflags); \ dcpu = smp_processor_id(); \ buf = per_cpu(dbuf, dcpu); \ ptr = per_cpu(dptr, dcpu); \ ptr += snprintf(ptr, 10, "CPU %d ", dcpu); \ ptr += snprintf(ptr, 490, x); \ if (ptr - buf > DLOG_SIZE - 500) \ ptr = buf; \ per_cpu(dptr, dcpu) = ptr; \ local_irq_restore(dflags); \ } while (0) const char *task_event_names[] = {"PUT_PREV_TASK", "PICK_NEXT_TASK", "TASK_WAKE", "TASK_MIGRATE", "TASK_UPDATE", "IRQ_UPDATE"}; Loading Loading @@ -3444,6 +3468,9 @@ prepare_task_switch(struct rq *rq, struct task_struct *prev, struct task_struct *next) { trace_sched_switch(prev, next); #ifdef CONFIG_ARCH_WANTS_CTXSW_LOGGING dlog("%s: end trace at %llu\n", __func__, sched_clock()); #endif sched_info_switch(prev, next); perf_event_task_sched_out(prev, next); fire_sched_out_preempt_notifiers(prev, next); Loading Loading @@ -3577,11 +3604,19 @@ context_switch(struct rq *rq, struct task_struct *prev, struct task_struct *next) { struct mm_struct *mm, *oldmm; #ifdef CONFIG_ARCH_WANTS_CTXSW_LOGGING u64 start, end; #endif prepare_task_switch(rq, prev, next); mm = next->mm; oldmm = prev->active_mm; #ifdef CONFIG_ARCH_WANTS_CTXSW_LOGGING start = sched_clock(); dlog("%s: n_mm: %p, finish pts at %llu\n", __func__, mm, start); #endif /* * For paravirt, this is coupled with an exit in switch_to to * combine the page table reload and the switch backend into Loading @@ -3600,6 +3635,15 @@ context_switch(struct rq *rq, struct task_struct *prev, prev->active_mm = NULL; rq->prev_mm = oldmm; } #ifdef CONFIG_ARCH_WANTS_CTXSW_LOGGING end = sched_clock(); dlog("%s: start task switch at %llu\n", __func__, end); if (end - start > MAX_CTXSW_LATENCY) msm_trigger_wdog_bite(); #endif /* * Since the runqueue lock will be released by the next * task (which is an invalid locking op but in the case Loading Loading @@ -4579,6 +4623,10 @@ need_resched: smp_mb__before_spinlock(); raw_spin_lock_irq(&rq->lock); #ifdef CONFIG_ARCH_WANTS_CTXSW_LOGGING dlog("%s: locked %p at %llu\n", __func__, &rq->lock, sched_clock()); #endif switch_count = &prev->nivcsw; if (prev->state && !(preempt_count() & PREEMPT_ACTIVE)) { if (unlikely(signal_pending_state(prev->state, prev))) { Loading Loading @@ -4623,6 +4671,10 @@ need_resched: rq->curr = next; ++*switch_count; #ifdef CONFIG_ARCH_WANTS_CTXSW_LOGGING dlog("%s: enter context_switch at %llu\n", __func__, sched_clock()); #endif context_switch(rq, prev, next); /* unlocks the rq */ /* * The context switch have flipped the stack from under us Loading Loading @@ -8858,6 +8910,7 @@ void __init sched_init(void) for_each_possible_cpu(i) { struct rq *rq; per_cpu(dptr, i) = per_cpu(dbuf, i); rq = cpu_rq(i); raw_spin_lock_init(&rq->lock); rq->nr_running = 0; Loading Loading
arch/arm64/Kconfig +6 −0 Original line number Diff line number Diff line Loading @@ -344,6 +344,12 @@ config SCHED_SMT MultiThreading at a cost of slightly increased overhead in some places. If unsure say N here. config ARCH_WANTS_CTXSW_LOGGING bool "Enable logging in context switch" depends on SMP help Logs critical context switch latencies. If unsure say N here. config NR_CPUS int "Maximum number of CPUs (2-32)" range 2 32 Loading
kernel/sched/core.c +53 −0 Original line number Diff line number Diff line Loading @@ -90,6 +90,30 @@ #define CREATE_TRACE_POINTS #include <trace/events/sched.h> #include <soc/qcom/watchdog.h> #define DLOG_SIZE 15000 #define MAX_CTXSW_LATENCY 1000000000 static DEFINE_PER_CPU(char[DLOG_SIZE], dbuf); static DEFINE_PER_CPU(char *, dptr); #define dlog(x...) \ do { \ unsigned long dflags; \ char *ptr, *buf; \ int dcpu; \ local_irq_save(dflags); \ dcpu = smp_processor_id(); \ buf = per_cpu(dbuf, dcpu); \ ptr = per_cpu(dptr, dcpu); \ ptr += snprintf(ptr, 10, "CPU %d ", dcpu); \ ptr += snprintf(ptr, 490, x); \ if (ptr - buf > DLOG_SIZE - 500) \ ptr = buf; \ per_cpu(dptr, dcpu) = ptr; \ local_irq_restore(dflags); \ } while (0) const char *task_event_names[] = {"PUT_PREV_TASK", "PICK_NEXT_TASK", "TASK_WAKE", "TASK_MIGRATE", "TASK_UPDATE", "IRQ_UPDATE"}; Loading Loading @@ -3444,6 +3468,9 @@ prepare_task_switch(struct rq *rq, struct task_struct *prev, struct task_struct *next) { trace_sched_switch(prev, next); #ifdef CONFIG_ARCH_WANTS_CTXSW_LOGGING dlog("%s: end trace at %llu\n", __func__, sched_clock()); #endif sched_info_switch(prev, next); perf_event_task_sched_out(prev, next); fire_sched_out_preempt_notifiers(prev, next); Loading Loading @@ -3577,11 +3604,19 @@ context_switch(struct rq *rq, struct task_struct *prev, struct task_struct *next) { struct mm_struct *mm, *oldmm; #ifdef CONFIG_ARCH_WANTS_CTXSW_LOGGING u64 start, end; #endif prepare_task_switch(rq, prev, next); mm = next->mm; oldmm = prev->active_mm; #ifdef CONFIG_ARCH_WANTS_CTXSW_LOGGING start = sched_clock(); dlog("%s: n_mm: %p, finish pts at %llu\n", __func__, mm, start); #endif /* * For paravirt, this is coupled with an exit in switch_to to * combine the page table reload and the switch backend into Loading @@ -3600,6 +3635,15 @@ context_switch(struct rq *rq, struct task_struct *prev, prev->active_mm = NULL; rq->prev_mm = oldmm; } #ifdef CONFIG_ARCH_WANTS_CTXSW_LOGGING end = sched_clock(); dlog("%s: start task switch at %llu\n", __func__, end); if (end - start > MAX_CTXSW_LATENCY) msm_trigger_wdog_bite(); #endif /* * Since the runqueue lock will be released by the next * task (which is an invalid locking op but in the case Loading Loading @@ -4579,6 +4623,10 @@ need_resched: smp_mb__before_spinlock(); raw_spin_lock_irq(&rq->lock); #ifdef CONFIG_ARCH_WANTS_CTXSW_LOGGING dlog("%s: locked %p at %llu\n", __func__, &rq->lock, sched_clock()); #endif switch_count = &prev->nivcsw; if (prev->state && !(preempt_count() & PREEMPT_ACTIVE)) { if (unlikely(signal_pending_state(prev->state, prev))) { Loading Loading @@ -4623,6 +4671,10 @@ need_resched: rq->curr = next; ++*switch_count; #ifdef CONFIG_ARCH_WANTS_CTXSW_LOGGING dlog("%s: enter context_switch at %llu\n", __func__, sched_clock()); #endif context_switch(rq, prev, next); /* unlocks the rq */ /* * The context switch have flipped the stack from under us Loading Loading @@ -8858,6 +8910,7 @@ void __init sched_init(void) for_each_possible_cpu(i) { struct rq *rq; per_cpu(dptr, i) = per_cpu(dbuf, i); rq = cpu_rq(i); raw_spin_lock_init(&rq->lock); rq->nr_running = 0; Loading