#define FREEZER_H_INCLUDED
#include <linux/sched.h>
+#include <linux/wait.h>
-#ifdef CONFIG_PM
+#ifdef CONFIG_FREEZER
/*
* Check if a process has been frozen
*/
clear_tsk_thread_flag(p, TIF_FREEZE);
}
-/*
- * Wake up a frozen process
- *
- * task_lock() is taken to prevent the race with refrigerator() which may
- * occur if the freezing of tasks fails. Namely, without the lock, if the
- * freezing of tasks failed, thaw_tasks() might have run before a task in
- * refrigerator() could call frozen_process(), in which case the task would be
- * frozen and no one would thaw it.
- */
-static inline int thaw_process(struct task_struct *p)
+static inline bool should_send_signal(struct task_struct *p)
{
- task_lock(p);
- if (frozen(p)) {
- p->flags &= ~PF_FROZEN;
- task_unlock(p);
- wake_up_process(p);
- return 1;
- }
- clear_freeze_flag(p);
- task_unlock(p);
- return 0;
+ return !(p->flags & PF_FREEZER_NOSIG);
}
+/* Takes and releases task alloc lock using task_lock() */
+extern int thaw_process(struct task_struct *p);
+
extern void refrigerator(void);
extern int freeze_processes(void);
extern void thaw_processes(void);
return 0;
}
+extern bool freeze_task(struct task_struct *p, bool sig_only);
+extern void cancel_freezing(struct task_struct *p);
+
+#ifdef CONFIG_CGROUP_FREEZER
+extern int cgroup_frozen(struct task_struct *task);
+#else /* !CONFIG_CGROUP_FREEZER */
+static inline int cgroup_frozen(struct task_struct *task) { return 0; }
+#endif /* !CONFIG_CGROUP_FREEZER */
+
/*
* The PF_FREEZER_SKIP flag should be set by a vfork parent right before it
* calls wait_for_completion(&vfork) and reset right after it returns from this
current->flags &= ~PF_NOFREEZE;
}
-#else
+/*
+ * Tell the freezer that the current task should be frozen by it and that it
+ * should send a fake signal to the task to freeze it.
+ */
+static inline void set_freezable_with_signal(void)
+{
+ current->flags &= ~(PF_NOFREEZE | PF_FREEZER_NOSIG);
+}
+
+/*
+ * Freezer-friendly wrappers around wait_event_interruptible() and
+ * wait_event_interruptible_timeout(), originally defined in <linux/wait.h>
+ */
+
+#define wait_event_freezable(wq, condition) \
+({ \
+ int __retval; \
+ do { \
+ __retval = wait_event_interruptible(wq, \
+ (condition) || freezing(current)); \
+ if (__retval && !freezing(current)) \
+ break; \
+ else if (!(condition)) \
+ __retval = -ERESTARTSYS; \
+ } while (try_to_freeze()); \
+ __retval; \
+})
+
+
+#define wait_event_freezable_timeout(wq, condition, timeout) \
+({ \
+ long __retval = timeout; \
+ do { \
+ __retval = wait_event_interruptible_timeout(wq, \
+ (condition) || freezing(current), \
+ __retval); \
+ } while (try_to_freeze()); \
+ __retval; \
+})
+#else /* !CONFIG_FREEZER */
static inline int frozen(struct task_struct *p) { return 0; }
static inline int freezing(struct task_struct *p) { return 0; }
static inline void set_freeze_flag(struct task_struct *p) {}
static inline void freezer_count(void) {}
static inline int freezer_should_skip(struct task_struct *p) { return 0; }
static inline void set_freezable(void) {}
-#endif
+static inline void set_freezable_with_signal(void) {}
+
+#define wait_event_freezable(wq, condition) \
+ wait_event_interruptible(wq, condition)
+
+#define wait_event_freezable_timeout(wq, condition, timeout) \
+ wait_event_interruptible_timeout(wq, condition, timeout)
+
+#endif /* !CONFIG_FREEZER */
#endif /* FREEZER_H_INCLUDED */