]>
Commit | Line | Data |
---|---|---|
91d1aa43 FW |
1 | #include <linux/context_tracking.h> |
2 | #include <linux/rcupdate.h> | |
3 | #include <linux/sched.h> | |
91d1aa43 FW |
4 | #include <linux/hardirq.h> |
5 | ||
91d1aa43 | 6 | |
95a79fd4 | 7 | DEFINE_PER_CPU(struct context_tracking, context_tracking) = { |
91d1aa43 FW |
8 | #ifdef CONFIG_CONTEXT_TRACKING_FORCE |
9 | .active = true, | |
10 | #endif | |
11 | }; | |
12 | ||
13 | void user_enter(void) | |
14 | { | |
15 | unsigned long flags; | |
16 | ||
17 | /* | |
18 | * Some contexts may involve an exception occuring in an irq, | |
19 | * leading to that nesting: | |
20 | * rcu_irq_enter() rcu_user_exit() rcu_user_exit() rcu_irq_exit() | |
21 | * This would mess up the dyntick_nesting count though. And rcu_irq_*() | |
22 | * helpers are enough to protect RCU uses inside the exception. So | |
23 | * just return immediately if we detect we are in an IRQ. | |
24 | */ | |
25 | if (in_interrupt()) | |
26 | return; | |
27 | ||
28 | WARN_ON_ONCE(!current->mm); | |
29 | ||
30 | local_irq_save(flags); | |
31 | if (__this_cpu_read(context_tracking.active) && | |
32 | __this_cpu_read(context_tracking.state) != IN_USER) { | |
abf917cd | 33 | vtime_user_enter(current); |
91d1aa43 | 34 | rcu_user_enter(); |
abf917cd | 35 | __this_cpu_write(context_tracking.state, IN_USER); |
91d1aa43 FW |
36 | } |
37 | local_irq_restore(flags); | |
38 | } | |
39 | ||
40 | void user_exit(void) | |
41 | { | |
42 | unsigned long flags; | |
43 | ||
44 | /* | |
45 | * Some contexts may involve an exception occuring in an irq, | |
46 | * leading to that nesting: | |
47 | * rcu_irq_enter() rcu_user_exit() rcu_user_exit() rcu_irq_exit() | |
48 | * This would mess up the dyntick_nesting count though. And rcu_irq_*() | |
49 | * helpers are enough to protect RCU uses inside the exception. So | |
50 | * just return immediately if we detect we are in an IRQ. | |
51 | */ | |
52 | if (in_interrupt()) | |
53 | return; | |
54 | ||
55 | local_irq_save(flags); | |
56 | if (__this_cpu_read(context_tracking.state) == IN_USER) { | |
91d1aa43 | 57 | rcu_user_exit(); |
abf917cd FW |
58 | vtime_user_exit(current); |
59 | __this_cpu_write(context_tracking.state, IN_KERNEL); | |
91d1aa43 FW |
60 | } |
61 | local_irq_restore(flags); | |
62 | } | |
63 | ||
64 | void context_tracking_task_switch(struct task_struct *prev, | |
65 | struct task_struct *next) | |
66 | { | |
67 | if (__this_cpu_read(context_tracking.active)) { | |
68 | clear_tsk_thread_flag(prev, TIF_NOHZ); | |
69 | set_tsk_thread_flag(next, TIF_NOHZ); | |
70 | } | |
71 | } |