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
44/*
45 * HACK: prevent sleeping while atomic warnings due to ARM signal handling
46 * disabling irqs
47 */
48static inline bool try_to_freeze_nowarn(void)
49{
50	if (likely(!freezing(current)))
51		return false;
52	return __refrigerator(false);
53}
54
55static inline bool try_to_freeze(void)
56{
57	might_sleep();
58	if (likely(!freezing(current)))
59		return false;
60	return __refrigerator(false);
61}
62
63extern bool freeze_task(struct task_struct *p);
64extern bool set_freezable(void);
65
66#ifdef CONFIG_CGROUP_FREEZER
67extern bool cgroup_freezing(struct task_struct *task);
68#else /* !CONFIG_CGROUP_FREEZER */
69static inline bool cgroup_freezing(struct task_struct *task)
70{
71	return false;
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. Fortunately, in the ____call_usermodehelper() case the
83 * parent won't really block freeze_processes(), since ____call_usermodehelper()
84 * (the child) does a little before exec/exit and it can't be frozen before
85 * waking up the parent.
86 */
87
88
89/* Tell the freezer not to count the current task as freezable. */
90static inline void freezer_do_not_count(void)
91{
92	current->flags |= PF_FREEZER_SKIP;
93}
94
95/*
96 * Tell the freezer to count the current task as freezable again and try to
97 * freeze it.
98 */
99static inline void freezer_count(void)
100{
101	current->flags &= ~PF_FREEZER_SKIP;
102	try_to_freeze();
103}
104
105/*
106 * Check if the task should be counted as freezable by the freezer
107 */
108static inline int freezer_should_skip(struct task_struct *p)
109{
110	return !!(p->flags & PF_FREEZER_SKIP);
111}
112
113/*
114 * These macros are intended to be used whenever you want allow a task that's
115 * sleeping in TASK_UNINTERRUPTIBLE or TASK_KILLABLE state to be frozen. Note
116 * that neither return any clear indication of whether a freeze event happened
117 * while in this function.
118 */
119
120/* Like schedule(), but should not block the freezer. */
121#define freezable_schedule()						\
122({									\
123	freezer_do_not_count();						\
124	schedule();							\
125	freezer_count();						\
126})
127
128/* Like schedule_timeout_killable(), but should not block the freezer. */
129#define freezable_schedule_timeout_killable(timeout)			\
130({									\
131	long __retval;							\
132	freezer_do_not_count();						\
133	__retval = schedule_timeout_killable(timeout);			\
134	freezer_count();						\
135	__retval;							\
136})
137
138/*
139 * Freezer-friendly wrappers around wait_event_interruptible(),
140 * wait_event_killable() and wait_event_interruptible_timeout(), originally
141 * defined in <linux/wait.h>
142 */
143
144#define wait_event_freezekillable(wq, condition)			\
145({									\
146	int __retval;							\
147	freezer_do_not_count();						\
148	__retval = wait_event_killable(wq, (condition));		\
149	freezer_count();						\
150	__retval;							\
151})
152
153#define wait_event_freezable(wq, condition)				\
154({									\
155	int __retval;							\
156	for (;;) {							\
157		__retval = wait_event_interruptible(wq, 		\
158				(condition) || freezing(current));	\
159		if (__retval || (condition))				\
160			break;						\
161		try_to_freeze();					\
162	}								\
163	__retval;							\
164})
165
166#define wait_event_freezable_timeout(wq, condition, timeout)		\
167({									\
168	long __retval = timeout;					\
169	for (;;) {							\
170		__retval = wait_event_interruptible_timeout(wq,		\
171				(condition) || freezing(current),	\
172				__retval); 				\
173		if (__retval <= 0 || (condition))			\
174			break;						\
175		try_to_freeze();					\
176	}								\
177	__retval;							\
178})
179
180#else /* !CONFIG_FREEZER */
181static inline bool frozen(struct task_struct *p) { return false; }
182static inline bool freezing(struct task_struct *p) { return false; }
183static inline void __thaw_task(struct task_struct *t) {}
184
185static inline bool __refrigerator(bool check_kthr_stop) { return false; }
186static inline int freeze_processes(void) { return -ENOSYS; }
187static inline int freeze_kernel_threads(void) { return -ENOSYS; }
188static inline void thaw_processes(void) {}
189static inline void thaw_kernel_threads(void) {}
190
191static inline bool try_to_freeze(void) { return false; }
192
193static inline void freezer_do_not_count(void) {}
194static inline void freezer_count(void) {}
195static inline int freezer_should_skip(struct task_struct *p) { return 0; }
196static inline void set_freezable(void) {}
197
198#define freezable_schedule()  schedule()
199
200#define freezable_schedule_timeout_killable(timeout)			\
201	schedule_timeout_killable(timeout)
202
203#define wait_event_freezable(wq, condition)				\
204		wait_event_interruptible(wq, condition)
205
206#define wait_event_freezable_timeout(wq, condition, timeout)		\
207		wait_event_interruptible_timeout(wq, condition, timeout)
208
209#define wait_event_freezekillable(wq, condition)		\
210		wait_event_killable(wq, condition)
211
212#endif /* !CONFIG_FREEZER */
213
214#endif	/* FREEZER_H_INCLUDED */
215