cregit-Linux how code gets into the kernel

Release 4.15 kernel/power/process.c

Directory: kernel/power
// SPDX-License-Identifier: GPL-2.0
/*
 * drivers/power/process.c - Functions for starting/stopping processes on 
 *                           suspend transitions.
 *
 * Originally from swsusp.
 */



#undef DEBUG

#include <linux/interrupt.h>
#include <linux/oom.h>
#include <linux/suspend.h>
#include <linux/module.h>
#include <linux/sched/debug.h>
#include <linux/sched/task.h>
#include <linux/syscalls.h>
#include <linux/freezer.h>
#include <linux/delay.h>
#include <linux/workqueue.h>
#include <linux/kmod.h>
#include <trace/events/power.h>
#include <linux/cpuset.h>

/*
 * Timeout for stopping processes
 */

unsigned int __read_mostly freeze_timeout_msecs = 20 * MSEC_PER_SEC;


static int try_to_freeze_tasks(bool user_only) { struct task_struct *g, *p; unsigned long end_time; unsigned int todo; bool wq_busy = false; ktime_t start, end, elapsed; unsigned int elapsed_msecs; bool wakeup = false; int sleep_usecs = USEC_PER_MSEC; start = ktime_get_boottime(); end_time = jiffies + msecs_to_jiffies(freeze_timeout_msecs); if (!user_only) freeze_workqueues_begin(); while (true) { todo = 0; read_lock(&tasklist_lock); for_each_process_thread(g, p) { if (p == current || !freeze_task(p)) continue; if (!freezer_should_skip(p)) todo++; } read_unlock(&tasklist_lock); if (!user_only) { wq_busy = freeze_workqueues_busy(); todo += wq_busy; } if (!todo || time_after(jiffies, end_time)) break; if (pm_wakeup_pending()) { wakeup = true; break; } /* * We need to retry, but first give the freezing tasks some * time to enter the refrigerator. Start with an initial * 1 ms sleep followed by exponential backoff until 8 ms. */ usleep_range(sleep_usecs / 2, sleep_usecs); if (sleep_usecs < 8 * USEC_PER_MSEC) sleep_usecs *= 2; } end = ktime_get_boottime(); elapsed = ktime_sub(end, start); elapsed_msecs = ktime_to_ms(elapsed); if (todo) { pr_cont("\n"); pr_err("Freezing of tasks %s after %d.%03d seconds " "(%d tasks refusing to freeze, wq_busy=%d):\n", wakeup ? "aborted" : "failed", elapsed_msecs / 1000, elapsed_msecs % 1000, todo - wq_busy, wq_busy); if (wq_busy) show_workqueue_state(); if (!wakeup) { read_lock(&tasklist_lock); for_each_process_thread(g, p) { if (p != current && !freezer_should_skip(p) && freezing(p) && !frozen(p)) sched_show_task(p); } read_unlock(&tasklist_lock); } } else { pr_cont("(elapsed %d.%03d seconds) ", elapsed_msecs / 1000, elapsed_msecs % 1000); } return todo ? -EBUSY : 0; }

Contributors

PersonTokensPropCommitsCommitProp
Rafael J. Wysocki12838.32%1142.31%
Patrick Mochel5616.77%27.69%
Tejun Heo5416.17%519.23%
Colin Cross3610.78%13.85%
Pavel Machek278.08%13.85%
Abhilash Jindal164.79%13.85%
Roger Lu72.10%13.85%
Michal Hocko51.50%27.69%
Li Fei41.20%13.85%
Xiaotian Feng10.30%13.85%
Total334100.00%26100.00%

/** * freeze_processes - Signal user space processes to enter the refrigerator. * The current thread will not be frozen. The same process that calls * freeze_processes must later call thaw_processes. * * On success, returns 0. On failure, -errno and system is fully thawed. */
int freeze_processes(void) { int error; error = __usermodehelper_disable(UMH_FREEZING); if (error) return error; /* Make sure this task doesn't get frozen */ current->flags |= PF_SUSPEND_TASK; if (!pm_freezing) atomic_inc(&system_freezing_cnt); pm_wakeup_clear(true); pr_info("Freezing user space processes ... "); pm_freezing = true; error = try_to_freeze_tasks(true); if (!error) { __usermodehelper_set_disable_depth(UMH_DISABLED); pr_cont("done."); } pr_cont("\n"); BUG_ON(in_atomic()); /* * Now that the whole userspace is frozen we need to disbale * the OOM killer to disallow any further interference with * killable tasks. There is no guarantee oom victims will * ever reach a point they go away we have to wait with a timeout. */ if (!error && !oom_killer_disable(msecs_to_jiffies(freeze_timeout_msecs))) error = -EBUSY; if (error) thaw_processes(); return error; }

