@ -4998,20 +4998,66 @@ static int binder_ioctl_get_node_debug_info(struct binder_proc *proc,
return 0 ;
}
static int binder_ioctl_freeze ( struct binder_freeze_info * info ,
struct binder_proc * target_proc )
{
int ret = 0 ;
if ( ! info - > enable ) {
binder_inner_proc_lock ( target_proc ) ;
target_proc - > sync_recv = false ;
target_proc - > async_recv = false ;
target_proc - > is_frozen = false ;
binder_inner_proc_unlock ( target_proc ) ;
return 0 ;
}
/*
* Freezing the target . Prevent new transactions by
* setting frozen state . If timeout specified , wait
* for transactions to drain .
*/
binder_inner_proc_lock ( target_proc ) ;
target_proc - > sync_recv = false ;
target_proc - > async_recv = false ;
target_proc - > is_frozen = true ;
binder_inner_proc_unlock ( target_proc ) ;
if ( info - > timeout_ms > 0 )
ret = wait_event_interruptible_timeout (
target_proc - > freeze_wait ,
( ! target_proc - > outstanding_txns ) ,
msecs_to_jiffies ( info - > timeout_ms ) ) ;
if ( ! ret & & target_proc - > outstanding_txns )
ret = - EAGAIN ;
if ( ret < 0 ) {
binder_inner_proc_lock ( target_proc ) ;
target_proc - > is_frozen = false ;
binder_inner_proc_unlock ( target_proc ) ;
}
return ret ;
}
static int binder_ioctl_get_freezer_info (
struct binder_frozen_status_info * info )
{
struct binder_proc * target_proc ;
bool found = false ;
info - > sync_recv = 0 ;
info - > async_recv = 0 ;
mutex_lock ( & binder_procs_lock ) ;
hlist_for_each_entry ( target_proc , & binder_procs , proc_node ) {
if ( target_proc - > pid = = info - > pid ) {
found = true ;
binder_inner_proc_lock ( target_proc ) ;
target_proc - > tmp_ref + + ;
info - > sync_recv | = target_proc - > sync_recv ;
info - > async_recv | = target_proc - > async_recv ;
binder_inner_proc_unlock ( target_proc ) ;
break ;
}
}
mutex_unlock ( & binder_procs_lock ) ;
@ -5019,13 +5065,6 @@ static int binder_ioctl_get_freezer_info(
if ( ! found )
return - EINVAL ;
binder_inner_proc_lock ( target_proc ) ;
info - > sync_recv = target_proc - > sync_recv ;
info - > async_recv = target_proc - > async_recv ;
binder_inner_proc_unlock ( target_proc ) ;
binder_proc_dec_tmpref ( target_proc ) ;
return 0 ;
}
@ -5150,7 +5189,7 @@ static long binder_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
case BINDER_FREEZE : {
struct binder_freeze_info info ;
struct binder_proc * target_proc ;
bool found = false ;
ret = - EINVAL ;
if ( copy_from_user ( & info , ubuf , sizeof ( info ) ) ) {
ret = - EFAULT ;
@ -5159,51 +5198,22 @@ static long binder_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
mutex_lock ( & binder_procs_lock ) ;
hlist_for_each_entry ( target_proc , & binder_procs , proc_node ) {
if ( target_proc - > pid = = info . pid ) {
found = true ;
binder_inner_proc_lock ( target_proc ) ;
target_proc - > tmp_ref + + ;
binder_inner_proc_unlock ( target_proc ) ;
break ;
mutex_unlock ( & binder_procs_lock ) ;
ret = binder_ioctl_freeze ( & info , target_proc ) ;
mutex_lock ( & binder_procs_lock ) ;
binder_proc_dec_tmpref ( target_proc ) ;
if ( ret < 0 )
break ;
}
}
mutex_unlock ( & binder_procs_lock ) ;
if ( ! found ) {
ret = - EINVAL ;
goto err ;
}
if ( ! info . enable ) {
binder_inner_proc_lock ( target_proc ) ;
target_proc - > sync_recv = false ;
target_proc - > async_recv = false ;
target_proc - > is_frozen = false ;
binder_inner_proc_unlock ( target_proc ) ;
binder_proc_dec_tmpref ( target_proc ) ;
break ;
}
/*
* Freezing the target . Prevent new transactions by
* setting frozen state . If timeout specified , wait
* for transactions to drain .
*/
binder_inner_proc_lock ( target_proc ) ;
target_proc - > sync_recv = false ;
target_proc - > async_recv = false ;
target_proc - > is_frozen = true ;
binder_inner_proc_unlock ( target_proc ) ;
if ( info . timeout_ms > 0 )
ret = wait_event_interruptible_timeout (
target_proc - > freeze_wait ,
( ! target_proc - > outstanding_txns ) ,
msecs_to_jiffies ( info . timeout_ms ) ) ;
if ( ! ret & & target_proc - > outstanding_txns ) {
ret = - EAGAIN ;
}
if ( ret < 0 ) {
binder_inner_proc_lock ( target_proc ) ;
target_proc - > is_frozen = false ;
binder_inner_proc_unlock ( target_proc ) ;
}
binder_proc_dec_tmpref ( target_proc ) ;
if ( ret < 0 )
goto err ;
break ;