Line data Source code
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 :
9 : #ifdef CONFIG_FREEZER
10 : /*
11 : * Check if a process has been frozen
12 : */
13 : static inline int frozen(struct task_struct *p)
14 : {
15 : return p->flags & PF_FROZEN;
16 : }
17 :
18 : /*
19 : * Check if there is a request to freeze a process
20 : */
21 : static 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 : */
29 : static 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 : */
37 : static inline void clear_freeze_flag(struct task_struct *p)
38 : {
39 : clear_tsk_thread_flag(p, TIF_FREEZE);
40 : }
41 :
42 : static inline bool should_send_signal(struct task_struct *p)
43 : {
44 : return !(p->flags & PF_FREEZER_NOSIG);
45 : }
46 :
47 : /* Takes and releases task alloc lock using task_lock() */
48 : extern int thaw_process(struct task_struct *p);
49 :
50 : extern void refrigerator(void);
51 : extern int freeze_processes(void);
52 : extern void thaw_processes(void);
53 :
54 : static inline int try_to_freeze(void)
55 : {
56 : if (freezing(current)) {
57 : refrigerator();
58 : return 1;
59 : } else
60 : return 0;
61 : }
62 :
63 : extern bool freeze_task(struct task_struct *p, bool sig_only);
64 : extern void cancel_freezing(struct task_struct *p);
65 :
66 : #ifdef CONFIG_CGROUP_FREEZER
67 : extern int cgroup_freezing_or_frozen(struct task_struct *task);
68 : #else /* !CONFIG_CGROUP_FREEZER */
69 : static inline int cgroup_freezing_or_frozen(struct task_struct *task)
70 : {
71 : return 0;
72 : }
73 : #endif /* !CONFIG_CGROUP_FREEZER */
74 :
75 : /*
76 : * The PF_FREEZER_SKIP flag should be set by a vfork parent right before it
77 : * calls wait_for_completion(&vfork) and reset right after it returns from this
78 : * function. Next, the parent should call try_to_freeze() to freeze itself
79 : * appropriately in case the child has exited before the freezing of tasks is
80 : * complete. However, we don't want kernel threads to be frozen in unexpected
81 : * places, so we allow them to block freeze_processes() instead or to set
82 : * PF_NOFREEZE if needed and PF_FREEZER_SKIP is only set for userland vfork
83 : * parents. Fortunately, in the ____call_usermodehelper() case the parent won't
84 : * really block freeze_processes(), since ____call_usermodehelper() (the child)
85 : * does a little before exec/exit and it can't be frozen before waking up the
86 : * parent.
87 : */
88 :
89 : /*
90 : * If the current task is a user space one, tell the freezer not to count it as
91 : * freezable.
92 : */
93 : static inline void freezer_do_not_count(void)
94 : {
95 : if (current->mm)
96 : current->flags |= PF_FREEZER_SKIP;
97 : }
98 :
99 : /*
100 : * If the current task is a user space one, tell the freezer to count it as
101 : * freezable again and try to freeze it.
102 : */
103 : static inline void freezer_count(void)
104 : {
105 : if (current->mm) {
106 : current->flags &= ~PF_FREEZER_SKIP;
107 : try_to_freeze();
108 : }
109 : }
110 :
111 : /*
112 : * Check if the task should be counted as freezeable by the freezer
113 : */
114 : static inline int freezer_should_skip(struct task_struct *p)
115 : {
116 : return !!(p->flags & PF_FREEZER_SKIP);
117 : }
118 :
119 : /*
120 : * Tell the freezer that the current task should be frozen by it
121 : */
122 : static inline void set_freezable(void)
123 : {
124 : current->flags &= ~PF_NOFREEZE;
125 : }
126 :
127 : /*
128 : * Tell the freezer that the current task should be frozen by it and that it
129 : * should send a fake signal to the task to freeze it.
130 : */
131 : static inline void set_freezable_with_signal(void)
132 : {
133 : current->flags &= ~(PF_NOFREEZE | PF_FREEZER_NOSIG);
134 : }
135 :
136 : /*
137 : * Freezer-friendly wrappers around wait_event_interruptible() and
138 : * wait_event_interruptible_timeout(), originally defined in <linux/wait.h>
139 : */
140 :
141 : #define wait_event_freezable(wq, condition) \
142 : ({ \
143 : int __retval; \
144 : do { \
145 : __retval = wait_event_interruptible(wq, \
146 : (condition) || freezing(current)); \
147 : if (__retval && !freezing(current)) \
148 : break; \
149 : else if (!(condition)) \
150 : __retval = -ERESTARTSYS; \
151 : } while (try_to_freeze()); \
152 : __retval; \
153 : })
154 :
155 :
156 : #define wait_event_freezable_timeout(wq, condition, timeout) \
157 : ({ \
158 : long __retval = timeout; \
159 : do { \
160 : __retval = wait_event_interruptible_timeout(wq, \
161 : (condition) || freezing(current), \
162 : __retval); \
163 : } while (try_to_freeze()); \
164 : __retval; \
165 : })
166 : #else /* !CONFIG_FREEZER */
167 : static inline int frozen(struct task_struct *p) { return 0; }
168 : static inline int freezing(struct task_struct *p) { return 0; }
169 : static inline void set_freeze_flag(struct task_struct *p) {}
170 : static inline void clear_freeze_flag(struct task_struct *p) {}
171 : static inline int thaw_process(struct task_struct *p) { return 1; }
172 :
173 : static inline void refrigerator(void) {}
174 : static inline int freeze_processes(void) { BUG(); return 0; }
175 : static inline void thaw_processes(void) {}
176 :
177 : static inline int try_to_freeze(void) { return 0; }
178 :
179 : static inline void freezer_do_not_count(void) {}
180 : static inline void freezer_count(void) {}
181 : static inline int freezer_should_skip(struct task_struct *p) { return 0; }
182 : static inline void set_freezable(void) {}
183 : static inline void set_freezable_with_signal(void) {}
184 0 :
185 : #define wait_event_freezable(wq, condition) \
186 : wait_event_interruptible(wq, condition)
187 :
188 : #define wait_event_freezable_timeout(wq, condition, timeout) \
189 : wait_event_interruptible_timeout(wq, condition, timeout)
190 :
191 : #endif /* !CONFIG_FREEZER */
192 :
193 : #endif /* FREEZER_H_INCLUDED */
|