| 1 | |
| 2 |
|
| 3 | #include <linux/user-return-notifier.h>
|
| 4 | #include <linux/percpu.h>
|
| 5 | #include <linux/sched.h>
|
| 6 | #include <linux/export.h>
|
| 7 |
|
| 8 | static DEFINE_PER_CPU(struct hlist_head, return_notifier_list);
|
| 9 |
|
| 10 | |
| 11 | * Request a notification when the current cpu returns to userspace. Must be
|
| 12 | * called in atomic context. The notifier will also be called in atomic
|
| 13 | * context.
|
| 14 |
|
| 15 | void user_return_notifier_register(struct user_return_notifier *urn)
|
| 16 | {
|
| 17 | set_tsk_thread_flag(current, TIF_USER_RETURN_NOTIFY);
|
| 18 | hlist_add_head(&urn->link, this_cpu_ptr(&return_notifier_list));
|
| 19 | }
|
| 20 | EXPORT_SYMBOL_GPL(user_return_notifier_register);
|
| 21 |
|
| 22 | |
| 23 | * Removes a registered user return notifier. Must be called from atomic
|
| 24 | * context, and from the same cpu registration occurred in.
|
| 25 |
|
| 26 | void user_return_notifier_unregister(struct user_return_notifier *urn)
|
| 27 | {
|
| 28 | hlist_del(&urn->link);
|
| 29 | if (hlist_empty(this_cpu_ptr(&return_notifier_list)))
|
| 30 | clear_tsk_thread_flag(current, TIF_USER_RETURN_NOTIFY);
|
| 31 | }
|
| 32 | EXPORT_SYMBOL_GPL(user_return_notifier_unregister);
|
| 33 |
|
| 34 |
|
| 35 | void fire_user_return_notifiers(void)
|
| 36 | {
|
| 37 | struct user_return_notifier *urn;
|
| 38 | struct hlist_node *tmp2;
|
| 39 | struct hlist_head *head;
|
| 40 |
|
| 41 | head = &get_cpu_var(return_notifier_list);
|
| 42 | hlist_for_each_entry_safe(urn, tmp2, head, link)
|
| 43 | urn->on_user_return(urn);
|
| 44 | put_cpu_var(return_notifier_list);
|
| 45 | }
|