Signed-off-by: Avi Kivity <avi@redhat.com>tirimbino
commit
58988b07cf
@ -0,0 +1,49 @@ |
||||
#ifndef _LINUX_USER_RETURN_NOTIFIER_H |
||||
#define _LINUX_USER_RETURN_NOTIFIER_H |
||||
|
||||
#ifdef CONFIG_USER_RETURN_NOTIFIER |
||||
|
||||
#include <linux/list.h> |
||||
#include <linux/sched.h> |
||||
|
||||
struct user_return_notifier { |
||||
void (*on_user_return)(struct user_return_notifier *urn); |
||||
struct hlist_node link; |
||||
}; |
||||
|
||||
|
||||
void user_return_notifier_register(struct user_return_notifier *urn); |
||||
void user_return_notifier_unregister(struct user_return_notifier *urn); |
||||
|
||||
static inline void propagate_user_return_notify(struct task_struct *prev, |
||||
struct task_struct *next) |
||||
{ |
||||
if (test_tsk_thread_flag(prev, TIF_USER_RETURN_NOTIFY)) { |
||||
clear_tsk_thread_flag(prev, TIF_USER_RETURN_NOTIFY); |
||||
set_tsk_thread_flag(next, TIF_USER_RETURN_NOTIFY); |
||||
} |
||||
} |
||||
|
||||
void fire_user_return_notifiers(void); |
||||
|
||||
static inline void clear_user_return_notifier(struct task_struct *p) |
||||
{ |
||||
clear_tsk_thread_flag(p, TIF_USER_RETURN_NOTIFY); |
||||
} |
||||
|
||||
#else |
||||
|
||||
struct user_return_notifier {}; |
||||
|
||||
static inline void propagate_user_return_notify(struct task_struct *prev, |
||||
struct task_struct *next) |
||||
{ |
||||
} |
||||
|
||||
static inline void fire_user_return_notifiers(void) {} |
||||
|
||||
static inline void clear_user_return_notifier(struct task_struct *p) {} |
||||
|
||||
#endif |
||||
|
||||
#endif |
@ -0,0 +1,46 @@ |
||||
|
||||
#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); |
||||
|
||||
#define URN_LIST_HEAD per_cpu(return_notifier_list, raw_smp_processor_id()) |
||||
|
||||
/*
|
||||
* 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, &URN_LIST_HEAD); |
||||
} |
||||
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(&URN_LIST_HEAD)) |
||||
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); |
||||
} |
Loading…
Reference in new issue