mirror of
https://github.com/AuxXxilium/linux_dsm_epyc7002.git
synced 2024-12-14 06:56:49 +07:00
c3bc8fd637
This patch detaches the preemptirq tracepoints from the tracers and keeps it separate. Advantages: * Lockdep and irqsoff event can now run in parallel since they no longer have their own calls. * This unifies the usecase of adding hooks to an irqsoff and irqson event, and a preemptoff and preempton event. 3 users of the events exist: - Lockdep - irqsoff and preemptoff tracers - irqs and preempt trace events The unification cleans up several ifdefs and makes the code in preempt tracer and irqsoff tracers simpler. It gets rid of all the horrific ifdeferry around PROVE_LOCKING and makes configuration of the different users of the tracepoints more easy and understandable. It also gets rid of the time_* function calls from the lockdep hooks used to call into the preemptirq tracer which is not needed anymore. The negative delta in lines of code in this patch is quite large too. In the patch we introduce a new CONFIG option PREEMPTIRQ_TRACEPOINTS as a single point for registering probes onto the tracepoints. With this, the web of config options for preempt/irq toggle tracepoints and its users becomes: PREEMPT_TRACER PREEMPTIRQ_EVENTS IRQSOFF_TRACER PROVE_LOCKING | | \ | | \ (selects) / \ \ (selects) / TRACE_PREEMPT_TOGGLE ----> TRACE_IRQFLAGS \ / \ (depends on) / PREEMPTIRQ_TRACEPOINTS Other than the performance tests mentioned in the previous patch, I also ran the locking API test suite. I verified that all tests cases are passing. I also injected issues by not registering lockdep probes onto the tracepoints and I see failures to confirm that the probes are indeed working. This series + lockdep probes not registered (just to inject errors): [ 0.000000] hard-irqs-on + irq-safe-A/21: ok | ok | ok | [ 0.000000] soft-irqs-on + irq-safe-A/21: ok | ok | ok | [ 0.000000] sirq-safe-A => hirqs-on/12:FAILED|FAILED| ok | [ 0.000000] sirq-safe-A => hirqs-on/21:FAILED|FAILED| ok | [ 0.000000] hard-safe-A + irqs-on/12:FAILED|FAILED| ok | [ 0.000000] soft-safe-A + irqs-on/12:FAILED|FAILED| ok | [ 0.000000] hard-safe-A + irqs-on/21:FAILED|FAILED| ok | [ 0.000000] soft-safe-A + irqs-on/21:FAILED|FAILED| ok | [ 0.000000] hard-safe-A + unsafe-B #1/123: ok | ok | ok | [ 0.000000] soft-safe-A + unsafe-B #1/123: ok | ok | ok | With this series + lockdep probes registered, all locking tests pass: [ 0.000000] hard-irqs-on + irq-safe-A/21: ok | ok | ok | [ 0.000000] soft-irqs-on + irq-safe-A/21: ok | ok | ok | [ 0.000000] sirq-safe-A => hirqs-on/12: ok | ok | ok | [ 0.000000] sirq-safe-A => hirqs-on/21: ok | ok | ok | [ 0.000000] hard-safe-A + irqs-on/12: ok | ok | ok | [ 0.000000] soft-safe-A + irqs-on/12: ok | ok | ok | [ 0.000000] hard-safe-A + irqs-on/21: ok | ok | ok | [ 0.000000] soft-safe-A + irqs-on/21: ok | ok | ok | [ 0.000000] hard-safe-A + unsafe-B #1/123: ok | ok | ok | [ 0.000000] soft-safe-A + unsafe-B #1/123: ok | ok | ok | Link: http://lkml.kernel.org/r/20180730222423.196630-4-joel@joelfernandes.org Acked-by: Peter Zijlstra (Intel) <peterz@infradead.org> Reviewed-by: Namhyung Kim <namhyung@kernel.org> Signed-off-by: Joel Fernandes (Google) <joel@joelfernandes.org> Signed-off-by: Steven Rostedt (VMware) <rostedt@goodmis.org>
168 lines
4.8 KiB
C
168 lines
4.8 KiB
C
/* SPDX-License-Identifier: GPL-2.0 */
|
|
/*
|
|
* include/linux/irqflags.h
|
|
*
|
|
* IRQ flags tracing: follow the state of the hardirq and softirq flags and
|
|
* provide callbacks for transitions between ON and OFF states.
|
|
*
|
|
* This file gets included from lowlevel asm headers too, to provide
|
|
* wrapped versions of the local_irq_*() APIs, based on the
|
|
* raw_local_irq_*() macros from the lowlevel headers.
|
|
*/
|
|
#ifndef _LINUX_TRACE_IRQFLAGS_H
|
|
#define _LINUX_TRACE_IRQFLAGS_H
|
|
|
|
#include <linux/typecheck.h>
|
|
#include <asm/irqflags.h>
|
|
|
|
/* Currently trace_softirqs_on/off is used only by lockdep */
|
|
#ifdef CONFIG_PROVE_LOCKING
|
|
extern void trace_softirqs_on(unsigned long ip);
|
|
extern void trace_softirqs_off(unsigned long ip);
|
|
#else
|
|
# define trace_softirqs_on(ip) do { } while (0)
|
|
# define trace_softirqs_off(ip) do { } while (0)
|
|
#endif
|
|
|
|
#ifdef CONFIG_TRACE_IRQFLAGS
|
|
extern void trace_hardirqs_on(void);
|
|
extern void trace_hardirqs_off(void);
|
|
# define trace_hardirq_context(p) ((p)->hardirq_context)
|
|
# define trace_softirq_context(p) ((p)->softirq_context)
|
|
# define trace_hardirqs_enabled(p) ((p)->hardirqs_enabled)
|
|
# define trace_softirqs_enabled(p) ((p)->softirqs_enabled)
|
|
# define trace_hardirq_enter() \
|
|
do { \
|
|
current->hardirq_context++; \
|
|
} while (0)
|
|
# define trace_hardirq_exit() \
|
|
do { \
|
|
current->hardirq_context--; \
|
|
} while (0)
|
|
# define lockdep_softirq_enter() \
|
|
do { \
|
|
current->softirq_context++; \
|
|
} while (0)
|
|
# define lockdep_softirq_exit() \
|
|
do { \
|
|
current->softirq_context--; \
|
|
} while (0)
|
|
#else
|
|
# define trace_hardirqs_on() do { } while (0)
|
|
# define trace_hardirqs_off() do { } while (0)
|
|
# define trace_hardirq_context(p) 0
|
|
# define trace_softirq_context(p) 0
|
|
# define trace_hardirqs_enabled(p) 0
|
|
# define trace_softirqs_enabled(p) 0
|
|
# define trace_hardirq_enter() do { } while (0)
|
|
# define trace_hardirq_exit() do { } while (0)
|
|
# define lockdep_softirq_enter() do { } while (0)
|
|
# define lockdep_softirq_exit() do { } while (0)
|
|
#endif
|
|
|
|
#if defined(CONFIG_IRQSOFF_TRACER) || \
|
|
defined(CONFIG_PREEMPT_TRACER)
|
|
extern void stop_critical_timings(void);
|
|
extern void start_critical_timings(void);
|
|
#else
|
|
# define stop_critical_timings() do { } while (0)
|
|
# define start_critical_timings() do { } while (0)
|
|
#endif
|
|
|
|
/*
|
|
* Wrap the arch provided IRQ routines to provide appropriate checks.
|
|
*/
|
|
#define raw_local_irq_disable() arch_local_irq_disable()
|
|
#define raw_local_irq_enable() arch_local_irq_enable()
|
|
#define raw_local_irq_save(flags) \
|
|
do { \
|
|
typecheck(unsigned long, flags); \
|
|
flags = arch_local_irq_save(); \
|
|
} while (0)
|
|
#define raw_local_irq_restore(flags) \
|
|
do { \
|
|
typecheck(unsigned long, flags); \
|
|
arch_local_irq_restore(flags); \
|
|
} while (0)
|
|
#define raw_local_save_flags(flags) \
|
|
do { \
|
|
typecheck(unsigned long, flags); \
|
|
flags = arch_local_save_flags(); \
|
|
} while (0)
|
|
#define raw_irqs_disabled_flags(flags) \
|
|
({ \
|
|
typecheck(unsigned long, flags); \
|
|
arch_irqs_disabled_flags(flags); \
|
|
})
|
|
#define raw_irqs_disabled() (arch_irqs_disabled())
|
|
#define raw_safe_halt() arch_safe_halt()
|
|
|
|
/*
|
|
* The local_irq_*() APIs are equal to the raw_local_irq*()
|
|
* if !TRACE_IRQFLAGS.
|
|
*/
|
|
#ifdef CONFIG_TRACE_IRQFLAGS
|
|
#define local_irq_enable() \
|
|
do { trace_hardirqs_on(); raw_local_irq_enable(); } while (0)
|
|
#define local_irq_disable() \
|
|
do { raw_local_irq_disable(); trace_hardirqs_off(); } while (0)
|
|
#define local_irq_save(flags) \
|
|
do { \
|
|
raw_local_irq_save(flags); \
|
|
trace_hardirqs_off(); \
|
|
} while (0)
|
|
|
|
|
|
#define local_irq_restore(flags) \
|
|
do { \
|
|
if (raw_irqs_disabled_flags(flags)) { \
|
|
raw_local_irq_restore(flags); \
|
|
trace_hardirqs_off(); \
|
|
} else { \
|
|
trace_hardirqs_on(); \
|
|
raw_local_irq_restore(flags); \
|
|
} \
|
|
} while (0)
|
|
|
|
#define safe_halt() \
|
|
do { \
|
|
trace_hardirqs_on(); \
|
|
raw_safe_halt(); \
|
|
} while (0)
|
|
|
|
|
|
#else /* !CONFIG_TRACE_IRQFLAGS */
|
|
|
|
#define local_irq_enable() do { raw_local_irq_enable(); } while (0)
|
|
#define local_irq_disable() do { raw_local_irq_disable(); } while (0)
|
|
#define local_irq_save(flags) \
|
|
do { \
|
|
raw_local_irq_save(flags); \
|
|
} while (0)
|
|
#define local_irq_restore(flags) do { raw_local_irq_restore(flags); } while (0)
|
|
#define safe_halt() do { raw_safe_halt(); } while (0)
|
|
|
|
#endif /* CONFIG_TRACE_IRQFLAGS */
|
|
|
|
#define local_save_flags(flags) raw_local_save_flags(flags)
|
|
|
|
/*
|
|
* Some architectures don't define arch_irqs_disabled(), so even if either
|
|
* definition would be fine we need to use different ones for the time being
|
|
* to avoid build issues.
|
|
*/
|
|
#ifdef CONFIG_TRACE_IRQFLAGS_SUPPORT
|
|
#define irqs_disabled() \
|
|
({ \
|
|
unsigned long _flags; \
|
|
raw_local_save_flags(_flags); \
|
|
raw_irqs_disabled_flags(_flags); \
|
|
})
|
|
#else /* !CONFIG_TRACE_IRQFLAGS_SUPPORT */
|
|
#define irqs_disabled() raw_irqs_disabled()
|
|
#endif /* CONFIG_TRACE_IRQFLAGS_SUPPORT */
|
|
|
|
#define irqs_disabled_flags(flags) raw_irqs_disabled_flags(flags)
|
|
|
|
#endif
|