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

Commit a2006e83 authored by Syed Rameez Mustafa's avatar Syed Rameez Mustafa
Browse files

sched: Provide an easy method to log context switch latencies



Allow logging of various sections of context switch in order to derive
the worst case latencies associated with them. This is required for
scheduler profiling.

Change-Id: I3a5009cb3088cc7ace2cd3130d4d7b24e957bada
Signed-off-by: default avatarSyed Rameez Mustafa <rameezmustafa@codeaurora.org>
parent 5856d862
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
@@ -8856,6 +8908,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;