--- zzzz-none-000/linux-4.4.271/kernel/softirq.c 2021-06-03 06:22:09.000000000 +0000 +++ hawkeye-5590-750/linux-4.4.271/kernel/softirq.c 2023-04-19 10:22:30.000000000 +0000 @@ -26,6 +26,15 @@ #include #include #include +#include + + +#ifdef CONFIG_STOPWATCH_SOFT_IRQ +#define __STOPWATCH_USE__ +#endif +#include +#include +#include #define CREATE_TRACE_POINTS #include @@ -53,6 +62,8 @@ EXPORT_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); @@ -116,9 +127,9 @@ if (preempt_count() == cnt) { #ifdef CONFIG_DEBUG_PREEMPT - current->preempt_disable_ip = get_parent_ip(CALLER_ADDR1); + current->preempt_disable_ip = get_lock_parent_ip(); #endif - trace_preempt_off(CALLER_ADDR0, get_parent_ip(CALLER_ADDR1)); + trace_preempt_off(CALLER_ADDR0, get_lock_parent_ip()); } } EXPORT_SYMBOL(__local_bh_disable_ip); @@ -178,6 +189,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. @@ -249,6 +291,7 @@ __local_bh_disable_ip(_RET_IP_, SOFTIRQ_OFFSET); in_hardirq = lockdep_softirq_start(); + avm_sum_softirq_enter(); restart: /* Reset the pending bitmask before enabling irqs */ @@ -259,6 +302,7 @@ h = softirq_vec; while ((softirq_bit = ffs(pending))) { + struct _runtime_stat *pts; unsigned int vec_nr; int prev_count; @@ -269,9 +313,17 @@ kstat_incr_softirqs_this_cpu(vec_nr); + avm_simple_profiling_log(avm_profile_data_type_sw_irq_begin, + (unsigned long)(h->action), (unsigned int)h); trace_softirq_entry(vec_nr); + pts = avm_softirq_enter(vec_nr); + STOPWATCH_START(softirq[vec_nr]); h->action(h); + STOPWATCH_STOP(softirq[vec_nr]); + avm_softirq_leave(pts); trace_softirq_exit(vec_nr); + avm_simple_profiling_log(avm_profile_data_type_sw_irq_end, + (unsigned long)(h->action), (unsigned int)h); if (unlikely(prev_count != preempt_count())) { pr_err("huh, entered softirq %u %s %p with preempt_count %08x, exited with %08x?\n", vec_nr, softirq_to_name[vec_nr], h->action, @@ -294,6 +346,7 @@ wakeup_softirqd(); } + avm_sum_softirq_leave(); lockdep_softirq_end(in_hardirq); account_irq_exit_time(current); __local_bh_enable(SOFTIRQ_OFFSET); @@ -454,6 +507,8 @@ t->next = NULL; *__this_cpu_read(tasklet_vec.tail) = t; __this_cpu_write(tasklet_vec.tail, &(t->next)); + avm_simple_profiling_log(avm_profile_data_type_trigger_tasklet_begin, + (unsigned long)(t->func), TASKLET_SOFTIRQ); raise_softirq_irqoff(TASKLET_SOFTIRQ); local_irq_restore(flags); } @@ -467,6 +522,8 @@ t->next = NULL; *__this_cpu_read(tasklet_hi_vec.tail) = t; __this_cpu_write(tasklet_hi_vec.tail, &(t->next)); + avm_simple_profiling_log(avm_profile_data_type_trigger_tasklet_begin, + (unsigned long)(t->func), HI_SOFTIRQ); raise_softirq_irqoff(HI_SOFTIRQ); local_irq_restore(flags); } @@ -493,6 +550,7 @@ local_irq_enable(); while (list) { + struct _runtime_stat *pfunc_stat; struct tasklet_struct *t = list; list = list->next; @@ -502,7 +560,18 @@ if (!test_and_clear_bit(TASKLET_STATE_SCHED, &t->state)) BUG(); + trace_tlet_entry(t); + avm_simple_profiling_log(avm_profile_data_type_trigger_tasklet_end, + (unsigned long)(t->func), TASKLET_SOFTIRQ); + avm_simple_profiling_log(avm_profile_data_type_tasklet_begin, + (unsigned long)(t->func), (unsigned int)(t->data)); + pfunc_stat = avm_taskletfunc_enter(t->func, TASKLET_SOFTIRQ); t->func(t->data); + avm_taskletfunc_leave(pfunc_stat); + avm_simple_profiling_log(avm_profile_data_type_tasklet_end, + (unsigned long)(t->func), (unsigned int)(t->data)); + + trace_tlet_exit(t); tasklet_unlock(t); continue; } @@ -529,6 +598,7 @@ local_irq_enable(); while (list) { + struct _runtime_stat *pfunc_stat; struct tasklet_struct *t = list; list = list->next; @@ -538,7 +608,17 @@ if (!test_and_clear_bit(TASKLET_STATE_SCHED, &t->state)) BUG(); + trace_tlet_entry(t); + avm_simple_profiling_log(avm_profile_data_type_trigger_tasklet_end, + (unsigned long)(t->func), HI_SOFTIRQ); + avm_simple_profiling_log(avm_profile_data_type_hi_tasklet_begin, + (unsigned long)(t->func), (unsigned int)(t->data)); + pfunc_stat = avm_taskletfunc_enter(t->func, HI_SOFTIRQ); t->func(t->data); + avm_taskletfunc_leave(pfunc_stat); + avm_simple_profiling_log(avm_profile_data_type_hi_tasklet_end, + (unsigned long)(t->func), (unsigned int)(t->data)); + trace_tlet_exit(t); tasklet_unlock(t); continue; }