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