1. Establish a simple API for process freezing defined in linux/include/sched.h:
   frozen(process)		Check for frozen process
   freezing(process)		Check if a process is being frozen
   freeze(process)		Tell a process to freeze (go to refrigerator)
   thaw_process(process)	Restart process
   frozen_process(process)	Process is frozen now
2. Remove all references to PF_FREEZE and PF_FROZEN from all
   kernel sources except sched.h
3. Fix numerous locations where try_to_freeze is manually done by a driver
4. Remove the argument that is no longer necessary from two function calls.
5. Some whitespace cleanup
6. Clear potential race in refrigerator (provides an open window of PF_FREEZE
   cleared before setting PF_FROZEN, recalc_sigpending does not check
   PF_FROZEN).
This patch does not address the problem of freeze_processes() violating the rule
that a task may only modify its own flags by setting PF_FREEZE. This is not clean
in an SMP environment. freeze(process) is therefore not SMP safe!
Signed-off-by: Christoph Lameter <christoph@lameter.com>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
        do {
                hub_events();
                wait_event_interruptible(khubd_wait, !list_empty(&hub_event_list));
-               if (current->flags & PF_FREEZE)
-                       refrigerator(PF_FREEZE);
+               try_to_freeze();
        } while (!signal_pending(current));
 
 from drivers/usb/core/hub.c::hub_thread()
 
 should be held at that point and it must be safe to sleep there), and
 add:
 
-            if (current->flags & PF_FREEZE)
-                    refrigerator(PF_FREEZE);
+            try_to_freeze();
 
 If the thread is needed for writing the image to storage, you should
 instead set the PF_NOFREEZE process flag when creating the thread.
 
        if (!user_mode(regs))
                return 1;
 
-       if (current->flags & PF_FREEZE) {
-               refrigerator(0);
+       if (try_to_freeze())
                goto no_signal;
-       }
 
        if (!oldset)
                oldset = ¤t->blocked;
 
        if ((regs->ccr & 0x10))
                return 1;
 
