LCOV - code coverage report
Current view: top level - kernel/power - process.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 97 0.0 %
Date: 2023-04-06 08:38:28 Functions: 0 5 0.0 %

          Line data    Source code
       1             : // SPDX-License-Identifier: GPL-2.0
       2             : /*
       3             :  * drivers/power/process.c - Functions for starting/stopping processes on
       4             :  *                           suspend transitions.
       5             :  *
       6             :  * Originally from swsusp.
       7             :  */
       8             : 
       9             : #include <linux/interrupt.h>
      10             : #include <linux/oom.h>
      11             : #include <linux/suspend.h>
      12             : #include <linux/module.h>
      13             : #include <linux/sched/debug.h>
      14             : #include <linux/sched/task.h>
      15             : #include <linux/syscalls.h>
      16             : #include <linux/freezer.h>
      17             : #include <linux/delay.h>
      18             : #include <linux/workqueue.h>
      19             : #include <linux/kmod.h>
      20             : #include <trace/events/power.h>
      21             : #include <linux/cpuset.h>
      22             : 
      23             : /*
      24             :  * Timeout for stopping processes
      25             :  */
      26             : unsigned int __read_mostly freeze_timeout_msecs = 20 * MSEC_PER_SEC;
      27             : 
      28           0 : static int try_to_freeze_tasks(bool user_only)
      29             : {
      30           0 :         const char *what = user_only ? "user space processes" :
      31             :                                         "remaining freezable tasks";
      32             :         struct task_struct *g, *p;
      33             :         unsigned long end_time;
      34             :         unsigned int todo;
      35           0 :         bool wq_busy = false;
      36             :         ktime_t start, end, elapsed;
      37             :         unsigned int elapsed_msecs;
      38           0 :         bool wakeup = false;
      39           0 :         int sleep_usecs = USEC_PER_MSEC;
      40             : 
      41           0 :         pr_info("Freezing %s\n", what);
      42             : 
      43           0 :         start = ktime_get_boottime();
      44             : 
      45           0 :         end_time = jiffies + msecs_to_jiffies(freeze_timeout_msecs);
      46             : 
      47           0 :         if (!user_only)
      48           0 :                 freeze_workqueues_begin();
      49             : 
      50             :         while (true) {
      51           0 :                 todo = 0;
      52           0 :                 read_lock(&tasklist_lock);
      53           0 :                 for_each_process_thread(g, p) {
      54           0 :                         if (p == current || !freeze_task(p))
      55           0 :                                 continue;
      56             : 
      57           0 :                         todo++;
      58             :                 }
      59           0 :                 read_unlock(&tasklist_lock);
      60             : 
      61           0 :                 if (!user_only) {
      62           0 :                         wq_busy = freeze_workqueues_busy();
      63           0 :                         todo += wq_busy;
      64             :                 }
      65             : 
      66           0 :                 if (!todo || time_after(jiffies, end_time))
      67             :                         break;
      68             : 
      69           0 :                 if (pm_wakeup_pending()) {
      70             :                         wakeup = true;
      71             :                         break;
      72             :                 }
      73             : 
      74             :                 /*
      75             :                  * We need to retry, but first give the freezing tasks some
      76             :                  * time to enter the refrigerator.  Start with an initial
      77             :                  * 1 ms sleep followed by exponential backoff until 8 ms.
      78             :                  */
      79           0 :                 usleep_range(sleep_usecs / 2, sleep_usecs);
      80           0 :                 if (sleep_usecs < 8 * USEC_PER_MSEC)
      81           0 :                         sleep_usecs *= 2;
      82             :         }
      83             : 
      84           0 :         end = ktime_get_boottime();
      85           0 :         elapsed = ktime_sub(end, start);
      86           0 :         elapsed_msecs = ktime_to_ms(elapsed);
      87             : 
      88           0 :         if (todo) {
      89           0 :                 pr_err("Freezing %s %s after %d.%03d seconds "
      90             :                        "(%d tasks refusing to freeze, wq_busy=%d):\n", what,
      91             :                        wakeup ? "aborted" : "failed",
      92             :                        elapsed_msecs / 1000, elapsed_msecs % 1000,
      93             :                        todo - wq_busy, wq_busy);
      94             : 
      95           0 :                 if (wq_busy)
      96           0 :                         show_all_workqueues();
      97             : 
      98           0 :                 if (!wakeup || pm_debug_messages_on) {
      99           0 :                         read_lock(&tasklist_lock);
     100           0 :                         for_each_process_thread(g, p) {
     101           0 :                                 if (p != current && freezing(p) && !frozen(p))
     102           0 :                                         sched_show_task(p);
     103             :                         }
     104           0 :                         read_unlock(&tasklist_lock);
     105             :                 }
     106             :         } else {
     107           0 :                 pr_info("Freezing %s completed (elapsed %d.%03d seconds)\n",
     108             :                         what, elapsed_msecs / 1000, elapsed_msecs % 1000);
     109             :         }
     110             : 
     111           0 :         return todo ? -EBUSY : 0;
     112             : }
     113             : 
     114             : /**
     115             :  * freeze_processes - Signal user space processes to enter the refrigerator.
     116             :  * The current thread will not be frozen.  The same process that calls
     117             :  * freeze_processes must later call thaw_processes.
     118             :  *
     119             :  * On success, returns 0.  On failure, -errno and system is fully thawed.
     120             :  */
     121           0 : int freeze_processes(void)
     122             : {
     123             :         int error;
     124             : 
     125           0 :         error = __usermodehelper_disable(UMH_FREEZING);
     126           0 :         if (error)
     127             :                 return error;
     128             : 
     129             :         /* Make sure this task doesn't get frozen */
     130           0 :         current->flags |= PF_SUSPEND_TASK;
     131             : 
     132           0 :         if (!pm_freezing)
     133           0 :                 static_branch_inc(&freezer_active);
     134             : 
     135           0 :         pm_wakeup_clear(0);
     136           0 :         pm_freezing = true;
     137           0 :         error = try_to_freeze_tasks(true);
     138           0 :         if (!error)
     139           0 :                 __usermodehelper_set_disable_depth(UMH_DISABLED);
     140             : 
     141           0 :         BUG_ON(in_atomic());
     142             : 
     143             :         /*
     144             :          * Now that the whole userspace is frozen we need to disable
     145             :          * the OOM killer to disallow any further interference with
     146             :          * killable tasks. There is no guarantee oom victims will
     147             :          * ever reach a point they go away we have to wait with a timeout.
     148             :          */
     149           0 :         if (!error && !oom_killer_disable(msecs_to_jiffies(freeze_timeout_msecs)))
     150           0 :                 error = -EBUSY;
     151             : 
     152           0 :         if (error)
     153           0 :                 thaw_processes();
     154             :         return error;
     155             : }
     156             : 
     157             : /**
     158             :  * freeze_kernel_threads - Make freezable kernel threads go to the refrigerator.
     159             :  *
     160             :  * On success, returns 0.  On failure, -errno and only the kernel threads are
     161             :  * thawed, so as to give a chance to the caller to do additional cleanups
     162             :  * (if any) before thawing the userspace tasks. So, it is the responsibility
     163             :  * of the caller to thaw the userspace tasks, when the time is right.
     164             :  */
     165           0 : int freeze_kernel_threads(void)
     166             : {
     167             :         int error;
     168             : 
     169           0 :         pm_nosig_freezing = true;
     170           0 :         error = try_to_freeze_tasks(false);
     171             : 
     172           0 :         BUG_ON(in_atomic());
     173             : 
     174           0 :         if (error)
     175           0 :                 thaw_kernel_threads();
     176           0 :         return error;
     177             : }
     178             : 
     179           0 : void thaw_processes(void)
     180             : {
     181             :         struct task_struct *g, *p;
     182           0 :         struct task_struct *curr = current;
     183             : 
     184           0 :         trace_suspend_resume(TPS("thaw_processes"), 0, true);
     185           0 :         if (pm_freezing)
     186           0 :                 static_branch_dec(&freezer_active);
     187           0 :         pm_freezing = false;
     188           0 :         pm_nosig_freezing = false;
     189             : 
     190           0 :         oom_killer_enable();
     191             : 
     192           0 :         pr_info("Restarting tasks ... ");
     193             : 
     194           0 :         __usermodehelper_set_disable_depth(UMH_FREEZING);
     195           0 :         thaw_workqueues();
     196             : 
     197             :         cpuset_wait_for_hotplug();
     198             : 
     199           0 :         read_lock(&tasklist_lock);
     200           0 :         for_each_process_thread(g, p) {
     201             :                 /* No other threads should have PF_SUSPEND_TASK set */
     202           0 :                 WARN_ON((p != curr) && (p->flags & PF_SUSPEND_TASK));
     203           0 :                 __thaw_task(p);
     204             :         }
     205           0 :         read_unlock(&tasklist_lock);
     206             : 
     207           0 :         WARN_ON(!(curr->flags & PF_SUSPEND_TASK));
     208           0 :         curr->flags &= ~PF_SUSPEND_TASK;
     209             : 
     210             :         usermodehelper_enable();
     211             : 
     212           0 :         schedule();
     213           0 :         pr_cont("done.\n");
     214           0 :         trace_suspend_resume(TPS("thaw_processes"), 0, false);
     215           0 : }
     216             : 
     217           0 : void thaw_kernel_threads(void)
     218             : {
     219             :         struct task_struct *g, *p;
     220             : 
     221           0 :         pm_nosig_freezing = false;
     222           0 :         pr_info("Restarting kernel threads ... ");
     223             : 
     224           0 :         thaw_workqueues();
     225             : 
     226           0 :         read_lock(&tasklist_lock);
     227           0 :         for_each_process_thread(g, p) {
     228           0 :                 if (p->flags & PF_KTHREAD)
     229           0 :                         __thaw_task(p);
     230             :         }
     231           0 :         read_unlock(&tasklist_lock);
     232             : 
     233           0 :         schedule();
     234           0 :         pr_cont("done.\n");
     235           0 : }

Generated by: LCOV version 1.14