X-Git-Url: http://ftp.safe.ca/?a=blobdiff_plain;f=include%2Flinux%2Ffreezer.h;h=5a361f85cfec483e0a595dcb2f4c2ee632ac56d9;hb=22a9d645677feefd402befd02edd59b122289ef1;hp=db5423eae24d8dd511bbd88714b5264b45b4ba19;hpb=33e1c288da62a6a5aa9077a6b7bfa690b1b02cf4;p=safe%2Fjmp%2Flinux-2.6 diff --git a/include/linux/freezer.h b/include/linux/freezer.h index db5423e..5a361f8 100644 --- a/include/linux/freezer.h +++ b/include/linux/freezer.h @@ -1,8 +1,12 @@ /* Freezer declarations */ +#ifndef FREEZER_H_INCLUDED +#define FREEZER_H_INCLUDED + #include +#include -#ifdef CONFIG_PM +#ifdef CONFIG_FREEZER /* * Check if a process has been frozen */ @@ -22,7 +26,7 @@ static inline int freezing(struct task_struct *p) /* * Request that a process be frozen */ -static inline void freeze(struct task_struct *p) +static inline void set_freeze_flag(struct task_struct *p) { set_tsk_thread_flag(p, TIF_FREEZE); } @@ -30,43 +34,18 @@ static inline void freeze(struct task_struct *p) /* * Sometimes we may need to cancel the previous 'freeze' request */ -static inline void do_not_freeze(struct task_struct *p) +static inline void clear_freeze_flag(struct task_struct *p) { clear_tsk_thread_flag(p, TIF_FREEZE); } -/* - * Wake up a frozen process - * - * task_lock() is taken to prevent the race with refrigerator() which may - * occur if the freezing of tasks fails. Namely, without the lock, if the - * freezing of tasks failed, thaw_tasks() might have run before a task in - * refrigerator() could call frozen_process(), in which case the task would be - * frozen and no one would thaw it. - */ -static inline int thaw_process(struct task_struct *p) +static inline bool should_send_signal(struct task_struct *p) { - task_lock(p); - if (frozen(p)) { - p->flags &= ~PF_FROZEN; - task_unlock(p); - wake_up_process(p); - return 1; - } - clear_tsk_thread_flag(p, TIF_FREEZE); - task_unlock(p); - return 0; + return !(p->flags & PF_FREEZER_NOSIG); } -/* - * freezing is complete, mark process as frozen - */ -static inline void frozen_process(struct task_struct *p) -{ - p->flags |= PF_FROZEN; - wmb(); - clear_tsk_thread_flag(p, TIF_FREEZE); -} +/* Takes and releases task alloc lock using task_lock() */ +extern int thaw_process(struct task_struct *p); extern void refrigerator(void); extern int freeze_processes(void); @@ -81,14 +60,112 @@ static inline int try_to_freeze(void) return 0; } -extern void thaw_some_processes(int all); +extern bool freeze_task(struct task_struct *p, bool sig_only); +extern void cancel_freezing(struct task_struct *p); + +#ifdef CONFIG_CGROUP_FREEZER +extern int cgroup_frozen(struct task_struct *task); +#else /* !CONFIG_CGROUP_FREEZER */ +static inline int cgroup_frozen(struct task_struct *task) { return 0; } +#endif /* !CONFIG_CGROUP_FREEZER */ -#else +/* + * The PF_FREEZER_SKIP flag should be set by a vfork parent right before it + * calls wait_for_completion(&vfork) and reset right after it returns from this + * function. Next, the parent should call try_to_freeze() to freeze itself + * appropriately in case the child has exited before the freezing of tasks is + * complete. However, we don't want kernel threads to be frozen in unexpected + * places, so we allow them to block freeze_processes() instead or to set + * PF_NOFREEZE if needed and PF_FREEZER_SKIP is only set for userland vfork + * parents. Fortunately, in the ____call_usermodehelper() case the parent won't + * really block freeze_processes(), since ____call_usermodehelper() (the child) + * does a little before exec/exit and it can't be frozen before waking up the + * parent. + */ + +/* + * If the current task is a user space one, tell the freezer not to count it as + * freezable. + */ +static inline void freezer_do_not_count(void) +{ + if (current->mm) + current->flags |= PF_FREEZER_SKIP; +} + +/* + * If the current task is a user space one, tell the freezer to count it as + * freezable again and try to freeze it. + */ +static inline void freezer_count(void) +{ + if (current->mm) { + current->flags &= ~PF_FREEZER_SKIP; + try_to_freeze(); + } +} + +/* + * Check if the task should be counted as freezeable by the freezer + */ +static inline int freezer_should_skip(struct task_struct *p) +{ + return !!(p->flags & PF_FREEZER_SKIP); +} + +/* + * Tell the freezer that the current task should be frozen by it + */ +static inline void set_freezable(void) +{ + current->flags &= ~PF_NOFREEZE; +} + +/* + * Tell the freezer that the current task should be frozen by it and that it + * should send a fake signal to the task to freeze it. + */ +static inline void set_freezable_with_signal(void) +{ + current->flags &= ~(PF_NOFREEZE | PF_FREEZER_NOSIG); +} + +/* + * Freezer-friendly wrappers around wait_event_interruptible() and + * wait_event_interruptible_timeout(), originally defined in + */ + +#define wait_event_freezable(wq, condition) \ +({ \ + int __retval; \ + do { \ + __retval = wait_event_interruptible(wq, \ + (condition) || freezing(current)); \ + if (__retval && !freezing(current)) \ + break; \ + else if (!(condition)) \ + __retval = -ERESTARTSYS; \ + } while (try_to_freeze()); \ + __retval; \ +}) + + +#define wait_event_freezable_timeout(wq, condition, timeout) \ +({ \ + long __retval = timeout; \ + do { \ + __retval = wait_event_interruptible_timeout(wq, \ + (condition) || freezing(current), \ + __retval); \ + } while (try_to_freeze()); \ + __retval; \ +}) +#else /* !CONFIG_FREEZER */ static inline int frozen(struct task_struct *p) { return 0; } static inline int freezing(struct task_struct *p) { return 0; } -static inline void freeze(struct task_struct *p) { BUG(); } +static inline void set_freeze_flag(struct task_struct *p) {} +static inline void clear_freeze_flag(struct task_struct *p) {} static inline int thaw_process(struct task_struct *p) { return 1; } -static inline void frozen_process(struct task_struct *p) { BUG(); } static inline void refrigerator(void) {} static inline int freeze_processes(void) { BUG(); return 0; } @@ -96,5 +173,18 @@ static inline void thaw_processes(void) {} static inline int try_to_freeze(void) { return 0; } +static inline void freezer_do_not_count(void) {} +static inline void freezer_count(void) {} +static inline int freezer_should_skip(struct task_struct *p) { return 0; } +static inline void set_freezable(void) {} +static inline void set_freezable_with_signal(void) {} + +#define wait_event_freezable(wq, condition) \ + wait_event_interruptible(wq, condition) + +#define wait_event_freezable_timeout(wq, condition, timeout) \ + wait_event_interruptible_timeout(wq, condition, timeout) + +#endif /* !CONFIG_FREEZER */ -#endif +#endif /* FREEZER_H_INCLUDED */