2009-09-19 10:40:22 +04:00
# include <linux/user-return-notifier.h>
# include <linux/percpu.h>
# include <linux/sched.h>
2011-05-23 22:51:41 +04:00
# include <linux/export.h>
2009-09-19 10:40:22 +04:00
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 ) ;
2009-11-30 13:54:51 +03:00
hlist_add_head ( & urn - > link , & __get_cpu_var ( return_notifier_list ) ) ;
2009-09-19 10:40:22 +04:00
}
EXPORT_SYMBOL_GPL ( user_return_notifier_register ) ;
/*
* Removes a registered user return notifier . Must be called from atomic
2011-03-31 05:57:33 +04:00
* context , and from the same cpu registration occurred in .
2009-09-19 10:40:22 +04:00
*/
void user_return_notifier_unregister ( struct user_return_notifier * urn )
{
hlist_del ( & urn - > link ) ;
2009-11-30 13:54:51 +03:00
if ( hlist_empty ( & __get_cpu_var ( return_notifier_list ) ) )
2009-09-19 10:40:22 +04:00
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 ) ;
2009-11-02 08:17:22 +03:00
put_cpu_var ( return_notifier_list ) ;
2009-09-19 10:40:22 +04:00
}