}
extern bool freeze_task(struct task_struct *p);
-extern bool set_freezable(void);
+extern bool __set_freezable(bool with_signal);
#ifdef CONFIG_CGROUP_FREEZER
extern bool cgroup_freezing(struct task_struct *task);
return !!(p->flags & PF_FREEZER_SKIP);
}
+/*
+ * Tell the freezer that the current task should be frozen by it
+ */
+static inline bool set_freezable(void)
+{
+ return __set_freezable(false);
+}
+
+/*
+ * 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 bool set_freezable_with_signal(void)
+{
+ return __set_freezable(true);
+}
+
/*
* Freezer-friendly wrappers around wait_event_interruptible(),
* wait_event_killable() and wait_event_interruptible_timeout(), originally
static inline void freezer_count(void) {}
static inline int freezer_should_skip(struct task_struct *p) { return 0; }
static inline void set_freezable(void) {}
+static inline void set_freezable_with_signal(void) {}
#define wait_event_freezable(wq, condition) \
wait_event_interruptible(wq, condition)
#define PF_MEMPOLICY 0x10000000 /* Non-default NUMA mempolicy */
#define PF_MUTEX_TESTER 0x20000000 /* Thread belongs to the rt mutex tester */
#define PF_FREEZER_SKIP 0x40000000 /* Freezer should not count it as freezable */
+#define PF_FREEZER_NOSIG 0x80000000 /* Freezer won't send signals to it */
/*
* Only the _current_ task can read/write to tsk->flags, but other
if (pm_nosig_freezing || cgroup_freezing(p))
return true;
- if (pm_freezing && !(p->flags & PF_KTHREAD))
+ if (pm_freezing && !(p->flags & PF_FREEZER_NOSIG))
return true;
return false;
schedule();
}
+ spin_lock_irq(¤t->sighand->siglock);
+ recalc_sigpending(); /* We sent fake signal, clean it up */
+ spin_unlock_irq(¤t->sighand->siglock);
+
pr_debug("%s left refrigerator\n", current->comm);
/*
return false;
}
- if (!(p->flags & PF_KTHREAD)) {
+ if (!(p->flags & PF_FREEZER_NOSIG)) {
fake_signal_wake_up(p);
/*
* fake_signal_wake_up() goes through p's scheduler
* be visible to @p as waking up implies wmb. Waking up inside
* freezer_lock also prevents wakeups from leaking outside
* refrigerator.
+ *
+ * If !FROZEN, @p hasn't reached refrigerator, recalc sigpending to
+ * avoid leaving dangling TIF_SIGPENDING behind.
*/
spin_lock_irqsave(&freezer_lock, flags);
- if (frozen(p))
+ if (frozen(p)) {
wake_up_process(p);
+ } else {
+ spin_lock(&p->sighand->siglock);
+ recalc_sigpending_and_wake(p);
+ spin_unlock(&p->sighand->siglock);
+ }
spin_unlock_irqrestore(&freezer_lock, flags);
}
/**
- * set_freezable - make %current freezable
+ * __set_freezable - make %current freezable
+ * @with_signal: do we want %TIF_SIGPENDING for notification too?
*
* Mark %current freezable and enter refrigerator if necessary.
*/
-bool set_freezable(void)
+bool __set_freezable(bool with_signal)
{
might_sleep();
*/
spin_lock_irq(&freezer_lock);
current->flags &= ~PF_NOFREEZE;
+ if (with_signal)
+ current->flags &= ~PF_FREEZER_NOSIG;
spin_unlock_irq(&freezer_lock);
return try_to_freeze();
}
-EXPORT_SYMBOL(set_freezable);
+EXPORT_SYMBOL(__set_freezable);