diff --git a/kernel/trace/trace_irqsoff.c b/kernel/trace/trace_irqsoff.c index 8523ea345f2b..89433a83dd2d 100644 --- a/kernel/trace/trace_irqsoff.c +++ b/kernel/trace/trace_irqsoff.c @@ -13,6 +13,7 @@ #include #include #include +#include #include "trace.h" @@ -510,8 +511,42 @@ EXPORT_SYMBOL(trace_hardirqs_off_caller); #endif /* CONFIG_IRQSOFF_TRACER */ #ifdef CONFIG_PREEMPT_TRACER +struct elem { + u64 pad[32]; + struct rcu_head rcu; +}; + +static DEFINE_PER_CPU(int, prog_active); +static void * test_alloc(void) +{ + struct elem *e = NULL; + + if (in_nmi()) + return e; + + preempt_disable_notrace(); + if (unlikely(__this_cpu_inc_return(prog_active) != 1)) + goto out; + + rcu_read_lock(); + e = kmalloc(sizeof(struct elem), GFP_ATOMIC); + rcu_read_unlock(); + if (!e) + goto out; + + kfree_rcu(e, rcu); +out: + __this_cpu_dec(prog_active); + preempt_enable_no_resched_notrace(); + return e; +} + void trace_preempt_on(unsigned long a0, unsigned long a1) { + void * buf = 0; + static int cnt = 0; + if (cnt++ > 3000000) + buf = test_alloc(); if (preempt_trace() && !irq_trace()) stop_critical_timing(a0, a1); }