Re: [RFC] Add the "icebox"

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Wednesday, 7 of November 2007, Alan Stern wrote:
> On Mon, 5 Nov 2007, Rafael J. Wysocki wrote:
> 
> > I like the idea, but I think that start_icebox() should be called after
> > freeze_processes().  Similarly, IMO it's better to call stop_icebox() before
> > thaw_processes().
> 
> Okay.  On the assumption that freezable kernel threads will continue to 
> use the freezer and won't try to use the icebox, I have updated the 
> patch.  Other comments?

OK by me.

> Alan Stern
> 
> P.S.: What about mutual exclusion in kernel/power/user.c?  If we stop 
> freezing user tasks, there's nothing to prevent more than one task 
> holding an open file reference to the snapshot file and submitting 
> ioctls concurrently.  Maybe the regions covered by pm_mutex should be 
> expanded.

/dev/snapshot can only be open once at a time.

Greetings,
Rafael


> Index: usb-2.6/include/linux/freezer.h
> ===================================================================
> --- usb-2.6.orig/include/linux/freezer.h
> +++ usb-2.6/include/linux/freezer.h
> @@ -157,6 +157,12 @@ static inline void set_freezable(void)
>  	} while (try_to_freeze());					\
>  	__retval;							\
>  })
> +
> +/*
> + * Kernel threads that want to freeze themselves go into the icebox.
> + */
> +extern void icebox(void);
> +
>  #else /* !CONFIG_PM_SLEEP */
>  static inline int frozen(struct task_struct *p) { return 0; }
>  static inline int freezing(struct task_struct *p) { return 0; }
> @@ -181,6 +187,7 @@ static inline void set_freezable(void) {
>  #define wait_event_freezable_timeout(wq, condition, timeout)		\
>  		wait_event_interruptible_timeout(wq, condition, timeout)
>  
> +static inline void icebox(void) {}
>  #endif /* !CONFIG_PM_SLEEP */
>  
>  #endif	/* FREEZER_H_INCLUDED */
> Index: usb-2.6/kernel/power/power.h
> ===================================================================
> --- usb-2.6.orig/kernel/power/power.h
> +++ usb-2.6/kernel/power/power.h
> @@ -207,3 +207,9 @@ static inline int suspend_devices_and_en
>  /* kernel/power/main.c */
>  extern int pm_notifier_call_chain(unsigned long val);
>  #endif
> +
> +#ifdef CONFIG_PM_SLEEP
> +/* kerne/power/process.c */
> +extern void start_icebox(void);
> +extern void stop_icebox(void);
> +#endif
> Index: usb-2.6/kernel/power/main.c
> ===================================================================
> --- usb-2.6.orig/kernel/power/main.c
> +++ usb-2.6/kernel/power/main.c
> @@ -108,6 +108,8 @@ static int suspend_prepare(void)
>  		goto Thaw;
>  	}
>  
> +	start_icebox();
> +
>  	free_pages = global_page_state(NR_FREE_PAGES);
>  	if (free_pages < FREE_PAGE_NUMBER) {
>  		pr_debug("PM: free some memory\n");
> @@ -120,6 +122,7 @@ static int suspend_prepare(void)
>  	if (!error)
>  		return 0;
>  
> +	stop_icebox();
>   Thaw:
>  	thaw_processes();
>  	pm_restore_console();
> @@ -215,6 +218,7 @@ int suspend_devices_and_enter(suspend_st
>   */
>  static void suspend_finish(void)
>  {
> +	stop_icebox();
>  	thaw_processes();
>  	pm_restore_console();
>  	pm_notifier_call_chain(PM_POST_SUSPEND);
> Index: usb-2.6/kernel/power/disk.c
> ===================================================================
> --- usb-2.6.orig/kernel/power/disk.c
> +++ usb-2.6/kernel/power/disk.c
> @@ -406,6 +406,8 @@ int hibernate(void)
>  	if (error)
>  		goto Finish;
>  
> +	start_icebox();
> +
>  	if (hibernation_mode == HIBERNATION_TESTPROC) {
>  		printk("swsusp debug: Waiting for 5 seconds.\n");
>  		mdelay(5000);
> @@ -427,6 +429,7 @@ int hibernate(void)
>  		swsusp_free();
>  	}
>   Thaw:
> +	stop_icebox();
>  	unprepare_processes();
>   Finish:
>  	free_basic_memory_bitmaps();
> @@ -504,6 +507,8 @@ static int software_resume(void)
>  		goto Done;
>  	}
>  
> +	start_icebox();
> +
>  	pr_debug("PM: Reading swsusp image.\n");
>  
>  	error = swsusp_read(&flags);
> @@ -512,6 +517,7 @@ static int software_resume(void)
>  
>  	printk(KERN_ERR "PM: Restore failed, recovering.\n");
>  	swsusp_free();
> +	stop_icebox();
>  	unprepare_processes();
>   Done:
>  	free_basic_memory_bitmaps();
> Index: usb-2.6/kernel/power/user.c
> ===================================================================
> --- usb-2.6.orig/kernel/power/user.c
> +++ usb-2.6/kernel/power/user.c
> @@ -172,13 +172,16 @@ static int snapshot_ioctl(struct inode *
>  		if (error)
>  			thaw_processes();
>  		mutex_unlock(&pm_mutex);
> -		if (!error)
> +		if (!error) {
>  			data->frozen = 1;
> +			start_icebox();
> +		}
>  		break;
>  
>  	case SNAPSHOT_UNFREEZE:
>  		if (!data->frozen || data->ready)
>  			break;
> +		stop_icebox();
>  		mutex_lock(&pm_mutex);
>  		thaw_processes();
>  		mutex_unlock(&pm_mutex);
> Index: usb-2.6/kernel/power/process.c
> ===================================================================
> --- usb-2.6.orig/kernel/power/process.c
> +++ usb-2.6/kernel/power/process.c
> @@ -14,6 +14,8 @@
>  #include <linux/syscalls.h>
>  #include <linux/freezer.h>
>  
> +#include "power.h"
> +
>  /* 
>   * Timeout for stopping processes
>   */
> @@ -283,3 +285,52 @@ void thaw_processes(void)
>  }
>  
>  EXPORT_SYMBOL(refrigerator);
> +
> +/*
> + * Routines for kernel threads that want to freeze themselves in the icebox
> + */
> +static DECLARE_WAIT_QUEUE_HEAD(icebox_wait_queue_head);
> +static int icebox_active;
> +
> +/**
> + * start_icebox -- activate the icebox
> + *
> + * Kernel power code should call this routine before sending the
> + * PM_HIBERNATION_PREPARE, PM_SUSPEND_PREPARE, or PM_RESTORE_PREPARE
> + * notifications.
> + */
> +void start_icebox(void)
> +{
> +	icebox_active = 1;
> +}
> +
> +/**
> + * stop_icebox -- deactivate the icebox and awaken waiting threads
> + *
> + * Kernel power code should call this routine before sending the
> + * PM_POST_HIBERNATION, PM_POST_SUSPEND, or PM_POST_RESTORE notifications.
> + */
> +void stop_icebox(void)
> +{
> +	icebox_active = 0;
> +	wake_up_all(&icebox_wait_queue_head);
> +}
> +
> +/**
> + * icebox -- place for kernel threads to wait during suspend or hibernation
> + *
> + * Tasks can call this routine at any time.  It will return immediately
> + * unless a system suspend or hibernation has started and the icebox is
> + * active, in which case it won't return until the suspend/hibernation
> + * is over.
> + *
> + * This routine should be used by drivers that want to delay user-initiated
> + * I/O until a system sleep is over.  Kernel threads should not use it
> + * in place of the freezer, because the icebox doesn't get activated until
> + * after freezing is complete.
> + */
> +void icebox(void)
> +{
> +	wait_event(icebox_wait_queue_head, !icebox_active);
> +}
> +EXPORT_SYMBOL_GPL(icebox);
> 
_______________________________________________
linux-pm mailing list
linux-pm@xxxxxxxxxxxxxxxxxxxxxxxxxx
https://lists.linux-foundation.org/mailman/listinfo/linux-pm

[Index of Archives]     [Linux ACPI]     [Netdev]     [Ethernet Bridging]     [Linux Wireless]     [CPU Freq]     [Kernel Newbies]     [Fedora Kernel]     [Security]     [Linux for Hams]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux RAID]     [Linux Admin]     [Samba]

  Powered by Linux