Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c44483c3 authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "sched: Provide an easy method to log context switch latencies"

parents fc53d6de a2006e83
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -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
+53 −0
Original line number Diff line number Diff line
@@ -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"};
@@ -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);
@@ -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
@@ -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
@@ -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))) {
@@ -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
@@ -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;