-       if (current->flags & PF_FREEZE) {
-               refrigerator(0);
+       if (try_to_freeze())
                goto no_signal;
-       }
 
        current->thread.esp0 = (unsigned long) regs;
 
 
        for ( ; ; ) {
                set_current_state(TASK_INTERRUPTIBLE);
                time_remaining = schedule_timeout(time_remaining);
-               try_to_freeze(PF_FREEZE);
+               try_to_freeze();
                if (time_after(jiffies,
                                prev_balance_time+balanced_irq_interval)) {
                        do_irq_balance();
 
        if (!user_mode(regs))
                return 1;
 
-       if (current->flags & PF_FREEZE) {
-               refrigerator(0);
+       if (try_to_freeze)
                goto no_signal;
-       }
 
        if (!oldset)
                oldset = ¤t->blocked;
 
        if (!user_mode(regs))
                return 1;
 
-       if (current->flags & PF_FREEZE) {
-               refrigerator(0);
+       if (try_to_freeze()) 
                goto no_signal;
-       }
 
        if (!oldset)
                oldset = ¤t->blocked;
 
        unsigned long frame, newsp;
        int signr, ret;
 
-       if (current->flags & PF_FREEZE) {
-               refrigerator(PF_FREEZE);
+       if (try_to_freeze()) {
                signr = 0;
                if (!signal_pending(current))
                        goto no_signal;
 
        if (!user_mode(regs))
                return 1;
 
-       if (try_to_freeze(0))
+       if (try_to_freeze())
                goto no_signal;
 
        if (!oldset)
 
                        VPRINTK("kcdrwd: wake up\n");
 
                        /* make swsusp happy with our thread */
-                       if (current->flags & PF_FREEZE)
-                               refrigerator(PF_FREEZE);
+                       try_to_freeze();
 
                        list_for_each_entry(pkt, &pd->cdrw.pkt_active_list, list) {
                                if (!pkt->sleep_time)
 
 
        while (1) {
                if (down_interruptible(&khpsbpkt_sig)) {
-                       if (current->flags & PF_FREEZE) {
-                               refrigerator(0);
+                       if (try_to_freeze())
                                continue;
-                       }
                        printk("khpsbpkt: received unexpected signal?!\n" );
                        break;
                }
 
 
                if (down_interruptible(&hi->reset_sem) ||
                    down_interruptible(&nodemgr_serialize)) {
-                       if (try_to_freeze(PF_FREEZE))
+                       if (try_to_freeze())
                                continue;
                        printk("NodeMgr: received unexpected signal?!\n" );
                        break;
 
        do {
                gameport_handle_events();
                wait_event_interruptible(gameport_wait, !list_empty(&gameport_event_list));
-               try_to_freeze(PF_FREEZE);
+               try_to_freeze();
        } while (!signal_pending(current));
 
        printk(KERN_DEBUG "gameport: kgameportd exiting\n");
 
        do {
                serio_handle_events();
                wait_event_interruptible(serio_wait, !list_empty(&serio_event_list));
-               try_to_freeze(PF_FREEZE);
+               try_to_freeze();
        } while (!signal_pending(current));
 
        printk(KERN_DEBUG "serio: kseriod exiting\n");
 
        struct thermostat* th = arg;
 
        while(!kthread_should_stop()) {
-               if (current->flags & PF_FREEZE)
-                       refrigerator(PF_FREEZE);
-
+               try_to_freeze();
                msleep_interruptible(2000);
 
 #ifndef DEBUG
 
                wait_event_interruptible_timeout(thread->wqueue,
                                                 test_bit(THREAD_WAKEUP, &thread->flags),
                                                 thread->timeout);
-               if (current->flags & PF_FREEZE)
-                       refrigerator(PF_FREEZE);
+               try_to_freeze();
 
                clear_bit(THREAD_WAKEUP, &thread->flags);
 
 
                        break;
                }
 
-               if (current->flags & PF_FREEZE)
-                       refrigerator(PF_FREEZE);
+               try_to_freeze();
 
                if (down_interruptible(&fepriv->sem))
                        break;
 
 #endif
                }
        }
-       if (current->flags & PF_FREEZE)
-               refrigerator(PF_FREEZE);
+       try_to_freeze();
        remove_wait_queue(&msp->wq, &wait);
        return msp->restart;
 }
 
                        break;
                if (kthread_should_stop())
                        break;
-               if (current->flags & PF_FREEZE)
-                       refrigerator(PF_FREEZE);
+               try_to_freeze();
 
                /* feed buffer data to demux */
                if (buf->state == STATE_DONE)
 
                do {
                        timeout = interruptible_sleep_on_timeout (&tp->thr_wait, timeout);
                        /* make swsusp happy with our thread */
-                       try_to_freeze(PF_FREEZE);
+                       try_to_freeze();
                } while (!signal_pending (current) && (timeout > 0));
 
                if (signal_pending (current)) {
 
                remove_wait_queue(&irda_rq_queue.kick, &wait);
 
                /* make swsusp happy with our thread */
-               if (current->flags & PF_FREEZE)
-                       refrigerator(PF_FREEZE);
+               try_to_freeze();
 
                run_irda_queue();
        }
 
        {
 #ifdef CONFIG_PM
                /* if suspending, then power off and wait */
-               if (unlikely(current->flags & PF_FREEZE)) {
+               if (unlikely(freezing(current))) {
                        if (stir->receiving)
                                receive_stop(stir);
                        else
 
                        write_reg(stir, REG_CTRL1, CTRL1_TXPWD|CTRL1_RXPWD);
 
-                       refrigerator(PF_FREEZE);
+                       refrigerator();
 
                        if (change_speed(stir, stir->speed))
                                break;
 
                        flush_signals(current);
 
                /* make swsusp happy with our thread */
-               try_to_freeze(PF_FREEZE);
+               try_to_freeze();
 
                if (test_bit(JOB_DIE, &ai->flags))
                        break;
 
                }
 
                schedule();
-               try_to_freeze(PF_FREEZE);
+               try_to_freeze();
 
                if (!skt->thread)
                        break;
 
                msleep_interruptible(2000);
 
                if(signal_pending(current)) {
-                       if (try_to_freeze(PF_FREEZE))
+                       if (try_to_freeze())
                                continue;
                        break;
                }
 
        do {
                hub_events();
                wait_event_interruptible(khubd_wait, !list_empty(&hub_event_list)); 
-               try_to_freeze(PF_FREEZE);
+               try_to_freeze();
        } while (!signal_pending(current));
 
        pr_debug ("%s: khubd exiting\n", usbcore_name);
 
        rc = wait_event_interruptible(fsg->thread_wqh,
                        fsg->thread_wakeup_needed);
        fsg->thread_wakeup_needed = 0;
-       if (current->flags & PF_FREEZE)
-               refrigerator(PF_FREEZE);
+       try_to_freeze();
        return (rc ? -EINTR : 0);
 }
 
 
                wait_event_interruptible_timeout(us->delay_wait,
                                test_bit(US_FLIDX_DISCONNECTING, &us->flags),
                                delay_use * HZ);
-               if (current->flags & PF_FREEZE) {
-                       refrigerator(PF_FREEZE);
+               if (try_to_freeze())
                        goto retry;
-               }
        }
 
        /* If the device is still connected, perform the scanning */
 
        while (!control_needs_exit || have_to_wait) {
                have_to_wait = 0;
 
-               try_to_freeze(PF_FREEZE);
+               try_to_freeze();
                msleep_interruptible(w1_timeout * 1000);
 
                if (signal_pending(current))
        allow_signal(SIGTERM);
 
        while (!test_bit(W1_MASTER_NEED_EXIT, &dev->flags)) {
-               try_to_freeze(PF_FREEZE);
+               try_to_freeze();
                msleep_interruptible(w1_timeout * 1000);
 
                if (signal_pending(current))
 
                remove_wait_queue(&kafsasyncd_sleepq, &myself);
                set_current_state(TASK_RUNNING);
 
-               try_to_freeze(PF_FREEZE);
+               try_to_freeze();
 
                /* discard pending signals */
                afs_discard_my_signals();
 
                        complete_and_exit(&kafstimod_dead, 0);
                }
 
-               try_to_freeze(PF_FREEZE);
+               try_to_freeze();
 
                /* discard pending signals */
                afs_discard_my_signals();
 
        }
 
        wake_up(&journal->j_wait_done_commit);
-       if (current->flags & PF_FREEZE) {
+       if (freezing(current)) {
                /*
                 * The simpler the better. Flushing journal isn't a
                 * good idea, because that depends on threads that may
                 */
                jbd_debug(1, "Now suspending kjournald\n");
                spin_unlock(&journal->j_state_lock);
-               refrigerator(PF_FREEZE);
+               refrigerator();
                spin_lock(&journal->j_state_lock);
        } else {
                /*
 
                        lbmStartIO(bp);
                        spin_lock_irq(&log_redrive_lock);
                }
-               if (current->flags & PF_FREEZE) {
+               if (freezing(current)) {
                        spin_unlock_irq(&log_redrive_lock);
-                       refrigerator(PF_FREEZE);
+                       refrigerator();
                } else {
                        add_wait_queue(&jfs_IO_thread_wait, &wq);
                        set_current_state(TASK_INTERRUPTIBLE);
 
                /* In case a wakeup came while all threads were active */
                jfs_commit_thread_waking = 0;
 
-               if (current->flags & PF_FREEZE) {
+               if (freezing(current)) {
                        LAZY_UNLOCK(flags);
-                       refrigerator(PF_FREEZE);
+                       refrigerator();
                } else {
                        DECLARE_WAITQUEUE(wq, current);
 
                /* Add anon_list2 back to anon_list */
                list_splice_init(&TxAnchor.anon_list2, &TxAnchor.anon_list);
 
-               if (current->flags & PF_FREEZE) {
+               if (freezing(current)) {
                        TXN_UNLOCK();
-                       refrigerator(PF_FREEZE);
+                       refrigerator();
                } else {
                        DECLARE_WAITQUEUE(wq, current);
 
 
        prepare_to_wait(queue, &wait, TASK_INTERRUPTIBLE);
        if (!signalled ()) {
                schedule_timeout(NLMCLNT_GRACE_WAIT);
-               try_to_freeze(PF_FREEZE);
+               try_to_freeze();
                if (!signalled ())
                        status = 0;
        }
 
 
        INIT_LIST_HEAD(&tmp);
        do {
-               if (unlikely(current->flags & PF_FREEZE)) {
+               if (unlikely(freezing(current))) {
                        xfsbufd_force_sleep = 1;
-                       refrigerator(PF_FREEZE);
+                       refrigerator();
                } else {
                        xfsbufd_force_sleep = 0;
                }
 
                set_current_state(TASK_INTERRUPTIBLE);
                timeleft = schedule_timeout(timeleft);
                /* swsusp */
-               try_to_freeze(PF_FREEZE);
+               try_to_freeze();
                if (vfsp->vfs_flag & VFS_UMOUNT)
                        break;
 
 
 
 #endif
 
-/* try_to_freeze
- *
- * Checks whether we need to enter the refrigerator
- * and returns 1 if we did so.
- */
 #ifdef CONFIG_PM
-extern void refrigerator(unsigned long);
+/*
+ * Check if a process has been frozen
+ */
+static inline int frozen(struct task_struct *p)
+{
+       return p->flags & PF_FROZEN;
+}
+
+/*
+ * Check if there is a request to freeze a process
+ */
+static inline int freezing(struct task_struct *p)
+{
+       return p->flags & PF_FREEZE;
+}
+
+/*
+ * Request that a process be frozen
+ * FIXME: SMP problem. We may not modify other process' flags!
+ */
+static inline void freeze(struct task_struct *p)
+{
+       p->flags |= PF_FREEZE;
+}
+
+/*
+ * Wake up a frozen process
+ */
+static inline int thaw_process(struct task_struct *p)
+{
+       if (frozen(p)) {
+               p->flags &= ~PF_FROZEN;
+               wake_up_process(p);
+               return 1;
+       }
+       return 0;
+}
+
+/*
+ * freezing is complete, mark process as frozen
+ */
+static inline void frozen_process(struct task_struct *p)
+{
+       p->flags = (p->flags & ~PF_FREEZE) | PF_FROZEN;
+}
+
+extern void refrigerator(void);
 extern int freeze_processes(void);
 extern void thaw_processes(void);
 
-static inline int try_to_freeze(unsigned long refrigerator_flags)
+static inline int try_to_freeze(void)
 {
-       if (unlikely(current->flags & PF_FREEZE)) {
-               refrigerator(refrigerator_flags);
+       if (freezing(current)) {
+               refrigerator();
                return 1;
        } else
                return 0;
 }
 #else
-static inline void refrigerator(unsigned long flag) {}
+static inline int frozen(struct task_struct *p) { return 0; }
+static inline int freezing(struct task_struct *p) { return 0; }
+static inline void freeze(struct task_struct *p) { BUG(); }
+static inline int thaw_process(struct task_struct *p) { return 1; }
+static inline void frozen_process(struct task_struct *p) { BUG(); }
+
+static inline void refrigerator(void) {}
 static inline int freeze_processes(void) { BUG(); return 0; }
 static inline void thaw_processes(void) {}
 
-static inline int try_to_freeze(unsigned long refrigerator_flags)
-{
-       return 0;
-}
+static inline int try_to_freeze(void) { return 0; }
+
 #endif /* CONFIG_PM */
 #endif /* __KERNEL__ */
 
 
 }
 
 /* Refrigerator is place where frozen processes are stored :-). */
-void refrigerator(unsigned long flag)
+void refrigerator(void)
 {
        /* Hmm, should we be allowed to suspend when there are realtime
           processes around? */
        current->state = TASK_UNINTERRUPTIBLE;
        pr_debug("%s entered refrigerator\n", current->comm);
        printk("=");
-       current->flags &= ~PF_FREEZE;
 
+       frozen_process(current);
        spin_lock_irq(¤t->sighand->siglock);
        recalc_sigpending(); /* We sent fake signal, clean it up */
        spin_unlock_irq(¤t->sighand->siglock);
 
-       current->flags |= PF_FROZEN;
-       while (current->flags & PF_FROZEN)
+       while (frozen(current))
                schedule();
        pr_debug("%s left refrigerator\n", current->comm);
        current->state = save;
 /* 0 = success, else # of processes that we failed to stop */
 int freeze_processes(void)
 {
-       int todo;
-       unsigned long start_time;
+       int todo;
+       unsigned long start_time;
        struct task_struct *g, *p;
-       
+
        printk( "Stopping tasks: " );
        start_time = jiffies;
        do {
                        unsigned long flags;
                        if (!freezeable(p))
                                continue;
-                       if ((p->flags & PF_FROZEN) ||
+                       if ((frozen(p)) ||
                            (p->state == TASK_TRACED) ||
                            (p->state == TASK_STOPPED))
                                continue;
 
-                       /* FIXME: smp problem here: we may not access other process' flags
-                          without locking */
-                       p->flags |= PF_FREEZE;
+                       freeze(p);
                        spin_lock_irqsave(&p->sighand->siglock, flags);
                        signal_wake_up(p, 0);
                        spin_unlock_irqrestore(&p->sighand->siglock, flags);
                        return todo;
                }
        } while(todo);
-       
+
        printk( "|\n" );
        BUG_ON(in_atomic());
        return 0;
        do_each_thread(g, p) {
                if (!freezeable(p))
                        continue;
-               if (p->flags & PF_FROZEN) {
-                       p->flags &= ~PF_FROZEN;
-                       wake_up_process(p);
-               } else
+               if (!thaw_process(p))
                        printk(KERN_INFO " Strange, %s not stopped\n", p->comm );
        } while_each_thread(g, p);
 
 
                struct list_head *head;
                migration_req_t *req;
 
-               if (current->flags & PF_FREEZE)
-                       refrigerator(PF_FREEZE);
+               try_to_freeze();
 
                spin_lock_irq(&rq->lock);
 
 
 fastcall void recalc_sigpending_tsk(struct task_struct *t)
 {
        if (t->signal->group_stop_count > 0 ||
-           (t->flags & PF_FREEZE) ||
+           (freezing(t)) ||
            PENDING(&t->pending, &t->blocked) ||
            PENDING(&t->signal->shared_pending, &t->blocked))
                set_tsk_thread_flag(t, TIF_SIGPENDING);
                        current->state = TASK_INTERRUPTIBLE;
                        timeout = schedule_timeout(timeout);
 
-                       if (current->flags & PF_FREEZE)
-                               refrigerator(PF_FREEZE);
+                       try_to_freeze();
                        spin_lock_irq(¤t->sighand->siglock);
                        sig = dequeue_signal(current, &these, &info);
                        current->blocked = current->real_blocked;
 
                spin_unlock_irq(&pdflush_lock);
 
                schedule();
-               if (try_to_freeze(PF_FREEZE)) {
+               if (try_to_freeze()) {
                        spin_lock_irq(&pdflush_lock);
                        continue;
                }
 
        order = 0;
        for ( ; ; ) {
                unsigned long new_order;
-               if (current->flags & PF_FREEZE)
-                       refrigerator(PF_FREEZE);
+
+               try_to_freeze();
 
                prepare_to_wait(&pgdat->kswapd_wait, &wait, TASK_INTERRUPTIBLE);
                new_order = pgdat->kswapd_max_order;
 
 
                _debug("### End Work");
 
-               try_to_freeze(PF_FREEZE);
+               try_to_freeze();
 
                 /* discard pending signals */
                rxrpc_discard_my_signals();
 
 
                _debug("### End Inbound Calls");
 
-               try_to_freeze(PF_FREEZE);
+               try_to_freeze();
 
                 /* discard pending signals */
                rxrpc_discard_my_signals();
 
                        complete_and_exit(&krxtimod_dead, 0);
                }
 
-               try_to_freeze(PF_FREEZE);
+               try_to_freeze();
 
                /* discard pending signals */
                rxrpc_discard_my_signals();
 
        arg->page_len = (pages-2)*PAGE_SIZE;
        arg->len = (pages-1)*PAGE_SIZE;
        arg->tail[0].iov_len = 0;
-       
-       try_to_freeze(PF_FREEZE);
+
+       try_to_freeze();
        if (signalled())
                return -EINTR;
 
 
                schedule_timeout(timeout);
 
-               try_to_freeze(PF_FREEZE);
+               try_to_freeze();
 
                spin_lock_bh(&serv->sv_lock);
                remove_wait_queue(&rqstp->rq_wait, &wait);