diff options
Diffstat (limited to 'kernel/notifier.c')
-rw-r--r-- | kernel/notifier.c | 31 |
1 files changed, 28 insertions, 3 deletions
diff --git a/kernel/notifier.c b/kernel/notifier.c index 2488ba7eb56..e8481427153 100644 --- a/kernel/notifier.c +++ b/kernel/notifier.c @@ -5,6 +5,7 @@ #include <linux/rcupdate.h> #include <linux/vmalloc.h> #include <linux/reboot.h> +#include <linux/idle.h> /* * Notifier list for kernel code which wants to be called @@ -148,7 +149,7 @@ int atomic_notifier_chain_unregister(struct atomic_notifier_head *nh, spin_lock_irqsave(&nh->lock, flags); ret = notifier_chain_unregister(&nh->head, n); spin_unlock_irqrestore(&nh->lock, flags); - synchronize_rcu(); + synchronize_sched(); return ret; } EXPORT_SYMBOL_GPL(atomic_notifier_chain_unregister); @@ -178,9 +179,9 @@ int __kprobes __atomic_notifier_call_chain(struct atomic_notifier_head *nh, { int ret; - rcu_read_lock(); + rcu_read_lock_sched_notrace(); ret = notifier_call_chain(&nh->head, val, v, nr_to_call, nr_calls); - rcu_read_unlock(); + rcu_read_unlock_sched_notrace(); return ret; } EXPORT_SYMBOL_GPL(__atomic_notifier_call_chain); @@ -584,3 +585,27 @@ int unregister_die_notifier(struct notifier_block *nb) return atomic_notifier_chain_unregister(&die_chain, nb); } EXPORT_SYMBOL_GPL(unregister_die_notifier); + +static ATOMIC_NOTIFIER_HEAD(idle_notifier); + +/* + * Trace last event before calling notifiers. Notifiers flush data from buffers + * before going to idle. + */ +int notrace notify_idle(enum idle_val val) +{ + return atomic_notifier_call_chain(&idle_notifier, val, NULL); +} +EXPORT_SYMBOL_GPL(notify_idle); + +void register_idle_notifier(struct notifier_block *n) +{ + atomic_notifier_chain_register(&idle_notifier, n); +} +EXPORT_SYMBOL_GPL(register_idle_notifier); + +void unregister_idle_notifier(struct notifier_block *n) +{ + atomic_notifier_chain_unregister(&idle_notifier, n); +} +EXPORT_SYMBOL_GPL(unregister_idle_notifier); |