diff options
| author | H. Peter Anvin <hpa@zytor.com> | 2010-02-10 16:55:28 -0800 |
|---|---|---|
| committer | H. Peter Anvin <hpa@zytor.com> | 2010-02-10 16:55:28 -0800 |
| commit | 84abd88a70090cf00f9e45c3a81680874f17626e (patch) | |
| tree | 4f58b80057f6e1f5817af1dc33a5458b3dfc9a99 /kernel/user-return-notifier.c | |
| parent | 13ca0fcaa33f6b1984c4111b6ec5df42689fea6f (diff) | |
| parent | e28cab42f384745c8a947a9ccd51e4aae52f5d51 (diff) | |
Merge remote branch 'linus/master' into x86/bootmem
Diffstat (limited to 'kernel/user-return-notifier.c')
| -rw-r--r-- | kernel/user-return-notifier.c | 44 |
1 files changed, 44 insertions, 0 deletions
diff --git a/kernel/user-return-notifier.c b/kernel/user-return-notifier.c new file mode 100644 index 00000000000..eb27fd3430a --- /dev/null +++ b/kernel/user-return-notifier.c @@ -0,0 +1,44 @@ + +#include <linux/user-return-notifier.h> +#include <linux/percpu.h> +#include <linux/sched.h> +#include <linux/module.h> + +static DEFINE_PER_CPU(struct hlist_head, return_notifier_list); + +/* + * Request a notification when the current cpu returns to userspace. Must be + * called in atomic context. The notifier will also be called in atomic + * context. + */ +void user_return_notifier_register(struct user_return_notifier *urn) +{ + set_tsk_thread_flag(current, TIF_USER_RETURN_NOTIFY); + hlist_add_head(&urn->link, &__get_cpu_var(return_notifier_list)); +} +EXPORT_SYMBOL_GPL(user_return_notifier_register); + +/* + * Removes a registered user return notifier. Must be called from atomic + * context, and from the same cpu registration occured in. + */ +void user_return_notifier_unregister(struct user_return_notifier *urn) +{ + hlist_del(&urn->link); + if (hlist_empty(&__get_cpu_var(return_notifier_list))) + clear_tsk_thread_flag(current, TIF_USER_RETURN_NOTIFY); +} +EXPORT_SYMBOL_GPL(user_return_notifier_unregister); + +/* Calls registered user return notifiers */ +void fire_user_return_notifiers(void) +{ + struct user_return_notifier *urn; + struct hlist_node *tmp1, *tmp2; + struct hlist_head *head; + + head = &get_cpu_var(return_notifier_list); + hlist_for_each_entry_safe(urn, tmp1, tmp2, head, link) + urn->on_user_return(urn); + put_cpu_var(return_notifier_list); +} |
