/** * freeze_task - send a freeze request to given task * @p: task to send the request to * @sig_only: if set, the request will only be sent if the task has the * PF_FREEZER_NOSIG flag unset * Return value: 'false', if @sig_only is set and the task has * PF_FREEZER_NOSIG set or the task is frozen, 'true', otherwise * * The freeze request is sent by setting the tasks's TIF_FREEZE flag and * either sending a fake signal to it or waking it up, depending on whether * or not it has PF_FREEZER_NOSIG set. If @sig_only is set and the task * has PF_FREEZER_NOSIG set (ie. it is a typical kernel thread), its * TIF_FREEZE flag will not be set. */ bool freeze_task(struct task_struct *p, bool sig_only) { /* * We first check if the task is freezing and next if it has already * been frozen to avoid the race with frozen_process() which first marks * the task as frozen and next clears its TIF_FREEZE. */ if (!freezing(p)) { rmb(); if (frozen(p)) return false; if (!sig_only || should_send_signal(p)) set_freeze_flag(p); else return false; } if (should_send_signal(p)) { if (!signal_pending(p)) fake_signal_wake_up(p); } else if (sig_only) { return false; } else { wake_up_state(p, TASK_INTERRUPTIBLE); } return true; }
/** * freeze_task - send a freeze request to given task * @p: task to send the request to * @sig_only: if set, the request will only be sent if the task has the * PF_FREEZER_NOSIG flag unset * Return value: 'false', if @sig_only is set and the task has * PF_FREEZER_NOSIG set or the task is frozen, 'true', otherwise * * The freeze request is sent by setting the tasks's TIF_FREEZE flag and * either sending a fake signal to it or waking it up, depending on whether * or not it has PF_FREEZER_NOSIG set. If @sig_only is set and the task * has PF_FREEZER_NOSIG set (ie. it is a typical kernel thread), its * TIF_FREEZE flag will not be set. */ bool freeze_task(struct task_struct *p, bool sig_only) { /* * We first check if the task is freezing and next if it has already * been frozen to avoid the race with frozen_process() which first marks * the task as frozen and next clears its TIF_FREEZE. */ if (!freezing(p)) { smp_rmb(); if (frozen(p)) return false; if (!sig_only || should_send_signal(p)) set_freeze_flag(p); else return false; } if (should_send_signal(p)) { fake_signal_wake_up(p); /* * fake_signal_wake_up() goes through p's scheduler * lock and guarantees that TASK_STOPPED/TRACED -> * TASK_RUNNING transition can't race with task state * testing in try_to_freeze_tasks(). */ } else if (sig_only) { return false; } else { wake_up_state(p, TASK_INTERRUPTIBLE); } return true; }
bool freeze_task(struct task_struct *p, bool sig_only) { if (!freezing(p)) { rmb(); if (frozen(p)) return false; if (!sig_only || should_send_signal(p)) set_freeze_flag(p); else return false; } if (should_send_signal(p)) { if (!signal_pending(p)) fake_signal_wake_up(p); } else if (sig_only) { return false; } else { wake_up_state(p, TASK_INTERRUPTIBLE); } return true; }
static ssize_t state_store(struct kobject *kobj, struct kobj_attribute *attr, const char *buf, size_t n) { #ifdef CONFIG_SUSPEND #ifdef CONFIG_EARLYSUSPEND suspend_state_t state = PM_SUSPEND_ON; #else suspend_state_t state = PM_SUSPEND_STANDBY; #endif const char * const *s; #endif char *p; int len; int error = -EINVAL; p = memchr(buf, '\n', n); len = p ? p - buf : n; /* First, check if we are requested to hibernate */ if (len == 4 && !strncmp(buf, "disk", len)) { error = hibernate(); goto Exit; } #ifdef CONFIG_SUSPEND for (s = &pm_states[state]; state < PM_SUSPEND_MAX; s++, state++) { if (*s && len == strlen(*s) && !strncmp(buf, *s, len)) break; } if (state < PM_SUSPEND_MAX && *s) #ifdef CONFIG_EARLYSUSPEND && CONFIG_HAS_WAKELOCK if (state == PM_SUSPEND_ON || valid_state(state)) { error = 0; request_suspend_state(state); } #elif defined CONFIG_HAS_WAKELOCK wake_unlock(&main_wake_lock); //Release main lock in the hope of going to sleep if (!has_wake_lock(WAKE_LOCK_SUSPEND)) { wake_timer.data = current; mod_timer(&wake_timer, jiffies + HZ * 5); //To prevent us from freezing indefinitely set_freeze_flag(current); try_to_freeze(); del_timer(&wake_timer); } wake_lock(&main_wake_lock); //Re-grab the main lock so that we do not go into sleep again #else error = enter_state(state); #endif #endif Exit: return error ? error : n; }
/** * freeze_task - send a freeze request to given task * @p: task to send the request to * @with_mm_only: if set, the request will only be sent if the task has its * own mm * Return value: 0, if @with_mm_only is set and the task has no mm of its * own or the task is frozen, 1, otherwise * * The freeze request is sent by seting the tasks's TIF_FREEZE flag and * either sending a fake signal to it or waking it up, depending on whether * or not it has its own mm (ie. it is a user land task). If @with_mm_only * is set and the task has no mm of its own (ie. it is a kernel thread), * its TIF_FREEZE flag should not be set. * * The task_lock() is necessary to prevent races with exit_mm() or * use_mm()/unuse_mm() from occuring. */ static int freeze_task(struct task_struct *p, int with_mm_only) { int ret = 1; task_lock(p); if (freezing(p)) { if (has_mm(p)) { if (!signal_pending(p)) fake_signal_wake_up(p, 0); } else { if (with_mm_only) ret = 0; else wake_up_state(p, TASK_INTERRUPTIBLE); } } else { rmb(); if (frozen(p)) { ret = 0; } else { if (has_mm(p)) { set_freeze_flag(p); send_fake_signal(p); } else { if (with_mm_only) { ret = 0; } else { set_freeze_flag(p); wake_up_state(p, TASK_INTERRUPTIBLE); } } } } task_unlock(p); return ret; }