--- zzzz-none-000/linux-5.4.213/kernel/softirq.c 2022-09-15 10:04:56.000000000 +0000 +++ alder-5690pro-762/linux-5.4.213/kernel/softirq.c 2024-08-14 09:02:11.000000000 +0000 @@ -25,9 +25,15 @@ #include #include #include +#include +#ifdef CONFIG_STOPWATCH_SOFT_IRQ +#define __STOPWATCH_USE__ +#endif +#include #define CREATE_TRACE_POINTS #include +#include /* - No shared variables, all the data are CPU local. @@ -52,6 +58,8 @@ EXPORT_PER_CPU_SYMBOL(irq_stat); #endif +DEFINE_STOPWATCH_ARRAY(softirq, NR_SOFTIRQS); + static struct softirq_action softirq_vec[NR_SOFTIRQS] __cacheline_aligned_in_smp; DEFINE_PER_CPU(struct task_struct *, ksoftirqd); @@ -197,6 +205,37 @@ } EXPORT_SYMBOL(__local_bh_enable_ip); +#ifdef __STOPWATCH_USE__ +int stopwatch_softirq_show(struct seq_file *f, void *v) +{ + int cpu; + int sirq = *((loff_t *) v); + + if (sirq == 0) + seq_printf(f, "%20s\tCPU\tmin(us)\tavg(us)\tmax(us)\n\n", ""); + + seq_printf(f, "%2d:%-18s", sirq, softirq_to_name[sirq]); + for_each_cpu(cpu, cpu_online_mask) { + if (!cpu) + seq_printf(f, "\t%d", cpu); + else + seq_printf(f, "%20s\t%d", "", cpu); + stopwatch_show(&STOPWATCH_INSTANCE_CPU(softirq[sirq], cpu), f, STOPWATCH_MICRO); + seq_printf(f, "\n"); + } + seq_printf(f, "\n"); + return 0; +} + +static int __init softirq_stopwatch_init(void) +{ + INIT_STOPWATCH_ARRAY(softirq, NR_SOFTIRQS); + return stopwatch_register("softirq", NR_SOFTIRQS, stopwatch_softirq_show); +} +module_init(softirq_stopwatch_init) +#endif + + /* * We restart softirq processing for at most MAX_SOFTIRQ_RESTART times, * but break the loop if need_resched() is set or after 2 ms. @@ -289,7 +328,13 @@ kstat_incr_softirqs_this_cpu(vec_nr); trace_softirq_entry(vec_nr); + STOPWATCH_START(softirq[vec_nr]); + avm_simple_profiling_log(avm_profile_data_type_sw_irq_begin, + (unsigned long)(h->action), vec_nr); h->action(h); + avm_simple_profiling_log(avm_profile_data_type_sw_irq_end, + (unsigned long)(h->action), vec_nr); + STOPWATCH_STOP(softirq[vec_nr]); trace_softirq_exit(vec_nr); if (unlikely(prev_count != preempt_count())) { pr_err("huh, entered softirq %u %s %p with preempt_count %08x, exited with %08x?\n", @@ -480,6 +525,8 @@ t->next = NULL; *head->tail = t; head->tail = &(t->next); + avm_simple_profiling_log(avm_profile_data_type_trigger_tasklet_begin, + (unsigned long)(t->func), softirq_nr); raise_softirq_irqoff(softirq_nr); local_irq_restore(flags); } @@ -520,7 +567,13 @@ if (!test_and_clear_bit(TASKLET_STATE_SCHED, &t->state)) BUG(); + avm_simple_profiling_log(avm_profile_data_type_trigger_tasklet_end, + (unsigned long)(t->func), softirq_nr); + avm_simple_profiling_log(avm_profile_data_type_tasklet_begin, + (unsigned long)(t->func), softirq_nr); t->func(t->data); + avm_simple_profiling_log(avm_profile_data_type_tasklet_end, + (unsigned long)(t->func), softirq_nr); tasklet_unlock(t); continue; }