From f9dded0930461ef56f717aa88f333fdde3a07894 Mon Sep 17 00:00:00 2001 From: Kai Vehmanen Date: Mon, 1 Nov 2021 18:31:09 +0200 Subject: [PATCH] ll_schedule: add a DSP load tracker to ll_tasks_execute Add a lightweight load calculatio to ll_tasks_execute() and prints out the average every 2^10 runs (roughly once per second on most systems). Example log output: --cut-- [ 6950848.421715] ( 809129.187500) c0 ll-schedule ./schedule/ll_schedule.c:139 INFO ll avg 19720/38400 [ 8868838.449667] ( 679100.000000) c0 ll-schedule ./schedule/ll_schedule.c:139 INFO ll avg 19658/38400 [ 10802857.643650] ( 565147.187500) c0 ll-schedule ./schedule/ll_schedule.c:139 INFO ll avg 19822/38400 --cut-- Signed-off-by: Kai Vehmanen --- src/schedule/ll_schedule.c | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/src/schedule/ll_schedule.c b/src/schedule/ll_schedule.c index d06d8b15c811..c1717a0ecfbd 100644 --- a/src/schedule/ll_schedule.c +++ b/src/schedule/ll_schedule.c @@ -38,6 +38,11 @@ DECLARE_SOF_UUID("ll-schedule", ll_sched_uuid, 0x4f9c3ec7, 0x7b55, 0x400c, DECLARE_TR_CTX(ll_tr, SOF_UUID(ll_sched_uuid), LOG_LEVEL_INFO); +struct ll_dsp_load { + unsigned int cycles_sum; + unsigned int checks; +}; + /* one instance of data allocated per core */ struct ll_schedule_data { struct list_item tasks; /* list of ll tasks */ @@ -45,6 +50,7 @@ struct ll_schedule_data { #if CONFIG_PERFORMANCE_COUNTERS struct perf_cnt_data pcd; #endif + struct ll_dsp_load dsp_load; struct ll_schedule_domain *domain; /* scheduling domain */ }; @@ -113,13 +119,39 @@ static void schedule_ll_task_done(struct ll_schedule_data *sch, atomic_read(&sch->domain->total_num_tasks)); } +/* perf measurement windows size 2^x */ +#define CHECKS_WINDOW_SIZE 10 + +static inline void dsp_load_check(struct ll_dsp_load *load, uint32_t cycles0, uint32_t cycles1) +{ + uint32_t diff, max; + + if (cycles1 > cycles0) + diff = cycles1 - cycles0; + else + diff = UINT32_MAX - cycles0 + cycles1; + + load->cycles_sum += diff; + + if (++load->checks == 1 << CHECKS_WINDOW_SIZE) { + load->cycles_sum >>= CHECKS_WINDOW_SIZE; + max = clock_us_to_ticks(PLATFORM_DEFAULT_CLOCK, CONFIG_SYSTICK_PERIOD); + tr_info(&ll_tr, "ll avg %u/%u", load->cycles_sum, max); + load->cycles_sum = 0; + load->checks = 0; + } +} + static void schedule_ll_tasks_execute(struct ll_schedule_data *sch) { struct ll_schedule_domain *domain = sch->domain; + uint32_t cycles0, cycles1; struct list_item *wlist; struct list_item *tlist; struct task *task; + cycles0 = (uint32_t)platform_timer_get(timer_get()); + /* check each task in the list for pending */ list_for_item_safe(wlist, tlist, &sch->tasks) { task = container_of(wlist, struct task, list); @@ -152,6 +184,9 @@ static void schedule_ll_tasks_execute(struct ll_schedule_data *sch) spin_unlock(&domain->lock); } + + cycles1 = (uint32_t)platform_timer_get(timer_get()); + dsp_load_check(&sch->dsp_load, cycles0, cycles1); } static void schedule_ll_client_reschedule(struct ll_schedule_data *sch)