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