linux/kernel/power/process.c
<<
>>
Prefs
   1/*
   2 * drivers/power/process.c - Functions for starting/stopping processes on 
   3 *                           suspend transitions.
   4 *
   5 * Originally from swsusp.
   6 */
   7
   8
   9#undef DEBUG
  10
  11#include <linux/interrupt.h>
  12#include <linux/oom.h>
  13#include <linux/suspend.h>
  14#include <linux/module.h>
  15#include <linux/syscalls.h>
  16#include <linux/freezer.h>
  17#include <linux/delay.h>
  18
  19/* 
  20 * Timeout for stopping processes
  21 */
  22#define TIMEOUT (20 * HZ)
  23
  24static inline int freezeable(struct task_struct * p)
  25{
  26        if ((p == current) ||
  27            (p->flags & PF_NOFREEZE) ||
  28            (p->exit_state != 0))
  29                return 0;
  30        return 1;
  31}
  32
  33static int try_to_freeze_tasks(bool sig_only)
  34{
  35        struct task_struct *g, *p;
  36        unsigned long end_time;
  37        unsigned int todo;
  38        struct timeval start, end;
  39        u64 elapsed_csecs64;
  40        unsigned int elapsed_csecs;
  41
  42        do_gettimeofday(&start);
  43
  44        end_time = jiffies + TIMEOUT;
  45        while (true) {
  46                todo = 0;
  47                read_lock(&tasklist_lock);
  48                do_each_thread(g, p) {
  49                        if (frozen(p) || !freezeable(p))
  50                                continue;
  51
  52                        if (!freeze_task(p, sig_only))
  53                                continue;
  54
  55                        /*
  56                         * Now that we've done set_freeze_flag, don't
  57                         * perturb a task in TASK_STOPPED or TASK_TRACED.
  58                         * It is "frozen enough".  If the task does wake
  59                         * up, it will immediately call try_to_freeze.
  60                         */
  61                        if (!task_is_stopped_or_traced(p) &&
  62                            !freezer_should_skip(p))
  63                                todo++;
  64                } while_each_thread(g, p);
  65                read_unlock(&tasklist_lock);
  66                if (!todo || time_after(jiffies, end_time))
  67                        break;
  68
  69                /*
  70                 * We need to retry, but first give the freezing tasks some
  71                 * time to enter the regrigerator.
  72                 */
  73                msleep(10);
  74        }
  75
  76        do_gettimeofday(&end);
  77        elapsed_csecs64 = timeval_to_ns(&end) - timeval_to_ns(&start);
  78        do_div(elapsed_csecs64, NSEC_PER_SEC / 100);
  79        elapsed_csecs = elapsed_csecs64;
  80
  81        if (todo) {
  82                /* This does not unfreeze processes that are already frozen
  83                 * (we have slightly ugly calling convention in that respect,
  84                 * and caller must call thaw_processes() if something fails),
  85                 * but it cleans up leftover PF_FREEZE requests.
  86                 */
  87                printk("\n");
  88                printk(KERN_ERR "Freezing of tasks failed after %d.%02d seconds "
  89                                "(%d tasks refusing to freeze):\n",
  90                                elapsed_csecs / 100, elapsed_csecs % 100, todo);
  91                read_lock(&tasklist_lock);
  92                do_each_thread(g, p) {
  93                        task_lock(p);
  94                        if (freezing(p) && !freezer_should_skip(p))
  95                                sched_show_task(p);
  96                        cancel_freezing(p);
  97                        task_unlock(p);
  98                } while_each_thread(g, p);
  99                read_unlock(&tasklist_lock);
 100        } else {
 101                printk("(elapsed %d.%02d seconds) ", elapsed_csecs / 100,
 102                        elapsed_csecs % 100);
 103        }
 104
 105        return todo ? -EBUSY : 0;
 106}
 107
 108/**
 109 *      freeze_processes - tell processes to enter the refrigerator
 110 */
 111int freeze_processes(void)
 112{
 113        int error;
 114
 115        printk("Freezing user space processes ... ");
 116        error = try_to_freeze_tasks(true);
 117        if (error)
 118                goto Exit;
 119        printk("done.\n");
 120
 121        printk("Freezing remaining freezable tasks ... ");
 122        error = try_to_freeze_tasks(false);
 123        if (error)
 124                goto Exit;
 125        printk("done.");
 126
 127        oom_killer_disable();
 128 Exit:
 129        BUG_ON(in_atomic());
 130        printk("\n");
 131
 132        return error;
 133}
 134
 135static void thaw_tasks(bool nosig_only)
 136{
 137        struct task_struct *g, *p;
 138
 139        read_lock(&tasklist_lock);
 140        do_each_thread(g, p) {
 141                if (!freezeable(p))
 142                        continue;
 143
 144                if (nosig_only && should_send_signal(p))
 145                        continue;
 146
 147                if (cgroup_freezing_or_frozen(p))
 148                        continue;
 149
 150                thaw_process(p);
 151        } while_each_thread(g, p);
 152        read_unlock(&tasklist_lock);
 153}
 154
 155void thaw_processes(void)
 156{
 157        oom_killer_enable();
 158
 159        printk("Restarting tasks ... ");
 160        thaw_tasks(true);
 161        thaw_tasks(false);
 162        schedule();
 163        printk("done.\n");
 164}
 165
 166
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.