Re: [RFC] Add the "icebox"

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

 



On Mon, Nov 05, 2007 at 04:27:47PM -0500, Alan Stern wrote:
> Rafael:
> 
> This patch adds the icebox, for use by kernel threads that want to 
> freeze themselves without using the freezer -- which is likely to crop 
> up when the freezer gets eliminated.

Why can't we have a runque per cpu that never gets scheduled and we simply
migrate the treads to those?  no more yield loops.

--mgross

> 
> It's straightforward enough.  It could be used as-is, for example for 
> freezing workqueue threads.  Using it for other sorts of kernel threads 
> seems to be rather difficult, requiring a fair amount of extra code 
> that's hard to centralize since each thread will have to be woken up 
> its own way.
> 
> Do you have any particular suggestions?
> 
> Alan Stern
> 
> 
> 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
> @@ -205,3 +205,8 @@ static inline int suspend_devices_and_en
>  
>  /* kernel/power/process.c */
>  extern int pm_notifier_call_chain(unsigned long val);
> +
> +#ifdef CONFIG_PM_SLEEP
> +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
> @@ -71,6 +71,8 @@ static int suspend_prepare(void)
>  	if (!suspend_ops || !suspend_ops->enter)
>  		return -EPERM;
>  
> +	start_icebox();
> +
>  	error = pm_notifier_call_chain(PM_SUSPEND_PREPARE);
>  	if (error)
>  		goto Finish;
> @@ -98,6 +100,7 @@ static int suspend_prepare(void)
>  	thaw_processes();
>  	pm_restore_console();
>   Finish:
> +	stop_icebox();
>  	pm_notifier_call_chain(PM_POST_SUSPEND);
>  	return error;
>  }
> @@ -191,6 +194,7 @@ static void suspend_finish(void)
>  {
>  	thaw_processes();
>  	pm_restore_console();
> +	stop_icebox();
>  	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
> @@ -389,6 +389,8 @@ int hibernate(void)
>  		goto Unlock;
>  	}
>  
> +	start_icebox();
> +
>  	error = pm_notifier_call_chain(PM_HIBERNATION_PREPARE);
>  	if (error)
>  		goto Exit;
> @@ -431,6 +433,7 @@ int hibernate(void)
>   Finish:
>  	free_basic_memory_bitmaps();
>   Exit:
> +	stop_icebox();
>  	pm_notifier_call_chain(PM_POST_HIBERNATION);
>  	atomic_inc(&snapshot_device_available);
>   Unlock:
> @@ -489,6 +492,8 @@ static int software_resume(void)
>  		goto Unlock;
>  	}
>  
> +	start_icebox();
> +
>  	error = pm_notifier_call_chain(PM_RESTORE_PREPARE);
>  	if (error)
>  		goto Finish;
> @@ -516,6 +521,7 @@ static int software_resume(void)
>   Done:
>  	free_basic_memory_bitmaps();
>   Finish:
> +	stop_icebox();
>  	pm_notifier_call_chain(PM_POST_RESTORE);
>  	atomic_inc(&snapshot_device_available);
>  	/* For success case, the suspend path will release the lock */
> Index: usb-2.6/kernel/power/user.c
> ===================================================================
> --- usb-2.6.orig/kernel/power/user.c
> +++ usb-2.6/kernel/power/user.c
> @@ -45,6 +45,7 @@ static int snapshot_open(struct inode *i
>  {
>  	struct snapshot_data *data;
>  	int error;
> +	unsigned long cancel;
>  
>  	if (!atomic_add_unless(&snapshot_device_available, -1, 0))
>  		return -EBUSY;
> @@ -61,21 +62,22 @@ static int snapshot_open(struct inode *i
>  	data = &snapshot_state;
>  	filp->private_data = data;
>  	memset(&data->handle, 0, sizeof(struct snapshot_handle));
> +	start_icebox();
>  	if ((filp->f_flags & O_ACCMODE) == O_RDONLY) {
>  		data->swap = swsusp_resume_device ?
>  			swap_type_of(swsusp_resume_device, 0, NULL) : -1;
>  		data->mode = O_RDONLY;
>  		error = pm_notifier_call_chain(PM_RESTORE_PREPARE);
> -		if (error)
> -			pm_notifier_call_chain(PM_POST_RESTORE);
> +		cancel = PM_POST_RESTORE;
>  	} else {
>  		data->swap = -1;
>  		data->mode = O_WRONLY;
>  		error = pm_notifier_call_chain(PM_HIBERNATION_PREPARE);
> -		if (error)
> -			pm_notifier_call_chain(PM_POST_HIBERNATION);
> +		cancel = PM_POST_HIBERNATION;
>  	}
>  	if (error) {
> +		stop_icebox();
> +		pm_notifier_call_chain(cancel);
>  		atomic_inc(&snapshot_device_available);
>  		return error;
>  	}
> @@ -99,6 +101,7 @@ static int snapshot_release(struct inode
>  		thaw_processes();
>  		mutex_unlock(&pm_mutex);
>  	}
> +	stop_icebox();
>  	pm_notifier_call_chain(data->mode == O_WRONLY ?
>  			PM_POST_HIBERNATION : PM_POST_RESTORE);
>  	atomic_inc(&snapshot_device_available);
> 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
>   */
> @@ -305,3 +307,49 @@ int pm_notifier_call_chain(unsigned long
>  	return (blocking_notifier_call_chain(&pm_chain_head, val, NULL)
>  			== NOTIFY_BAD) ? -EINVAL : 0;
>  }
> +
> +/*
> + * Routines for kernel threads that want to freeze themselves
> + */
> +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 or PM_SUSPEND_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 or PM_POST_SUSPEND 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
> + *
> + * Threads 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.
> + *
> + * Freezable kernel threads should use this routine rather than relying on
> + * the freezer.
> + */
> +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
_______________________________________________
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