The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/kernel/freezer.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*
    2  * kernel/freezer.c - Function to freeze a process
    3  *
    4  * Originally from kernel/power/process.c
    5  */
    6 
    7 #include <linux/interrupt.h>
    8 #include <linux/suspend.h>
    9 #include <linux/export.h>
   10 #include <linux/syscalls.h>
   11 #include <linux/freezer.h>
   12 #include <linux/kthread.h>
   13 
   14 /* total number of freezing conditions in effect */
   15 atomic_t system_freezing_cnt = ATOMIC_INIT(0);
   16 EXPORT_SYMBOL(system_freezing_cnt);
   17 
   18 /* indicate whether PM freezing is in effect, protected by pm_mutex */
   19 bool pm_freezing;
   20 bool pm_nosig_freezing;
   21 
   22 /* protects freezing and frozen transitions */
   23 static DEFINE_SPINLOCK(freezer_lock);
   24 
   25 /**
   26  * freezing_slow_path - slow path for testing whether a task needs to be frozen
   27  * @p: task to be tested
   28  *
   29  * This function is called by freezing() if system_freezing_cnt isn't zero
   30  * and tests whether @p needs to enter and stay in frozen state.  Can be
   31  * called under any context.  The freezers are responsible for ensuring the
   32  * target tasks see the updated state.
   33  */
   34 bool freezing_slow_path(struct task_struct *p)
   35 {
   36         if (p->flags & PF_NOFREEZE)
   37                 return false;
   38 
   39         if (pm_nosig_freezing || cgroup_freezing(p))
   40                 return true;
   41 
   42         if (pm_freezing && !(p->flags & PF_KTHREAD))
   43                 return true;
   44 
   45         return false;
   46 }
   47 EXPORT_SYMBOL(freezing_slow_path);
   48 
   49 /* Refrigerator is place where frozen processes are stored :-). */
   50 bool __refrigerator(bool check_kthr_stop)
   51 {
   52         /* Hmm, should we be allowed to suspend when there are realtime
   53            processes around? */
   54         bool was_frozen = false;
   55         long save = current->state;
   56 
   57         pr_debug("%s entered refrigerator\n", current->comm);
   58 
   59         for (;;) {
   60                 set_current_state(TASK_UNINTERRUPTIBLE);
   61 
   62                 spin_lock_irq(&freezer_lock);
   63                 current->flags |= PF_FROZEN;
   64                 if (!freezing(current) ||
   65                     (check_kthr_stop && kthread_should_stop()))
   66                         current->flags &= ~PF_FROZEN;
   67                 spin_unlock_irq(&freezer_lock);
   68 
   69                 if (!(current->flags & PF_FROZEN))
   70                         break;
   71                 was_frozen = true;
   72                 schedule();
   73         }
   74 
   75         pr_debug("%s left refrigerator\n", current->comm);
   76 
   77         /*
   78          * Restore saved task state before returning.  The mb'd version
   79          * needs to be used; otherwise, it might silently break
   80          * synchronization which depends on ordered task state change.
   81          */
   82         set_current_state(save);
   83 
   84         return was_frozen;
   85 }
   86 EXPORT_SYMBOL(__refrigerator);
   87 
   88 static void fake_signal_wake_up(struct task_struct *p)
   89 {
   90         unsigned long flags;
   91 
   92         if (lock_task_sighand(p, &flags)) {
   93                 signal_wake_up(p, 0);
   94                 unlock_task_sighand(p, &flags);
   95         }
   96 }
   97 
   98 /**
   99  * freeze_task - send a freeze request to given task
  100  * @p: task to send the request to
  101  *
  102  * If @p is freezing, the freeze request is sent either by sending a fake
  103  * signal (if it's not a kernel thread) or waking it up (if it's a kernel
  104  * thread).
  105  *
  106  * RETURNS:
  107  * %false, if @p is not freezing or already frozen; %true, otherwise
  108  */
  109 bool freeze_task(struct task_struct *p)
  110 {
  111         unsigned long flags;
  112 
  113         spin_lock_irqsave(&freezer_lock, flags);
  114         if (!freezing(p) || frozen(p)) {
  115                 spin_unlock_irqrestore(&freezer_lock, flags);
  116                 return false;
  117         }
  118 
  119         if (!(p->flags & PF_KTHREAD))
  120                 fake_signal_wake_up(p);
  121         else
  122                 wake_up_state(p, TASK_INTERRUPTIBLE);
  123 
  124         spin_unlock_irqrestore(&freezer_lock, flags);
  125         return true;
  126 }
  127 
  128 void __thaw_task(struct task_struct *p)
  129 {
  130         unsigned long flags;
  131 
  132         /*
  133          * Clear freezing and kick @p if FROZEN.  Clearing is guaranteed to
  134          * be visible to @p as waking up implies wmb.  Waking up inside
  135          * freezer_lock also prevents wakeups from leaking outside
  136          * refrigerator.
  137          */
  138         spin_lock_irqsave(&freezer_lock, flags);
  139         if (frozen(p))
  140                 wake_up_process(p);
  141         spin_unlock_irqrestore(&freezer_lock, flags);
  142 }
  143 
  144 /**
  145  * set_freezable - make %current freezable
  146  *
  147  * Mark %current freezable and enter refrigerator if necessary.
  148  */
  149 bool set_freezable(void)
  150 {
  151         might_sleep();
  152 
  153         /*
  154          * Modify flags while holding freezer_lock.  This ensures the
  155          * freezer notices that we aren't frozen yet or the freezing
  156          * condition is visible to try_to_freeze() below.
  157          */
  158         spin_lock_irq(&freezer_lock);
  159         current->flags &= ~PF_NOFREEZE;
  160         spin_unlock_irq(&freezer_lock);
  161 
  162         return try_to_freeze();
  163 }
  164 EXPORT_SYMBOL(set_freezable);

Cache object: 8fef3c2d4dc81614fea12eaa0a475235


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.