aboutsummaryrefslogtreecommitdiffstats
path: root/include/linux/freezer.h
diff options
context:
space:
mode:
authorJonathan Herman <hermanjl@cs.unc.edu>2013-01-17 16:15:55 -0500
committerJonathan Herman <hermanjl@cs.unc.edu>2013-01-17 16:15:55 -0500
commit8dea78da5cee153b8af9c07a2745f6c55057fe12 (patch)
treea8f4d49d63b1ecc92f2fddceba0655b2472c5bd9 /include/linux/freezer.h
parent406089d01562f1e2bf9f089fd7637009ebaad589 (diff)
Patched in Tegra support.
Diffstat (limited to 'include/linux/freezer.h')
-rw-r--r--include/linux/freezer.h226
1 files changed, 91 insertions, 135 deletions
diff --git a/include/linux/freezer.h b/include/linux/freezer.h
index e4238ceaa4d..1effc8b56b4 100644
--- a/include/linux/freezer.h
+++ b/include/linux/freezer.h
@@ -5,59 +5,70 @@
5 5
6#include <linux/sched.h> 6#include <linux/sched.h>
7#include <linux/wait.h> 7#include <linux/wait.h>
8#include <linux/atomic.h>
9 8
10#ifdef CONFIG_FREEZER 9#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/* 10/*
16 * Check if a process has been frozen 11 * Check if a process has been frozen
17 */ 12 */
18static inline bool frozen(struct task_struct *p) 13static inline int frozen(struct task_struct *p)
19{ 14{
20 return p->flags & PF_FROZEN; 15 return p->flags & PF_FROZEN;
21} 16}
22 17
23extern bool freezing_slow_path(struct task_struct *p);
24
25/* 18/*
26 * Check if there is a request to freeze a process 19 * Check if there is a request to freeze a process
27 */ 20 */
28static inline bool freezing(struct task_struct *p) 21static inline int freezing(struct task_struct *p)
22{
23 return test_tsk_thread_flag(p, TIF_FREEZE);
24}
25
26/*
27 * Request that a process be frozen
28 */
29static inline void set_freeze_flag(struct task_struct *p)
30{
31 set_tsk_thread_flag(p, TIF_FREEZE);
32}
33
34/*
35 * Sometimes we may need to cancel the previous 'freeze' request
36 */
37static inline void clear_freeze_flag(struct task_struct *p)
38{
39 clear_tsk_thread_flag(p, TIF_FREEZE);
40}
41
42static inline bool should_send_signal(struct task_struct *p)
29{ 43{
30 if (likely(!atomic_read(&system_freezing_cnt))) 44 return !(p->flags & PF_FREEZER_NOSIG);
31 return false;
32 return freezing_slow_path(p);
33} 45}
34 46
35/* Takes and releases task alloc lock using task_lock() */ 47/* Takes and releases task alloc lock using task_lock() */
36extern void __thaw_task(struct task_struct *t); 48extern int thaw_process(struct task_struct *p);
37 49
38extern bool __refrigerator(bool check_kthr_stop); 50extern void refrigerator(void);
39extern int freeze_processes(void); 51extern int freeze_processes(void);
40extern int freeze_kernel_threads(void);
41extern void thaw_processes(void); 52extern void thaw_processes(void);
42extern void thaw_kernel_threads(void);
43 53
44static inline bool try_to_freeze(void) 54static inline int try_to_freeze(void)
45{ 55{
46 might_sleep(); 56 if (freezing(current)) {
47 if (likely(!freezing(current))) 57 refrigerator();
48 return false; 58 return 1;
49 return __refrigerator(false); 59 } else
60 return 0;
50} 61}
51 62
52extern bool freeze_task(struct task_struct *p); 63extern bool freeze_task(struct task_struct *p, bool sig_only);
53extern bool set_freezable(void); 64extern void cancel_freezing(struct task_struct *p);
54 65
55#ifdef CONFIG_CGROUP_FREEZER 66#ifdef CONFIG_CGROUP_FREEZER
56extern bool cgroup_freezing(struct task_struct *task); 67extern int cgroup_freezing_or_frozen(struct task_struct *task);
57#else /* !CONFIG_CGROUP_FREEZER */ 68#else /* !CONFIG_CGROUP_FREEZER */
58static inline bool cgroup_freezing(struct task_struct *task) 69static inline int cgroup_freezing_or_frozen(struct task_struct *task)
59{ 70{
60 return false; 71 return 0;
61} 72}
62#endif /* !CONFIG_CGROUP_FREEZER */ 73#endif /* !CONFIG_CGROUP_FREEZER */
63 74
@@ -68,160 +79,108 @@ static inline bool cgroup_freezing(struct task_struct *task)
68 * appropriately in case the child has exited before the freezing of tasks is 79 * 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 80 * 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 81 * 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 82 * PF_NOFREEZE if needed and PF_FREEZER_SKIP is only set for userland vfork
72 * parent won't really block freeze_processes(), since ____call_usermodehelper() 83 * parents. Fortunately, in the ____call_usermodehelper() case the parent won't
73 * (the child) does a little before exec/exit and it can't be frozen before 84 * really block freeze_processes(), since ____call_usermodehelper() (the child)
74 * waking up the parent. 85 * does a little before exec/exit and it can't be frozen before waking up the
86 * parent.
75 */ 87 */
76 88
77 89/*
78/** 90 * If the current task is a user space one, tell the freezer not to count it as
79 * freezer_do_not_count - tell freezer to ignore %current 91 * freezable.
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 */ 92 */
89static inline void freezer_do_not_count(void) 93static inline void freezer_do_not_count(void)
90{ 94{
91 current->flags |= PF_FREEZER_SKIP; 95 if (current->mm)
96 current->flags |= PF_FREEZER_SKIP;
92} 97}
93 98
94/** 99/*
95 * freezer_count - tell freezer to stop ignoring %current 100 * If the current task is a user space one, tell the freezer to count it as
96 * 101 * freezable again and try to freeze it.
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 */ 102 */
101static inline void freezer_count(void) 103static inline void freezer_count(void)
102{ 104{
103 current->flags &= ~PF_FREEZER_SKIP; 105 if (current->mm) {
104 /* 106 current->flags &= ~PF_FREEZER_SKIP;
105 * If freezing is in progress, the following paired with smp_mb() 107 try_to_freeze();
106 * in freezer_should_skip() ensures that either we see %true 108 }
107 * freezing() or freezer_should_skip() sees !PF_FREEZER_SKIP.
108 */
109 smp_mb();
110 try_to_freeze();
111} 109}
112 110
113/** 111/*
114 * freezer_should_skip - whether to skip a task when determining frozen 112 * Check if the task should be counted as freezable by the freezer
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 */ 113 */
123static inline bool freezer_should_skip(struct task_struct *p) 114static inline int freezer_should_skip(struct task_struct *p)
124{ 115{
125 /* 116 return !!(p->flags & PF_FREEZER_SKIP);
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} 117}
135 118
136/* 119/*
137 * These macros are intended to be used whenever you want allow a sleeping 120 * Tell the freezer that the current task should be frozen by it
138 * task to be frozen. Note that neither return any clear indication of
139 * whether a freeze event happened while in this function.
140 */ 121 */
141 122static inline void set_freezable(void)
142/* Like schedule(), but should not block the freezer. */ 123{
143#define freezable_schedule() \ 124 current->flags &= ~PF_NOFREEZE;
144({ \ 125}
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 126
160/* 127/*
161 * Freezer-friendly wrappers around wait_event_interruptible(), 128 * Tell the freezer that the current task should be frozen by it and that it
162 * wait_event_killable() and wait_event_interruptible_timeout(), originally 129 * should send a fake signal to the task to freeze it.
163 * defined in <linux/wait.h>
164 */ 130 */
131static inline void set_freezable_with_signal(void)
132{
133 current->flags &= ~(PF_NOFREEZE | PF_FREEZER_NOSIG);
134}
165 135
166#define wait_event_freezekillable(wq, condition) \ 136/*
167({ \ 137 * Freezer-friendly wrappers around wait_event_interruptible() and
168 int __retval; \ 138 * wait_event_interruptible_timeout(), originally defined in <linux/wait.h>
169 freezer_do_not_count(); \ 139 */
170 __retval = wait_event_killable(wq, (condition)); \
171 freezer_count(); \
172 __retval; \
173})
174 140
175#define wait_event_freezable(wq, condition) \ 141#define wait_event_freezable(wq, condition) \
176({ \ 142({ \
177 int __retval; \ 143 int __retval; \
178 for (;;) { \ 144 do { \
179 __retval = wait_event_interruptible(wq, \ 145 __retval = wait_event_interruptible(wq, \
180 (condition) || freezing(current)); \ 146 (condition) || freezing(current)); \
181 if (__retval || (condition)) \ 147 if (__retval && !freezing(current)) \
182 break; \ 148 break; \
183 try_to_freeze(); \ 149 else if (!(condition)) \
184 } \ 150 __retval = -ERESTARTSYS; \
151 } while (try_to_freeze()); \
185 __retval; \ 152 __retval; \
186}) 153})
187 154
155
188#define wait_event_freezable_timeout(wq, condition, timeout) \ 156#define wait_event_freezable_timeout(wq, condition, timeout) \
189({ \ 157({ \
190 long __retval = timeout; \ 158 long __retval = timeout; \
191 for (;;) { \ 159 do { \
192 __retval = wait_event_interruptible_timeout(wq, \ 160 __retval = wait_event_interruptible_timeout(wq, \
193 (condition) || freezing(current), \ 161 (condition) || freezing(current), \
194 __retval); \ 162 __retval); \
195 if (__retval <= 0 || (condition)) \ 163 } while (try_to_freeze()); \
196 break; \
197 try_to_freeze(); \
198 } \
199 __retval; \ 164 __retval; \
200}) 165})
201
202#else /* !CONFIG_FREEZER */ 166#else /* !CONFIG_FREEZER */
203static inline bool frozen(struct task_struct *p) { return false; } 167static inline int frozen(struct task_struct *p) { return 0; }
204static inline bool freezing(struct task_struct *p) { return false; } 168static inline int freezing(struct task_struct *p) { return 0; }
205static inline void __thaw_task(struct task_struct *t) {} 169static inline void set_freeze_flag(struct task_struct *p) {}
206 170static inline void clear_freeze_flag(struct task_struct *p) {}
207static inline bool __refrigerator(bool check_kthr_stop) { return false; } 171static inline int thaw_process(struct task_struct *p) { return 1; }
208static inline int freeze_processes(void) { return -ENOSYS; } 172
209static inline int freeze_kernel_threads(void) { return -ENOSYS; } 173static inline void refrigerator(void) {}
174static inline int freeze_processes(void) { BUG(); return 0; }
210static inline void thaw_processes(void) {} 175static inline void thaw_processes(void) {}
211static inline void thaw_kernel_threads(void) {}
212 176
213static inline bool try_to_freeze_nowarn(void) { return false; } 177static inline int try_to_freeze(void) { return 0; }
214static inline bool try_to_freeze(void) { return false; }
215 178
216static inline void freezer_do_not_count(void) {} 179static inline void freezer_do_not_count(void) {}
217static inline void freezer_count(void) {} 180static inline void freezer_count(void) {}
218static inline int freezer_should_skip(struct task_struct *p) { return 0; } 181static inline int freezer_should_skip(struct task_struct *p) { return 0; }
219static inline void set_freezable(void) {} 182static inline void set_freezable(void) {}
220 183static inline void set_freezable_with_signal(void) {}
221#define freezable_schedule() schedule()
222
223#define freezable_schedule_timeout_killable(timeout) \
224 schedule_timeout_killable(timeout)
225 184
226#define wait_event_freezable(wq, condition) \ 185#define wait_event_freezable(wq, condition) \
227 wait_event_interruptible(wq, condition) 186 wait_event_interruptible(wq, condition)
@@ -229,9 +188,6 @@ static inline void set_freezable(void) {}
229#define wait_event_freezable_timeout(wq, condition, timeout) \ 188#define wait_event_freezable_timeout(wq, condition, timeout) \
230 wait_event_interruptible_timeout(wq, condition, timeout) 189 wait_event_interruptible_timeout(wq, condition, timeout)
231 190
232#define wait_event_freezekillable(wq, condition) \
233 wait_event_killable(wq, condition)
234
235#endif /* !CONFIG_FREEZER */ 191#endif /* !CONFIG_FREEZER */
236 192
237#endif /* FREEZER_H_INCLUDED */ 193#endif /* FREEZER_H_INCLUDED */