diff options
Diffstat (limited to 'kernel/power')
| -rw-r--r-- | kernel/power/hibernate.c | 15 | ||||
| -rw-r--r-- | kernel/power/process.c | 77 | ||||
| -rw-r--r-- | kernel/power/suspend.c | 8 | ||||
| -rw-r--r-- | kernel/power/user.c | 4 | 
4 files changed, 37 insertions, 67 deletions
diff --git a/kernel/power/hibernate.c b/kernel/power/hibernate.c index 5314a94a92c..605149a6d21 100644 --- a/kernel/power/hibernate.c +++ b/kernel/power/hibernate.c @@ -590,17 +590,6 @@ static void power_down(void)  	while(1);  } -static int prepare_processes(void) -{ -	int error = 0; - -	if (freeze_processes()) { -		error = -EBUSY; -		thaw_processes(); -	} -	return error; -} -  /**   * hibernate - Carry out system hibernation, including saving the image.   */ @@ -633,7 +622,7 @@ int hibernate(void)  	sys_sync();  	printk("done.\n"); -	error = prepare_processes(); +	error = freeze_processes();  	if (error)  		goto Finish; @@ -796,7 +785,7 @@ static int software_resume(void)  	}  	pr_debug("PM: Preparing processes for restore.\n"); -	error = prepare_processes(); +	error = freeze_processes();  	if (error) {  		swsusp_close(FMODE_READ);  		goto Done; diff --git a/kernel/power/process.c b/kernel/power/process.c index addbbe5531b..77274c9ba2f 100644 --- a/kernel/power/process.c +++ b/kernel/power/process.c @@ -22,16 +22,7 @@   */  #define TIMEOUT	(20 * HZ) -static inline int freezable(struct task_struct * p) -{ -	if ((p == current) || -	    (p->flags & PF_NOFREEZE) || -	    (p->exit_state != 0)) -		return 0; -	return 1; -} - -static int try_to_freeze_tasks(bool sig_only) +static int try_to_freeze_tasks(bool user_only)  {  	struct task_struct *g, *p;  	unsigned long end_time; @@ -46,17 +37,14 @@ static int try_to_freeze_tasks(bool sig_only)  	end_time = jiffies + TIMEOUT; -	if (!sig_only) +	if (!user_only)  		freeze_workqueues_begin();  	while (true) {  		todo = 0;  		read_lock(&tasklist_lock);  		do_each_thread(g, p) { -			if (frozen(p) || !freezable(p)) -				continue; - -			if (!freeze_task(p, sig_only)) +			if (p == current || !freeze_task(p))  				continue;  			/* @@ -77,7 +65,7 @@ static int try_to_freeze_tasks(bool sig_only)  		} while_each_thread(g, p);  		read_unlock(&tasklist_lock); -		if (!sig_only) { +		if (!user_only) {  			wq_busy = freeze_workqueues_busy();  			todo += wq_busy;  		} @@ -103,11 +91,6 @@ static int try_to_freeze_tasks(bool sig_only)  	elapsed_csecs = elapsed_csecs64;  	if (todo) { -		/* This does not unfreeze processes that are already frozen -		 * (we have slightly ugly calling convention in that respect, -		 * and caller must call thaw_processes() if something fails), -		 * but it cleans up leftover PF_FREEZE requests. -		 */  		printk("\n");  		printk(KERN_ERR "Freezing of tasks %s after %d.%02d seconds "  		       "(%d tasks refusing to freeze, wq_busy=%d):\n", @@ -115,15 +98,11 @@ static int try_to_freeze_tasks(bool sig_only)  		       elapsed_csecs / 100, elapsed_csecs % 100,  		       todo - wq_busy, wq_busy); -		thaw_workqueues(); -  		read_lock(&tasklist_lock);  		do_each_thread(g, p) { -			task_lock(p); -			if (!wakeup && freezing(p) && !freezer_should_skip(p)) +			if (!wakeup && !freezer_should_skip(p) && +			    p != current && freezing(p) && !frozen(p))  				sched_show_task(p); -			cancel_freezing(p); -			task_unlock(p);  		} while_each_thread(g, p);  		read_unlock(&tasklist_lock);  	} else { @@ -136,12 +115,18 @@ static int try_to_freeze_tasks(bool sig_only)  /**   * freeze_processes - Signal user space processes to enter the refrigerator. + * + * On success, returns 0.  On failure, -errno and system is fully thawed.   */  int freeze_processes(void)  {  	int error; +	if (!pm_freezing) +		atomic_inc(&system_freezing_cnt); +  	printk("Freezing user space processes ... "); +	pm_freezing = true;  	error = try_to_freeze_tasks(true);  	if (!error) {  		printk("done."); @@ -150,17 +135,22 @@ int freeze_processes(void)  	printk("\n");  	BUG_ON(in_atomic()); +	if (error) +		thaw_processes();  	return error;  }  /**   * freeze_kernel_threads - Make freezable kernel threads go to the refrigerator. + * + * On success, returns 0.  On failure, -errno and system is fully thawed.   */  int freeze_kernel_threads(void)  {  	int error;  	printk("Freezing remaining freezable tasks ... "); +	pm_nosig_freezing = true;  	error = try_to_freeze_tasks(false);  	if (!error)  		printk("done."); @@ -168,37 +158,32 @@ int freeze_kernel_threads(void)  	printk("\n");  	BUG_ON(in_atomic()); +	if (error) +		thaw_processes();  	return error;  } -static void thaw_tasks(bool nosig_only) +void thaw_processes(void)  {  	struct task_struct *g, *p; -	read_lock(&tasklist_lock); -	do_each_thread(g, p) { -		if (!freezable(p)) -			continue; +	if (pm_freezing) +		atomic_dec(&system_freezing_cnt); +	pm_freezing = false; +	pm_nosig_freezing = false; -		if (nosig_only && should_send_signal(p)) -			continue; +	oom_killer_enable(); + +	printk("Restarting tasks ... "); -		if (cgroup_freezing_or_frozen(p)) -			continue; +	thaw_workqueues(); -		thaw_process(p); +	read_lock(&tasklist_lock); +	do_each_thread(g, p) { +		__thaw_task(p);  	} while_each_thread(g, p);  	read_unlock(&tasklist_lock); -} -void thaw_processes(void) -{ -	oom_killer_enable(); - -	printk("Restarting tasks ... "); -	thaw_workqueues(); -	thaw_tasks(true); -	thaw_tasks(false);  	schedule();  	printk("done.\n");  } diff --git a/kernel/power/suspend.c b/kernel/power/suspend.c index 4953dc054c5..d336b27d110 100644 --- a/kernel/power/suspend.c +++ b/kernel/power/suspend.c @@ -106,13 +106,11 @@ static int suspend_prepare(void)  		goto Finish;  	error = suspend_freeze_processes(); -	if (error) { -		suspend_stats.failed_freeze++; -		dpm_save_failed_step(SUSPEND_FREEZE); -	} else +	if (!error)  		return 0; -	suspend_thaw_processes(); +	suspend_stats.failed_freeze++; +	dpm_save_failed_step(SUSPEND_FREEZE);  	usermodehelper_enable();   Finish:  	pm_notifier_call_chain(PM_POST_SUSPEND); diff --git a/kernel/power/user.c b/kernel/power/user.c index e2aff0fc269..c202e2e1a2d 100644 --- a/kernel/power/user.c +++ b/kernel/power/user.c @@ -257,10 +257,8 @@ static long snapshot_ioctl(struct file *filp, unsigned int cmd,  			break;  		error = freeze_processes(); -		if (error) { -			thaw_processes(); +		if (error)  			usermodehelper_enable(); -		}  		if (!error)  			data->frozen = 1;  		break;  |