Contributors

PersonTokensPropCommitsCommitProp
Rafael J. Wysocki6553.72%956.25%
Michal Hocko2722.31%425.00%
Tejun Heo2218.18%212.50%
Colin Cross75.79%16.25%
Total121100.00%16100.00%

/** * freeze_kernel_threads - Make freezable kernel threads go to the refrigerator. * * On success, returns 0. On failure, -errno and only the kernel threads are * thawed, so as to give a chance to the caller to do additional cleanups * (if any) before thawing the userspace tasks. So, it is the responsibility * of the caller to thaw the userspace tasks, when the time is right. */
int freeze_kernel_threads(void) { int error; pr_info("Freezing remaining freezable tasks ... "); pm_nosig_freezing = true; error = try_to_freeze_tasks(false); if (!error) pr_cont("done."); pr_cont("\n"); BUG_ON(in_atomic()); if (error) thaw_kernel_threads(); return error; }

Contributors

PersonTokensPropCommitsCommitProp
Rafael J. Wysocki3154.39%654.55%
Patrick Mochel1221.05%19.09%
Tejun Heo1017.54%218.18%
Michal Hocko35.26%19.09%
Srivatsa S. Bhat11.75%19.09%
Total57100.00%11100.00%


void thaw_processes(void) { struct task_struct *g, *p; struct task_struct *curr = current; trace_suspend_resume(TPS("thaw_processes"), 0, true); if (pm_freezing) atomic_dec(&system_freezing_cnt); pm_freezing = false; pm_nosig_freezing = false; oom_killer_enable(); pr_info("Restarting tasks ... "); __usermodehelper_set_disable_depth(UMH_FREEZING); thaw_workqueues(); cpuset_wait_for_hotplug(); read_lock(&tasklist_lock); for_each_process_thread(g, p) { /* No other threads should have PF_SUSPEND_TASK set */ WARN_ON((p != curr) && (p->flags & PF_SUSPEND_TASK)); __thaw_task(p); } read_unlock(&tasklist_lock); WARN_ON(!(curr->flags & PF_SUSPEND_TASK)); curr->flags &= ~PF_SUSPEND_TASK; usermodehelper_enable(); schedule(); pr_cont("done.\n"); trace_suspend_resume(TPS("thaw_processes"), 0, false); }

Contributors

PersonTokensPropCommitsCommitProp
Colin Cross4428.21%17.69%
Patrick Mochel4226.92%215.38%
Tejun Heo3119.87%323.08%
Todd E Brandt2415.38%17.69%
Takashi Iwai53.21%17.69%
Michal Hocko31.92%215.38%
Rafael J. Wysocki31.92%17.69%
Peter Zijlstra31.92%17.69%
Nigel Cunningham10.64%17.69%
Total156100.00%13100.00%


void thaw_kernel_threads(void) { struct task_struct *g, *p; pm_nosig_freezing = false; pr_info("Restarting kernel threads ... "); thaw_workqueues(); read_lock(&tasklist_lock); for_each_process_thread(g, p) { if (p->flags & (PF_KTHREAD | PF_WQ_WORKER)) __thaw_task(p); } read_unlock(&tasklist_lock); schedule(); pr_cont("done.\n"); }

Contributors

PersonTokensPropCommitsCommitProp
Rafael J. Wysocki6995.83%133.33%
Michal Hocko34.17%266.67%
Total72100.00%3100.00%


Overall Contributors

PersonTokensPropCommitsCommitProp
Rafael J. Wysocki30237.94%1936.54%
Patrick Mochel12315.45%23.85%
Tejun Heo12315.45%917.31%
Colin Cross8811.06%23.85%
Michal Hocko415.15%59.62%
Pavel Machek273.39%11.92%
Todd E Brandt273.39%11.92%
Abhilash Jindal162.01%11.92%
Li Fei131.63%11.92%
Roger Lu70.88%11.92%
Peter Zijlstra70.88%11.92%
Ingo Molnar60.75%23.85%
Takashi Iwai50.63%11.92%
Nigel Cunningham40.50%23.85%
Alexey Dobriyan30.38%11.92%
Srivatsa S. Bhat20.25%11.92%
Xiaotian Feng10.13%11.92%
Greg Kroah-Hartman10.13%11.92%
Total796100.00%52100.00%
Directory: kernel/power
Information contained on this website is for historical information purposes only and does not indicate or represent copyright ownership.
Created with cregit.