at v3.9 7.3 kB view raw
1/* Freezer declarations */ 2 3#ifndef FREEZER_H_INCLUDED 4#define FREEZER_H_INCLUDED 5 6#include <linux/sched.h> 7#include <linux/wait.h> 8#include <linux/atomic.h> 9 10#ifdef CONFIG_FREEZER 11extern atomic_t system_freezing_cnt; /* nr of freezing conds in effect */ 12extern bool pm_freezing; /* PM freezing in effect */ 13extern bool pm_nosig_freezing; /* PM nosig freezing in effect */ 14 15/* 16 * Timeout for stopping processes 17 */ 18extern unsigned int freeze_timeout_msecs; 19 20/* 21 * Check if a process has been frozen 22 */ 23static inline bool frozen(struct task_struct *p) 24{ 25 return p->flags & PF_FROZEN; 26} 27 28extern bool freezing_slow_path(struct task_struct *p); 29 30/* 31 * Check if there is a request to freeze a process 32 */ 33static inline bool freezing(struct task_struct *p) 34{ 35 if (likely(!atomic_read(&system_freezing_cnt))) 36 return false; 37 return freezing_slow_path(p); 38} 39 40/* Takes and releases task alloc lock using task_lock() */ 41extern void __thaw_task(struct task_struct *t); 42 43extern bool __refrigerator(bool check_kthr_stop); 44extern int freeze_processes(void); 45extern int freeze_kernel_threads(void); 46extern void thaw_processes(void); 47extern void thaw_kernel_threads(void); 48 49static inline bool try_to_freeze(void) 50{ 51 might_sleep(); 52 if (likely(!freezing(current))) 53 return false; 54 return __refrigerator(false); 55} 56 57extern bool freeze_task(struct task_struct *p); 58extern bool set_freezable(void); 59 60#ifdef CONFIG_CGROUP_FREEZER 61extern bool cgroup_freezing(struct task_struct *task); 62#else /* !CONFIG_CGROUP_FREEZER */ 63static inline bool cgroup_freezing(struct task_struct *task) 64{ 65 return false; 66} 67#endif /* !CONFIG_CGROUP_FREEZER */ 68 69/* 70 * The PF_FREEZER_SKIP flag should be set by a vfork parent right before it 71 * calls wait_for_completion(&vfork) and reset right after it returns from this 72 * function. Next, the parent should call try_to_freeze() to freeze itself 73 * appropriately in case the child has exited before the freezing of tasks is 74 * complete. However, we don't want kernel threads to be frozen in unexpected 75 * places, so we allow them to block freeze_processes() instead or to set 76 * PF_NOFREEZE if needed. Fortunately, in the ____call_usermodehelper() case the 77 * parent won't really block freeze_processes(), since ____call_usermodehelper() 78 * (the child) does a little before exec/exit and it can't be frozen before 79 * waking up the parent. 80 */ 81 82 83/** 84 * freezer_do_not_count - tell freezer to ignore %current 85 * 86 * Tell freezers to ignore the current task when determining whether the 87 * target frozen state is reached. IOW, the current task will be 88 * considered frozen enough by freezers. 89 * 90 * The caller shouldn't do anything which isn't allowed for a frozen task 91 * until freezer_cont() is called. Usually, freezer[_do_not]_count() pair 92 * wrap a scheduling operation and nothing much else. 93 */ 94static inline void freezer_do_not_count(void) 95{ 96 current->flags |= PF_FREEZER_SKIP; 97} 98 99/** 100 * freezer_count - tell freezer to stop ignoring %current 101 * 102 * Undo freezer_do_not_count(). It tells freezers that %current should be 103 * considered again and tries to freeze if freezing condition is already in 104 * effect. 105 */ 106static inline void freezer_count(void) 107{ 108 current->flags &= ~PF_FREEZER_SKIP; 109 /* 110 * If freezing is in progress, the following paired with smp_mb() 111 * in freezer_should_skip() ensures that either we see %true 112 * freezing() or freezer_should_skip() sees !PF_FREEZER_SKIP. 113 */ 114 smp_mb(); 115 try_to_freeze(); 116} 117 118/** 119 * freezer_should_skip - whether to skip a task when determining frozen 120 * state is reached 121 * @p: task in quesion 122 * 123 * This function is used by freezers after establishing %true freezing() to 124 * test whether a task should be skipped when determining the target frozen 125 * state is reached. IOW, if this function returns %true, @p is considered 126 * frozen enough. 127 */ 128static inline bool freezer_should_skip(struct task_struct *p) 129{ 130 /* 131 * The following smp_mb() paired with the one in freezer_count() 132 * ensures that either freezer_count() sees %true freezing() or we 133 * see cleared %PF_FREEZER_SKIP and return %false. This makes it 134 * impossible for a task to slip frozen state testing after 135 * clearing %PF_FREEZER_SKIP. 136 */ 137 smp_mb(); 138 return p->flags & PF_FREEZER_SKIP; 139} 140 141/* 142 * These macros are intended to be used whenever you want allow a sleeping 143 * task to be frozen. Note that neither return any clear indication of 144 * whether a freeze event happened while in this function. 145 */ 146 147/* Like schedule(), but should not block the freezer. */ 148#define freezable_schedule() \ 149({ \ 150 freezer_do_not_count(); \ 151 schedule(); \ 152 freezer_count(); \ 153}) 154 155/* Like schedule_timeout_killable(), but should not block the freezer. */ 156#define freezable_schedule_timeout_killable(timeout) \ 157({ \ 158 long __retval; \ 159 freezer_do_not_count(); \ 160 __retval = schedule_timeout_killable(timeout); \ 161 freezer_count(); \ 162 __retval; \ 163}) 164 165/* 166 * Freezer-friendly wrappers around wait_event_interruptible(), 167 * wait_event_killable() and wait_event_interruptible_timeout(), originally 168 * defined in <linux/wait.h> 169 */ 170 171#define wait_event_freezekillable(wq, condition) \ 172({ \ 173 int __retval; \ 174 freezer_do_not_count(); \ 175 __retval = wait_event_killable(wq, (condition)); \ 176 freezer_count(); \ 177 __retval; \ 178}) 179 180#define wait_event_freezable(wq, condition) \ 181({ \ 182 int __retval; \ 183 for (;;) { \ 184 __retval = wait_event_interruptible(wq, \ 185 (condition) || freezing(current)); \ 186 if (__retval || (condition)) \ 187 break; \ 188 try_to_freeze(); \ 189 } \ 190 __retval; \ 191}) 192 193#define wait_event_freezable_timeout(wq, condition, timeout) \ 194({ \ 195 long __retval = timeout; \ 196 for (;;) { \ 197 __retval = wait_event_interruptible_timeout(wq, \ 198 (condition) || freezing(current), \ 199 __retval); \ 200 if (__retval <= 0 || (condition)) \ 201 break; \ 202 try_to_freeze(); \ 203 } \ 204 __retval; \ 205}) 206 207#else /* !CONFIG_FREEZER */ 208static inline bool frozen(struct task_struct *p) { return false; } 209static inline bool freezing(struct task_struct *p) { return false; } 210static inline void __thaw_task(struct task_struct *t) {} 211 212static inline bool __refrigerator(bool check_kthr_stop) { return false; } 213static inline int freeze_processes(void) { return -ENOSYS; } 214static inline int freeze_kernel_threads(void) { return -ENOSYS; } 215static inline void thaw_processes(void) {} 216static inline void thaw_kernel_threads(void) {} 217 218static inline bool try_to_freeze_nowarn(void) { return false; } 219static inline bool try_to_freeze(void) { return false; } 220 221static inline void freezer_do_not_count(void) {} 222static inline void freezer_count(void) {} 223static inline int freezer_should_skip(struct task_struct *p) { return 0; } 224static inline void set_freezable(void) {} 225 226#define freezable_schedule() schedule() 227 228#define freezable_schedule_timeout_killable(timeout) \ 229 schedule_timeout_killable(timeout) 230 231#define wait_event_freezable(wq, condition) \ 232 wait_event_interruptible(wq, condition) 233 234#define wait_event_freezable_timeout(wq, condition, timeout) \ 235 wait_event_interruptible_timeout(wq, condition, timeout) 236 237#define wait_event_freezekillable(wq, condition) \ 238 wait_event_killable(wq, condition) 239 240#endif /* !CONFIG_FREEZER */ 241 242#endif /* FREEZER_H_INCLUDED */