at v2.6.22 133 lines 3.6 kB view raw
1/* Freezer declarations */ 2 3#include <linux/sched.h> 4 5#ifdef CONFIG_PM 6/* 7 * Check if a process has been frozen 8 */ 9static inline int frozen(struct task_struct *p) 10{ 11 return p->flags & PF_FROZEN; 12} 13 14/* 15 * Check if there is a request to freeze a process 16 */ 17static inline int freezing(struct task_struct *p) 18{ 19 return test_tsk_thread_flag(p, TIF_FREEZE); 20} 21 22/* 23 * Request that a process be frozen 24 */ 25static inline void freeze(struct task_struct *p) 26{ 27 set_tsk_thread_flag(p, TIF_FREEZE); 28} 29 30/* 31 * Sometimes we may need to cancel the previous 'freeze' request 32 */ 33static inline void do_not_freeze(struct task_struct *p) 34{ 35 clear_tsk_thread_flag(p, TIF_FREEZE); 36} 37 38/* 39 * Wake up a frozen process 40 * 41 * task_lock() is taken to prevent the race with refrigerator() which may 42 * occur if the freezing of tasks fails. Namely, without the lock, if the 43 * freezing of tasks failed, thaw_tasks() might have run before a task in 44 * refrigerator() could call frozen_process(), in which case the task would be 45 * frozen and no one would thaw it. 46 */ 47static inline int thaw_process(struct task_struct *p) 48{ 49 task_lock(p); 50 if (frozen(p)) { 51 p->flags &= ~PF_FROZEN; 52 task_unlock(p); 53 wake_up_process(p); 54 return 1; 55 } 56 clear_tsk_thread_flag(p, TIF_FREEZE); 57 task_unlock(p); 58 return 0; 59} 60 61extern void refrigerator(void); 62extern int freeze_processes(void); 63extern void thaw_processes(void); 64 65static inline int try_to_freeze(void) 66{ 67 if (freezing(current)) { 68 refrigerator(); 69 return 1; 70 } else 71 return 0; 72} 73 74/* 75 * The PF_FREEZER_SKIP flag should be set by a vfork parent right before it 76 * calls wait_for_completion(&vfork) and reset right after it returns from this 77 * function. Next, the parent should call try_to_freeze() to freeze itself 78 * appropriately in case the child has exited before the freezing of tasks is 79 * complete. However, we don't want kernel threads to be frozen in unexpected 80 * places, so we allow them to block freeze_processes() instead or to set 81 * PF_NOFREEZE if needed and PF_FREEZER_SKIP is only set for userland vfork 82 * parents. Fortunately, in the ____call_usermodehelper() case the parent won't 83 * really block freeze_processes(), since ____call_usermodehelper() (the child) 84 * does a little before exec/exit and it can't be frozen before waking up the 85 * parent. 86 */ 87 88/* 89 * If the current task is a user space one, tell the freezer not to count it as 90 * freezable. 91 */ 92static inline void freezer_do_not_count(void) 93{ 94 if (current->mm) 95 current->flags |= PF_FREEZER_SKIP; 96} 97 98/* 99 * If the current task is a user space one, tell the freezer to count it as 100 * freezable again and try to freeze it. 101 */ 102static inline void freezer_count(void) 103{ 104 if (current->mm) { 105 current->flags &= ~PF_FREEZER_SKIP; 106 try_to_freeze(); 107 } 108} 109 110/* 111 * Check if the task should be counted as freezeable by the freezer 112 */ 113static inline int freezer_should_skip(struct task_struct *p) 114{ 115 return !!(p->flags & PF_FREEZER_SKIP); 116} 117 118#else 119static inline int frozen(struct task_struct *p) { return 0; } 120static inline int freezing(struct task_struct *p) { return 0; } 121static inline void freeze(struct task_struct *p) { BUG(); } 122static inline int thaw_process(struct task_struct *p) { return 1; } 123 124static inline void refrigerator(void) {} 125static inline int freeze_processes(void) { BUG(); return 0; } 126static inline void thaw_processes(void) {} 127 128static inline int try_to_freeze(void) { return 0; } 129 130static inline void freezer_do_not_count(void) {} 131static inline void freezer_count(void) {} 132static inline int freezer_should_skip(struct task_struct *p) { return 0; } 133#endif