2017-02-02 19:15:33 +01:00
# include <linux/sched/signal.h>
2016-02-19 09:46:37 +01:00
# include <linux/swait.h>
void __init_swait_queue_head ( struct swait_queue_head * q , const char * name ,
struct lock_class_key * key )
{
raw_spin_lock_init ( & q - > lock ) ;
lockdep_set_class_and_name ( & q - > lock , key , name ) ;
INIT_LIST_HEAD ( & q - > task_list ) ;
}
EXPORT_SYMBOL ( __init_swait_queue_head ) ;
/*
* The thing about the wake_up_state ( ) return value ; I think we can ignore it .
*
* If for some reason it would return 0 , that means the previously waiting
* task is already running , so it will observe condition true ( or has already ) .
*/
void swake_up_locked ( struct swait_queue_head * q )
{
struct swait_queue * curr ;
if ( list_empty ( & q - > task_list ) )
return ;
curr = list_first_entry ( & q - > task_list , typeof ( * curr ) , task_list ) ;
wake_up_process ( curr - > task ) ;
list_del_init ( & curr - > task_list ) ;
}
EXPORT_SYMBOL ( swake_up_locked ) ;
void swake_up ( struct swait_queue_head * q )
{
unsigned long flags ;
if ( ! swait_active ( q ) )
return ;
raw_spin_lock_irqsave ( & q - > lock , flags ) ;
swake_up_locked ( q ) ;
raw_spin_unlock_irqrestore ( & q - > lock , flags ) ;
}
EXPORT_SYMBOL ( swake_up ) ;
/*
* Does not allow usage from IRQ disabled , since we must be able to
* release IRQs to guarantee bounded hold time .
*/
void swake_up_all ( struct swait_queue_head * q )
{
struct swait_queue * curr ;
LIST_HEAD ( tmp ) ;
if ( ! swait_active ( q ) )
return ;
raw_spin_lock_irq ( & q - > lock ) ;
list_splice_init ( & q - > task_list , & tmp ) ;
while ( ! list_empty ( & tmp ) ) {
curr = list_first_entry ( & tmp , typeof ( * curr ) , task_list ) ;
wake_up_state ( curr - > task , TASK_NORMAL ) ;
list_del_init ( & curr - > task_list ) ;
if ( list_empty ( & tmp ) )
break ;
raw_spin_unlock_irq ( & q - > lock ) ;
raw_spin_lock_irq ( & q - > lock ) ;
}
raw_spin_unlock_irq ( & q - > lock ) ;
}
EXPORT_SYMBOL ( swake_up_all ) ;
void __prepare_to_swait ( struct swait_queue_head * q , struct swait_queue * wait )
{
wait - > task = current ;
if ( list_empty ( & wait - > task_list ) )
list_add ( & wait - > task_list , & q - > task_list ) ;
}
void prepare_to_swait ( struct swait_queue_head * q , struct swait_queue * wait , int state )
{
unsigned long flags ;
raw_spin_lock_irqsave ( & q - > lock , flags ) ;
__prepare_to_swait ( q , wait ) ;
set_current_state ( state ) ;
raw_spin_unlock_irqrestore ( & q - > lock , flags ) ;
}
EXPORT_SYMBOL ( prepare_to_swait ) ;
long prepare_to_swait_event ( struct swait_queue_head * q , struct swait_queue * wait , int state )
{
if ( signal_pending_state ( state , current ) )
return - ERESTARTSYS ;
prepare_to_swait ( q , wait , state ) ;
return 0 ;
}
EXPORT_SYMBOL ( prepare_to_swait_event ) ;
void __finish_swait ( struct swait_queue_head * q , struct swait_queue * wait )
{
__set_current_state ( TASK_RUNNING ) ;
if ( ! list_empty ( & wait - > task_list ) )
list_del_init ( & wait - > task_list ) ;
}
void finish_swait ( struct swait_queue_head * q , struct swait_queue * wait )
{
unsigned long flags ;
__set_current_state ( TASK_RUNNING ) ;
if ( ! list_empty_careful ( & wait - > task_list ) ) {
raw_spin_lock_irqsave ( & q - > lock , flags ) ;
list_del_init ( & wait - > task_list ) ;
raw_spin_unlock_irqrestore ( & q - > lock , flags ) ;
}
}
EXPORT_SYMBOL ( finish_swait ) ;