/* total number of freezing conditions in effect */
DEFINE_STATIC_KEY_FALSE(freezer_active);
EXPORT_SYMBOL(freezer_active);
/* * indicate whether PM freezing is in effect, protected by * system_transition_mutex
*/ bool pm_freezing; bool pm_nosig_freezing;
/* protects freezing and frozen transitions */ static DEFINE_SPINLOCK(freezer_lock);
/** * freezing_slow_path - slow path for testing whether a task needs to be frozen * @p: task to be tested * * This function is called by freezing() if freezer_active isn't zero * and tests whether @p needs to enter and stay in frozen state. Can be * called under any context. The freezers are responsible for ensuring the * target tasks see the updated state.
*/ bool freezing_slow_path(struct task_struct *p)
{ if (p->flags & (PF_NOFREEZE | PF_SUSPEND_TASK)) returnfalse;
if (test_tsk_thread_flag(p, TIF_MEMDIE)) returnfalse;
if (pm_nosig_freezing || cgroup_freezing(p)) returntrue;
if (pm_freezing && !(p->flags & PF_KTHREAD)) returntrue;
/* Refrigerator is place where frozen processes are stored :-). */ bool __refrigerator(bool check_kthr_stop)
{ unsignedint state = get_current_state(); bool was_frozen = false;
raw_spin_lock_irq(¤t->pi_lock);
WRITE_ONCE(current->__state, TASK_FROZEN); /* unstale saved_state so that __thaw_task() will wake us up */
current->saved_state = TASK_RUNNING;
raw_spin_unlock_irq(¤t->pi_lock);
/* * Allow freezing the sched_delayed tasks; they will not execute until * ttwu() fixes them up, so it is safe to swap their state now, instead * of waiting for them to get fully dequeued.
*/ if (task_is_runnable(p)) return 0;
if (p != current && task_curr(p)) return 0;
if (!(state & (TASK_FREEZABLE | __TASK_STOPPED | __TASK_TRACED))) return 0;
/* * Only TASK_NORMAL can be augmented with TASK_FREEZABLE, since they * can suffer spurious wakeups.
*/ if (state & TASK_FREEZABLE)
WARN_ON_ONCE(!(state & TASK_NORMAL));
#ifdef CONFIG_LOCKDEP /* * It's dangerous to freeze with locks held; there be dragons there.
*/ if (!(state & __TASK_FREEZABLE_UNSAFE))
WARN_ON_ONCE(debug_locks && p->lockdep_depth); #endif
/** * freeze_task - send a freeze request to given task * @p: task to send the request to * * If @p is freezing, the freeze request is sent either by sending a fake * signal (if it's not a kernel thread) or waking it up (if it's a kernel * thread). * * RETURNS: * %false, if @p is not freezing or already frozen; %true, otherwise
*/ bool freeze_task(struct task_struct *p)
{ unsignedlong flags;
/* * Restore the saved_state before the task entered freezer. For typical task * in the __refrigerator(), saved_state == TASK_RUNNING so nothing happens * here. For tasks which were TASK_NORMAL | TASK_FREEZABLE, their initial state * is restored unless they got an expected wakeup (see ttwu_state_match()). * Returns 1 if the task state was restored.
*/ staticint __restore_freezer_state(struct task_struct *p, void *arg)
{ unsignedint state = p->saved_state;
/** * set_freezable - make %current freezable * * Mark %current freezable and enter refrigerator if necessary.
*/ bool set_freezable(void)
{
might_sleep();
/* * Modify flags while holding freezer_lock. This ensures the * freezer notices that we aren't frozen yet or the freezing * condition is visible to try_to_freeze() below.
*/
spin_lock_irq(&freezer_lock);
current->flags &= ~PF_NOFREEZE;
spin_unlock_irq(&freezer_lock);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.