linux-mm.kvack.org archive mirror
 help / color / mirror / Atom feed
* [RFC] Fix SMP brokenness for PF_FREEZE and make freezing usable for other purposes
@ 2005-06-24 20:20 Christoph Lameter
  2005-06-24 22:25 ` Nigel Cunningham
                   ` (2 more replies)
  0 siblings, 3 replies; 35+ messages in thread
From: Christoph Lameter @ 2005-06-24 20:20 UTC (permalink / raw)
  To: linux-mm; +Cc: linux-kernel, raybry, pavel, torvalds

The process freezing used by software suspend currently relies on modifying
current->flags from outside of the processes context. This makes freezing and
unfreezing SMP unsafe since a process may change the flags at any time without
locking. The following patch introduces a new atomic_t field in task_struct
to allow SMP safe freezing and unfreezing.

It provides a simple API for process freezing:

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

I only know that this boots correctly since I have no system that can do 
suspend. But Ray needs an effective means of process suspension for 
his process migration patches.

Some of the code may still need to be moved around from kernel/power/* to 
kernel/*.

But is this the correct way to fix this?

Signed-off-by: Christoph Lameter <christoph@lameter.com>

Index: linux-2.6.12/include/linux/sched.h
===================================================================
--- linux-2.6.12.orig/include/linux/sched.h	2005-06-24 20:03:24.000000000 +0000
+++ linux-2.6.12/include/linux/sched.h	2005-06-24 20:03:25.000000000 +0000
@@ -720,6 +720,7 @@ struct task_struct {
 
 	unsigned long ptrace_message;
 	siginfo_t *last_siginfo; /* For ptrace use.  */
+	atomic_t freeze_status;
 /*
  * current io wait handle: wait queue entry to use for io waits
  * If this thread is processing aio, this points at the waitqueue
@@ -784,9 +785,7 @@ do { if (atomic_dec_and_test(&(tsk)->usa
 #define PF_MEMALLOC	0x00000800	/* Allocating memory */
 #define PF_FLUSHER	0x00001000	/* responsible for disk writeback */
 #define PF_USED_MATH	0x00002000	/* if unset the fpu must be initialized before use */
-#define PF_FREEZE	0x00004000	/* this task is being frozen for suspend now */
 #define PF_NOFREEZE	0x00008000	/* this thread should not be frozen */
-#define PF_FROZEN	0x00010000	/* frozen for system suspend */
 #define PF_FSTRANS	0x00020000	/* inside a filesystem transaction */
 #define PF_KSWAPD	0x00040000	/* I am kswapd */
 #define PF_SWAPOFF	0x00080000	/* I am in swapoff */
@@ -1250,29 +1249,36 @@ extern void normalize_rt_tasks(void);
  * Checks whether we need to enter the refrigerator
  * and returns 1 if we did so.
  */
-#ifdef CONFIG_PM
-extern void refrigerator(unsigned long);
+#define FROZEN 0x1000000
+
+#define frozen(__process) (atomic_read(&(__process)->freeze_status) >= FROZEN)
+#define freezing(__process) atomic_read(&(__process)->freeze_status)
+#define freeze(__process) atomic_inc(&(__process)->freeze_status)
+/*
+ * Must hold read_lock(&tasklist_lock) when calling thaw_process
+ */
+static inline int thaw_process(struct task_struct *p)
+{
+	if (frozen(p)) {
+		atomic_set(&p->freeze_status, 0);
+		wake_up_process(p);
+		return 1;
+	}
+	return 0;
+}
+
+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 freeze_processes(void) { BUG(); return 0; }
-static inline void thaw_processes(void) {}
-
-static inline int try_to_freeze(unsigned long refrigerator_flags)
-{
-	return 0;
-}
-#endif /* CONFIG_PM */
 #endif /* __KERNEL__ */
 
 #endif
Index: linux-2.6.12/drivers/block/pktcdvd.c
===================================================================
--- linux-2.6.12.orig/drivers/block/pktcdvd.c	2005-06-24 20:03:23.000000000 +0000
+++ linux-2.6.12/drivers/block/pktcdvd.c	2005-06-24 20:03:25.000000000 +0000
@@ -1251,8 +1251,7 @@ static int kcdrwd(void *foobar)
 			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)
Index: linux-2.6.12/kernel/power/process.c
===================================================================
--- linux-2.6.12.orig/kernel/power/process.c	2005-06-17 19:48:29.000000000 +0000
+++ linux-2.6.12/kernel/power/process.c	2005-06-24 20:03:25.000000000 +0000
@@ -32,7 +32,7 @@ static inline int freezeable(struct task
 }
 
 /* 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? */
@@ -40,15 +40,13 @@ void refrigerator(unsigned long flag)
 	save = current->state;
 	current->state = TASK_UNINTERRUPTIBLE;
 	pr_debug("%s entered refrigerator\n", current->comm);
-	printk("=");
-	current->flags &= ~PF_FREEZE;
 
 	spin_lock_irq(&current->sighand->siglock);
 	recalc_sigpending(); /* We sent fake signal, clean it up */
 	spin_unlock_irq(&current->sighand->siglock);
 
-	current->flags |= PF_FROZEN;
-	while (current->flags & PF_FROZEN)
+	atomic_set(&current->freeze_status, FROZEN);
+	while (frozen(current))
 		schedule();
 	pr_debug("%s left refrigerator\n", current->comm);
 	current->state = save;
@@ -57,10 +55,10 @@ void refrigerator(unsigned long flag)
 /* 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 {
@@ -70,14 +68,12 @@ int freeze_processes(void)
 			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);
@@ -91,7 +87,7 @@ int freeze_processes(void)
 			return todo;
 		}
 	} while(todo);
-	
+
 	printk( "|\n" );
 	BUG_ON(in_atomic());
 	return 0;
@@ -106,10 +102,7 @@ void thaw_processes(void)
 	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);
 
Index: linux-2.6.12/mm/vmscan.c
===================================================================
--- linux-2.6.12.orig/mm/vmscan.c	2005-06-24 20:03:25.000000000 +0000
+++ linux-2.6.12/mm/vmscan.c	2005-06-24 20:03:25.000000000 +0000
@@ -1216,8 +1216,8 @@ static int kswapd(void *p)
 	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;
Index: linux-2.6.12/kernel/signal.c
===================================================================
--- linux-2.6.12.orig/kernel/signal.c	2005-06-24 20:03:25.000000000 +0000
+++ linux-2.6.12/kernel/signal.c	2005-06-24 20:03:25.000000000 +0000
@@ -213,7 +213,7 @@ static inline int has_pending_signals(si
 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);
@@ -2231,8 +2231,7 @@ sys_rt_sigtimedwait(const sigset_t __use
 			current->state = TASK_INTERRUPTIBLE;
 			timeout = schedule_timeout(timeout);
 
-			if (current->flags & PF_FREEZE)
-				refrigerator(PF_FREEZE);
+			try_to_freeze();
 			spin_lock_irq(&current->sighand->siglock);
 			sig = dequeue_signal(current, &these, &info);
 			current->blocked = current->real_blocked;
Index: linux-2.6.12/mm/pdflush.c
===================================================================
--- linux-2.6.12.orig/mm/pdflush.c	2005-06-17 19:48:29.000000000 +0000
+++ linux-2.6.12/mm/pdflush.c	2005-06-24 20:03:25.000000000 +0000
@@ -105,7 +105,7 @@ static int __pdflush(struct pdflush_work
 		spin_unlock_irq(&pdflush_lock);
 
 		schedule();
-		if (try_to_freeze(PF_FREEZE)) {
+		if (try_to_freeze()) {
 			spin_lock_irq(&pdflush_lock);
 			continue;
 		}
Index: linux-2.6.12/kernel/sched.c
===================================================================
--- linux-2.6.12.orig/kernel/sched.c	2005-06-24 20:03:25.000000000 +0000
+++ linux-2.6.12/kernel/sched.c	2005-06-24 20:03:25.000000000 +0000
@@ -4174,8 +4174,7 @@ static int migration_thread(void * data)
 		struct list_head *head;
 		migration_req_t *req;
 
-		if (current->flags & PF_FREEZE)
-			refrigerator(PF_FREEZE);
+		try_to_freeze();
 
 		spin_lock_irq(&rq->lock);
 
Index: linux-2.6.12/drivers/pcmcia/cs.c
===================================================================
--- linux-2.6.12.orig/drivers/pcmcia/cs.c	2005-06-24 20:03:24.000000000 +0000
+++ linux-2.6.12/drivers/pcmcia/cs.c	2005-06-24 20:03:25.000000000 +0000
@@ -718,7 +718,7 @@ static int pccardd(void *__skt)
 		}
 
 		schedule();
-		try_to_freeze(PF_FREEZE);
+		try_to_freeze();
 
 		if (!skt->thread)
 			break;
Index: linux-2.6.12/drivers/usb/core/hub.c
===================================================================
--- linux-2.6.12.orig/drivers/usb/core/hub.c	2005-06-17 19:48:29.000000000 +0000
+++ linux-2.6.12/drivers/usb/core/hub.c	2005-06-24 20:03:25.000000000 +0000
@@ -2808,7 +2808,7 @@ static int hub_thread(void *__unused)
 	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);
Index: linux-2.6.12/drivers/input/serio/serio.c
===================================================================
--- linux-2.6.12.orig/drivers/input/serio/serio.c	2005-06-24 20:03:24.000000000 +0000
+++ linux-2.6.12/drivers/input/serio/serio.c	2005-06-24 20:03:25.000000000 +0000
@@ -344,7 +344,7 @@ static int serio_thread(void *nothing)
 	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");
Index: linux-2.6.12/fs/jbd/journal.c
===================================================================
--- linux-2.6.12.orig/fs/jbd/journal.c	2005-06-17 19:48:29.000000000 +0000
+++ linux-2.6.12/fs/jbd/journal.c	2005-06-24 20:03:25.000000000 +0000
@@ -167,7 +167,7 @@ loop:
 	}
 
 	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
@@ -175,7 +175,7 @@ loop:
 		 */
 		jbd_debug(1, "Now suspending kjournald\n");
 		spin_unlock(&journal->j_state_lock);
-		refrigerator(PF_FREEZE);
+		refrigerator();
 		spin_lock(&journal->j_state_lock);
 	} else {
 		/*
Index: linux-2.6.12/drivers/usb/storage/usb.c
===================================================================
--- linux-2.6.12.orig/drivers/usb/storage/usb.c	2005-06-17 19:48:29.000000000 +0000
+++ linux-2.6.12/drivers/usb/storage/usb.c	2005-06-24 20:03:25.000000000 +0000
@@ -847,10 +847,8 @@ retry:
 		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 */
Index: linux-2.6.12/drivers/ieee1394/ieee1394_core.c
===================================================================
--- linux-2.6.12.orig/drivers/ieee1394/ieee1394_core.c	2005-06-24 20:03:24.000000000 +0000
+++ linux-2.6.12/drivers/ieee1394/ieee1394_core.c	2005-06-24 20:03:25.000000000 +0000
@@ -1041,10 +1041,8 @@ static int hpsbpkt_thread(void *__hi)
 
 	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;
 		}
Index: linux-2.6.12/arch/i386/kernel/io_apic.c
===================================================================
--- linux-2.6.12.orig/arch/i386/kernel/io_apic.c	2005-06-24 20:03:23.000000000 +0000
+++ linux-2.6.12/arch/i386/kernel/io_apic.c	2005-06-24 20:03:25.000000000 +0000
@@ -573,7 +573,7 @@ static int balanced_irq(void *unused)
 	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();
Index: linux-2.6.12/net/sunrpc/svcsock.c
===================================================================
--- linux-2.6.12.orig/net/sunrpc/svcsock.c	2005-06-17 19:48:29.000000000 +0000
+++ linux-2.6.12/net/sunrpc/svcsock.c	2005-06-24 20:03:25.000000000 +0000
@@ -1185,8 +1185,8 @@ svc_recv(struct svc_serv *serv, struct s
 	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;
 
@@ -1227,7 +1227,7 @@ svc_recv(struct svc_serv *serv, struct s
 
 		schedule_timeout(timeout);
 
-		try_to_freeze(PF_FREEZE);
+		try_to_freeze();
 
 		spin_lock_bh(&serv->sv_lock);
 		remove_wait_queue(&rqstp->rq_wait, &wait);
Index: linux-2.6.12/drivers/ieee1394/nodemgr.c
===================================================================
--- linux-2.6.12.orig/drivers/ieee1394/nodemgr.c	2005-06-24 20:03:24.000000000 +0000
+++ linux-2.6.12/drivers/ieee1394/nodemgr.c	2005-06-24 20:03:25.000000000 +0000
@@ -1510,7 +1510,7 @@ static int nodemgr_host_thread(void *__h
 
 		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;
Index: linux-2.6.12/drivers/md/md.c
===================================================================
--- linux-2.6.12.orig/drivers/md/md.c	2005-06-24 20:03:24.000000000 +0000
+++ linux-2.6.12/drivers/md/md.c	2005-06-24 20:03:25.000000000 +0000
@@ -2976,8 +2976,7 @@ static int md_thread(void * arg)
 		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);
 
Index: linux-2.6.12/fs/jfs/jfs_logmgr.c
===================================================================
--- linux-2.6.12.orig/fs/jfs/jfs_logmgr.c	2005-06-24 20:03:24.000000000 +0000
+++ linux-2.6.12/fs/jfs/jfs_logmgr.c	2005-06-24 20:03:25.000000000 +0000
@@ -2359,9 +2359,9 @@ int jfsIOWait(void *arg)
 			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);
Index: linux-2.6.12/fs/jfs/jfs_txnmgr.c
===================================================================
--- linux-2.6.12.orig/fs/jfs/jfs_txnmgr.c	2005-06-24 20:03:24.000000000 +0000
+++ linux-2.6.12/fs/jfs/jfs_txnmgr.c	2005-06-24 20:03:25.000000000 +0000
@@ -2788,9 +2788,9 @@ int jfs_lazycommit(void *arg)
 		/* 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);
 
@@ -2987,9 +2987,9 @@ int jfs_sync(void *arg)
 		/* 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);
 
Index: linux-2.6.12/arch/i386/kernel/signal.c
===================================================================
--- linux-2.6.12.orig/arch/i386/kernel/signal.c	2005-06-24 20:03:23.000000000 +0000
+++ linux-2.6.12/arch/i386/kernel/signal.c	2005-06-24 20:03:25.000000000 +0000
@@ -608,10 +608,8 @@ int fastcall do_signal(struct pt_regs *r
 	if (!user_mode(regs))
 		return 1;
 
-	if (current->flags & PF_FREEZE) {
-		refrigerator(0);
+	if (try_to_freeze)
 		goto no_signal;
-	}
 
 	if (!oldset)
 		oldset = &current->blocked;
Index: linux-2.6.12/fs/lockd/clntproc.c
===================================================================
--- linux-2.6.12.orig/fs/lockd/clntproc.c	2005-06-24 20:03:24.000000000 +0000
+++ linux-2.6.12/fs/lockd/clntproc.c	2005-06-24 20:03:25.000000000 +0000
@@ -313,7 +313,7 @@ static int nlm_wait_on_grace(wait_queue_
 	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;
 	}
Index: linux-2.6.12/fs/xfs/linux-2.6/xfs_buf.c
===================================================================
--- linux-2.6.12.orig/fs/xfs/linux-2.6/xfs_buf.c	2005-06-24 20:03:24.000000000 +0000
+++ linux-2.6.12/fs/xfs/linux-2.6/xfs_buf.c	2005-06-24 20:03:25.000000000 +0000
@@ -1771,9 +1771,9 @@ xfsbufd(
 
 	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;
 		}
Index: linux-2.6.12/arch/x86_64/kernel/signal.c
===================================================================
--- linux-2.6.12.orig/arch/x86_64/kernel/signal.c	2005-06-24 20:03:23.000000000 +0000
+++ linux-2.6.12/arch/x86_64/kernel/signal.c	2005-06-24 20:03:25.000000000 +0000
@@ -425,7 +425,7 @@ int do_signal(struct pt_regs *regs, sigs
 	if (!user_mode(regs))
 		return 1;
 
-	if (try_to_freeze(0))
+	if (try_to_freeze())
 		goto no_signal;
 
 	if (!oldset)
Index: linux-2.6.12/fs/xfs/linux-2.6/xfs_super.c
===================================================================
--- linux-2.6.12.orig/fs/xfs/linux-2.6/xfs_super.c	2005-06-24 20:03:24.000000000 +0000
+++ linux-2.6.12/fs/xfs/linux-2.6/xfs_super.c	2005-06-24 20:03:25.000000000 +0000
@@ -483,7 +483,7 @@ xfssyncd(
 		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;
 
Index: linux-2.6.12/arch/ppc/kernel/signal.c
===================================================================
--- linux-2.6.12.orig/arch/ppc/kernel/signal.c	2005-06-17 19:48:29.000000000 +0000
+++ linux-2.6.12/arch/ppc/kernel/signal.c	2005-06-24 20:07:44.000000000 +0000
@@ -705,8 +705,7 @@ int do_signal(sigset_t *oldset, struct p
 	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;
Index: linux-2.6.12/Documentation/power/kernel_threads.txt
===================================================================
--- linux-2.6.12.orig/Documentation/power/kernel_threads.txt	2005-06-17 19:48:29.000000000 +0000
+++ linux-2.6.12/Documentation/power/kernel_threads.txt	2005-06-24 20:05:14.000000000 +0000
@@ -12,8 +12,7 @@ refrigerator. Code to do this looks like
 	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()
Index: linux-2.6.12/arch/h8300/kernel/signal.c
===================================================================
--- linux-2.6.12.orig/arch/h8300/kernel/signal.c	2005-06-17 19:48:29.000000000 +0000
+++ linux-2.6.12/arch/h8300/kernel/signal.c	2005-06-24 20:07:44.000000000 +0000
@@ -517,10 +517,8 @@ asmlinkage int do_signal(struct pt_regs 
 	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;
 
Index: linux-2.6.12/arch/m32r/kernel/signal.c
===================================================================
--- linux-2.6.12.orig/arch/m32r/kernel/signal.c	2005-06-17 19:48:29.000000000 +0000
+++ linux-2.6.12/arch/m32r/kernel/signal.c	2005-06-24 20:07:44.000000000 +0000
@@ -371,10 +371,8 @@ int do_signal(struct pt_regs *regs, sigs
 	if (!user_mode(regs))
 		return 1;
 
-	if (current->flags & PF_FREEZE) {
-		refrigerator(0);
+	if (try_to_freeze()) 
 		goto no_signal;
-	}
 
 	if (!oldset)
 		oldset = &current->blocked;
Index: linux-2.6.12/fs/afs/kafsasyncd.c
===================================================================
--- linux-2.6.12.orig/fs/afs/kafsasyncd.c	2005-06-17 19:48:29.000000000 +0000
+++ linux-2.6.12/fs/afs/kafsasyncd.c	2005-06-24 20:07:18.000000000 +0000
@@ -116,7 +116,7 @@ static int kafsasyncd(void *arg)
 		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();
Index: linux-2.6.12/fs/afs/kafstimod.c
===================================================================
--- linux-2.6.12.orig/fs/afs/kafstimod.c	2005-06-17 19:48:29.000000000 +0000
+++ linux-2.6.12/fs/afs/kafstimod.c	2005-06-24 20:07:18.000000000 +0000
@@ -91,7 +91,7 @@ static int kafstimod(void *arg)
 			complete_and_exit(&kafstimod_dead, 0);
 		}
 
-		try_to_freeze(PF_FREEZE);
+		try_to_freeze();
 
 		/* discard pending signals */
 		afs_discard_my_signals();
Index: linux-2.6.12/Documentation/power/swsusp.txt
===================================================================
--- linux-2.6.12.orig/Documentation/power/swsusp.txt	2005-06-17 19:48:29.000000000 +0000
+++ linux-2.6.12/Documentation/power/swsusp.txt	2005-06-24 20:05:53.000000000 +0000
@@ -164,8 +164,7 @@ place where the thread is safe to be fro
 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.
Index: linux-2.6.12/arch/frv/kernel/signal.c
===================================================================
--- linux-2.6.12.orig/arch/frv/kernel/signal.c	2005-06-17 19:48:29.000000000 +0000
+++ linux-2.6.12/arch/frv/kernel/signal.c	2005-06-24 20:07:44.000000000 +0000
@@ -536,10 +536,8 @@ int do_signal(struct pt_regs *regs, sigs
 	if (!user_mode(regs))
 		return 1;
 
-	if (current->flags & PF_FREEZE) {
-		refrigerator(0);
+	if (try_to_freeze())
 		goto no_signal;
-	}
 
 	if (!oldset)
 		oldset = &current->blocked;
Index: linux-2.6.12/net/rxrpc/krxtimod.c
===================================================================
--- linux-2.6.12.orig/net/rxrpc/krxtimod.c	2005-06-17 19:48:29.000000000 +0000
+++ linux-2.6.12/net/rxrpc/krxtimod.c	2005-06-24 20:09:14.000000000 +0000
@@ -90,7 +90,7 @@ static int krxtimod(void *arg)
 			complete_and_exit(&krxtimod_dead, 0);
 		}
 
-		try_to_freeze(PF_FREEZE);
+		try_to_freeze();
 
 		/* discard pending signals */
 		rxrpc_discard_my_signals();
Index: linux-2.6.12/net/rxrpc/krxiod.c
===================================================================
--- linux-2.6.12.orig/net/rxrpc/krxiod.c	2005-06-17 19:48:29.000000000 +0000
+++ linux-2.6.12/net/rxrpc/krxiod.c	2005-06-24 20:09:14.000000000 +0000
@@ -138,7 +138,7 @@ static int rxrpc_krxiod(void *arg)
 
 		_debug("### End Work");
 
-		try_to_freeze(PF_FREEZE);
+		try_to_freeze();
 
                 /* discard pending signals */
 		rxrpc_discard_my_signals();
Index: linux-2.6.12/net/rxrpc/krxsecd.c
===================================================================
--- linux-2.6.12.orig/net/rxrpc/krxsecd.c	2005-06-17 19:48:29.000000000 +0000
+++ linux-2.6.12/net/rxrpc/krxsecd.c	2005-06-24 20:09:14.000000000 +0000
@@ -107,7 +107,7 @@ static int rxrpc_krxsecd(void *arg)
 
 		_debug("### End Inbound Calls");
 
-		try_to_freeze(PF_FREEZE);
+		try_to_freeze();
 
                 /* discard pending signals */
 		rxrpc_discard_my_signals();
Index: linux-2.6.12/drivers/media/dvb/dvb-core/dvb_frontend.c
===================================================================
--- linux-2.6.12.orig/drivers/media/dvb/dvb-core/dvb_frontend.c	2005-06-24 20:03:24.000000000 +0000
+++ linux-2.6.12/drivers/media/dvb/dvb-core/dvb_frontend.c	2005-06-24 20:13:56.000000000 +0000
@@ -391,8 +391,7 @@ static int dvb_frontend_thread(void *dat
 			break;
 		}
 
-		if (current->flags & PF_FREEZE)
-			refrigerator(PF_FREEZE);
+		try_to_freeze();
 
 		if (down_interruptible(&fepriv->sem))
 			break;
Index: linux-2.6.12/drivers/media/video/msp3400.c
===================================================================
--- linux-2.6.12.orig/drivers/media/video/msp3400.c	2005-06-24 20:03:24.000000000 +0000
+++ linux-2.6.12/drivers/media/video/msp3400.c	2005-06-24 20:14:47.000000000 +0000
@@ -750,8 +750,7 @@ static int msp34xx_sleep(struct msp3400c
 #endif
 		}
 	}
-	if (current->flags & PF_FREEZE)
-		refrigerator(PF_FREEZE);
+	try_to_freeze();
 	remove_wait_queue(&msp->wq, &wait);
 	return msp->restart;
 }
Index: linux-2.6.12/drivers/net/irda/stir4200.c
===================================================================
--- linux-2.6.12.orig/drivers/net/irda/stir4200.c	2005-06-17 19:48:29.000000000 +0000
+++ linux-2.6.12/drivers/net/irda/stir4200.c	2005-06-24 20:11:27.000000000 +0000
@@ -763,7 +763,7 @@ static int stir_transmit_thread(void *ar
 	{
 #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
@@ -771,7 +771,7 @@ static int stir_transmit_thread(void *ar
 
 			write_reg(stir, REG_CTRL1, CTRL1_TXPWD|CTRL1_RXPWD);
 
-			refrigerator(PF_FREEZE);
+			refrigerator();
 
 			if (change_speed(stir, stir->speed))
 				break;
Index: linux-2.6.12/drivers/input/gameport/gameport.c
===================================================================
--- linux-2.6.12.orig/drivers/input/gameport/gameport.c	2005-06-24 20:03:24.000000000 +0000
+++ linux-2.6.12/drivers/input/gameport/gameport.c	2005-06-24 20:13:09.000000000 +0000
@@ -439,7 +439,7 @@ static int gameport_thread(void *nothing
 	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");
Index: linux-2.6.12/drivers/usb/gadget/file_storage.c
===================================================================
--- linux-2.6.12.orig/drivers/usb/gadget/file_storage.c	2005-06-24 20:03:24.000000000 +0000
+++ linux-2.6.12/drivers/usb/gadget/file_storage.c	2005-06-24 20:12:46.000000000 +0000
@@ -1554,8 +1554,7 @@ static int sleep_thread(struct fsg_dev *
 	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);
 }
 
Index: linux-2.6.12/drivers/pnp/pnpbios/core.c
===================================================================
--- linux-2.6.12.orig/drivers/pnp/pnpbios/core.c	2005-06-17 19:48:29.000000000 +0000
+++ linux-2.6.12/drivers/pnp/pnpbios/core.c	2005-06-24 20:12:24.000000000 +0000
@@ -182,7 +182,7 @@ static int pnp_dock_thread(void * unused
 		msleep_interruptible(2000);
 
 		if(signal_pending(current)) {
-			if (try_to_freeze(PF_FREEZE))
+			if (try_to_freeze())
 				continue;
 			break;
 		}
Index: linux-2.6.12/drivers/net/wireless/airo.c
===================================================================
--- linux-2.6.12.orig/drivers/net/wireless/airo.c	2005-06-17 19:48:29.000000000 +0000
+++ linux-2.6.12/drivers/net/wireless/airo.c	2005-06-24 20:12:06.000000000 +0000
@@ -2918,7 +2918,7 @@ static int airo_thread(void *data) {
 			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;
Index: linux-2.6.12/drivers/macintosh/therm_adt746x.c
===================================================================
--- linux-2.6.12.orig/drivers/macintosh/therm_adt746x.c	2005-06-24 20:03:24.000000000 +0000
+++ linux-2.6.12/drivers/macintosh/therm_adt746x.c	2005-06-24 20:15:14.000000000 +0000
@@ -328,9 +328,7 @@ static int monitor_task(void *arg)
 	struct thermostat* th = arg;
 
 	while(!kthread_should_stop()) {
-		if (current->flags & PF_FREEZE)
-			refrigerator(PF_FREEZE);
-
+		try_to_freeze();
 		msleep_interruptible(2000);
 
 #ifndef DEBUG
Index: linux-2.6.12/drivers/net/irda/sir_kthread.c
===================================================================
--- linux-2.6.12.orig/drivers/net/irda/sir_kthread.c	2005-06-17 19:48:29.000000000 +0000
+++ linux-2.6.12/drivers/net/irda/sir_kthread.c	2005-06-24 20:11:51.000000000 +0000
@@ -135,8 +135,7 @@ static int irda_thread(void *startup)
 		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();
 	}
Index: linux-2.6.12/drivers/media/video/video-buf-dvb.c
===================================================================
--- linux-2.6.12.orig/drivers/media/video/video-buf-dvb.c	2005-06-17 19:48:29.000000000 +0000
+++ linux-2.6.12/drivers/media/video/video-buf-dvb.c	2005-06-24 20:14:26.000000000 +0000
@@ -62,8 +62,7 @@ static int videobuf_dvb_thread(void *dat
 			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)
Index: linux-2.6.12/drivers/net/8139too.c
===================================================================
--- linux-2.6.12.orig/drivers/net/8139too.c	2005-06-24 20:03:24.000000000 +0000
+++ linux-2.6.12/drivers/net/8139too.c	2005-06-24 20:10:54.000000000 +0000
@@ -1606,7 +1606,7 @@ static int rtl8139_thread (void *data)
 		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)) {
Index: linux-2.6.12/drivers/w1/w1.c
===================================================================
--- linux-2.6.12.orig/drivers/w1/w1.c	2005-06-24 20:03:24.000000000 +0000
+++ linux-2.6.12/drivers/w1/w1.c	2005-06-24 20:15:38.000000000 +0000
@@ -646,7 +646,7 @@ static int w1_control(void *data)
 	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))
@@ -725,7 +725,7 @@ int w1_process(void *data)
 	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))
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"aart@kvack.org"> aart@kvack.org </a>

^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: [RFC] Fix SMP brokenness for PF_FREEZE and make freezing usable for other purposes
  2005-06-24 20:20 [RFC] Fix SMP brokenness for PF_FREEZE and make freezing usable for other purposes Christoph Lameter
@ 2005-06-24 22:25 ` Nigel Cunningham
  2005-06-25  2:51 ` Pavel Machek
  2005-06-25  7:35 ` Kirill Korotaev
  2 siblings, 0 replies; 35+ messages in thread
From: Nigel Cunningham @ 2005-06-24 22:25 UTC (permalink / raw)
  To: Christoph Lameter
  Cc: Linux Memory Management, Linux Kernel Mailing List, raybry,
	pavel, Linus Torvalds

Hi.

try_to_freeze used to have a flag indicating whether we should clear the
sigpending. It stopped some threads going into infinite cpu-sucking
loops thinking they had a signal to process. It looks to me like Pavel
(or someone else) has made the recalc_sigpending unconditional and
you've cleaned up the left overs. Is that right, and is it the right
thing to do? I think so, but want to be sure.

Apart from that query, looks great to me. Will apply in Suspend2 and get
it tested there if you like. (Not sure if it will happen today though as
it's Saturday now).

Regards,

Nigel

On Sat, 2005-06-25 at 06:20, Christoph Lameter wrote:
> The process freezing used by software suspend currently relies on modifying
> current->flags from outside of the processes context. This makes freezing and
> unfreezing SMP unsafe since a process may change the flags at any time without
> locking. The following patch introduces a new atomic_t field in task_struct
> to allow SMP safe freezing and unfreezing.
> 
> It provides a simple API for process freezing:
> 
> 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
> 
> I only know that this boots correctly since I have no system that can do 
> suspend. But Ray needs an effective means of process suspension for 
> his process migration patches.
> 
> Some of the code may still need to be moved around from kernel/power/* to 
> kernel/*.
> 
> But is this the correct way to fix this?
> 
> Signed-off-by: Christoph Lameter <christoph@lameter.com>
> 
> Index: linux-2.6.12/include/linux/sched.h
> ===================================================================
> --- linux-2.6.12.orig/include/linux/sched.h	2005-06-24 20:03:24.000000000 +0000
> +++ linux-2.6.12/include/linux/sched.h	2005-06-24 20:03:25.000000000 +0000
> @@ -720,6 +720,7 @@ struct task_struct {
>  
>  	unsigned long ptrace_message;
>  	siginfo_t *last_siginfo; /* For ptrace use.  */
> +	atomic_t freeze_status;
>  /*
>   * current io wait handle: wait queue entry to use for io waits
>   * If this thread is processing aio, this points at the waitqueue
> @@ -784,9 +785,7 @@ do { if (atomic_dec_and_test(&(tsk)->usa
>  #define PF_MEMALLOC	0x00000800	/* Allocating memory */
>  #define PF_FLUSHER	0x00001000	/* responsible for disk writeback */
>  #define PF_USED_MATH	0x00002000	/* if unset the fpu must be initialized before use */
> -#define PF_FREEZE	0x00004000	/* this task is being frozen for suspend now */
>  #define PF_NOFREEZE	0x00008000	/* this thread should not be frozen */
> -#define PF_FROZEN	0x00010000	/* frozen for system suspend */
>  #define PF_FSTRANS	0x00020000	/* inside a filesystem transaction */
>  #define PF_KSWAPD	0x00040000	/* I am kswapd */
>  #define PF_SWAPOFF	0x00080000	/* I am in swapoff */
> @@ -1250,29 +1249,36 @@ extern void normalize_rt_tasks(void);
>   * Checks whether we need to enter the refrigerator
>   * and returns 1 if we did so.
>   */
> -#ifdef CONFIG_PM
> -extern void refrigerator(unsigned long);
> +#define FROZEN 0x1000000
> +
> +#define frozen(__process) (atomic_read(&(__process)->freeze_status) >= FROZEN)
> +#define freezing(__process) atomic_read(&(__process)->freeze_status)
> +#define freeze(__process) atomic_inc(&(__process)->freeze_status)
> +/*
> + * Must hold read_lock(&tasklist_lock) when calling thaw_process
> + */
> +static inline int thaw_process(struct task_struct *p)
> +{
> +	if (frozen(p)) {
> +		atomic_set(&p->freeze_status, 0);
> +		wake_up_process(p);
> +		return 1;
> +	}
> +	return 0;
> +}
> +
> +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 freeze_processes(void) { BUG(); return 0; }
> -static inline void thaw_processes(void) {}
> -
> -static inline int try_to_freeze(unsigned long refrigerator_flags)
> -{
> -	return 0;
> -}
> -#endif /* CONFIG_PM */
>  #endif /* __KERNEL__ */
>  
>  #endif
> Index: linux-2.6.12/drivers/block/pktcdvd.c
> ===================================================================
> --- linux-2.6.12.orig/drivers/block/pktcdvd.c	2005-06-24 20:03:23.000000000 +0000
> +++ linux-2.6.12/drivers/block/pktcdvd.c	2005-06-24 20:03:25.000000000 +0000
> @@ -1251,8 +1251,7 @@ static int kcdrwd(void *foobar)
>  			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)
> Index: linux-2.6.12/kernel/power/process.c
> ===================================================================
> --- linux-2.6.12.orig/kernel/power/process.c	2005-06-17 19:48:29.000000000 +0000
> +++ linux-2.6.12/kernel/power/process.c	2005-06-24 20:03:25.000000000 +0000
> @@ -32,7 +32,7 @@ static inline int freezeable(struct task
>  }
>  
>  /* 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? */
> @@ -40,15 +40,13 @@ void refrigerator(unsigned long flag)
>  	save = current->state;
>  	current->state = TASK_UNINTERRUPTIBLE;
>  	pr_debug("%s entered refrigerator\n", current->comm);
> -	printk("=");
> -	current->flags &= ~PF_FREEZE;
>  
>  	spin_lock_irq(&current->sighand->siglock);
>  	recalc_sigpending(); /* We sent fake signal, clean it up */
>  	spin_unlock_irq(&current->sighand->siglock);
>  
> -	current->flags |= PF_FROZEN;
> -	while (current->flags & PF_FROZEN)
> +	atomic_set(&current->freeze_status, FROZEN);
> +	while (frozen(current))
>  		schedule();
>  	pr_debug("%s left refrigerator\n", current->comm);
>  	current->state = save;
> @@ -57,10 +55,10 @@ void refrigerator(unsigned long flag)
>  /* 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 {
> @@ -70,14 +68,12 @@ int freeze_processes(void)
>  			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);
> @@ -91,7 +87,7 @@ int freeze_processes(void)
>  			return todo;
>  		}
>  	} while(todo);
> -	
> +
>  	printk( "|\n" );
>  	BUG_ON(in_atomic());
>  	return 0;
> @@ -106,10 +102,7 @@ void thaw_processes(void)
>  	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);
>  
> Index: linux-2.6.12/mm/vmscan.c
> ===================================================================
> --- linux-2.6.12.orig/mm/vmscan.c	2005-06-24 20:03:25.000000000 +0000
> +++ linux-2.6.12/mm/vmscan.c	2005-06-24 20:03:25.000000000 +0000
> @@ -1216,8 +1216,8 @@ static int kswapd(void *p)
>  	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;
> Index: linux-2.6.12/kernel/signal.c
> ===================================================================
> --- linux-2.6.12.orig/kernel/signal.c	2005-06-24 20:03:25.000000000 +0000
> +++ linux-2.6.12/kernel/signal.c	2005-06-24 20:03:25.000000000 +0000
> @@ -213,7 +213,7 @@ static inline int has_pending_signals(si
>  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);
> @@ -2231,8 +2231,7 @@ sys_rt_sigtimedwait(const sigset_t __use
>  			current->state = TASK_INTERRUPTIBLE;
>  			timeout = schedule_timeout(timeout);
>  
> -			if (current->flags & PF_FREEZE)
> -				refrigerator(PF_FREEZE);
> +			try_to_freeze();
>  			spin_lock_irq(&current->sighand->siglock);
>  			sig = dequeue_signal(current, &these, &info);
>  			current->blocked = current->real_blocked;
> Index: linux-2.6.12/mm/pdflush.c
> ===================================================================
> --- linux-2.6.12.orig/mm/pdflush.c	2005-06-17 19:48:29.000000000 +0000
> +++ linux-2.6.12/mm/pdflush.c	2005-06-24 20:03:25.000000000 +0000
> @@ -105,7 +105,7 @@ static int __pdflush(struct pdflush_work
>  		spin_unlock_irq(&pdflush_lock);
>  
>  		schedule();
> -		if (try_to_freeze(PF_FREEZE)) {
> +		if (try_to_freeze()) {
>  			spin_lock_irq(&pdflush_lock);
>  			continue;
>  		}
> Index: linux-2.6.12/kernel/sched.c
> ===================================================================
> --- linux-2.6.12.orig/kernel/sched.c	2005-06-24 20:03:25.000000000 +0000
> +++ linux-2.6.12/kernel/sched.c	2005-06-24 20:03:25.000000000 +0000
> @@ -4174,8 +4174,7 @@ static int migration_thread(void * data)
>  		struct list_head *head;
>  		migration_req_t *req;
>  
> -		if (current->flags & PF_FREEZE)
> -			refrigerator(PF_FREEZE);
> +		try_to_freeze();
>  
>  		spin_lock_irq(&rq->lock);
>  
> Index: linux-2.6.12/drivers/pcmcia/cs.c
> ===================================================================
> --- linux-2.6.12.orig/drivers/pcmcia/cs.c	2005-06-24 20:03:24.000000000 +0000
> +++ linux-2.6.12/drivers/pcmcia/cs.c	2005-06-24 20:03:25.000000000 +0000
> @@ -718,7 +718,7 @@ static int pccardd(void *__skt)
>  		}
>  
>  		schedule();
> -		try_to_freeze(PF_FREEZE);
> +		try_to_freeze();
>  
>  		if (!skt->thread)
>  			break;
> Index: linux-2.6.12/drivers/usb/core/hub.c
> ===================================================================
> --- linux-2.6.12.orig/drivers/usb/core/hub.c	2005-06-17 19:48:29.000000000 +0000
> +++ linux-2.6.12/drivers/usb/core/hub.c	2005-06-24 20:03:25.000000000 +0000
> @@ -2808,7 +2808,7 @@ static int hub_thread(void *__unused)
>  	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);
> Index: linux-2.6.12/drivers/input/serio/serio.c
> ===================================================================
> --- linux-2.6.12.orig/drivers/input/serio/serio.c	2005-06-24 20:03:24.000000000 +0000
> +++ linux-2.6.12/drivers/input/serio/serio.c	2005-06-24 20:03:25.000000000 +0000
> @@ -344,7 +344,7 @@ static int serio_thread(void *nothing)
>  	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");
> Index: linux-2.6.12/fs/jbd/journal.c
> ===================================================================
> --- linux-2.6.12.orig/fs/jbd/journal.c	2005-06-17 19:48:29.000000000 +0000
> +++ linux-2.6.12/fs/jbd/journal.c	2005-06-24 20:03:25.000000000 +0000
> @@ -167,7 +167,7 @@ loop:
>  	}
>  
>  	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
> @@ -175,7 +175,7 @@ loop:
>  		 */
>  		jbd_debug(1, "Now suspending kjournald\n");
>  		spin_unlock(&journal->j_state_lock);
> -		refrigerator(PF_FREEZE);
> +		refrigerator();
>  		spin_lock(&journal->j_state_lock);
>  	} else {
>  		/*
> Index: linux-2.6.12/drivers/usb/storage/usb.c
> ===================================================================
> --- linux-2.6.12.orig/drivers/usb/storage/usb.c	2005-06-17 19:48:29.000000000 +0000
> +++ linux-2.6.12/drivers/usb/storage/usb.c	2005-06-24 20:03:25.000000000 +0000
> @@ -847,10 +847,8 @@ retry:
>  		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 */
> Index: linux-2.6.12/drivers/ieee1394/ieee1394_core.c
> ===================================================================
> --- linux-2.6.12.orig/drivers/ieee1394/ieee1394_core.c	2005-06-24 20:03:24.000000000 +0000
> +++ linux-2.6.12/drivers/ieee1394/ieee1394_core.c	2005-06-24 20:03:25.000000000 +0000
> @@ -1041,10 +1041,8 @@ static int hpsbpkt_thread(void *__hi)
>  
>  	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;
>  		}
> Index: linux-2.6.12/arch/i386/kernel/io_apic.c
> ===================================================================
> --- linux-2.6.12.orig/arch/i386/kernel/io_apic.c	2005-06-24 20:03:23.000000000 +0000
> +++ linux-2.6.12/arch/i386/kernel/io_apic.c	2005-06-24 20:03:25.000000000 +0000
> @@ -573,7 +573,7 @@ static int balanced_irq(void *unused)
>  	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();
> Index: linux-2.6.12/net/sunrpc/svcsock.c
> ===================================================================
> --- linux-2.6.12.orig/net/sunrpc/svcsock.c	2005-06-17 19:48:29.000000000 +0000
> +++ linux-2.6.12/net/sunrpc/svcsock.c	2005-06-24 20:03:25.000000000 +0000
> @@ -1185,8 +1185,8 @@ svc_recv(struct svc_serv *serv, struct s
>  	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;
>  
> @@ -1227,7 +1227,7 @@ svc_recv(struct svc_serv *serv, struct s
>  
>  		schedule_timeout(timeout);
>  
> -		try_to_freeze(PF_FREEZE);
> +		try_to_freeze();
>  
>  		spin_lock_bh(&serv->sv_lock);
>  		remove_wait_queue(&rqstp->rq_wait, &wait);
> Index: linux-2.6.12/drivers/ieee1394/nodemgr.c
> ===================================================================
> --- linux-2.6.12.orig/drivers/ieee1394/nodemgr.c	2005-06-24 20:03:24.000000000 +0000
> +++ linux-2.6.12/drivers/ieee1394/nodemgr.c	2005-06-24 20:03:25.000000000 +0000
> @@ -1510,7 +1510,7 @@ static int nodemgr_host_thread(void *__h
>  
>  		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;
> Index: linux-2.6.12/drivers/md/md.c
> ===================================================================
> --- linux-2.6.12.orig/drivers/md/md.c	2005-06-24 20:03:24.000000000 +0000
> +++ linux-2.6.12/drivers/md/md.c	2005-06-24 20:03:25.000000000 +0000
> @@ -2976,8 +2976,7 @@ static int md_thread(void * arg)
>  		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);
>  
> Index: linux-2.6.12/fs/jfs/jfs_logmgr.c
> ===================================================================
> --- linux-2.6.12.orig/fs/jfs/jfs_logmgr.c	2005-06-24 20:03:24.000000000 +0000
> +++ linux-2.6.12/fs/jfs/jfs_logmgr.c	2005-06-24 20:03:25.000000000 +0000
> @@ -2359,9 +2359,9 @@ int jfsIOWait(void *arg)
>  			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);
> Index: linux-2.6.12/fs/jfs/jfs_txnmgr.c
> ===================================================================
> --- linux-2.6.12.orig/fs/jfs/jfs_txnmgr.c	2005-06-24 20:03:24.000000000 +0000
> +++ linux-2.6.12/fs/jfs/jfs_txnmgr.c	2005-06-24 20:03:25.000000000 +0000
> @@ -2788,9 +2788,9 @@ int jfs_lazycommit(void *arg)
>  		/* 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);
>  
> @@ -2987,9 +2987,9 @@ int jfs_sync(void *arg)
>  		/* 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);
>  
> Index: linux-2.6.12/arch/i386/kernel/signal.c
> ===================================================================
> --- linux-2.6.12.orig/arch/i386/kernel/signal.c	2005-06-24 20:03:23.000000000 +0000
> +++ linux-2.6.12/arch/i386/kernel/signal.c	2005-06-24 20:03:25.000000000 +0000
> @@ -608,10 +608,8 @@ int fastcall do_signal(struct pt_regs *r
>  	if (!user_mode(regs))
>  		return 1;
>  
> -	if (current->flags & PF_FREEZE) {
> -		refrigerator(0);
> +	if (try_to_freeze)
>  		goto no_signal;
> -	}
>  
>  	if (!oldset)
>  		oldset = &current->blocked;
> Index: linux-2.6.12/fs/lockd/clntproc.c
> ===================================================================
> --- linux-2.6.12.orig/fs/lockd/clntproc.c	2005-06-24 20:03:24.000000000 +0000
> +++ linux-2.6.12/fs/lockd/clntproc.c	2005-06-24 20:03:25.000000000 +0000
> @@ -313,7 +313,7 @@ static int nlm_wait_on_grace(wait_queue_
>  	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;
>  	}
> Index: linux-2.6.12/fs/xfs/linux-2.6/xfs_buf.c
> ===================================================================
> --- linux-2.6.12.orig/fs/xfs/linux-2.6/xfs_buf.c	2005-06-24 20:03:24.000000000 +0000
> +++ linux-2.6.12/fs/xfs/linux-2.6/xfs_buf.c	2005-06-24 20:03:25.000000000 +0000
> @@ -1771,9 +1771,9 @@ xfsbufd(
>  
>  	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;
>  		}
> Index: linux-2.6.12/arch/x86_64/kernel/signal.c
> ===================================================================
> --- linux-2.6.12.orig/arch/x86_64/kernel/signal.c	2005-06-24 20:03:23.000000000 +0000
> +++ linux-2.6.12/arch/x86_64/kernel/signal.c	2005-06-24 20:03:25.000000000 +0000
> @@ -425,7 +425,7 @@ int do_signal(struct pt_regs *regs, sigs
>  	if (!user_mode(regs))
>  		return 1;
>  
> -	if (try_to_freeze(0))
> +	if (try_to_freeze())
>  		goto no_signal;
>  
>  	if (!oldset)
> Index: linux-2.6.12/fs/xfs/linux-2.6/xfs_super.c
> ===================================================================
> --- linux-2.6.12.orig/fs/xfs/linux-2.6/xfs_super.c	2005-06-24 20:03:24.000000000 +0000
> +++ linux-2.6.12/fs/xfs/linux-2.6/xfs_super.c	2005-06-24 20:03:25.000000000 +0000
> @@ -483,7 +483,7 @@ xfssyncd(
>  		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;
>  
> Index: linux-2.6.12/arch/ppc/kernel/signal.c
> ===================================================================
> --- linux-2.6.12.orig/arch/ppc/kernel/signal.c	2005-06-17 19:48:29.000000000 +0000
> +++ linux-2.6.12/arch/ppc/kernel/signal.c	2005-06-24 20:07:44.000000000 +0000
> @@ -705,8 +705,7 @@ int do_signal(sigset_t *oldset, struct p
>  	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;
> Index: linux-2.6.12/Documentation/power/kernel_threads.txt
> ===================================================================
> --- linux-2.6.12.orig/Documentation/power/kernel_threads.txt	2005-06-17 19:48:29.000000000 +0000
> +++ linux-2.6.12/Documentation/power/kernel_threads.txt	2005-06-24 20:05:14.000000000 +0000
> @@ -12,8 +12,7 @@ refrigerator. Code to do this looks like
>  	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()
> Index: linux-2.6.12/arch/h8300/kernel/signal.c
> ===================================================================
> --- linux-2.6.12.orig/arch/h8300/kernel/signal.c	2005-06-17 19:48:29.000000000 +0000
> +++ linux-2.6.12/arch/h8300/kernel/signal.c	2005-06-24 20:07:44.000000000 +0000
> @@ -517,10 +517,8 @@ asmlinkage int do_signal(struct pt_regs 
>  	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;
>  
> Index: linux-2.6.12/arch/m32r/kernel/signal.c
> ===================================================================
> --- linux-2.6.12.orig/arch/m32r/kernel/signal.c	2005-06-17 19:48:29.000000000 +0000
> +++ linux-2.6.12/arch/m32r/kernel/signal.c	2005-06-24 20:07:44.000000000 +0000
> @@ -371,10 +371,8 @@ int do_signal(struct pt_regs *regs, sigs
>  	if (!user_mode(regs))
>  		return 1;
>  
> -	if (current->flags & PF_FREEZE) {
> -		refrigerator(0);
> +	if (try_to_freeze()) 
>  		goto no_signal;
> -	}
>  
>  	if (!oldset)
>  		oldset = &current->blocked;
> Index: linux-2.6.12/fs/afs/kafsasyncd.c
> ===================================================================
> --- linux-2.6.12.orig/fs/afs/kafsasyncd.c	2005-06-17 19:48:29.000000000 +0000
> +++ linux-2.6.12/fs/afs/kafsasyncd.c	2005-06-24 20:07:18.000000000 +0000
> @@ -116,7 +116,7 @@ static int kafsasyncd(void *arg)
>  		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();
> Index: linux-2.6.12/fs/afs/kafstimod.c
> ===================================================================
> --- linux-2.6.12.orig/fs/afs/kafstimod.c	2005-06-17 19:48:29.000000000 +0000
> +++ linux-2.6.12/fs/afs/kafstimod.c	2005-06-24 20:07:18.000000000 +0000
> @@ -91,7 +91,7 @@ static int kafstimod(void *arg)
>  			complete_and_exit(&kafstimod_dead, 0);
>  		}
>  
> -		try_to_freeze(PF_FREEZE);
> +		try_to_freeze();
>  
>  		/* discard pending signals */
>  		afs_discard_my_signals();
> Index: linux-2.6.12/Documentation/power/swsusp.txt
> ===================================================================
> --- linux-2.6.12.orig/Documentation/power/swsusp.txt	2005-06-17 19:48:29.000000000 +0000
> +++ linux-2.6.12/Documentation/power/swsusp.txt	2005-06-24 20:05:53.000000000 +0000
> @@ -164,8 +164,7 @@ place where the thread is safe to be fro
>  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.
> Index: linux-2.6.12/arch/frv/kernel/signal.c
> ===================================================================
> --- linux-2.6.12.orig/arch/frv/kernel/signal.c	2005-06-17 19:48:29.000000000 +0000
> +++ linux-2.6.12/arch/frv/kernel/signal.c	2005-06-24 20:07:44.000000000 +0000
> @@ -536,10 +536,8 @@ int do_signal(struct pt_regs *regs, sigs
>  	if (!user_mode(regs))
>  		return 1;
>  
> -	if (current->flags & PF_FREEZE) {
> -		refrigerator(0);
> +	if (try_to_freeze())
>  		goto no_signal;
> -	}
>  
>  	if (!oldset)
>  		oldset = &current->blocked;
> Index: linux-2.6.12/net/rxrpc/krxtimod.c
> ===================================================================
> --- linux-2.6.12.orig/net/rxrpc/krxtimod.c	2005-06-17 19:48:29.000000000 +0000
> +++ linux-2.6.12/net/rxrpc/krxtimod.c	2005-06-24 20:09:14.000000000 +0000
> @@ -90,7 +90,7 @@ static int krxtimod(void *arg)
>  			complete_and_exit(&krxtimod_dead, 0);
>  		}
>  
> -		try_to_freeze(PF_FREEZE);
> +		try_to_freeze();
>  
>  		/* discard pending signals */
>  		rxrpc_discard_my_signals();
> Index: linux-2.6.12/net/rxrpc/krxiod.c
> ===================================================================
> --- linux-2.6.12.orig/net/rxrpc/krxiod.c	2005-06-17 19:48:29.000000000 +0000
> +++ linux-2.6.12/net/rxrpc/krxiod.c	2005-06-24 20:09:14.000000000 +0000
> @@ -138,7 +138,7 @@ static int rxrpc_krxiod(void *arg)
>  
>  		_debug("### End Work");
>  
> -		try_to_freeze(PF_FREEZE);
> +		try_to_freeze();
>  
>                  /* discard pending signals */
>  		rxrpc_discard_my_signals();
> Index: linux-2.6.12/net/rxrpc/krxsecd.c
> ===================================================================
> --- linux-2.6.12.orig/net/rxrpc/krxsecd.c	2005-06-17 19:48:29.000000000 +0000
> +++ linux-2.6.12/net/rxrpc/krxsecd.c	2005-06-24 20:09:14.000000000 +0000
> @@ -107,7 +107,7 @@ static int rxrpc_krxsecd(void *arg)
>  
>  		_debug("### End Inbound Calls");
>  
> -		try_to_freeze(PF_FREEZE);
> +		try_to_freeze();
>  
>                  /* discard pending signals */
>  		rxrpc_discard_my_signals();
> Index: linux-2.6.12/drivers/media/dvb/dvb-core/dvb_frontend.c
> ===================================================================
> --- linux-2.6.12.orig/drivers/media/dvb/dvb-core/dvb_frontend.c	2005-06-24 20:03:24.000000000 +0000
> +++ linux-2.6.12/drivers/media/dvb/dvb-core/dvb_frontend.c	2005-06-24 20:13:56.000000000 +0000
> @@ -391,8 +391,7 @@ static int dvb_frontend_thread(void *dat
>  			break;
>  		}
>  
> -		if (current->flags & PF_FREEZE)
> -			refrigerator(PF_FREEZE);
> +		try_to_freeze();
>  
>  		if (down_interruptible(&fepriv->sem))
>  			break;
> Index: linux-2.6.12/drivers/media/video/msp3400.c
> ===================================================================
> --- linux-2.6.12.orig/drivers/media/video/msp3400.c	2005-06-24 20:03:24.000000000 +0000
> +++ linux-2.6.12/drivers/media/video/msp3400.c	2005-06-24 20:14:47.000000000 +0000
> @@ -750,8 +750,7 @@ static int msp34xx_sleep(struct msp3400c
>  #endif
>  		}
>  	}
> -	if (current->flags & PF_FREEZE)
> -		refrigerator(PF_FREEZE);
> +	try_to_freeze();
>  	remove_wait_queue(&msp->wq, &wait);
>  	return msp->restart;
>  }
> Index: linux-2.6.12/drivers/net/irda/stir4200.c
> ===================================================================
> --- linux-2.6.12.orig/drivers/net/irda/stir4200.c	2005-06-17 19:48:29.000000000 +0000
> +++ linux-2.6.12/drivers/net/irda/stir4200.c	2005-06-24 20:11:27.000000000 +0000
> @@ -763,7 +763,7 @@ static int stir_transmit_thread(void *ar
>  	{
>  #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
> @@ -771,7 +771,7 @@ static int stir_transmit_thread(void *ar
>  
>  			write_reg(stir, REG_CTRL1, CTRL1_TXPWD|CTRL1_RXPWD);
>  
> -			refrigerator(PF_FREEZE);
> +			refrigerator();
>  
>  			if (change_speed(stir, stir->speed))
>  				break;
> Index: linux-2.6.12/drivers/input/gameport/gameport.c
> ===================================================================
> --- linux-2.6.12.orig/drivers/input/gameport/gameport.c	2005-06-24 20:03:24.000000000 +0000
> +++ linux-2.6.12/drivers/input/gameport/gameport.c	2005-06-24 20:13:09.000000000 +0000
> @@ -439,7 +439,7 @@ static int gameport_thread(void *nothing
>  	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");
> Index: linux-2.6.12/drivers/usb/gadget/file_storage.c
> ===================================================================
> --- linux-2.6.12.orig/drivers/usb/gadget/file_storage.c	2005-06-24 20:03:24.000000000 +0000
> +++ linux-2.6.12/drivers/usb/gadget/file_storage.c	2005-06-24 20:12:46.000000000 +0000
> @@ -1554,8 +1554,7 @@ static int sleep_thread(struct fsg_dev *
>  	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);
>  }
>  
> Index: linux-2.6.12/drivers/pnp/pnpbios/core.c
> ===================================================================
> --- linux-2.6.12.orig/drivers/pnp/pnpbios/core.c	2005-06-17 19:48:29.000000000 +0000
> +++ linux-2.6.12/drivers/pnp/pnpbios/core.c	2005-06-24 20:12:24.000000000 +0000
> @@ -182,7 +182,7 @@ static int pnp_dock_thread(void * unused
>  		msleep_interruptible(2000);
>  
>  		if(signal_pending(current)) {
> -			if (try_to_freeze(PF_FREEZE))
> +			if (try_to_freeze())
>  				continue;
>  			break;
>  		}
> Index: linux-2.6.12/drivers/net/wireless/airo.c
> ===================================================================
> --- linux-2.6.12.orig/drivers/net/wireless/airo.c	2005-06-17 19:48:29.000000000 +0000
> +++ linux-2.6.12/drivers/net/wireless/airo.c	2005-06-24 20:12:06.000000000 +0000
> @@ -2918,7 +2918,7 @@ static int airo_thread(void *data) {
>  			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;
> Index: linux-2.6.12/drivers/macintosh/therm_adt746x.c
> ===================================================================
> --- linux-2.6.12.orig/drivers/macintosh/therm_adt746x.c	2005-06-24 20:03:24.000000000 +0000
> +++ linux-2.6.12/drivers/macintosh/therm_adt746x.c	2005-06-24 20:15:14.000000000 +0000
> @@ -328,9 +328,7 @@ static int monitor_task(void *arg)
>  	struct thermostat* th = arg;
>  
>  	while(!kthread_should_stop()) {
> -		if (current->flags & PF_FREEZE)
> -			refrigerator(PF_FREEZE);
> -
> +		try_to_freeze();
>  		msleep_interruptible(2000);
>  
>  #ifndef DEBUG
> Index: linux-2.6.12/drivers/net/irda/sir_kthread.c
> ===================================================================
> --- linux-2.6.12.orig/drivers/net/irda/sir_kthread.c	2005-06-17 19:48:29.000000000 +0000
> +++ linux-2.6.12/drivers/net/irda/sir_kthread.c	2005-06-24 20:11:51.000000000 +0000
> @@ -135,8 +135,7 @@ static int irda_thread(void *startup)
>  		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();
>  	}
> Index: linux-2.6.12/drivers/media/video/video-buf-dvb.c
> ===================================================================
> --- linux-2.6.12.orig/drivers/media/video/video-buf-dvb.c	2005-06-17 19:48:29.000000000 +0000
> +++ linux-2.6.12/drivers/media/video/video-buf-dvb.c	2005-06-24 20:14:26.000000000 +0000
> @@ -62,8 +62,7 @@ static int videobuf_dvb_thread(void *dat
>  			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)
> Index: linux-2.6.12/drivers/net/8139too.c
> ===================================================================
> --- linux-2.6.12.orig/drivers/net/8139too.c	2005-06-24 20:03:24.000000000 +0000
> +++ linux-2.6.12/drivers/net/8139too.c	2005-06-24 20:10:54.000000000 +0000
> @@ -1606,7 +1606,7 @@ static int rtl8139_thread (void *data)
>  		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)) {
> Index: linux-2.6.12/drivers/w1/w1.c
> ===================================================================
> --- linux-2.6.12.orig/drivers/w1/w1.c	2005-06-24 20:03:24.000000000 +0000
> +++ linux-2.6.12/drivers/w1/w1.c	2005-06-24 20:15:38.000000000 +0000
> @@ -646,7 +646,7 @@ static int w1_control(void *data)
>  	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))
> @@ -725,7 +725,7 @@ int w1_process(void *data)
>  	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))
> -
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at  http://www.tux.org/lkml/
-- 

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"aart@kvack.org"> aart@kvack.org </a>

^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: [RFC] Fix SMP brokenness for PF_FREEZE and make freezing usable for other purposes
  2005-06-24 20:20 [RFC] Fix SMP brokenness for PF_FREEZE and make freezing usable for other purposes Christoph Lameter
  2005-06-24 22:25 ` Nigel Cunningham
@ 2005-06-25  2:51 ` Pavel Machek
  2005-06-25  4:31   ` Christoph Lameter
                     ` (2 more replies)
  2005-06-25  7:35 ` Kirill Korotaev
  2 siblings, 3 replies; 35+ messages in thread
From: Pavel Machek @ 2005-06-25  2:51 UTC (permalink / raw)
  To: Christoph Lameter; +Cc: linux-mm, linux-kernel, raybry, torvalds

Hi!

> The process freezing used by software suspend currently relies on modifying
> current->flags from outside of the processes context. This makes freezing and
> unfreezing SMP unsafe since a process may change the flags at any time without
> locking. The following patch introduces a new atomic_t field in task_struct
> to allow SMP safe freezing and unfreezing.
> 
> It provides a simple API for process freezing:
> 
> 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
> 
> I only know that this boots correctly since I have no system that can do 
> suspend. But Ray needs an effective means of process suspension for 
> his process migration patches.

Any i386 or x86-64 machine can do suspend... It should be easy to get
some notebook... [What kind of hardware are you working on normally?]

> Some of the code may still need to be moved around from kernel/power/* to 
> kernel/*.
> 
> But is this the correct way to fix this?

It includes whitespace changes and most of patch is nice cleanup that
should probably go in separately. (Hint hint :-). 

Previous code had important property: try_to_freeze was optimized away
in !CONFIG_PM case. Please keep that.

Best way is to introduce macros and cleanup the code to use the
macros, without actually changing any object code. That can go in very
fast. Then we can switch to atomic_t ... yeah I think that's
neccessary, but I'd like cleanups first.
								Pavel
-- 
Boycott Kodak -- for their patent abuse against Java.
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"aart@kvack.org"> aart@kvack.org </a>

^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: [RFC] Fix SMP brokenness for PF_FREEZE and make freezing usable for other purposes
  2005-06-25  2:51 ` Pavel Machek
@ 2005-06-25  4:31   ` Christoph Lameter
  2005-06-25  4:46     ` Nigel Cunningham
  2005-06-25 22:37     ` Pavel Machek
  2005-06-25  6:13   ` Christoph Lameter
  2005-06-25  6:18   ` Christoph Lameter
  2 siblings, 2 replies; 35+ messages in thread
From: Christoph Lameter @ 2005-06-25  4:31 UTC (permalink / raw)
  To: Pavel Machek; +Cc: linux-mm, linux-kernel, raybry, torvalds

On Sat, 25 Jun 2005, Pavel Machek wrote:

> > I only know that this boots correctly since I have no system that can do 
> > suspend. But Ray needs an effective means of process suspension for 
> > his process migration patches.
> 
> Any i386 or x86-64 machine can do suspend... It should be easy to get
> some notebook... [What kind of hardware are you working on normally?]

Umm... Sorry to be so negative but that has never worked for me on lots of 
laptops. Usually something with ACPI or some driver I guess... After 
awhile I gave up trying.

> > But is this the correct way to fix this?
> It includes whitespace changes and most of patch is nice cleanup that
> should probably go in separately. (Hint hint :-). 

Ok.

> Previous code had important property: try_to_freeze was optimized away
> in !CONFIG_PM case. Please keep that.

Obviously that will not work if we use try_to_freeze for 
non-power-management purposes. The code from kernel/power/process.c may 
have to be merged into some other kernel file. kernel/sched.c?


--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"aart@kvack.org"> aart@kvack.org </a>

^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: [RFC] Fix SMP brokenness for PF_FREEZE and make freezing usable for other purposes
  2005-06-25  4:31   ` Christoph Lameter
@ 2005-06-25  4:46     ` Nigel Cunningham
  2005-06-25 22:37     ` Pavel Machek
  1 sibling, 0 replies; 35+ messages in thread
From: Nigel Cunningham @ 2005-06-25  4:46 UTC (permalink / raw)
  To: Christoph Lameter
  Cc: Pavel Machek, Linux Memory Management, Linux Kernel Mailing List,
	raybry, Linus Torvalds

Hi.

On Sat, 2005-06-25 at 14:31, Christoph Lameter wrote:
> > Previous code had important property: try_to_freeze was optimized away
> > in !CONFIG_PM case. Please keep that.
> 
> Obviously that will not work if we use try_to_freeze for 
> non-power-management purposes. The code from kernel/power/process.c may 
> have to be merged into some other kernel file. kernel/sched.c?

Do you have a non-power-management purpose in mind?

Regards,

Nigel

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"aart@kvack.org"> aart@kvack.org </a>

^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: [RFC] Fix SMP brokenness for PF_FREEZE and make freezing usable for other purposes
  2005-06-25  2:51 ` Pavel Machek
  2005-06-25  4:31   ` Christoph Lameter
@ 2005-06-25  6:13   ` Christoph Lameter
  2005-06-26  2:30     ` Pavel Machek
  2005-06-25  6:18   ` Christoph Lameter
  2 siblings, 1 reply; 35+ messages in thread
From: Christoph Lameter @ 2005-06-25  6:13 UTC (permalink / raw)
  To: Pavel Machek; +Cc: linux-mm, linux-kernel, raybry, torvalds

On Sat, 25 Jun 2005, Pavel Machek wrote:

> It includes whitespace changes and most of patch is nice cleanup that
> should probably go in separately. (Hint hint :-). 

> Previous code had important property: try_to_freeze was optimized away
> in !CONFIG_PM case. Please keep that.
> 
> Best way is to introduce macros and cleanup the code to use the
> macros, without actually changing any object code. That can go in very
> fast. Then we can switch to atomic_t ... yeah I think that's
> neccessary, but I'd like cleanups first.

Here is such a patch:

---
Cleanup patch for freezing against 2.6.12-git5.

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>

Index: linux-2.6.12/drivers/block/pktcdvd.c
===================================================================
--- linux-2.6.12.orig/drivers/block/pktcdvd.c	2005-06-25 05:01:26.000000000 +0000
+++ linux-2.6.12/drivers/block/pktcdvd.c	2005-06-25 05:01:28.000000000 +0000
@@ -1251,8 +1251,7 @@ static int kcdrwd(void *foobar)
 			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)
Index: linux-2.6.12/kernel/power/process.c
===================================================================
--- linux-2.6.12.orig/kernel/power/process.c	2005-06-25 05:01:26.000000000 +0000
+++ linux-2.6.12/kernel/power/process.c	2005-06-25 05:33:16.000000000 +0000
@@ -32,7 +32,7 @@ static inline int freezeable(struct task
 }
 
 /* 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? */
@@ -41,14 +41,13 @@ void refrigerator(unsigned long flag)
 	current->state = TASK_UNINTERRUPTIBLE;
 	pr_debug("%s entered refrigerator\n", current->comm);
 	printk("=");
-	current->flags &= ~PF_FREEZE;
 
+	frozen_process(current);
 	spin_lock_irq(&current->sighand->siglock);
 	recalc_sigpending(); /* We sent fake signal, clean it up */
 	spin_unlock_irq(&current->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;
@@ -57,10 +56,10 @@ void refrigerator(unsigned long flag)
 /* 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 {
@@ -70,14 +69,12 @@ int freeze_processes(void)
 			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);
@@ -91,7 +88,7 @@ int freeze_processes(void)
 			return todo;
 		}
 	} while(todo);
-	
+
 	printk( "|\n" );
 	BUG_ON(in_atomic());
 	return 0;
@@ -106,10 +103,7 @@ void thaw_processes(void)
 	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);
 
Index: linux-2.6.12/mm/vmscan.c
===================================================================
--- linux-2.6.12.orig/mm/vmscan.c	2005-06-25 05:01:26.000000000 +0000
+++ linux-2.6.12/mm/vmscan.c	2005-06-25 05:01:28.000000000 +0000
@@ -1216,8 +1216,8 @@ static int kswapd(void *p)
 	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;
Index: linux-2.6.12/kernel/signal.c
===================================================================
--- linux-2.6.12.orig/kernel/signal.c	2005-06-25 05:01:26.000000000 +0000
+++ linux-2.6.12/kernel/signal.c	2005-06-25 05:01:28.000000000 +0000
@@ -213,7 +213,7 @@ static inline int has_pending_signals(si
 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);
@@ -2231,8 +2231,7 @@ sys_rt_sigtimedwait(const sigset_t __use
 			current->state = TASK_INTERRUPTIBLE;
 			timeout = schedule_timeout(timeout);
 
-			if (current->flags & PF_FREEZE)
-				refrigerator(PF_FREEZE);
+			try_to_freeze();
 			spin_lock_irq(&current->sighand->siglock);
 			sig = dequeue_signal(current, &these, &info);
 			current->blocked = current->real_blocked;
Index: linux-2.6.12/mm/pdflush.c
===================================================================
--- linux-2.6.12.orig/mm/pdflush.c	2005-06-25 05:01:26.000000000 +0000
+++ linux-2.6.12/mm/pdflush.c	2005-06-25 05:01:28.000000000 +0000
@@ -105,7 +105,7 @@ static int __pdflush(struct pdflush_work
 		spin_unlock_irq(&pdflush_lock);
 
 		schedule();
-		if (try_to_freeze(PF_FREEZE)) {
+		if (try_to_freeze()) {
 			spin_lock_irq(&pdflush_lock);
 			continue;
 		}
Index: linux-2.6.12/kernel/sched.c
===================================================================
--- linux-2.6.12.orig/kernel/sched.c	2005-06-25 05:01:26.000000000 +0000
+++ linux-2.6.12/kernel/sched.c	2005-06-25 05:01:28.000000000 +0000
@@ -4174,8 +4174,7 @@ static int migration_thread(void * data)
 		struct list_head *head;
 		migration_req_t *req;
 
-		if (current->flags & PF_FREEZE)
-			refrigerator(PF_FREEZE);
+		try_to_freeze();
 
 		spin_lock_irq(&rq->lock);
 
Index: linux-2.6.12/drivers/pcmcia/cs.c
===================================================================
--- linux-2.6.12.orig/drivers/pcmcia/cs.c	2005-06-25 05:01:26.000000000 +0000
+++ linux-2.6.12/drivers/pcmcia/cs.c	2005-06-25 05:01:28.000000000 +0000
@@ -718,7 +718,7 @@ static int pccardd(void *__skt)
 		}
 
 		schedule();
-		try_to_freeze(PF_FREEZE);
+		try_to_freeze();
 
 		if (!skt->thread)
 			break;
Index: linux-2.6.12/drivers/usb/core/hub.c
===================================================================
--- linux-2.6.12.orig/drivers/usb/core/hub.c	2005-06-25 05:01:26.000000000 +0000
+++ linux-2.6.12/drivers/usb/core/hub.c	2005-06-25 05:01:28.000000000 +0000
@@ -2808,7 +2808,7 @@ static int hub_thread(void *__unused)
 	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);
Index: linux-2.6.12/drivers/input/serio/serio.c
===================================================================
--- linux-2.6.12.orig/drivers/input/serio/serio.c	2005-06-25 05:01:26.000000000 +0000
+++ linux-2.6.12/drivers/input/serio/serio.c	2005-06-25 05:01:28.000000000 +0000
@@ -344,7 +344,7 @@ static int serio_thread(void *nothing)
 	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");
Index: linux-2.6.12/fs/jbd/journal.c
===================================================================
--- linux-2.6.12.orig/fs/jbd/journal.c	2005-06-25 05:01:26.000000000 +0000
+++ linux-2.6.12/fs/jbd/journal.c	2005-06-25 05:01:28.000000000 +0000
@@ -167,7 +167,7 @@ loop:
 	}
 
 	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
@@ -175,7 +175,7 @@ loop:
 		 */
 		jbd_debug(1, "Now suspending kjournald\n");
 		spin_unlock(&journal->j_state_lock);
-		refrigerator(PF_FREEZE);
+		refrigerator();
 		spin_lock(&journal->j_state_lock);
 	} else {
 		/*
Index: linux-2.6.12/drivers/usb/storage/usb.c
===================================================================
--- linux-2.6.12.orig/drivers/usb/storage/usb.c	2005-06-25 05:01:26.000000000 +0000
+++ linux-2.6.12/drivers/usb/storage/usb.c	2005-06-25 05:01:28.000000000 +0000
@@ -847,10 +847,8 @@ retry:
 		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 */
Index: linux-2.6.12/drivers/ieee1394/ieee1394_core.c
===================================================================
--- linux-2.6.12.orig/drivers/ieee1394/ieee1394_core.c	2005-06-25 05:01:26.000000000 +0000
+++ linux-2.6.12/drivers/ieee1394/ieee1394_core.c	2005-06-25 05:01:28.000000000 +0000
@@ -1041,10 +1041,8 @@ static int hpsbpkt_thread(void *__hi)
 
 	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;
 		}
Index: linux-2.6.12/arch/i386/kernel/io_apic.c
===================================================================
--- linux-2.6.12.orig/arch/i386/kernel/io_apic.c	2005-06-25 05:01:26.000000000 +0000
+++ linux-2.6.12/arch/i386/kernel/io_apic.c	2005-06-25 05:01:28.000000000 +0000
@@ -573,7 +573,7 @@ static int balanced_irq(void *unused)
 	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();
Index: linux-2.6.12/net/sunrpc/svcsock.c
===================================================================
--- linux-2.6.12.orig/net/sunrpc/svcsock.c	2005-06-25 05:01:26.000000000 +0000
+++ linux-2.6.12/net/sunrpc/svcsock.c	2005-06-25 05:01:28.000000000 +0000
@@ -1185,8 +1185,8 @@ svc_recv(struct svc_serv *serv, struct s
 	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;
 
@@ -1227,7 +1227,7 @@ svc_recv(struct svc_serv *serv, struct s
 
 		schedule_timeout(timeout);
 
-		try_to_freeze(PF_FREEZE);
+		try_to_freeze();
 
 		spin_lock_bh(&serv->sv_lock);
 		remove_wait_queue(&rqstp->rq_wait, &wait);
Index: linux-2.6.12/drivers/ieee1394/nodemgr.c
===================================================================
--- linux-2.6.12.orig/drivers/ieee1394/nodemgr.c	2005-06-25 05:01:26.000000000 +0000
+++ linux-2.6.12/drivers/ieee1394/nodemgr.c	2005-06-25 05:01:28.000000000 +0000
@@ -1510,7 +1510,7 @@ static int nodemgr_host_thread(void *__h
 
 		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;
Index: linux-2.6.12/drivers/md/md.c
===================================================================
--- linux-2.6.12.orig/drivers/md/md.c	2005-06-25 05:01:26.000000000 +0000
+++ linux-2.6.12/drivers/md/md.c	2005-06-25 05:01:28.000000000 +0000
@@ -2976,8 +2976,7 @@ static int md_thread(void * arg)
 		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);
 
Index: linux-2.6.12/fs/jfs/jfs_logmgr.c
===================================================================
--- linux-2.6.12.orig/fs/jfs/jfs_logmgr.c	2005-06-25 05:01:26.000000000 +0000
+++ linux-2.6.12/fs/jfs/jfs_logmgr.c	2005-06-25 05:01:28.000000000 +0000
@@ -2359,9 +2359,9 @@ int jfsIOWait(void *arg)
 			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);
Index: linux-2.6.12/fs/jfs/jfs_txnmgr.c
===================================================================
--- linux-2.6.12.orig/fs/jfs/jfs_txnmgr.c	2005-06-25 05:01:26.000000000 +0000
+++ linux-2.6.12/fs/jfs/jfs_txnmgr.c	2005-06-25 05:01:28.000000000 +0000
@@ -2788,9 +2788,9 @@ int jfs_lazycommit(void *arg)
 		/* 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);
 
@@ -2987,9 +2987,9 @@ int jfs_sync(void *arg)
 		/* 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);
 
Index: linux-2.6.12/arch/i386/kernel/signal.c
===================================================================
--- linux-2.6.12.orig/arch/i386/kernel/signal.c	2005-06-25 05:01:26.000000000 +0000
+++ linux-2.6.12/arch/i386/kernel/signal.c	2005-06-25 05:01:28.000000000 +0000
@@ -608,10 +608,8 @@ int fastcall do_signal(struct pt_regs *r
 	if (!user_mode(regs))
 		return 1;
 
-	if (current->flags & PF_FREEZE) {
-		refrigerator(0);
+	if (try_to_freeze)
 		goto no_signal;
-	}
 
 	if (!oldset)
 		oldset = &current->blocked;
Index: linux-2.6.12/fs/lockd/clntproc.c
===================================================================
--- linux-2.6.12.orig/fs/lockd/clntproc.c	2005-06-25 05:01:26.000000000 +0000
+++ linux-2.6.12/fs/lockd/clntproc.c	2005-06-25 05:01:28.000000000 +0000
@@ -313,7 +313,7 @@ static int nlm_wait_on_grace(wait_queue_
 	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;
 	}
Index: linux-2.6.12/fs/xfs/linux-2.6/xfs_buf.c
===================================================================
--- linux-2.6.12.orig/fs/xfs/linux-2.6/xfs_buf.c	2005-06-25 05:01:26.000000000 +0000
+++ linux-2.6.12/fs/xfs/linux-2.6/xfs_buf.c	2005-06-25 05:01:28.000000000 +0000
@@ -1771,9 +1771,9 @@ xfsbufd(
 
 	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;
 		}
Index: linux-2.6.12/arch/x86_64/kernel/signal.c
===================================================================
--- linux-2.6.12.orig/arch/x86_64/kernel/signal.c	2005-06-25 05:01:26.000000000 +0000
+++ linux-2.6.12/arch/x86_64/kernel/signal.c	2005-06-25 05:01:28.000000000 +0000
@@ -425,7 +425,7 @@ int do_signal(struct pt_regs *regs, sigs
 	if (!user_mode(regs))
 		return 1;
 
-	if (try_to_freeze(0))
+	if (try_to_freeze())
 		goto no_signal;
 
 	if (!oldset)
Index: linux-2.6.12/fs/xfs/linux-2.6/xfs_super.c
===================================================================
--- linux-2.6.12.orig/fs/xfs/linux-2.6/xfs_super.c	2005-06-25 05:01:26.000000000 +0000
+++ linux-2.6.12/fs/xfs/linux-2.6/xfs_super.c	2005-06-25 05:01:28.000000000 +0000
@@ -483,7 +483,7 @@ xfssyncd(
 		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;
 
Index: linux-2.6.12/arch/ppc/kernel/signal.c
===================================================================
--- linux-2.6.12.orig/arch/ppc/kernel/signal.c	2005-06-25 05:01:26.000000000 +0000
+++ linux-2.6.12/arch/ppc/kernel/signal.c	2005-06-25 05:01:28.000000000 +0000
@@ -705,8 +705,7 @@ int do_signal(sigset_t *oldset, struct p
 	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;
Index: linux-2.6.12/Documentation/power/kernel_threads.txt
===================================================================
--- linux-2.6.12.orig/Documentation/power/kernel_threads.txt	2005-06-25 05:01:26.000000000 +0000
+++ linux-2.6.12/Documentation/power/kernel_threads.txt	2005-06-25 05:01:28.000000000 +0000
@@ -12,8 +12,7 @@ refrigerator. Code to do this looks like
 	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()
Index: linux-2.6.12/arch/h8300/kernel/signal.c
===================================================================
--- linux-2.6.12.orig/arch/h8300/kernel/signal.c	2005-06-25 05:01:26.000000000 +0000
+++ linux-2.6.12/arch/h8300/kernel/signal.c	2005-06-25 05:01:28.000000000 +0000
@@ -517,10 +517,8 @@ asmlinkage int do_signal(struct pt_regs 
 	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;
 
Index: linux-2.6.12/arch/m32r/kernel/signal.c
===================================================================
--- linux-2.6.12.orig/arch/m32r/kernel/signal.c	2005-06-25 05:01:26.000000000 +0000
+++ linux-2.6.12/arch/m32r/kernel/signal.c	2005-06-25 05:01:28.000000000 +0000
@@ -371,10 +371,8 @@ int do_signal(struct pt_regs *regs, sigs
 	if (!user_mode(regs))
 		return 1;
 
-	if (current->flags & PF_FREEZE) {
-		refrigerator(0);
+	if (try_to_freeze()) 
 		goto no_signal;
-	}
 
 	if (!oldset)
 		oldset = &current->blocked;
Index: linux-2.6.12/fs/afs/kafsasyncd.c
===================================================================
--- linux-2.6.12.orig/fs/afs/kafsasyncd.c	2005-06-25 05:01:26.000000000 +0000
+++ linux-2.6.12/fs/afs/kafsasyncd.c	2005-06-25 05:01:28.000000000 +0000
@@ -116,7 +116,7 @@ static int kafsasyncd(void *arg)
 		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();
Index: linux-2.6.12/fs/afs/kafstimod.c
===================================================================
--- linux-2.6.12.orig/fs/afs/kafstimod.c	2005-06-25 05:01:26.000000000 +0000
+++ linux-2.6.12/fs/afs/kafstimod.c	2005-06-25 05:01:28.000000000 +0000
@@ -91,7 +91,7 @@ static int kafstimod(void *arg)
 			complete_and_exit(&kafstimod_dead, 0);
 		}
 
-		try_to_freeze(PF_FREEZE);
+		try_to_freeze();
 
 		/* discard pending signals */
 		afs_discard_my_signals();
Index: linux-2.6.12/Documentation/power/swsusp.txt
===================================================================
--- linux-2.6.12.orig/Documentation/power/swsusp.txt	2005-06-25 05:01:26.000000000 +0000
+++ linux-2.6.12/Documentation/power/swsusp.txt	2005-06-25 05:01:28.000000000 +0000
@@ -164,8 +164,7 @@ place where the thread is safe to be fro
 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.
Index: linux-2.6.12/arch/frv/kernel/signal.c
===================================================================
--- linux-2.6.12.orig/arch/frv/kernel/signal.c	2005-06-25 05:01:26.000000000 +0000
+++ linux-2.6.12/arch/frv/kernel/signal.c	2005-06-25 05:01:28.000000000 +0000
@@ -536,10 +536,8 @@ int do_signal(struct pt_regs *regs, sigs
 	if (!user_mode(regs))
 		return 1;
 
-	if (current->flags & PF_FREEZE) {
-		refrigerator(0);
+	if (try_to_freeze())
 		goto no_signal;
-	}
 
 	if (!oldset)
 		oldset = &current->blocked;
Index: linux-2.6.12/net/rxrpc/krxtimod.c
===================================================================
--- linux-2.6.12.orig/net/rxrpc/krxtimod.c	2005-06-25 05:01:26.000000000 +0000
+++ linux-2.6.12/net/rxrpc/krxtimod.c	2005-06-25 05:01:28.000000000 +0000
@@ -90,7 +90,7 @@ static int krxtimod(void *arg)
 			complete_and_exit(&krxtimod_dead, 0);
 		}
 
-		try_to_freeze(PF_FREEZE);
+		try_to_freeze();
 
 		/* discard pending signals */
 		rxrpc_discard_my_signals();
Index: linux-2.6.12/net/rxrpc/krxiod.c
===================================================================
--- linux-2.6.12.orig/net/rxrpc/krxiod.c	2005-06-25 05:01:26.000000000 +0000
+++ linux-2.6.12/net/rxrpc/krxiod.c	2005-06-25 05:01:28.000000000 +0000
@@ -138,7 +138,7 @@ static int rxrpc_krxiod(void *arg)
 
 		_debug("### End Work");
 
-		try_to_freeze(PF_FREEZE);
+		try_to_freeze();
 
                 /* discard pending signals */
 		rxrpc_discard_my_signals();
Index: linux-2.6.12/net/rxrpc/krxsecd.c
===================================================================
--- linux-2.6.12.orig/net/rxrpc/krxsecd.c	2005-06-25 05:01:26.000000000 +0000
+++ linux-2.6.12/net/rxrpc/krxsecd.c	2005-06-25 05:01:28.000000000 +0000
@@ -107,7 +107,7 @@ static int rxrpc_krxsecd(void *arg)
 
 		_debug("### End Inbound Calls");
 
-		try_to_freeze(PF_FREEZE);
+		try_to_freeze();
 
                 /* discard pending signals */
 		rxrpc_discard_my_signals();
Index: linux-2.6.12/drivers/media/dvb/dvb-core/dvb_frontend.c
===================================================================
--- linux-2.6.12.orig/drivers/media/dvb/dvb-core/dvb_frontend.c	2005-06-25 05:01:26.000000000 +0000
+++ linux-2.6.12/drivers/media/dvb/dvb-core/dvb_frontend.c	2005-06-25 05:01:28.000000000 +0000
@@ -391,8 +391,7 @@ static int dvb_frontend_thread(void *dat
 			break;
 		}
 
-		if (current->flags & PF_FREEZE)
-			refrigerator(PF_FREEZE);
+		try_to_freeze();
 
 		if (down_interruptible(&fepriv->sem))
 			break;
Index: linux-2.6.12/drivers/media/video/msp3400.c
===================================================================
--- linux-2.6.12.orig/drivers/media/video/msp3400.c	2005-06-25 05:01:26.000000000 +0000
+++ linux-2.6.12/drivers/media/video/msp3400.c	2005-06-25 05:01:28.000000000 +0000
@@ -750,8 +750,7 @@ static int msp34xx_sleep(struct msp3400c
 #endif
 		}
 	}
-	if (current->flags & PF_FREEZE)
-		refrigerator(PF_FREEZE);
+	try_to_freeze();
 	remove_wait_queue(&msp->wq, &wait);
 	return msp->restart;
 }
Index: linux-2.6.12/drivers/net/irda/stir4200.c
===================================================================
--- linux-2.6.12.orig/drivers/net/irda/stir4200.c	2005-06-25 05:01:26.000000000 +0000
+++ linux-2.6.12/drivers/net/irda/stir4200.c	2005-06-25 05:01:28.000000000 +0000
@@ -763,7 +763,7 @@ static int stir_transmit_thread(void *ar
 	{
 #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
@@ -771,7 +771,7 @@ static int stir_transmit_thread(void *ar
 
 			write_reg(stir, REG_CTRL1, CTRL1_TXPWD|CTRL1_RXPWD);
 
-			refrigerator(PF_FREEZE);
+			refrigerator();
 
 			if (change_speed(stir, stir->speed))
 				break;
Index: linux-2.6.12/drivers/input/gameport/gameport.c
===================================================================
--- linux-2.6.12.orig/drivers/input/gameport/gameport.c	2005-06-25 05:01:26.000000000 +0000
+++ linux-2.6.12/drivers/input/gameport/gameport.c	2005-06-25 05:01:28.000000000 +0000
@@ -439,7 +439,7 @@ static int gameport_thread(void *nothing
 	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");
Index: linux-2.6.12/drivers/usb/gadget/file_storage.c
===================================================================
--- linux-2.6.12.orig/drivers/usb/gadget/file_storage.c	2005-06-25 05:01:26.000000000 +0000
+++ linux-2.6.12/drivers/usb/gadget/file_storage.c	2005-06-25 05:01:28.000000000 +0000
@@ -1554,8 +1554,7 @@ static int sleep_thread(struct fsg_dev *
 	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);
 }
 
Index: linux-2.6.12/drivers/pnp/pnpbios/core.c
===================================================================
--- linux-2.6.12.orig/drivers/pnp/pnpbios/core.c	2005-06-25 05:01:26.000000000 +0000
+++ linux-2.6.12/drivers/pnp/pnpbios/core.c	2005-06-25 05:01:28.000000000 +0000
@@ -182,7 +182,7 @@ static int pnp_dock_thread(void * unused
 		msleep_interruptible(2000);
 
 		if(signal_pending(current)) {
-			if (try_to_freeze(PF_FREEZE))
+			if (try_to_freeze())
 				continue;
 			break;
 		}
Index: linux-2.6.12/drivers/net/wireless/airo.c
===================================================================
--- linux-2.6.12.orig/drivers/net/wireless/airo.c	2005-06-25 05:01:26.000000000 +0000
+++ linux-2.6.12/drivers/net/wireless/airo.c	2005-06-25 05:01:28.000000000 +0000
@@ -2918,7 +2918,7 @@ static int airo_thread(void *data) {
 			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;
Index: linux-2.6.12/drivers/macintosh/therm_adt746x.c
===================================================================
--- linux-2.6.12.orig/drivers/macintosh/therm_adt746x.c	2005-06-25 05:01:26.000000000 +0000
+++ linux-2.6.12/drivers/macintosh/therm_adt746x.c	2005-06-25 05:01:28.000000000 +0000
@@ -328,9 +328,7 @@ static int monitor_task(void *arg)
 	struct thermostat* th = arg;
 
 	while(!kthread_should_stop()) {
-		if (current->flags & PF_FREEZE)
-			refrigerator(PF_FREEZE);
-
+		try_to_freeze();
 		msleep_interruptible(2000);
 
 #ifndef DEBUG
Index: linux-2.6.12/drivers/net/irda/sir_kthread.c
===================================================================
--- linux-2.6.12.orig/drivers/net/irda/sir_kthread.c	2005-06-25 05:01:26.000000000 +0000
+++ linux-2.6.12/drivers/net/irda/sir_kthread.c	2005-06-25 05:01:28.000000000 +0000
@@ -135,8 +135,7 @@ static int irda_thread(void *startup)
 		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();
 	}
Index: linux-2.6.12/drivers/media/video/video-buf-dvb.c
===================================================================
--- linux-2.6.12.orig/drivers/media/video/video-buf-dvb.c	2005-06-25 05:01:26.000000000 +0000
+++ linux-2.6.12/drivers/media/video/video-buf-dvb.c	2005-06-25 05:01:28.000000000 +0000
@@ -62,8 +62,7 @@ static int videobuf_dvb_thread(void *dat
 			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)
Index: linux-2.6.12/drivers/net/8139too.c
===================================================================
--- linux-2.6.12.orig/drivers/net/8139too.c	2005-06-25 05:01:26.000000000 +0000
+++ linux-2.6.12/drivers/net/8139too.c	2005-06-25 05:01:28.000000000 +0000
@@ -1606,7 +1606,7 @@ static int rtl8139_thread (void *data)
 		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)) {
Index: linux-2.6.12/drivers/w1/w1.c
===================================================================
--- linux-2.6.12.orig/drivers/w1/w1.c	2005-06-25 05:01:26.000000000 +0000
+++ linux-2.6.12/drivers/w1/w1.c	2005-06-25 05:01:28.000000000 +0000
@@ -646,7 +646,7 @@ static int w1_control(void *data)
 	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))
@@ -725,7 +725,7 @@ int w1_process(void *data)
 	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))
Index: linux-2.6.12/include/linux/sched.h
===================================================================
--- linux-2.6.12.orig/include/linux/sched.h	2005-06-25 05:01:26.000000000 +0000
+++ linux-2.6.12/include/linux/sched.h	2005-06-25 05:41:28.000000000 +0000
@@ -1245,33 +1245,78 @@ extern void normalize_rt_tasks(void);
 
 #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__ */
 
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"aart@kvack.org"> aart@kvack.org </a>

^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: [RFC] Fix SMP brokenness for PF_FREEZE and make freezing usable for other purposes
  2005-06-25  2:51 ` Pavel Machek
  2005-06-25  4:31   ` Christoph Lameter
  2005-06-25  6:13   ` Christoph Lameter
@ 2005-06-25  6:18   ` Christoph Lameter
  2 siblings, 0 replies; 35+ messages in thread
From: Christoph Lameter @ 2005-06-25  6:18 UTC (permalink / raw)
  To: Pavel Machek; +Cc: linux-mm, linux-kernel, raybry, torvalds

And the patch to deal with the SMP issue:

---

Fix SMP brokenness for PF_FREEZE and make freezing usable for other purposes

The process freezing used by software suspend currently relies on modifying
current->flags from outside of the processes context. This makes freezing and
unfreezing SMP unsafe since a process may change the flags at any time without
locking. The following patch introduces a new atomic_t field in task_struct
to allow SMP safe freezing and unfreezing.

Signed-off-by: Christoph Lameter <christoph@lameter.com>

Index: linux-2.6.12/include/linux/sched.h
===================================================================
--- linux-2.6.12.orig/include/linux/sched.h	2005-06-25 05:41:28.000000000 +0000
+++ linux-2.6.12/include/linux/sched.h	2005-06-25 06:03:30.000000000 +0000
@@ -720,6 +720,8 @@ struct task_struct {
 
 	unsigned long ptrace_message;
 	siginfo_t *last_siginfo; /* For ptrace use.  */
+
+	atomic_t freeze;	/* For freezing a process. 0 = running, if >0 freezing request pending, if < 0 frozen */
 /*
  * current io wait handle: wait queue entry to use for io waits
  * If this thread is processing aio, this points at the waitqueue
@@ -784,9 +786,7 @@ do { if (atomic_dec_and_test(&(tsk)->usa
 #define PF_MEMALLOC	0x00000800	/* Allocating memory */
 #define PF_FLUSHER	0x00001000	/* responsible for disk writeback */
 #define PF_USED_MATH	0x00002000	/* if unset the fpu must be initialized before use */
-#define PF_FREEZE	0x00004000	/* this task is being frozen for suspend now */
 #define PF_NOFREEZE	0x00008000	/* this thread should not be frozen */
-#define PF_FROZEN	0x00010000	/* frozen for system suspend */
 #define PF_FSTRANS	0x00020000	/* inside a filesystem transaction */
 #define PF_KSWAPD	0x00040000	/* I am kswapd */
 #define PF_SWAPOFF	0x00080000	/* I am in swapoff */
@@ -1245,13 +1245,12 @@ extern void normalize_rt_tasks(void);
 
 #endif
 
-#ifdef CONFIG_PM
 /*
  * Check if a process has been frozen
  */
 static inline int frozen(struct task_struct *p)
 {
-	return p->flags & PF_FROZEN;
+	return atomic_read(&p->freeze) < 0;
 }
 
 /*
@@ -1259,16 +1258,15 @@ static inline int frozen(struct task_str
  */
 static inline int freezing(struct task_struct *p)
 {
-	return p->flags & PF_FREEZE;
+	return atomic_read(&p->freeze) > 0;
 }
 
 /*
  * 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;
+	atomic_inc(&p->freeze);
 }
 
 /*
@@ -1277,21 +1275,13 @@ static inline void freeze(struct task_st
 static inline int thaw_process(struct task_struct *p)
 {
 	if (frozen(p)) {
-		p->flags &= ~PF_FROZEN;
+		atomic_set(&p->freeze, 0);
 		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);
@@ -1304,20 +1294,6 @@ static inline int try_to_freeze(void)
 	} else
 		return 0;
 }
-#else
-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(void) { return 0; }
-
-#endif /* CONFIG_PM */
 #endif /* __KERNEL__ */
 
 #endif
Index: linux-2.6.12/kernel/power/process.c
===================================================================
--- linux-2.6.12.orig/kernel/power/process.c	2005-06-25 05:33:16.000000000 +0000
+++ linux-2.6.12/kernel/power/process.c	2005-06-25 05:57:34.000000000 +0000
@@ -31,28 +31,6 @@ static inline int freezeable(struct task
 	return 1;
 }
 
-/* Refrigerator is place where frozen processes are stored :-). */
-void refrigerator(void)
-{
-	/* Hmm, should we be allowed to suspend when there are realtime
-	   processes around? */
-	long save;
-	save = current->state;
-	current->state = TASK_UNINTERRUPTIBLE;
-	pr_debug("%s entered refrigerator\n", current->comm);
-	printk("=");
-
-	frozen_process(current);
-	spin_lock_irq(&current->sighand->siglock);
-	recalc_sigpending(); /* We sent fake signal, clean it up */
-	spin_unlock_irq(&current->sighand->siglock);
-
-	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)
 {
Index: linux-2.6.12/kernel/sched.c
===================================================================
--- linux-2.6.12.orig/kernel/sched.c	2005-06-25 05:01:28.000000000 +0000
+++ linux-2.6.12/kernel/sched.c	2005-06-25 06:04:03.000000000 +0000
@@ -4988,6 +4988,35 @@ void __might_sleep(char *file, int line)
 EXPORT_SYMBOL(__might_sleep);
 #endif
 
+/*
+ * The refrigerator is called by a process if a request has been made
+ * to the process by freeze()
+ */
+void refrigerator(void)
+{
+	/* Hmm, should we be allowed to suspend when there are realtime
+	   processes around? */
+	long save;
+	save = current->state;
+	current->state = TASK_UNINTERRUPTIBLE;
+
+	/* Use large negative value to be able to tolerate
+	 * additional freeze requests that may be issued
+	 * while moving into the refrigerator.
+	 * We have no way of locking for the freeze
+	 * field.
+	 */
+	atomic_set(&current->freeze, - (1 << 30));
+
+	spin_lock_irq(&current->sighand->siglock);
+	recalc_sigpending(); /* We may have sent a fake signal, clean it up */
+	spin_unlock_irq(&current->sighand->siglock);
+
+	while (frozen(current))
+		schedule();
+	current->state = save;
+}
+
 #ifdef CONFIG_MAGIC_SYSRQ
 void normalize_rt_tasks(void)
 {
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"aart@kvack.org"> aart@kvack.org </a>

^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: [RFC] Fix SMP brokenness for PF_FREEZE and make freezing usable for other purposes
  2005-06-24 20:20 [RFC] Fix SMP brokenness for PF_FREEZE and make freezing usable for other purposes Christoph Lameter
  2005-06-24 22:25 ` Nigel Cunningham
  2005-06-25  2:51 ` Pavel Machek
@ 2005-06-25  7:35 ` Kirill Korotaev
  2005-06-27  7:06   ` Ray Bryant
  2 siblings, 1 reply; 35+ messages in thread
From: Kirill Korotaev @ 2005-06-25  7:35 UTC (permalink / raw)
  To: Christoph Lameter; +Cc: linux-mm, linux-kernel, raybry, pavel, torvalds

CL> The process freezing used by software suspend currently relies on modifying
current->>flags from outside of the processes context. This makes freezing and
CL> unfreezing SMP unsafe since a process may change the flags at any time without
CL> locking. The following patch introduces a new atomic_t field in task_struct
CL> to allow SMP safe freezing and unfreezing.

CL> It provides a simple API for process freezing:

CL> frozen(process)             Check for frozen process
CL> freezing(process)   Check if a process is being frozen
CL> freeze(process)             Tell a process to freeze (go to refrigerator)
CL> thaw_process(process)       Restart process

CL> I only know that this boots correctly since I have no system that can do
CL> suspend. But Ray needs an effective means of process suspension for
CL> his process migration patches.
Just out of curiosity what patches are you talking about?
Is it possible to take a glance at it if it is what I think of?

comments below...

[skip]
CL>  /* Refrigerator is place where frozen processes are stored :-). */
CL> -void refrigerator(unsigned long flag)
CL> +void refrigerator(void)
CL>  {
CL>  	/* Hmm, should we be allowed to suspend when there are realtime
CL>  	   processes around? */
CL> @@ -40,15 +40,13 @@ void refrigerator(unsigned long flag)
CL>  	save = current->state;
CL>  	current->state = TASK_UNINTERRUPTIBLE;
CL>  	pr_debug("%s entered refrigerator\n", current->comm);
CL> -	printk("=");
-	current->>flags &= ~PF_FREEZE;
 
CL>  	spin_lock_irq(&current->sighand->siglock);
CL>  	recalc_sigpending(); /* We sent fake signal, clean it up */
CL>  	spin_unlock_irq(&current->sighand->siglock);
 
-	current->>flags |= PF_FROZEN;
-	while (current->>flags & PF_FROZEN)
CL> +	atomic_set(&current->freeze_status, FROZEN);
<<<< this looks unsafe... what if thaw_process() was called exactly
before this atomic_set()? then you won't wake up anymore...
CL> +	while (frozen(current))
CL>  		schedule();
CL>  	pr_debug("%s left refrigerator\n", current->comm);
CL>  	current->state = save;
CL> @@ -57,10 +55,10 @@ void refrigerator(unsigned long flag)
CL>  /* 0 = success, else # of processes that we failed to stop */
CL>  int freeze_processes(void)
CL>  {
CL> -       int todo;
CL> -       unsigned long start_time;
CL> +	int todo;
CL> +	unsigned long start_time;
CL>  	struct task_struct *g, *p;
CL> -	
CL> +
CL>  	printk( "Stopping tasks: " );
CL>  	start_time = jiffies;
CL>  	do {
CL> @@ -70,14 +68,12 @@ int freeze_processes(void)
CL>  			unsigned long flags;
CL>  			if (!freezeable(p))
CL>  				continue;
-			if ((p->>flags & PF_FROZEN) ||
CL> +			if ((frozen(p)) ||
<<<< this looks unsafe also... i think you have to check freezing()
instead of frozen(). otherwise you will be constantly incrementing
freezing counter and it can potentially overflow... Though this is
unlikely I see no reason to call freeze() if we are freezing
already... But we can call signal_wake_up() to speed up the process...
CL>  			    (p->state == TASK_TRACED) ||
CL>  			    (p->state == TASK_STOPPED))
CL>  				continue;
 
CL> -			/* FIXME: smp problem here: we may not access other process' flags
CL> -			   without locking */
-			p->>flags |= PF_FREEZE;
CL> +			freeze(p);
CL>  			spin_lock_irqsave(&p->sighand->siglock, flags);
CL>  			signal_wake_up(p, 0);
CL>  			spin_unlock_irqrestore(&p->sighand->siglock, flags);
CL> @@ -91,7 +87,7 @@ int freeze_processes(void)
CL>  			return todo;
CL>  		}
CL>  	} while(todo);
CL> -	
CL> +
CL>  	printk( "|\n" );
CL>  	BUG_ON(in_atomic());
CL>  	return 0;
CL> @@ -106,10 +102,7 @@ void thaw_processes(void)
CL>  	do_each_thread(g, p) {
CL>  		if (!freezeable(p))
CL>  			continue;
-		if (p->>flags & PF_FROZEN) {
-			p->>flags &= ~PF_FROZEN;
CL> -			wake_up_process(p);
CL> -		} else
CL> +		if (!thaw_process(p))
CL>  			printk(KERN_INFO " Strange, %s not stopped\n", p->comm );
CL>  	} while_each_thread(g, p);
 
[skip]

CL> Index: linux-2.6.12/arch/i386/kernel/signal.c
CL> ===================================================================
CL> --- linux-2.6.12.orig/arch/i386/kernel/signal.c	2005-06-24 20:03:23.000000000 +0000
CL> +++ linux-2.6.12/arch/i386/kernel/signal.c	2005-06-24 20:03:25.000000000 +0000
CL> @@ -608,10 +608,8 @@ int fastcall do_signal(struct pt_regs *r
CL>  	if (!user_mode(regs))
CL>  		return 1;
 
-	if (current->>flags & PF_FREEZE) {
CL> -		refrigerator(0);
CL> +	if (try_to_freeze)
<<<< missed ()?
CL>  		goto no_signal;

Kirill
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"aart@kvack.org"> aart@kvack.org </a>

^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: [RFC] Fix SMP brokenness for PF_FREEZE and make freezing usable for other purposes
  2005-06-25  4:31   ` Christoph Lameter
  2005-06-25  4:46     ` Nigel Cunningham
@ 2005-06-25 22:37     ` Pavel Machek
  1 sibling, 0 replies; 35+ messages in thread
From: Pavel Machek @ 2005-06-25 22:37 UTC (permalink / raw)
  To: Christoph Lameter; +Cc: linux-mm, linux-kernel, raybry, torvalds

Hi!
> > > I only know that this boots correctly since I have no system that can do 
> > > suspend. But Ray needs an effective means of process suspension for 
> > > his process migration patches.
> > 
> > Any i386 or x86-64 machine can do suspend... It should be easy to get
> > some notebook... [What kind of hardware are you working on normally?]
> 
> Umm... Sorry to be so negative but that has never worked for me on lots of 
> laptops. Usually something with ACPI or some driver I guess... After 
> awhile I gave up trying.

You should be able to do acpi=off if it gives you a problem. Going
with minimal drivers help, too...

> > Previous code had important property: try_to_freeze was optimized away
> > in !CONFIG_PM case. Please keep that.
> 
> Obviously that will not work if we use try_to_freeze for 
> non-power-management purposes. The code from kernel/power/process.c may 
> have to be merged into some other kernel file. kernel/sched.c?

You want to use it for process migration, right? Not everyone wants
either software or process migration... We may want to keep overhead
low for embedded systems...

								Pavel 

-- 
Boycott Kodak -- for their patent abuse against Java.
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"aart@kvack.org"> aart@kvack.org </a>

^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: [RFC] Fix SMP brokenness for PF_FREEZE and make freezing usable for other purposes
  2005-06-25  6:13   ` Christoph Lameter
@ 2005-06-26  2:30     ` Pavel Machek
  2005-06-26  2:55       ` Christoph Lameter
  2005-06-26 10:54       ` Nigel Cunningham
  0 siblings, 2 replies; 35+ messages in thread
From: Pavel Machek @ 2005-06-26  2:30 UTC (permalink / raw)
  To: Christoph Lameter; +Cc: linux-mm, linux-kernel, raybry, torvalds

Hi!

> > It includes whitespace changes and most of patch is nice cleanup that
> > should probably go in separately. (Hint hint :-). 
> 
> > Previous code had important property: try_to_freeze was optimized away
> > in !CONFIG_PM case. Please keep that.
> > 
> > Best way is to introduce macros and cleanup the code to use the
> > macros, without actually changing any object code. That can go in very
> > fast. Then we can switch to atomic_t ... yeah I think that's
> > neccessary, but I'd like cleanups first.
> 
> Here is such a patch:
> 
> ---
> Cleanup patch for freezing against 2.6.12-git5.
> 
> 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.

Can you just keep the argument? Rename it to int unused or whatever,
but if you do it, it stays backwards-compatible (and smaller patch,
too).

> 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>

Looks mostly good but:

> Index: linux-2.6.12/arch/i386/kernel/signal.c
> ===================================================================
> --- linux-2.6.12.orig/arch/i386/kernel/signal.c	2005-06-25 05:01:26.000000000 +0000
> +++ linux-2.6.12/arch/i386/kernel/signal.c	2005-06-25 05:01:28.000000000 +0000
> @@ -608,10 +608,8 @@ int fastcall do_signal(struct pt_regs *r
>  	if (!user_mode(regs))
>  		return 1;
>  
> -	if (current->flags & PF_FREEZE) {
> -		refrigerator(0);
> +	if (try_to_freeze)
>  		goto no_signal;
> -	}
>  

This is not good. Missing ().

							Pavel
-- 
Boycott Kodak -- for their patent abuse against Java.
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"aart@kvack.org"> aart@kvack.org </a>

^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: [RFC] Fix SMP brokenness for PF_FREEZE and make freezing usable for other purposes
  2005-06-26  2:30     ` Pavel Machek
@ 2005-06-26  2:55       ` Christoph Lameter
  2005-06-26  3:09         ` Pavel Machek
  2005-06-26 10:54       ` Nigel Cunningham
  1 sibling, 1 reply; 35+ messages in thread
From: Christoph Lameter @ 2005-06-26  2:55 UTC (permalink / raw)
  To: Pavel Machek; +Cc: linux-mm, linux-kernel, raybry, torvalds

On Sun, 26 Jun 2005, Pavel Machek wrote:

> > 4. Remove the argument that is no longer necessary from two function
> > calls.
> 
> Can you just keep the argument? Rename it to int unused or whatever,
> but if you do it, it stays backwards-compatible (and smaller patch,
> too).

Why do you want to specify a parameter that is never used? It was quite confusing to me 
and I would think that such a parameter will also be confusing to others.
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"aart@kvack.org"> aart@kvack.org </a>

^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: [RFC] Fix SMP brokenness for PF_FREEZE and make freezing usable for other purposes
  2005-06-26  2:55       ` Christoph Lameter
@ 2005-06-26  3:09         ` Pavel Machek
  2005-06-27  3:51           ` Christoph Lameter
  0 siblings, 1 reply; 35+ messages in thread
From: Pavel Machek @ 2005-06-26  3:09 UTC (permalink / raw)
  To: Christoph Lameter; +Cc: linux-mm, linux-kernel, raybry, torvalds

Hi!

> > > 4. Remove the argument that is no longer necessary from two function
> > > calls.
> > 
> > Can you just keep the argument? Rename it to int unused or whatever,
> > but if you do it, it stays backwards-compatible (and smaller patch,
> > too).
> 
> Why do you want to specify a parameter that is never used? It was quite confusing to me 
> and I would think that such a parameter will also be confusing to others.

Well, yes, it is slightly confusing, but such patch can go in through
different maintainers, and different pieces can come in at different
times.

If you delete an argument, it is "flag day", and I'll (or you) will
have to coordinate it with akpm as one "atomic" patch.... As lots of
different subsystems (and => lots of maintainers) are involved, I'd
prefer to keep the argument for now.
								Pavel
-- 
Boycott Kodak -- for their patent abuse against Java.
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"aart@kvack.org"> aart@kvack.org </a>

^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: [RFC] Fix SMP brokenness for PF_FREEZE and make freezing usable for other purposes
  2005-06-26  2:30     ` Pavel Machek
  2005-06-26  2:55       ` Christoph Lameter
@ 2005-06-26 10:54       ` Nigel Cunningham
  1 sibling, 0 replies; 35+ messages in thread
From: Nigel Cunningham @ 2005-06-26 10:54 UTC (permalink / raw)
  To: Pavel Machek
  Cc: Christoph Lameter, Linux Memory Management,
	Linux Kernel Mailing List, raybry, Linus Torvalds

Hi!

On Sun, 2005-06-26 at 12:30, Pavel Machek wrote:
> > Index: linux-2.6.12/arch/i386/kernel/signal.c
> > ===================================================================
> > --- linux-2.6.12.orig/arch/i386/kernel/signal.c	2005-06-25 05:01:26.000000000 +0000
> > +++ linux-2.6.12/arch/i386/kernel/signal.c	2005-06-25 05:01:28.000000000 +0000
> > @@ -608,10 +608,8 @@ int fastcall do_signal(struct pt_regs *r
> >  	if (!user_mode(regs))
> >  		return 1;
> >  
> > -	if (current->flags & PF_FREEZE) {
> > -		refrigerator(0);
> > +	if (try_to_freeze)
> >  		goto no_signal;
> > -	}
> >  
> 
> This is not good. Missing ().

Thanks!

I was just going to begin a search to find out why, after applying it,
everything stopped dead in the water :>

Nigel

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"aart@kvack.org"> aart@kvack.org </a>

^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: [RFC] Fix SMP brokenness for PF_FREEZE and make freezing usable for other purposes
  2005-06-26  3:09         ` Pavel Machek
@ 2005-06-27  3:51           ` Christoph Lameter
  2005-06-27  4:21             ` Pavel Machek
  2005-06-27  4:24             ` Linus Torvalds
  0 siblings, 2 replies; 35+ messages in thread
From: Christoph Lameter @ 2005-06-27  3:51 UTC (permalink / raw)
  To: Pavel Machek; +Cc: linux-mm, linux-kernel, raybry, torvalds

On Sun, 26 Jun 2005, Pavel Machek wrote:

> > Why do you want to specify a parameter that is never used? It was quite confusing to me 
> > and I would think that such a parameter will also be confusing to others.
> 
> Well, yes, it is slightly confusing, but such patch can go in through
> different maintainers, and different pieces can come in at different
> times.

The cleanup patch is already in Linus' tree so the discussion is moot. So 
I think the basic API is now stable.

The other outstanding issues may best be addressed in the 
following way.

1. Have a semaphore to insure that allows control over the freezing 
process. Each action involving freezing of processes needs to first 
take the semaphore. This will insure that only the suspend code or the 
process migration code (or something else in the future) are freezing processes.

2. A completion handler seems to be the right instrument in the 
refrigerator and allows the removal of a lot of code.

3. I wish there would be a better way to handle the PF_FREEZE. Its like a 
signal delivery after all. Is there any way to define an in kernel signal? 
Or a way to make a process execute a certain bit of code?

The following patch will still need to be verified to be correct, 
cleaned up to move code around and do the right thing with 
CONFIG_FREEZING CONFIG_PM and CONFIG_MIGRATE???

---

Revise handling of freezing in the suspend code (against 2.6.12-git8)

The current suspend code modifies thread flags from outside the context of process.
This creates a SMP race.

The patch fixes that by introducing a freeze_request flag and uses a completion
handler instead of waiting in a schedule loop in the refrigerator.

It also introduces a semaphore freezer_sem to provide a way that multiple kernel
subsystems can use the freezing ability without interfering.

Would this be satisfying everyones concerns? I have never used a completion handler
before so some better check up on me.

Signed-off-by: Christoph Lameter <christoph@lameter.com>

Index: linux-2.6.12/include/linux/sched.h
===================================================================
--- linux-2.6.12.orig/include/linux/sched.h	2005-06-27 02:23:01.000000000 +0000
+++ linux-2.6.12/include/linux/sched.h	2005-06-27 03:43:02.000000000 +0000
@@ -719,6 +719,8 @@ struct task_struct {
 	struct audit_context *audit_context;
 	seccomp_t seccomp;
 
+	int freeze_request;	/* Written to by external process to request freeze */
+
 /* Thread group tracking */
    	u32 parent_exec_id;
    	u32 self_exec_id;
@@ -804,7 +806,6 @@ do { if (atomic_dec_and_test(&(tsk)->usa
 #define PF_MEMALLOC	0x00000800	/* Allocating memory */
 #define PF_FLUSHER	0x00001000	/* responsible for disk writeback */
 #define PF_USED_MATH	0x00002000	/* if unset the fpu must be initialized before use */
-#define PF_FREEZE	0x00004000	/* this task is being frozen for suspend now */
 #define PF_NOFREEZE	0x00008000	/* this thread should not be frozen */
 #define PF_FROZEN	0x00010000	/* frozen for system suspend */
 #define PF_FSTRANS	0x00020000	/* inside a filesystem transaction */
@@ -1265,7 +1266,13 @@ extern void normalize_rt_tasks(void);
 
 #endif
 
-#ifdef CONFIG_PM
+#if defined(CONFIG_PM) || defined(CONFIG_MIGRATE)
+#define CONFIG_FREEZING
+#endif
+
+#ifdef CONFIG_FREEZING
+extern struct semaphore freezer_sem;
+extern struct completion thaw;
 /*
  * Check if a process has been frozen
  */
@@ -1279,39 +1286,20 @@ static inline int frozen(struct task_str
  */
 static inline int freezing(struct task_struct *p)
 {
-	return p->flags & PF_FREEZE;
+	return p->freeze_request;
 }
 
 /*
  * 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;
+	p->freeze_request = 1;
 }
 
 /*
  * 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);
@@ -1328,16 +1316,11 @@ static inline int try_to_freeze(void)
 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(void) { return 0; }
-
-#endif /* CONFIG_PM */
+#endif /* CONFIG_FREEZING */
 #endif /* __KERNEL__ */
 
 #endif
Index: linux-2.6.12/kernel/power/process.c
===================================================================
--- linux-2.6.12.orig/kernel/power/process.c	2005-06-27 02:23:01.000000000 +0000
+++ linux-2.6.12/kernel/power/process.c	2005-06-27 03:42:15.000000000 +0000
@@ -18,6 +18,8 @@
  */
 #define TIMEOUT	(6 * HZ)
 
+DECLARE_MUTEX(freezer_sem);
+DECLARE_COMPLETION(thaw);
 
 static inline int freezeable(struct task_struct * p)
 {
@@ -31,27 +33,14 @@ static inline int freezeable(struct task
 	return 1;
 }
 
-/* Refrigerator is place where frozen processes are stored :-). */
 void refrigerator(void)
 {
-	/* Hmm, should we be allowed to suspend when there are realtime
-	   processes around? */
-	long save;
-	save = current->state;
-	current->state = TASK_UNINTERRUPTIBLE;
-	pr_debug("%s entered refrigerator\n", current->comm);
-	printk("=");
-
-	frozen_process(current);
-	spin_lock_irq(&current->sighand->siglock);
-	recalc_sigpending(); /* We sent fake signal, clean it up */
-	spin_unlock_irq(&current->sighand->siglock);
-
-	while (frozen(current))
-		schedule();
-	pr_debug("%s left refrigerator\n", current->comm);
-	current->state = save;
+	current->flags |= PF_FROZEN;
+	current->freeze_request = 0;
+	wait_for_completion(&thaw);
+	current->flags &= ~PF_FROZEN;
 }
+EXPORT_SYMBOL(refrigerator);
 
 /* 0 = success, else # of processes that we failed to stop */
 int freeze_processes(void)
@@ -60,6 +49,7 @@ int freeze_processes(void)
 	unsigned long start_time;
 	struct task_struct *g, *p;
 
+	down(&freezer_sem);
 	printk( "Stopping tasks: " );
 	start_time = jiffies;
 	do {
@@ -96,20 +86,6 @@ int freeze_processes(void)
 
 void thaw_processes(void)
 {
-	struct task_struct *g, *p;
-
-	printk( "Restarting tasks..." );
-	read_lock(&tasklist_lock);
-	do_each_thread(g, p) {
-		if (!freezeable(p))
-			continue;
-		if (!thaw_process(p))
-			printk(KERN_INFO " Strange, %s not stopped\n", p->comm );
-	} while_each_thread(g, p);
-
-	read_unlock(&tasklist_lock);
-	schedule();
-	printk( " done\n" );
+	complete_all(&thaw);
+	up(&freezer_sem);
 }
-
-EXPORT_SYMBOL(refrigerator);





--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"aart@kvack.org"> aart@kvack.org </a>

^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: [RFC] Fix SMP brokenness for PF_FREEZE and make freezing usable for other purposes
  2005-06-27  3:51           ` Christoph Lameter
@ 2005-06-27  4:21             ` Pavel Machek
  2005-06-27  4:24             ` Linus Torvalds
  1 sibling, 0 replies; 35+ messages in thread
From: Pavel Machek @ 2005-06-27  4:21 UTC (permalink / raw)
  To: Christoph Lameter; +Cc: linux-mm, linux-kernel, raybry, torvalds

Hi!

> > > Why do you want to specify a parameter that is never used? It was quite confusing to me 
> > > and I would think that such a parameter will also be confusing to others.
> > 
> > Well, yes, it is slightly confusing, but such patch can go in through
> > different maintainers, and different pieces can come in at different
> > times.
> 
> The cleanup patch is already in Linus' tree so the discussion is moot. So 
> I think the basic API is now stable.

Okay, good. I was worried I'll have to push it myself.

> The other outstanding issues may best be addressed in the 
> following way.
> 
> 1. Have a semaphore to insure that allows control over the freezing 
> process. Each action involving freezing of processes needs to first 
> take the semaphore. This will insure that only the suspend code or the 
> process migration code (or something else in the future) are freezing processes.
> 
> 2. A completion handler seems to be the right instrument in the 
> refrigerator and allows the removal of a lot of code.
> 
> 3. I wish there would be a better way to handle the PF_FREEZE. Its like a 
> signal delivery after all. Is there any way to define an in kernel signal? 
> Or a way to make a process execute a certain bit of code?

Well... but kernel threads are simply not designed to handle signals,
that's why we had to add all those try_to_freeze()s.

> The following patch will still need to be verified to be correct, 
> cleaned up to move code around and do the right thing with 
> CONFIG_FREEZING CONFIG_PM and CONFIG_MIGRATE???

I'm not able to test the patch now (have to get some sleep, etc), but
it looks good.

								Pavel
-- 
Boycott Kodak -- for their patent abuse against Java.
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"aart@kvack.org"> aart@kvack.org </a>

^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: [RFC] Fix SMP brokenness for PF_FREEZE and make freezing usable for other purposes
  2005-06-27  3:51           ` Christoph Lameter
  2005-06-27  4:21             ` Pavel Machek
@ 2005-06-27  4:24             ` Linus Torvalds
  2005-06-27  5:53               ` Christoph Lameter
  1 sibling, 1 reply; 35+ messages in thread
From: Linus Torvalds @ 2005-06-27  4:24 UTC (permalink / raw)
  To: Christoph Lameter; +Cc: Pavel Machek, linux-mm, linux-kernel, raybry


On Sun, 26 Jun 2005, Christoph Lameter wrote:
> 
> 3. I wish there would be a better way to handle the PF_FREEZE. Its like a 
> signal delivery after all. Is there any way to define an in kernel signal? 
> Or a way to make a process execute a certain bit of code?

It's called "work", and we have the "TIF_xxx" flags for it. That's how 
"need-resched" and "sigpending" are done. There could be a 
"TIF_FREEZEPENDING" thing there too..

		Linus
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"aart@kvack.org"> aart@kvack.org </a>

^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: [RFC] Fix SMP brokenness for PF_FREEZE and make freezing usable for other purposes
  2005-06-27  4:24             ` Linus Torvalds
@ 2005-06-27  5:53               ` Christoph Lameter
  2005-06-27 14:13                 ` Pavel Machek
  2005-06-28 21:50                 ` [RFC] Fix SMP brokenness for PF_FREEZE and make freezing usable for other purposes Ray Bryant
  0 siblings, 2 replies; 35+ messages in thread
From: Christoph Lameter @ 2005-06-27  5:53 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: Pavel Machek, linux-mm, linux-kernel, raybry

On Sun, 26 Jun 2005, Linus Torvalds wrote:

> It's called "work", and we have the "TIF_xxx" flags for it. That's how 
> "need-resched" and "sigpending" are done. There could be a 
> "TIF_FREEZEPENDING" thing there too..

Ok. Here is yet another version of the patch:

---
The current suspend code modifies thread flags from outside the context of process.
This creates a SMP race.

The patch fixes that by introducing a TIF_FREEZE flag (for all arches). Also

- Uses a completion handler instead of waiting in a schedule loop in the refrigerator.

- Introduces a semaphore freezer_sem to provide a way that multiple kernel
  subsystems can use the freezing ability without interfering with one another.

- Include necessary definitions for the migration code if CONFIG_MIGRATE is set.

- Removes PF_FREEZE

If this approach is okay then we will need to move the refrigerator() and the
definition of the semaphore and the completion variable out of kernel/power/process.c
into kernel/sched.c (right?).

Signed-off-by: Christoph Lameter <christoph@lameter.com>

Index: linux-2.6.12/include/linux/sched.h
===================================================================
--- linux-2.6.12.orig/include/linux/sched.h	2005-06-27 05:20:15.000000000 +0000
+++ linux-2.6.12/include/linux/sched.h	2005-06-27 05:33:46.000000000 +0000
@@ -804,7 +804,6 @@ do { if (atomic_dec_and_test(&(tsk)->usa
 #define PF_MEMALLOC	0x00000800	/* Allocating memory */
 #define PF_FLUSHER	0x00001000	/* responsible for disk writeback */
 #define PF_USED_MATH	0x00002000	/* if unset the fpu must be initialized before use */
-#define PF_FREEZE	0x00004000	/* this task is being frozen for suspend now */
 #define PF_NOFREEZE	0x00008000	/* this thread should not be frozen */
 #define PF_FROZEN	0x00010000	/* frozen for system suspend */
 #define PF_FSTRANS	0x00020000	/* inside a filesystem transaction */
@@ -1265,78 +1264,37 @@ extern void normalize_rt_tasks(void);
 
 #endif
 
-#ifdef CONFIG_PM
-/*
- * 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;
-}
+#if defined(CONFIG_PM) || defined(CONFIG_MIGRATE)
+extern struct semaphore freezer_sem;
+extern struct completion thaw;
 
-/*
- * 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;
-}
+extern void refrigerator(void);
 
-/*
- * freezing is complete, mark process as frozen
- */
-static inline void frozen_process(struct task_struct *p)
+static inline int freezing(struct task_struct *p)
 {
-	p->flags = (p->flags & ~PF_FREEZE) | PF_FROZEN;
+	return test_ti_thread_flag(p->thread_info, TIF_FREEZE);
 }
 
-extern void refrigerator(void);
-extern int freeze_processes(void);
-extern void thaw_processes(void);
-
 static inline int try_to_freeze(void)
 {
-	if (freezing(current)) {
+	if (test_thread_flag(TIF_FREEZE)) {
 		refrigerator();
 		return 1;
 	} else
 		return 0;
 }
 #else
-static inline int frozen(struct task_struct *p) { return 0; }
+static inline void refrigerator(void) {}
 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 int try_to_freeze(void) { return 0; }
+#endif
 
-static inline void refrigerator(void) {}
+#ifdef CONFIG_PM
+extern int freeze_processes(void);
+extern void thaw_processes(void);
+#else
 static inline int freeze_processes(void) { BUG(); return 0; }
 static inline void thaw_processes(void) {}
-
-static inline int try_to_freeze(void) { return 0; }
-
 #endif /* CONFIG_PM */
 #endif /* __KERNEL__ */
 
Index: linux-2.6.12/kernel/power/process.c
===================================================================
--- linux-2.6.12.orig/kernel/power/process.c	2005-06-27 05:20:15.000000000 +0000
+++ linux-2.6.12/kernel/power/process.c	2005-06-27 05:22:00.000000000 +0000
@@ -18,6 +18,8 @@
  */
 #define TIMEOUT	(6 * HZ)
 
+DECLARE_MUTEX(freezer_sem);
+DECLARE_COMPLETION(thaw);
 
 static inline int freezeable(struct task_struct * p)
 {
@@ -31,27 +33,18 @@ static inline int freezeable(struct task
 	return 1;
 }
 
-/* Refrigerator is place where frozen processes are stored :-). */
 void refrigerator(void)
 {
-	/* Hmm, should we be allowed to suspend when there are realtime
-	   processes around? */
-	long save;
-	save = current->state;
-	current->state = TASK_UNINTERRUPTIBLE;
-	pr_debug("%s entered refrigerator\n", current->comm);
-	printk("=");
-
-	frozen_process(current);
+	current->flags |= PF_FROZEN;
+	clear_thread_flag(TIF_FREEZE);
+	/* A fake signal 0 may have been sent. Recalculate sigpending */
 	spin_lock_irq(&current->sighand->siglock);
-	recalc_sigpending(); /* We sent fake signal, clean it up */
+	recalc_sigpending();
 	spin_unlock_irq(&current->sighand->siglock);
-
-	while (frozen(current))
-		schedule();
-	pr_debug("%s left refrigerator\n", current->comm);
-	current->state = save;
+	wait_for_completion(&thaw);
+	current->flags &= ~PF_FROZEN;
 }
+EXPORT_SYMBOL(refrigerator);
 
 /* 0 = success, else # of processes that we failed to stop */
 int freeze_processes(void)
@@ -60,6 +53,7 @@ int freeze_processes(void)
 	unsigned long start_time;
 	struct task_struct *g, *p;
 
+	down(&freezer_sem);
 	printk( "Stopping tasks: " );
 	start_time = jiffies;
 	do {
@@ -69,12 +63,12 @@ int freeze_processes(void)
 			unsigned long flags;
 			if (!freezeable(p))
 				continue;
-			if ((frozen(p)) ||
+			if ((p->flags & PF_FROZEN) ||
 			    (p->state == TASK_TRACED) ||
 			    (p->state == TASK_STOPPED))
 				continue;
 
-			freeze(p);
+			set_thread_flag(TIF_FREEZE);
 			spin_lock_irqsave(&p->sighand->siglock, flags);
 			signal_wake_up(p, 0);
 			spin_unlock_irqrestore(&p->sighand->siglock, flags);
@@ -96,20 +90,6 @@ int freeze_processes(void)
 
 void thaw_processes(void)
 {
-	struct task_struct *g, *p;
-
-	printk( "Restarting tasks..." );
-	read_lock(&tasklist_lock);
-	do_each_thread(g, p) {
-		if (!freezeable(p))
-			continue;
-		if (!thaw_process(p))
-			printk(KERN_INFO " Strange, %s not stopped\n", p->comm );
-	} while_each_thread(g, p);
-
-	read_unlock(&tasklist_lock);
-	schedule();
-	printk( " done\n" );
+	complete_all(&thaw);
+	up(&freezer_sem);
 }
-
-EXPORT_SYMBOL(refrigerator);
Index: linux-2.6.12/include/asm-x86_64/thread_info.h
===================================================================
--- linux-2.6.12.orig/include/asm-x86_64/thread_info.h	2005-06-27 05:20:15.000000000 +0000
+++ linux-2.6.12/include/asm-x86_64/thread_info.h	2005-06-27 05:37:24.000000000 +0000
@@ -108,6 +108,7 @@ static inline struct thread_info *stack_
 #define TIF_FORK		18	/* ret_from_fork */
 #define TIF_ABI_PENDING		19
 #define TIF_MEMDIE		20
+#define TIF_FREEZE		21	/* Freeze process */
 
 #define _TIF_SYSCALL_TRACE	(1<<TIF_SYSCALL_TRACE)
 #define _TIF_NOTIFY_RESUME	(1<<TIF_NOTIFY_RESUME)
Index: linux-2.6.12/include/asm-ia64/thread_info.h
===================================================================
--- linux-2.6.12.orig/include/asm-ia64/thread_info.h	2005-06-27 05:20:15.000000000 +0000
+++ linux-2.6.12/include/asm-ia64/thread_info.h	2005-06-27 05:26:12.000000000 +0000
@@ -76,6 +76,7 @@ struct thread_info {
 #define TIF_SIGDELAYED		5	/* signal delayed from MCA/INIT/NMI/PMI context */
 #define TIF_POLLING_NRFLAG	16	/* true if poll_idle() is polling TIF_NEED_RESCHED */
 #define TIF_MEMDIE		17
+#define TIF_FREEZE		18	/* Freeze process */
 
 #define _TIF_SYSCALL_TRACE	(1 << TIF_SYSCALL_TRACE)
 #define _TIF_SYSCALL_AUDIT	(1 << TIF_SYSCALL_AUDIT)
Index: linux-2.6.12/include/asm-i386/thread_info.h
===================================================================
--- linux-2.6.12.orig/include/asm-i386/thread_info.h	2005-06-27 05:20:15.000000000 +0000
+++ linux-2.6.12/include/asm-i386/thread_info.h	2005-06-27 05:25:49.000000000 +0000
@@ -143,6 +143,7 @@ register unsigned long current_stack_poi
 #define TIF_SECCOMP		8	/* secure computing */
 #define TIF_POLLING_NRFLAG	16	/* true if poll_idle() is polling TIF_NEED_RESCHED */
 #define TIF_MEMDIE		17
+#define TIF_FREEZE		18	/* Freeze thread */
 
 #define _TIF_SYSCALL_TRACE	(1<<TIF_SYSCALL_TRACE)
 #define _TIF_NOTIFY_RESUME	(1<<TIF_NOTIFY_RESUME)
Index: linux-2.6.12/include/asm-xtensa/thread_info.h
===================================================================
--- linux-2.6.12.orig/include/asm-xtensa/thread_info.h	2005-06-27 02:23:01.000000000 +0000
+++ linux-2.6.12/include/asm-xtensa/thread_info.h	2005-06-27 05:36:54.000000000 +0000
@@ -118,6 +118,7 @@ static inline struct thread_info *curren
 #define TIF_SINGLESTEP		4	/* restore singlestep on return to user mode */
 #define TIF_IRET		5	/* return with iret */
 #define TIF_MEMDIE		6
+#define TIF_FREEZE		7
 #define TIF_POLLING_NRFLAG	16	/* true if poll_idle() is polling TIF_NEED_RESCHED */
 
 #define _TIF_SYSCALL_TRACE	(1<<TIF_SYSCALL_TRACE)
Index: linux-2.6.12/include/asm-h8300/thread_info.h
===================================================================
--- linux-2.6.12.orig/include/asm-h8300/thread_info.h	2005-06-27 02:23:01.000000000 +0000
+++ linux-2.6.12/include/asm-h8300/thread_info.h	2005-06-27 05:25:25.000000000 +0000
@@ -94,6 +94,7 @@ static inline struct thread_info *curren
 #define TIF_POLLING_NRFLAG	4	/* true if poll_idle() is polling
 					   TIF_NEED_RESCHED */
 #define TIF_MEMDIE		5
+#define TIF_FREEZE		6
 
 /* as above, but as bit values */
 #define _TIF_SYSCALL_TRACE	(1<<TIF_SYSCALL_TRACE)
Index: linux-2.6.12/include/asm-ppc/thread_info.h
===================================================================
--- linux-2.6.12.orig/include/asm-ppc/thread_info.h	2005-06-27 02:23:01.000000000 +0000
+++ linux-2.6.12/include/asm-ppc/thread_info.h	2005-06-27 05:28:53.000000000 +0000
@@ -80,6 +80,7 @@ static inline struct thread_info *curren
 #define TIF_MEMDIE		5
 #define TIF_SYSCALL_AUDIT       6       /* syscall auditing active */
 #define TIF_SECCOMP             7      /* secure computing */
+#define TIF_FREEZE		8
 
 /* as above, but as bit values */
 #define _TIF_SYSCALL_TRACE	(1<<TIF_SYSCALL_TRACE)
Index: linux-2.6.12/include/asm-sh64/thread_info.h
===================================================================
--- linux-2.6.12.orig/include/asm-sh64/thread_info.h	2005-06-27 02:23:01.000000000 +0000
+++ linux-2.6.12/include/asm-sh64/thread_info.h	2005-06-27 05:35:02.000000000 +0000
@@ -80,6 +80,7 @@ static inline struct thread_info *curren
 #define TIF_SIGPENDING		2	/* signal pending */
 #define TIF_NEED_RESCHED	3	/* rescheduling necessary */
 #define TIF_MEMDIE		4
+#define TIF_FREEZE		5
 
 
 #endif /* __KERNEL__ */
Index: linux-2.6.12/include/asm-alpha/thread_info.h
===================================================================
--- linux-2.6.12.orig/include/asm-alpha/thread_info.h	2005-06-17 19:48:29.000000000 +0000
+++ linux-2.6.12/include/asm-alpha/thread_info.h	2005-06-27 05:23:06.000000000 +0000
@@ -78,6 +78,7 @@ register struct thread_info *__current_t
 #define TIF_UAC_NOFIX		7
 #define TIF_UAC_SIGBUS		8
 #define TIF_MEMDIE		9
+#define TIF_FREEZE		10
 
 #define _TIF_SYSCALL_TRACE	(1<<TIF_SYSCALL_TRACE)
 #define _TIF_NOTIFY_RESUME	(1<<TIF_NOTIFY_RESUME)
Index: linux-2.6.12/include/asm-sparc/thread_info.h
===================================================================
--- linux-2.6.12.orig/include/asm-sparc/thread_info.h	2005-06-27 02:23:01.000000000 +0000
+++ linux-2.6.12/include/asm-sparc/thread_info.h	2005-06-27 05:35:23.000000000 +0000
@@ -139,6 +139,7 @@ BTFIXUPDEF_CALL(void, free_thread_info, 
 #define TIF_POLLING_NRFLAG	9	/* true if poll_idle() is polling
 					 * TIF_NEED_RESCHED */
 #define TIF_MEMDIE		10
+#define TIF_FREEZE		11
 
 /* as above, but as bit values */
 #define _TIF_SYSCALL_TRACE	(1<<TIF_SYSCALL_TRACE)
Index: linux-2.6.12/include/asm-frv/thread_info.h
===================================================================
--- linux-2.6.12.orig/include/asm-frv/thread_info.h	2005-06-27 02:23:01.000000000 +0000
+++ linux-2.6.12/include/asm-frv/thread_info.h	2005-06-27 05:25:02.000000000 +0000
@@ -133,6 +133,7 @@ register struct thread_info *__current_t
 #define TIF_IRET		5	/* return with iret */
 #define TIF_POLLING_NRFLAG	16	/* true if poll_idle() is polling TIF_NEED_RESCHED */
 #define TIF_MEMDIE		17	/* OOM killer killed process */
+#define TIF_FREEZE		18
 
 #define _TIF_SYSCALL_TRACE	(1 << TIF_SYSCALL_TRACE)
 #define _TIF_NOTIFY_RESUME	(1 << TIF_NOTIFY_RESUME)
Index: linux-2.6.12/include/asm-parisc/thread_info.h
===================================================================
--- linux-2.6.12.orig/include/asm-parisc/thread_info.h	2005-06-27 02:23:01.000000000 +0000
+++ linux-2.6.12/include/asm-parisc/thread_info.h	2005-06-27 05:28:34.000000000 +0000
@@ -64,6 +64,7 @@ struct thread_info {
 #define TIF_POLLING_NRFLAG	4	/* true if poll_idle() is polling TIF_NEED_RESCHED */
 #define TIF_32BIT               5       /* 32 bit binary */
 #define TIF_MEMDIE		6
+#define TIF_FREEZE		7
 
 #define _TIF_SYSCALL_TRACE	(1 << TIF_SYSCALL_TRACE)
 #define _TIF_NOTIFY_RESUME	(1 << TIF_NOTIFY_RESUME)
Index: linux-2.6.12/include/asm-m68knommu/thread_info.h
===================================================================
--- linux-2.6.12.orig/include/asm-m68knommu/thread_info.h	2005-06-27 02:23:01.000000000 +0000
+++ linux-2.6.12/include/asm-m68knommu/thread_info.h	2005-06-27 05:27:13.000000000 +0000
@@ -91,6 +91,7 @@ static inline struct thread_info *curren
 #define TIF_POLLING_NRFLAG	4	/* true if poll_idle() is polling
 					   TIF_NEED_RESCHED */
 #define TIF_MEMDIE		5
+#define TIF_FREEZE		6
 
 /* as above, but as bit values */
 #define _TIF_SYSCALL_TRACE	(1<<TIF_SYSCALL_TRACE)
Index: linux-2.6.12/include/asm-m68k/thread_info.h
===================================================================
--- linux-2.6.12.orig/include/asm-m68k/thread_info.h	2005-06-27 02:23:01.000000000 +0000
+++ linux-2.6.12/include/asm-m68k/thread_info.h	2005-06-27 05:26:49.000000000 +0000
@@ -49,6 +49,7 @@ struct thread_info {
 #define TIF_SIGPENDING		3	/* signal pending */
 #define TIF_NEED_RESCHED	4	/* rescheduling necessary */
 #define TIF_MEMDIE		5
+#define TIF_FREEZE		6
 
 extern int thread_flag_fixme(void);
 
Index: linux-2.6.12/include/asm-sh/thread_info.h
===================================================================
--- linux-2.6.12.orig/include/asm-sh/thread_info.h	2005-06-27 02:23:01.000000000 +0000
+++ linux-2.6.12/include/asm-sh/thread_info.h	2005-06-27 05:34:43.000000000 +0000
@@ -84,6 +84,7 @@ static inline struct thread_info *curren
 #define TIF_USEDFPU		16	/* FPU was used by this task this quantum (SMP) */
 #define TIF_POLLING_NRFLAG	17	/* true if poll_idle() is polling TIF_NEED_RESCHED */
 #define TIF_MEMDIE		18
+#define TIF_FREEZE		19
 #define TIF_USERSPACE		31	/* true if FS sets userspace */
 
 #define _TIF_SYSCALL_TRACE	(1<<TIF_SYSCALL_TRACE)
Index: linux-2.6.12/include/asm-s390/thread_info.h
===================================================================
--- linux-2.6.12.orig/include/asm-s390/thread_info.h	2005-06-27 02:23:01.000000000 +0000
+++ linux-2.6.12/include/asm-s390/thread_info.h	2005-06-27 05:34:19.000000000 +0000
@@ -102,6 +102,7 @@ static inline struct thread_info *curren
 					   TIF_NEED_RESCHED */
 #define TIF_31BIT		18	/* 32bit process */ 
 #define TIF_MEMDIE		19
+#define TIF_FREEZE		20
 
 #define _TIF_SYSCALL_TRACE	(1<<TIF_SYSCALL_TRACE)
 #define _TIF_NOTIFY_RESUME	(1<<TIF_NOTIFY_RESUME)
Index: linux-2.6.12/include/asm-arm/thread_info.h
===================================================================
--- linux-2.6.12.orig/include/asm-arm/thread_info.h	2005-06-27 02:23:01.000000000 +0000
+++ linux-2.6.12/include/asm-arm/thread_info.h	2005-06-27 05:23:34.000000000 +0000
@@ -132,6 +132,7 @@ extern void iwmmxt_task_release(struct t
 #define TIF_POLLING_NRFLAG	16
 #define TIF_USING_IWMMXT	17
 #define TIF_MEMDIE		18
+#define TIF_FREEZE		19
 
 #define _TIF_NOTIFY_RESUME	(1 << TIF_NOTIFY_RESUME)
 #define _TIF_SIGPENDING		(1 << TIF_SIGPENDING)
Index: linux-2.6.12/include/asm-v850/thread_info.h
===================================================================
--- linux-2.6.12.orig/include/asm-v850/thread_info.h	2005-06-27 02:23:01.000000000 +0000
+++ linux-2.6.12/include/asm-v850/thread_info.h	2005-06-27 05:36:25.000000000 +0000
@@ -85,6 +85,7 @@ struct thread_info {
 #define TIF_POLLING_NRFLAG	4	/* true if poll_idle() is polling
 					   TIF_NEED_RESCHED */
 #define TIF_MEMDIE		5
+#define TIF_FREEZE		6
 
 /* as above, but as bit values */
 #define _TIF_SYSCALL_TRACE	(1<<TIF_SYSCALL_TRACE)
Index: linux-2.6.12/include/asm-mips/thread_info.h
===================================================================
--- linux-2.6.12.orig/include/asm-mips/thread_info.h	2005-06-27 02:23:01.000000000 +0000
+++ linux-2.6.12/include/asm-mips/thread_info.h	2005-06-27 05:27:41.000000000 +0000
@@ -117,6 +117,7 @@ register struct thread_info *__current_t
 #define TIF_USEDFPU		16	/* FPU was used by this task this quantum (SMP) */
 #define TIF_POLLING_NRFLAG	17	/* true if poll_idle() is polling TIF_NEED_RESCHED */
 #define TIF_MEMDIE		18
+#define TIF_FREEZE		19
 #define TIF_SYSCALL_TRACE	31	/* syscall trace active */
 
 #define _TIF_SYSCALL_TRACE	(1<<TIF_SYSCALL_TRACE)
Index: linux-2.6.12/include/asm-cris/thread_info.h
===================================================================
--- linux-2.6.12.orig/include/asm-cris/thread_info.h	2005-06-27 02:23:01.000000000 +0000
+++ linux-2.6.12/include/asm-cris/thread_info.h	2005-06-27 05:24:28.000000000 +0000
@@ -86,6 +86,7 @@ struct thread_info {
 #define TIF_NEED_RESCHED	3	/* rescheduling necessary */
 #define TIF_POLLING_NRFLAG	16	/* true if poll_idle() is polling TIF_NEED_RESCHED */
 #define TIF_MEMDIE		17
+#define TIF_FREEZE		18
 
 #define _TIF_SYSCALL_TRACE	(1<<TIF_SYSCALL_TRACE)
 #define _TIF_NOTIFY_RESUME	(1<<TIF_NOTIFY_RESUME)
Index: linux-2.6.12/include/asm-arm26/thread_info.h
===================================================================
--- linux-2.6.12.orig/include/asm-arm26/thread_info.h	2005-06-27 02:23:01.000000000 +0000
+++ linux-2.6.12/include/asm-arm26/thread_info.h	2005-06-27 05:24:02.000000000 +0000
@@ -127,6 +127,7 @@ extern void free_thread_info(struct thre
 #define TIF_USED_FPU		16
 #define TIF_POLLING_NRFLAG	17
 #define TIF_MEMDIE		18
+#define TIF_FREEZE		19
 
 #define _TIF_NOTIFY_RESUME	(1 << TIF_NOTIFY_RESUME)
 #define _TIF_SIGPENDING		(1 << TIF_SIGPENDING)
Index: linux-2.6.12/include/asm-sparc64/thread_info.h
===================================================================
--- linux-2.6.12.orig/include/asm-sparc64/thread_info.h	2005-06-27 02:23:01.000000000 +0000
+++ linux-2.6.12/include/asm-sparc64/thread_info.h	2005-06-27 05:35:45.000000000 +0000
@@ -229,6 +229,7 @@ register struct thread_info *current_thr
  */
 #define TIF_ABI_PENDING		12
 #define TIF_MEMDIE		13
+#define TIF_FREEZE		14
 
 #define _TIF_SYSCALL_TRACE	(1<<TIF_SYSCALL_TRACE)
 #define _TIF_NOTIFY_RESUME	(1<<TIF_NOTIFY_RESUME)
Index: linux-2.6.12/include/asm-m32r/thread_info.h
===================================================================
--- linux-2.6.12.orig/include/asm-m32r/thread_info.h	2005-06-27 02:23:01.000000000 +0000
+++ linux-2.6.12/include/asm-m32r/thread_info.h	2005-06-27 05:26:33.000000000 +0000
@@ -156,6 +156,7 @@ static inline unsigned int get_thread_fa
 #define TIF_POLLING_NRFLAG	16	/* true if poll_idle() is polling TIF_NEED_RESCHED */
 					/* 31..28 fault code */
 #define TIF_MEMDIE		17
+#define TIF_FREEZE		18
 
 #define _TIF_SYSCALL_TRACE	(1<<TIF_SYSCALL_TRACE)
 #define _TIF_NOTIFY_RESUME	(1<<TIF_NOTIFY_RESUME)
Index: linux-2.6.12/include/asm-ppc64/thread_info.h
===================================================================
--- linux-2.6.12.orig/include/asm-ppc64/thread_info.h	2005-06-27 02:23:01.000000000 +0000
+++ linux-2.6.12/include/asm-ppc64/thread_info.h	2005-06-27 05:29:13.000000000 +0000
@@ -102,6 +102,7 @@ static inline struct thread_info *curren
 #define TIF_SINGLESTEP		9	/* singlestepping active */
 #define TIF_MEMDIE		10
 #define TIF_SECCOMP		11	/* secure computing */
+#define TIF_FREEZE		12
 
 /* as above, but as bit values */
 #define _TIF_SYSCALL_TRACE	(1<<TIF_SYSCALL_TRACE)
Index: linux-2.6.12/include/asm-um/thread_info.h
===================================================================
--- linux-2.6.12.orig/include/asm-um/thread_info.h	2005-06-27 02:23:01.000000000 +0000
+++ linux-2.6.12/include/asm-um/thread_info.h	2005-06-27 05:36:07.000000000 +0000
@@ -72,6 +72,7 @@ static inline struct thread_info *curren
 #define TIF_RESTART_BLOCK 	4
 #define TIF_MEMDIE	 	5
 #define TIF_SYSCALL_AUDIT	6
+#define TIF_FREEZE		7
 
 #define _TIF_SYSCALL_TRACE	(1 << TIF_SYSCALL_TRACE)
 #define _TIF_SIGPENDING		(1 << TIF_SIGPENDING)
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"aart@kvack.org"> aart@kvack.org </a>

^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: [RFC] Fix SMP brokenness for PF_FREEZE and make freezing usable for other purposes
  2005-06-25  7:35 ` Kirill Korotaev
@ 2005-06-27  7:06   ` Ray Bryant
  2005-06-27 13:17     ` Pavel Machek
  0 siblings, 1 reply; 35+ messages in thread
From: Ray Bryant @ 2005-06-27  7:06 UTC (permalink / raw)
  To: Kirill Korotaev
  Cc: Christoph Lameter, linux-mm, linux-kernel, pavel, torvalds, raybry, lhms

Kirill Korotaev wrote:
> CL> The process freezing used by software suspend currently relies on modifying
> current->>flags from outside of the processes context. This makes freezing and
> CL> unfreezing SMP unsafe since a process may change the flags at any time without
> CL> locking. The following patch introduces a new atomic_t field in task_struct
> CL> to allow SMP safe freezing and unfreezing.
> 
> CL> It provides a simple API for process freezing:
> 
> CL> frozen(process)             Check for frozen process
> CL> freezing(process)   Check if a process is being frozen
> CL> freeze(process)             Tell a process to freeze (go to refrigerator)
> CL> thaw_process(process)       Restart process
> 
> CL> I only know that this boots correctly since I have no system that can do
> CL> suspend. But Ray needs an effective means of process suspension for
> CL> his process migration patches.

The process migration patches that Christoph mentions are avaialable at

http://marc.theaimsgroup.com/?l=linux-mm&m=111945947315561&w=2

and subsequent notes to the -mm or lhms-devel lists.  The problem there is
that this code depends on user space code to suspend and then resume the
processes to be migrated before/after the migration.  Christoph suggested
using PF_FREEZE, but I pointed out that was broken on SMP so hence the
current patch.

The idea would be to use PF_FREEZE to cause the process suspension.
A minor flaw in this approach is what happens if a process migration
is in progress when the machine is suspended/resumed.  (Probably not
a common occurrence on Altix... :-), but anyway...).  If the processes
are PF_FROZEN by the migration code, then unfrozen by the resume code,
and then the migration code continues, then we have unstopped processes
being migratated again.  Not a good thing.  On the other hand, the
manual page migration stuff is only existent on NUMA boxes, so the
question is whether any NUMA boxes support suspend/resume.  (Anyone
have a NUMA laptop handy to test this on?   Thought not....)

Is the above scenario even possible?  manual page migration runs as a system
call.  Do system calls all complete before suspend starts?  If that is
the case, then the above is not something to worry about.

The other approach would be to fix the manual page migration code to
handle non-suspended processes, but that hasn't been achieved yet,
in spite of the fact that the underlying page migration code from the
memory hotplug project is designed to support that.  Even then,
there is still a potential race if the migrated application also uses
SIGTOP/SIGCONT, which is how the migrated processes are suspended
today.

Finally, how comfortable are people about using the PF_FREEZE stuff
to start and resume processes for purposes unrelated to suspend/resume?
-- 
Best Regards,
Ray
-----------------------------------------------
                   Ray Bryant
512-453-9679 (work)         512-507-7807 (cell)
raybry@sgi.com             raybry@austin.rr.com
The box said: "Requires Windows 98 or better",
            so I installed Linux.
-----------------------------------------------
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"aart@kvack.org"> aart@kvack.org </a>

^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: [RFC] Fix SMP brokenness for PF_FREEZE and make freezing usable for other purposes
  2005-06-27  7:06   ` Ray Bryant
@ 2005-06-27 13:17     ` Pavel Machek
  2005-06-27 14:59       ` Ray Bryant
  0 siblings, 1 reply; 35+ messages in thread
From: Pavel Machek @ 2005-06-27 13:17 UTC (permalink / raw)
  To: Ray Bryant
  Cc: Kirill Korotaev, Christoph Lameter, linux-mm, linux-kernel,
	torvalds, lhms

Hi!

> >CL> frozen(process)             Check for frozen process
> >CL> freezing(process)   Check if a process is being frozen
> >CL> freeze(process)             Tell a process to freeze (go to 
> >refrigerator)
> >CL> thaw_process(process)       Restart process
> >
> >CL> I only know that this boots correctly since I have no system that can 
> >do
> >CL> suspend. But Ray needs an effective means of process suspension for
> >CL> his process migration patches.
> 
> The process migration patches that Christoph mentions are avaialable at
> 
> http://marc.theaimsgroup.com/?l=linux-mm&m=111945947315561&w=2
> 
> and subsequent notes to the -mm or lhms-devel lists.  The problem there is
> that this code depends on user space code to suspend and then resume the
> processes to be migrated before/after the migration.  Christoph suggested
> using PF_FREEZE, but I pointed out that was broken on SMP so hence the
> current patch.
> 
> The idea would be to use PF_FREEZE to cause the process suspension.
> A minor flaw in this approach is what happens if a process migration
> is in progress when the machine is suspended/resumed.  (Probably not
> a common occurrence on Altix... :-), but anyway...).  If the processes
> are PF_FROZEN by the migration code, then unfrozen by the resume code,
> and then the migration code continues, then we have unstopped processes
> being migratated again.  Not a good thing.  On the other hand, the

Should be very easy to solve with one semaphore. Simply make swsusp
wait until all migrations are done.  

> Is the above scenario even possible?  manual page migration runs as a system
> call.  Do system calls all complete before suspend starts?  If that is
> the case, then the above is not something to worry about.

Yes, are normal system calls complete before suspend starts -- but
that's what refrigerator cares about.

> Finally, how comfortable are people about using the PF_FREEZE stuff
> to start and resume processes for purposes unrelated to suspend/resume?

No problem with that...

BTW smp notebooks will come, sooner or later, and 2-core 2-way-HT
notebook is already NUMA system.
								Pavel
-- 
Boycott Kodak -- for their patent abuse against Java.
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"aart@kvack.org"> aart@kvack.org </a>

^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: [RFC] Fix SMP brokenness for PF_FREEZE and make freezing usable for other purposes
  2005-06-27  5:53               ` Christoph Lameter
@ 2005-06-27 14:13                 ` Pavel Machek
  2005-06-27 15:13                   ` Christoph Lameter
  2005-06-28 21:50                 ` [RFC] Fix SMP brokenness for PF_FREEZE and make freezing usable for other purposes Ray Bryant
  1 sibling, 1 reply; 35+ messages in thread
From: Pavel Machek @ 2005-06-27 14:13 UTC (permalink / raw)
  To: Christoph Lameter; +Cc: Linus Torvalds, linux-mm, linux-kernel, raybry

Hi!

> > It's called "work", and we have the "TIF_xxx" flags for it. That's how 
> > "need-resched" and "sigpending" are done. There could be a 
> > "TIF_FREEZEPENDING" thing there too..
> 
> Ok. Here is yet another version of the patch:
> 
> ---
> The current suspend code modifies thread flags from outside the context of process.
> This creates a SMP race.
> 
> The patch fixes that by introducing a TIF_FREEZE flag (for all arches). Also
> 
> - Uses a completion handler instead of waiting in a schedule loop in the refrigerator.
> 
> - Introduces a semaphore freezer_sem to provide a way that multiple kernel
>   subsystems can use the freezing ability without interfering with one another.
> 
> - Include necessary definitions for the migration code if CONFIG_MIGRATE is set.
> 
> - Removes PF_FREEZE
> 
> If this approach is okay then we will need to move the refrigerator() and the
> definition of the semaphore and the completion variable out of kernel/power/process.c
> into kernel/sched.c (right?).

Approach seems okay... Perhaps better place is something like
kernel/freezer.c so it stays separate file? It is not really scheduler
core, and it is only conditionally compiled...
								Pavel
-- 
Boycott Kodak -- for their patent abuse against Java.
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"aart@kvack.org"> aart@kvack.org </a>

^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: [RFC] Fix SMP brokenness for PF_FREEZE and make freezing usable for other purposes
  2005-06-27 13:17     ` Pavel Machek
@ 2005-06-27 14:59       ` Ray Bryant
  2005-06-27 18:05         ` Pavel Machek
  0 siblings, 1 reply; 35+ messages in thread
From: Ray Bryant @ 2005-06-27 14:59 UTC (permalink / raw)
  To: Pavel Machek
  Cc: Kirill Korotaev, Christoph Lameter, linux-mm, linux-kernel,
	torvalds, lhms

Hi Pavel,

Pavel Machek wrote:

> 
> Should be very easy to solve with one semaphore. Simply make swsusp
> wait until all migrations are done.  
>

This may not be needed.  If I understand things correctly, the system
won't suspsend until all tasks have returned from system calls and end
up in the refrigerator.  So if a memory migration is  running when
someone tries to suspend the system, the suspend won't
occur until the memory migration system call returns.

Is that correct?

What happens if a system call calls schedule() (or otherwise gets blocked,
e. g. by trying to obtain a semaphore?)

-- 
Best Regards,
Ray
-----------------------------------------------
                   Ray Bryant
512-453-9679 (work)         512-507-7807 (cell)
raybry@sgi.com             raybry@austin.rr.com
The box said: "Requires Windows 98 or better",
            so I installed Linux.
-----------------------------------------------
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"aart@kvack.org"> aart@kvack.org </a>

^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: [RFC] Fix SMP brokenness for PF_FREEZE and make freezing usable for other purposes
  2005-06-27 14:13                 ` Pavel Machek
@ 2005-06-27 15:13                   ` Christoph Lameter
  2005-06-28  6:18                     ` Kirill Korotaev
  0 siblings, 1 reply; 35+ messages in thread
From: Christoph Lameter @ 2005-06-27 15:13 UTC (permalink / raw)
  To: Pavel Machek; +Cc: Linus Torvalds, linux-mm, linux-kernel, raybry

On Mon, 27 Jun 2005, Pavel Machek wrote:

> Approach seems okay... Perhaps better place is something like
> kernel/freezer.c so it stays separate file? It is not really scheduler
> core, and it is only conditionally compiled...

There is already lots of other conditional code in kernel/sched.c and this 
is just one function. It is scheduler like and uses scheduler variables 
since it suspends a process. So lets move it there.

I think this is as far as I can take it. Could you test this and see 
if it works okay?

For suspension for migration do:

1. down(&freezer_sem)

2. Signal processes to sleep (see kernel/power/process.c). Basically
   set the TIF_FREEZE and may be do the fake signal thing.

3. If all processes have PF_FROZEN set then they are asleep.

4. Do migration things

5. complete_all(&thaw)

6. up(&freezer_sem)

----
Revise handling of freezing in the suspend code

The current suspend code modifies thread flags from outside the context of process.
This creates a SMP race.

The patch fixes that by introducing a TIF_FREEZE flag (for all arches). Also

- Uses a completion handler instead of waiting in a schedule loop in the refrigerator.

- Introduces a semaphore freezer_sem to provide a way that multiple kernel
  subsystems can use the freezing ability without interfering with one another.

- Include necessary definitions for the migration code if CONFIG_MIGRATE is set.

- Removes PF_FREEZE

Signed-off-by: Christoph Lameter <christoph@lameter.com>

Index: linux-2.6.12/include/linux/sched.h
===================================================================
--- linux-2.6.12.orig/include/linux/sched.h	2005-06-27 05:20:15.000000000 +0000
+++ linux-2.6.12/include/linux/sched.h	2005-06-27 05:33:46.000000000 +0000
@@ -804,7 +804,6 @@ do { if (atomic_dec_and_test(&(tsk)->usa
 #define PF_MEMALLOC	0x00000800	/* Allocating memory */
 #define PF_FLUSHER	0x00001000	/* responsible for disk writeback */
 #define PF_USED_MATH	0x00002000	/* if unset the fpu must be initialized before use */
-#define PF_FREEZE	0x00004000	/* this task is being frozen for suspend now */
 #define PF_NOFREEZE	0x00008000	/* this thread should not be frozen */
 #define PF_FROZEN	0x00010000	/* frozen for system suspend */
 #define PF_FSTRANS	0x00020000	/* inside a filesystem transaction */
@@ -1265,78 +1264,37 @@ extern void normalize_rt_tasks(void);
 
 #endif
 
-#ifdef CONFIG_PM
-/*
- * 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;
-}
+#if defined(CONFIG_PM) || defined(CONFIG_MIGRATE)
+extern struct semaphore freezer_sem;
+extern struct completion thaw;
 
-/*
- * 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;
-}
+extern void refrigerator(void);
 
-/*
- * freezing is complete, mark process as frozen
- */
-static inline void frozen_process(struct task_struct *p)
+static inline int freezing(struct task_struct *p)
 {
-	p->flags = (p->flags & ~PF_FREEZE) | PF_FROZEN;
+	return test_ti_thread_flag(p->thread_info, TIF_FREEZE);
 }
 
-extern void refrigerator(void);
-extern int freeze_processes(void);
-extern void thaw_processes(void);
-
 static inline int try_to_freeze(void)
 {
-	if (freezing(current)) {
+	if (test_thread_flag(TIF_FREEZE)) {
 		refrigerator();
 		return 1;
 	} else
 		return 0;
 }
 #else
-static inline int frozen(struct task_struct *p) { return 0; }
+static inline void refrigerator(void) {}
 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 int try_to_freeze(void) { return 0; }
+#endif
 
-static inline void refrigerator(void) {}
+#ifdef CONFIG_PM
+extern int freeze_processes(void);
+extern void thaw_processes(void);
+#else
 static inline int freeze_processes(void) { BUG(); return 0; }
 static inline void thaw_processes(void) {}
-
-static inline int try_to_freeze(void) { return 0; }
-
 #endif /* CONFIG_PM */
 #endif /* __KERNEL__ */
 
Index: linux-2.6.12/kernel/power/process.c
===================================================================
--- linux-2.6.12.orig/kernel/power/process.c	2005-06-27 05:20:15.000000000 +0000
+++ linux-2.6.12/kernel/power/process.c	2005-06-27 15:07:46.000000000 +0000
@@ -18,7 +18,6 @@
  */
 #define TIMEOUT	(6 * HZ)
 
-
 static inline int freezeable(struct task_struct * p)
 {
 	if ((p == current) || 
@@ -31,28 +30,6 @@ static inline int freezeable(struct task
 	return 1;
 }
 
-/* Refrigerator is place where frozen processes are stored :-). */
-void refrigerator(void)
-{
-	/* Hmm, should we be allowed to suspend when there are realtime
-	   processes around? */
-	long save;
-	save = current->state;
-	current->state = TASK_UNINTERRUPTIBLE;
-	pr_debug("%s entered refrigerator\n", current->comm);
-	printk("=");
-
-	frozen_process(current);
-	spin_lock_irq(&current->sighand->siglock);
-	recalc_sigpending(); /* We sent fake signal, clean it up */
-	spin_unlock_irq(&current->sighand->siglock);
-
-	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)
 {
@@ -60,6 +37,7 @@ int freeze_processes(void)
 	unsigned long start_time;
 	struct task_struct *g, *p;
 
+	down(&freezer_sem);
 	printk( "Stopping tasks: " );
 	start_time = jiffies;
 	do {
@@ -69,12 +47,12 @@ int freeze_processes(void)
 			unsigned long flags;
 			if (!freezeable(p))
 				continue;
-			if ((frozen(p)) ||
+			if ((p->flags & PF_FROZEN) ||
 			    (p->state == TASK_TRACED) ||
 			    (p->state == TASK_STOPPED))
 				continue;
 
-			freeze(p);
+			set_thread_flag(TIF_FREEZE);
 			spin_lock_irqsave(&p->sighand->siglock, flags);
 			signal_wake_up(p, 0);
 			spin_unlock_irqrestore(&p->sighand->siglock, flags);
@@ -96,20 +74,6 @@ int freeze_processes(void)
 
 void thaw_processes(void)
 {
-	struct task_struct *g, *p;
-
-	printk( "Restarting tasks..." );
-	read_lock(&tasklist_lock);
-	do_each_thread(g, p) {
-		if (!freezeable(p))
-			continue;
-		if (!thaw_process(p))
-			printk(KERN_INFO " Strange, %s not stopped\n", p->comm );
-	} while_each_thread(g, p);
-
-	read_unlock(&tasklist_lock);
-	schedule();
-	printk( " done\n" );
+	complete_all(&thaw);
+	up(&freezer_sem);
 }
-
-EXPORT_SYMBOL(refrigerator);
Index: linux-2.6.12/include/asm-x86_64/thread_info.h
===================================================================
--- linux-2.6.12.orig/include/asm-x86_64/thread_info.h	2005-06-27 05:20:15.000000000 +0000
+++ linux-2.6.12/include/asm-x86_64/thread_info.h	2005-06-27 05:37:24.000000000 +0000
@@ -108,6 +108,7 @@ static inline struct thread_info *stack_
 #define TIF_FORK		18	/* ret_from_fork */
 #define TIF_ABI_PENDING		19
 #define TIF_MEMDIE		20
+#define TIF_FREEZE		21	/* Freeze process */
 
 #define _TIF_SYSCALL_TRACE	(1<<TIF_SYSCALL_TRACE)
 #define _TIF_NOTIFY_RESUME	(1<<TIF_NOTIFY_RESUME)
Index: linux-2.6.12/include/asm-ia64/thread_info.h
===================================================================
--- linux-2.6.12.orig/include/asm-ia64/thread_info.h	2005-06-27 05:20:15.000000000 +0000
+++ linux-2.6.12/include/asm-ia64/thread_info.h	2005-06-27 05:26:12.000000000 +0000
@@ -76,6 +76,7 @@ struct thread_info {
 #define TIF_SIGDELAYED		5	/* signal delayed from MCA/INIT/NMI/PMI context */
 #define TIF_POLLING_NRFLAG	16	/* true if poll_idle() is polling TIF_NEED_RESCHED */
 #define TIF_MEMDIE		17
+#define TIF_FREEZE		18	/* Freeze process */
 
 #define _TIF_SYSCALL_TRACE	(1 << TIF_SYSCALL_TRACE)
 #define _TIF_SYSCALL_AUDIT	(1 << TIF_SYSCALL_AUDIT)
Index: linux-2.6.12/include/asm-i386/thread_info.h
===================================================================
--- linux-2.6.12.orig/include/asm-i386/thread_info.h	2005-06-27 05:20:15.000000000 +0000
+++ linux-2.6.12/include/asm-i386/thread_info.h	2005-06-27 05:25:49.000000000 +0000
@@ -143,6 +143,7 @@ register unsigned long current_stack_poi
 #define TIF_SECCOMP		8	/* secure computing */
 #define TIF_POLLING_NRFLAG	16	/* true if poll_idle() is polling TIF_NEED_RESCHED */
 #define TIF_MEMDIE		17
+#define TIF_FREEZE		18	/* Freeze thread */
 
 #define _TIF_SYSCALL_TRACE	(1<<TIF_SYSCALL_TRACE)
 #define _TIF_NOTIFY_RESUME	(1<<TIF_NOTIFY_RESUME)
Index: linux-2.6.12/include/asm-xtensa/thread_info.h
===================================================================
--- linux-2.6.12.orig/include/asm-xtensa/thread_info.h	2005-06-27 02:23:01.000000000 +0000
+++ linux-2.6.12/include/asm-xtensa/thread_info.h	2005-06-27 05:36:54.000000000 +0000
@@ -118,6 +118,7 @@ static inline struct thread_info *curren
 #define TIF_SINGLESTEP		4	/* restore singlestep on return to user mode */
 #define TIF_IRET		5	/* return with iret */
 #define TIF_MEMDIE		6
+#define TIF_FREEZE		7
 #define TIF_POLLING_NRFLAG	16	/* true if poll_idle() is polling TIF_NEED_RESCHED */
 
 #define _TIF_SYSCALL_TRACE	(1<<TIF_SYSCALL_TRACE)
Index: linux-2.6.12/include/asm-h8300/thread_info.h
===================================================================
--- linux-2.6.12.orig/include/asm-h8300/thread_info.h	2005-06-27 02:23:01.000000000 +0000
+++ linux-2.6.12/include/asm-h8300/thread_info.h	2005-06-27 05:25:25.000000000 +0000
@@ -94,6 +94,7 @@ static inline struct thread_info *curren
 #define TIF_POLLING_NRFLAG	4	/* true if poll_idle() is polling
 					   TIF_NEED_RESCHED */
 #define TIF_MEMDIE		5
+#define TIF_FREEZE		6
 
 /* as above, but as bit values */
 #define _TIF_SYSCALL_TRACE	(1<<TIF_SYSCALL_TRACE)
Index: linux-2.6.12/include/asm-ppc/thread_info.h
===================================================================
--- linux-2.6.12.orig/include/asm-ppc/thread_info.h	2005-06-27 02:23:01.000000000 +0000
+++ linux-2.6.12/include/asm-ppc/thread_info.h	2005-06-27 05:28:53.000000000 +0000
@@ -80,6 +80,7 @@ static inline struct thread_info *curren
 #define TIF_MEMDIE		5
 #define TIF_SYSCALL_AUDIT       6       /* syscall auditing active */
 #define TIF_SECCOMP             7      /* secure computing */
+#define TIF_FREEZE		8
 
 /* as above, but as bit values */
 #define _TIF_SYSCALL_TRACE	(1<<TIF_SYSCALL_TRACE)
Index: linux-2.6.12/include/asm-sh64/thread_info.h
===================================================================
--- linux-2.6.12.orig/include/asm-sh64/thread_info.h	2005-06-27 02:23:01.000000000 +0000
+++ linux-2.6.12/include/asm-sh64/thread_info.h	2005-06-27 05:35:02.000000000 +0000
@@ -80,6 +80,7 @@ static inline struct thread_info *curren
 #define TIF_SIGPENDING		2	/* signal pending */
 #define TIF_NEED_RESCHED	3	/* rescheduling necessary */
 #define TIF_MEMDIE		4
+#define TIF_FREEZE		5
 
 
 #endif /* __KERNEL__ */
Index: linux-2.6.12/include/asm-alpha/thread_info.h
===================================================================
--- linux-2.6.12.orig/include/asm-alpha/thread_info.h	2005-06-17 19:48:29.000000000 +0000
+++ linux-2.6.12/include/asm-alpha/thread_info.h	2005-06-27 05:23:06.000000000 +0000
@@ -78,6 +78,7 @@ register struct thread_info *__current_t
 #define TIF_UAC_NOFIX		7
 #define TIF_UAC_SIGBUS		8
 #define TIF_MEMDIE		9
+#define TIF_FREEZE		10
 
 #define _TIF_SYSCALL_TRACE	(1<<TIF_SYSCALL_TRACE)
 #define _TIF_NOTIFY_RESUME	(1<<TIF_NOTIFY_RESUME)
Index: linux-2.6.12/include/asm-sparc/thread_info.h
===================================================================
--- linux-2.6.12.orig/include/asm-sparc/thread_info.h	2005-06-27 02:23:01.000000000 +0000
+++ linux-2.6.12/include/asm-sparc/thread_info.h	2005-06-27 05:35:23.000000000 +0000
@@ -139,6 +139,7 @@ BTFIXUPDEF_CALL(void, free_thread_info, 
 #define TIF_POLLING_NRFLAG	9	/* true if poll_idle() is polling
 					 * TIF_NEED_RESCHED */
 #define TIF_MEMDIE		10
+#define TIF_FREEZE		11
 
 /* as above, but as bit values */
 #define _TIF_SYSCALL_TRACE	(1<<TIF_SYSCALL_TRACE)
Index: linux-2.6.12/include/asm-frv/thread_info.h
===================================================================
--- linux-2.6.12.orig/include/asm-frv/thread_info.h	2005-06-27 02:23:01.000000000 +0000
+++ linux-2.6.12/include/asm-frv/thread_info.h	2005-06-27 05:25:02.000000000 +0000
@@ -133,6 +133,7 @@ register struct thread_info *__current_t
 #define TIF_IRET		5	/* return with iret */
 #define TIF_POLLING_NRFLAG	16	/* true if poll_idle() is polling TIF_NEED_RESCHED */
 #define TIF_MEMDIE		17	/* OOM killer killed process */
+#define TIF_FREEZE		18
 
 #define _TIF_SYSCALL_TRACE	(1 << TIF_SYSCALL_TRACE)
 #define _TIF_NOTIFY_RESUME	(1 << TIF_NOTIFY_RESUME)
Index: linux-2.6.12/include/asm-parisc/thread_info.h
===================================================================
--- linux-2.6.12.orig/include/asm-parisc/thread_info.h	2005-06-27 02:23:01.000000000 +0000
+++ linux-2.6.12/include/asm-parisc/thread_info.h	2005-06-27 05:28:34.000000000 +0000
@@ -64,6 +64,7 @@ struct thread_info {
 #define TIF_POLLING_NRFLAG	4	/* true if poll_idle() is polling TIF_NEED_RESCHED */
 #define TIF_32BIT               5       /* 32 bit binary */
 #define TIF_MEMDIE		6
+#define TIF_FREEZE		7
 
 #define _TIF_SYSCALL_TRACE	(1 << TIF_SYSCALL_TRACE)
 #define _TIF_NOTIFY_RESUME	(1 << TIF_NOTIFY_RESUME)
Index: linux-2.6.12/include/asm-m68knommu/thread_info.h
===================================================================
--- linux-2.6.12.orig/include/asm-m68knommu/thread_info.h	2005-06-27 02:23:01.000000000 +0000
+++ linux-2.6.12/include/asm-m68knommu/thread_info.h	2005-06-27 05:27:13.000000000 +0000
@@ -91,6 +91,7 @@ static inline struct thread_info *curren
 #define TIF_POLLING_NRFLAG	4	/* true if poll_idle() is polling
 					   TIF_NEED_RESCHED */
 #define TIF_MEMDIE		5
+#define TIF_FREEZE		6
 
 /* as above, but as bit values */
 #define _TIF_SYSCALL_TRACE	(1<<TIF_SYSCALL_TRACE)
Index: linux-2.6.12/include/asm-m68k/thread_info.h
===================================================================
--- linux-2.6.12.orig/include/asm-m68k/thread_info.h	2005-06-27 02:23:01.000000000 +0000
+++ linux-2.6.12/include/asm-m68k/thread_info.h	2005-06-27 05:26:49.000000000 +0000
@@ -49,6 +49,7 @@ struct thread_info {
 #define TIF_SIGPENDING		3	/* signal pending */
 #define TIF_NEED_RESCHED	4	/* rescheduling necessary */
 #define TIF_MEMDIE		5
+#define TIF_FREEZE		6
 
 extern int thread_flag_fixme(void);
 
Index: linux-2.6.12/include/asm-sh/thread_info.h
===================================================================
--- linux-2.6.12.orig/include/asm-sh/thread_info.h	2005-06-27 02:23:01.000000000 +0000
+++ linux-2.6.12/include/asm-sh/thread_info.h	2005-06-27 05:34:43.000000000 +0000
@@ -84,6 +84,7 @@ static inline struct thread_info *curren
 #define TIF_USEDFPU		16	/* FPU was used by this task this quantum (SMP) */
 #define TIF_POLLING_NRFLAG	17	/* true if poll_idle() is polling TIF_NEED_RESCHED */
 #define TIF_MEMDIE		18
+#define TIF_FREEZE		19
 #define TIF_USERSPACE		31	/* true if FS sets userspace */
 
 #define _TIF_SYSCALL_TRACE	(1<<TIF_SYSCALL_TRACE)
Index: linux-2.6.12/include/asm-s390/thread_info.h
===================================================================
--- linux-2.6.12.orig/include/asm-s390/thread_info.h	2005-06-27 02:23:01.000000000 +0000
+++ linux-2.6.12/include/asm-s390/thread_info.h	2005-06-27 05:34:19.000000000 +0000
@@ -102,6 +102,7 @@ static inline struct thread_info *curren
 					   TIF_NEED_RESCHED */
 #define TIF_31BIT		18	/* 32bit process */ 
 #define TIF_MEMDIE		19
+#define TIF_FREEZE		20
 
 #define _TIF_SYSCALL_TRACE	(1<<TIF_SYSCALL_TRACE)
 #define _TIF_NOTIFY_RESUME	(1<<TIF_NOTIFY_RESUME)
Index: linux-2.6.12/include/asm-arm/thread_info.h
===================================================================
--- linux-2.6.12.orig/include/asm-arm/thread_info.h	2005-06-27 02:23:01.000000000 +0000
+++ linux-2.6.12/include/asm-arm/thread_info.h	2005-06-27 05:23:34.000000000 +0000
@@ -132,6 +132,7 @@ extern void iwmmxt_task_release(struct t
 #define TIF_POLLING_NRFLAG	16
 #define TIF_USING_IWMMXT	17
 #define TIF_MEMDIE		18
+#define TIF_FREEZE		19
 
 #define _TIF_NOTIFY_RESUME	(1 << TIF_NOTIFY_RESUME)
 #define _TIF_SIGPENDING		(1 << TIF_SIGPENDING)
Index: linux-2.6.12/include/asm-v850/thread_info.h
===================================================================
--- linux-2.6.12.orig/include/asm-v850/thread_info.h	2005-06-27 02:23:01.000000000 +0000
+++ linux-2.6.12/include/asm-v850/thread_info.h	2005-06-27 05:36:25.000000000 +0000
@@ -85,6 +85,7 @@ struct thread_info {
 #define TIF_POLLING_NRFLAG	4	/* true if poll_idle() is polling
 					   TIF_NEED_RESCHED */
 #define TIF_MEMDIE		5
+#define TIF_FREEZE		6
 
 /* as above, but as bit values */
 #define _TIF_SYSCALL_TRACE	(1<<TIF_SYSCALL_TRACE)
Index: linux-2.6.12/include/asm-mips/thread_info.h
===================================================================
--- linux-2.6.12.orig/include/asm-mips/thread_info.h	2005-06-27 02:23:01.000000000 +0000
+++ linux-2.6.12/include/asm-mips/thread_info.h	2005-06-27 05:27:41.000000000 +0000
@@ -117,6 +117,7 @@ register struct thread_info *__current_t
 #define TIF_USEDFPU		16	/* FPU was used by this task this quantum (SMP) */
 #define TIF_POLLING_NRFLAG	17	/* true if poll_idle() is polling TIF_NEED_RESCHED */
 #define TIF_MEMDIE		18
+#define TIF_FREEZE		19
 #define TIF_SYSCALL_TRACE	31	/* syscall trace active */
 
 #define _TIF_SYSCALL_TRACE	(1<<TIF_SYSCALL_TRACE)
Index: linux-2.6.12/include/asm-cris/thread_info.h
===================================================================
--- linux-2.6.12.orig/include/asm-cris/thread_info.h	2005-06-27 02:23:01.000000000 +0000
+++ linux-2.6.12/include/asm-cris/thread_info.h	2005-06-27 05:24:28.000000000 +0000
@@ -86,6 +86,7 @@ struct thread_info {
 #define TIF_NEED_RESCHED	3	/* rescheduling necessary */
 #define TIF_POLLING_NRFLAG	16	/* true if poll_idle() is polling TIF_NEED_RESCHED */
 #define TIF_MEMDIE		17
+#define TIF_FREEZE		18
 
 #define _TIF_SYSCALL_TRACE	(1<<TIF_SYSCALL_TRACE)
 #define _TIF_NOTIFY_RESUME	(1<<TIF_NOTIFY_RESUME)
Index: linux-2.6.12/include/asm-arm26/thread_info.h
===================================================================
--- linux-2.6.12.orig/include/asm-arm26/thread_info.h	2005-06-27 02:23:01.000000000 +0000
+++ linux-2.6.12/include/asm-arm26/thread_info.h	2005-06-27 05:24:02.000000000 +0000
@@ -127,6 +127,7 @@ extern void free_thread_info(struct thre
 #define TIF_USED_FPU		16
 #define TIF_POLLING_NRFLAG	17
 #define TIF_MEMDIE		18
+#define TIF_FREEZE		19
 
 #define _TIF_NOTIFY_RESUME	(1 << TIF_NOTIFY_RESUME)
 #define _TIF_SIGPENDING		(1 << TIF_SIGPENDING)
Index: linux-2.6.12/include/asm-sparc64/thread_info.h
===================================================================
--- linux-2.6.12.orig/include/asm-sparc64/thread_info.h	2005-06-27 02:23:01.000000000 +0000
+++ linux-2.6.12/include/asm-sparc64/thread_info.h	2005-06-27 05:35:45.000000000 +0000
@@ -229,6 +229,7 @@ register struct thread_info *current_thr
  */
 #define TIF_ABI_PENDING		12
 #define TIF_MEMDIE		13
+#define TIF_FREEZE		14
 
 #define _TIF_SYSCALL_TRACE	(1<<TIF_SYSCALL_TRACE)
 #define _TIF_NOTIFY_RESUME	(1<<TIF_NOTIFY_RESUME)
Index: linux-2.6.12/include/asm-m32r/thread_info.h
===================================================================
--- linux-2.6.12.orig/include/asm-m32r/thread_info.h	2005-06-27 02:23:01.000000000 +0000
+++ linux-2.6.12/include/asm-m32r/thread_info.h	2005-06-27 05:26:33.000000000 +0000
@@ -156,6 +156,7 @@ static inline unsigned int get_thread_fa
 #define TIF_POLLING_NRFLAG	16	/* true if poll_idle() is polling TIF_NEED_RESCHED */
 					/* 31..28 fault code */
 #define TIF_MEMDIE		17
+#define TIF_FREEZE		18
 
 #define _TIF_SYSCALL_TRACE	(1<<TIF_SYSCALL_TRACE)
 #define _TIF_NOTIFY_RESUME	(1<<TIF_NOTIFY_RESUME)
Index: linux-2.6.12/include/asm-ppc64/thread_info.h
===================================================================
--- linux-2.6.12.orig/include/asm-ppc64/thread_info.h	2005-06-27 02:23:01.000000000 +0000
+++ linux-2.6.12/include/asm-ppc64/thread_info.h	2005-06-27 05:29:13.000000000 +0000
@@ -102,6 +102,7 @@ static inline struct thread_info *curren
 #define TIF_SINGLESTEP		9	/* singlestepping active */
 #define TIF_MEMDIE		10
 #define TIF_SECCOMP		11	/* secure computing */
+#define TIF_FREEZE		12
 
 /* as above, but as bit values */
 #define _TIF_SYSCALL_TRACE	(1<<TIF_SYSCALL_TRACE)
Index: linux-2.6.12/include/asm-um/thread_info.h
===================================================================
--- linux-2.6.12.orig/include/asm-um/thread_info.h	2005-06-27 02:23:01.000000000 +0000
+++ linux-2.6.12/include/asm-um/thread_info.h	2005-06-27 05:36:07.000000000 +0000
@@ -72,6 +72,7 @@ static inline struct thread_info *curren
 #define TIF_RESTART_BLOCK 	4
 #define TIF_MEMDIE	 	5
 #define TIF_SYSCALL_AUDIT	6
+#define TIF_FREEZE		7
 
 #define _TIF_SYSCALL_TRACE	(1 << TIF_SYSCALL_TRACE)
 #define _TIF_SIGPENDING		(1 << TIF_SIGPENDING)
Index: linux-2.6.12/kernel/sched.c
===================================================================
--- linux-2.6.12.orig/kernel/sched.c	2005-06-27 02:23:01.000000000 +0000
+++ linux-2.6.12/kernel/sched.c	2005-06-27 15:08:19.000000000 +0000
@@ -5203,6 +5203,25 @@ void __init sched_init(void)
 	init_idle(current, smp_processor_id());
 }
 
+#if defined(CONFIG_PM) || defined(CONFIG_MIGRATE)
+DECLARE_MUTEX(freezer_sem);
+DECLARE_COMPLETION(thaw);
+
+void refrigerator(void)
+{
+	current->flags |= PF_FROZEN;
+	clear_thread_flag(TIF_FREEZE);
+	/* A fake signal 0 may have been sent. Recalculate sigpending */
+	spin_lock_irq(&current->sighand->siglock);
+	recalc_sigpending();
+	spin_unlock_irq(&current->sighand->siglock);
+	wait_for_completion(&thaw);
+	current->flags &= ~PF_FROZEN;
+}
+EXPORT_SYMBOL(refrigerator);
+#endif
+
+
 #ifdef CONFIG_DEBUG_SPINLOCK_SLEEP
 void __might_sleep(char *file, int line)
 {
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"aart@kvack.org"> aart@kvack.org </a>

^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: [RFC] Fix SMP brokenness for PF_FREEZE and make freezing usable for other purposes
  2005-06-27 14:59       ` Ray Bryant
@ 2005-06-27 18:05         ` Pavel Machek
  0 siblings, 0 replies; 35+ messages in thread
From: Pavel Machek @ 2005-06-27 18:05 UTC (permalink / raw)
  To: Ray Bryant
  Cc: Kirill Korotaev, Christoph Lameter, linux-mm, linux-kernel,
	torvalds, lhms

Hi!

> >Should be very easy to solve with one semaphore. Simply make swsusp
> >wait until all migrations are done.  
> 
> This may not be needed.  If I understand things correctly, the system
> won't suspsend until all tasks have returned from system calls and end
> up in the refrigerator.  So if a memory migration is  running when
> someone tries to suspend the system, the suspend won't
> occur until the memory migration system call returns.
> 
> Is that correct?

No, because now migration tries to using same freezer
mechanism. Oops. Semaphore solves it nicely....

								Pavel
-- 
Boycott Kodak -- for their patent abuse against Java.
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"aart@kvack.org"> aart@kvack.org </a>

^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: [RFC] Fix SMP brokenness for PF_FREEZE and make freezing usable for other purposes
  2005-06-27 15:13                   ` Christoph Lameter
@ 2005-06-28  6:18                     ` Kirill Korotaev
  2005-06-28  7:01                       ` Christoph Lameter
  2005-06-28 12:47                       ` Pavel Machek
  0 siblings, 2 replies; 35+ messages in thread
From: Kirill Korotaev @ 2005-06-28  6:18 UTC (permalink / raw)
  To: Christoph Lameter
  Cc: Pavel Machek, Linus Torvalds, linux-mm, linux-kernel, raybry,
	Alexey Kuznetsov

commented with <<<< inside

>>Approach seems okay... Perhaps better place is something like
>>kernel/freezer.c so it stays separate file? It is not really scheduler
>>core, and it is only conditionally compiled...
> 
> 
> There is already lots of other conditional code in kernel/sched.c and this 
> is just one function. It is scheduler like and uses scheduler variables 
> since it suspends a process. So lets move it there.
> 
> I think this is as far as I can take it. Could you test this and see 
> if it works okay?
> 
> For suspension for migration do:
> 
> 1. down(&freezer_sem)
> 
> 2. Signal processes to sleep (see kernel/power/process.c). Basically
>    set the TIF_FREEZE and may be do the fake signal thing.
> 
> 3. If all processes have PF_FROZEN set then they are asleep.
> 
> 4. Do migration things
> 
> 5. complete_all(&thaw)
> 
> 6. up(&freezer_sem)
> 
> ----
> Revise handling of freezing in the suspend code
> 
> The current suspend code modifies thread flags from outside the context of process.
> This creates a SMP race.
> 
> The patch fixes that by introducing a TIF_FREEZE flag (for all arches). Also
> 
> - Uses a completion handler instead of waiting in a schedule loop in the refrigerator.
> 
> - Introduces a semaphore freezer_sem to provide a way that multiple kernel
>   subsystems can use the freezing ability without interfering with one another.
> 
> - Include necessary definitions for the migration code if CONFIG_MIGRATE is set.
> 
> - Removes PF_FREEZE
> 
> Signed-off-by: Christoph Lameter <christoph@lameter.com>
> 
> Index: linux-2.6.12/include/linux/sched.h
> ===================================================================
> --- linux-2.6.12.orig/include/linux/sched.h	2005-06-27 05:20:15.000000000 +0000
> +++ linux-2.6.12/include/linux/sched.h	2005-06-27 05:33:46.000000000 +0000
> @@ -804,7 +804,6 @@ do { if (atomic_dec_and_test(&(tsk)->usa
>  #define PF_MEMALLOC	0x00000800	/* Allocating memory */
>  #define PF_FLUSHER	0x00001000	/* responsible for disk writeback */
>  #define PF_USED_MATH	0x00002000	/* if unset the fpu must be initialized before use */
> -#define PF_FREEZE	0x00004000	/* this task is being frozen for suspend now */
>  #define PF_NOFREEZE	0x00008000	/* this thread should not be frozen */
>  #define PF_FROZEN	0x00010000	/* frozen for system suspend */
>  #define PF_FSTRANS	0x00020000	/* inside a filesystem transaction */
> @@ -1265,78 +1264,37 @@ extern void normalize_rt_tasks(void);
>  
>  #endif
>  
> -#ifdef CONFIG_PM
> -/*
> - * 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;
> -}
> +#if defined(CONFIG_PM) || defined(CONFIG_MIGRATE)
<<<< why not to make a single option CONFIG_REFRIGERATOR? It looks to be 
a more robust way, since there are multiple users of it.
> +extern struct semaphore freezer_sem;
> +extern struct completion thaw;
>  
> -/*
> - * 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;
> -}
> +extern void refrigerator(void);
>  
> -/*
> - * freezing is complete, mark process as frozen
> - */
> -static inline void frozen_process(struct task_struct *p)
> +static inline int freezing(struct task_struct *p)
>  {
> -	p->flags = (p->flags & ~PF_FREEZE) | PF_FROZEN;
> +	return test_ti_thread_flag(p->thread_info, TIF_FREEZE);
>  }
>  
> -extern void refrigerator(void);
> -extern int freeze_processes(void);
> -extern void thaw_processes(void);
> -
>  static inline int try_to_freeze(void)
>  {
> -	if (freezing(current)) {
> +	if (test_thread_flag(TIF_FREEZE)) {
>  		refrigerator();
>  		return 1;
>  	} else
>  		return 0;
>  }
>  #else
> -static inline int frozen(struct task_struct *p) { return 0; }
> +static inline void refrigerator(void) {}
>  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 int try_to_freeze(void) { return 0; }
> +#endif
>  
> -static inline void refrigerator(void) {}
> +#ifdef CONFIG_PM
<<<< is it intentionaly? or you just lost CONFIG_MIGRATE?
> +extern int freeze_processes(void);
> +extern void thaw_processes(void);
> +#else
>  static inline int freeze_processes(void) { BUG(); return 0; }
>  static inline void thaw_processes(void) {}
> -
> -static inline int try_to_freeze(void) { return 0; }
> -
>  #endif /* CONFIG_PM */
>  #endif /* __KERNEL__ */
>  
> Index: linux-2.6.12/kernel/power/process.c
> ===================================================================
> --- linux-2.6.12.orig/kernel/power/process.c	2005-06-27 05:20:15.000000000 +0000
> +++ linux-2.6.12/kernel/power/process.c	2005-06-27 15:07:46.000000000 +0000
> @@ -18,7 +18,6 @@
>   */
>  #define TIMEOUT	(6 * HZ)
>  
> -
>  static inline int freezeable(struct task_struct * p)
>  {
>  	if ((p == current) || 
> @@ -31,28 +30,6 @@ static inline int freezeable(struct task
>  	return 1;
>  }
>  
> -/* Refrigerator is place where frozen processes are stored :-). */
> -void refrigerator(void)
> -{
> -	/* Hmm, should we be allowed to suspend when there are realtime
> -	   processes around? */
> -	long save;
> -	save = current->state;
> -	current->state = TASK_UNINTERRUPTIBLE;
> -	pr_debug("%s entered refrigerator\n", current->comm);
> -	printk("=");
> -
> -	frozen_process(current);
> -	spin_lock_irq(&current->sighand->siglock);
> -	recalc_sigpending(); /* We sent fake signal, clean it up */
> -	spin_unlock_irq(&current->sighand->siglock);
> -
> -	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)
>  {
> @@ -60,6 +37,7 @@ int freeze_processes(void)
>  	unsigned long start_time;
>  	struct task_struct *g, *p;
>  
> +	down(&freezer_sem);
>  	printk( "Stopping tasks: " );
>  	start_time = jiffies;
>  	do {
> @@ -69,12 +47,12 @@ int freeze_processes(void)
>  			unsigned long flags;
>  			if (!freezeable(p))
>  				continue;
> -			if ((frozen(p)) ||
> +			if ((p->flags & PF_FROZEN) ||
>  			    (p->state == TASK_TRACED) ||
>  			    (p->state == TASK_STOPPED))
>  				continue;
>  
> -			freeze(p);
> +			set_thread_flag(TIF_FREEZE);
>  			spin_lock_irqsave(&p->sighand->siglock, flags);
>  			signal_wake_up(p, 0);
>  			spin_unlock_irqrestore(&p->sighand->siglock, flags);
> @@ -96,20 +74,6 @@ int freeze_processes(void)
>  
>  void thaw_processes(void)
>  {
> -	struct task_struct *g, *p;
> -
> -	printk( "Restarting tasks..." );
> -	read_lock(&tasklist_lock);
> -	do_each_thread(g, p) {
> -		if (!freezeable(p))
> -			continue;
> -		if (!thaw_process(p))
> -			printk(KERN_INFO " Strange, %s not stopped\n", p->comm );
> -	} while_each_thread(g, p);
> -
> -	read_unlock(&tasklist_lock);
> -	schedule();
> -	printk( " done\n" );
> +	complete_all(&thaw);
> +	up(&freezer_sem);
>  }
> -
> -EXPORT_SYMBOL(refrigerator);
> Index: linux-2.6.12/include/asm-x86_64/thread_info.h
> ===================================================================
> --- linux-2.6.12.orig/include/asm-x86_64/thread_info.h	2005-06-27 05:20:15.000000000 +0000
> +++ linux-2.6.12/include/asm-x86_64/thread_info.h	2005-06-27 05:37:24.000000000 +0000
> @@ -108,6 +108,7 @@ static inline struct thread_info *stack_
>  #define TIF_FORK		18	/* ret_from_fork */
>  #define TIF_ABI_PENDING		19
>  #define TIF_MEMDIE		20
> +#define TIF_FREEZE		21	/* Freeze process */
>  
>  #define _TIF_SYSCALL_TRACE	(1<<TIF_SYSCALL_TRACE)
>  #define _TIF_NOTIFY_RESUME	(1<<TIF_NOTIFY_RESUME)
> Index: linux-2.6.12/include/asm-ia64/thread_info.h
> ===================================================================
> --- linux-2.6.12.orig/include/asm-ia64/thread_info.h	2005-06-27 05:20:15.000000000 +0000
> +++ linux-2.6.12/include/asm-ia64/thread_info.h	2005-06-27 05:26:12.000000000 +0000
> @@ -76,6 +76,7 @@ struct thread_info {
>  #define TIF_SIGDELAYED		5	/* signal delayed from MCA/INIT/NMI/PMI context */
>  #define TIF_POLLING_NRFLAG	16	/* true if poll_idle() is polling TIF_NEED_RESCHED */
>  #define TIF_MEMDIE		17
> +#define TIF_FREEZE		18	/* Freeze process */
>  
>  #define _TIF_SYSCALL_TRACE	(1 << TIF_SYSCALL_TRACE)
>  #define _TIF_SYSCALL_AUDIT	(1 << TIF_SYSCALL_AUDIT)
> Index: linux-2.6.12/include/asm-i386/thread_info.h
> ===================================================================
> --- linux-2.6.12.orig/include/asm-i386/thread_info.h	2005-06-27 05:20:15.000000000 +0000
> +++ linux-2.6.12/include/asm-i386/thread_info.h	2005-06-27 05:25:49.000000000 +0000
> @@ -143,6 +143,7 @@ register unsigned long current_stack_poi
>  #define TIF_SECCOMP		8	/* secure computing */
>  #define TIF_POLLING_NRFLAG	16	/* true if poll_idle() is polling TIF_NEED_RESCHED */
>  #define TIF_MEMDIE		17
> +#define TIF_FREEZE		18	/* Freeze thread */
>  
>  #define _TIF_SYSCALL_TRACE	(1<<TIF_SYSCALL_TRACE)
>  #define _TIF_NOTIFY_RESUME	(1<<TIF_NOTIFY_RESUME)
> Index: linux-2.6.12/include/asm-xtensa/thread_info.h
> ===================================================================
> --- linux-2.6.12.orig/include/asm-xtensa/thread_info.h	2005-06-27 02:23:01.000000000 +0000
> +++ linux-2.6.12/include/asm-xtensa/thread_info.h	2005-06-27 05:36:54.000000000 +0000
> @@ -118,6 +118,7 @@ static inline struct thread_info *curren
>  #define TIF_SINGLESTEP		4	/* restore singlestep on return to user mode */
>  #define TIF_IRET		5	/* return with iret */
>  #define TIF_MEMDIE		6
> +#define TIF_FREEZE		7
>  #define TIF_POLLING_NRFLAG	16	/* true if poll_idle() is polling TIF_NEED_RESCHED */
>  
>  #define _TIF_SYSCALL_TRACE	(1<<TIF_SYSCALL_TRACE)
> Index: linux-2.6.12/include/asm-h8300/thread_info.h
> ===================================================================
> --- linux-2.6.12.orig/include/asm-h8300/thread_info.h	2005-06-27 02:23:01.000000000 +0000
> +++ linux-2.6.12/include/asm-h8300/thread_info.h	2005-06-27 05:25:25.000000000 +0000
> @@ -94,6 +94,7 @@ static inline struct thread_info *curren
>  #define TIF_POLLING_NRFLAG	4	/* true if poll_idle() is polling
>  					   TIF_NEED_RESCHED */
>  #define TIF_MEMDIE		5
> +#define TIF_FREEZE		6
>  
>  /* as above, but as bit values */
>  #define _TIF_SYSCALL_TRACE	(1<<TIF_SYSCALL_TRACE)
> Index: linux-2.6.12/include/asm-ppc/thread_info.h
> ===================================================================
> --- linux-2.6.12.orig/include/asm-ppc/thread_info.h	2005-06-27 02:23:01.000000000 +0000
> +++ linux-2.6.12/include/asm-ppc/thread_info.h	2005-06-27 05:28:53.000000000 +0000
> @@ -80,6 +80,7 @@ static inline struct thread_info *curren
>  #define TIF_MEMDIE		5
>  #define TIF_SYSCALL_AUDIT       6       /* syscall auditing active */
>  #define TIF_SECCOMP             7      /* secure computing */
> +#define TIF_FREEZE		8
>  
>  /* as above, but as bit values */
>  #define _TIF_SYSCALL_TRACE	(1<<TIF_SYSCALL_TRACE)
> Index: linux-2.6.12/include/asm-sh64/thread_info.h
> ===================================================================
> --- linux-2.6.12.orig/include/asm-sh64/thread_info.h	2005-06-27 02:23:01.000000000 +0000
> +++ linux-2.6.12/include/asm-sh64/thread_info.h	2005-06-27 05:35:02.000000000 +0000
> @@ -80,6 +80,7 @@ static inline struct thread_info *curren
>  #define TIF_SIGPENDING		2	/* signal pending */
>  #define TIF_NEED_RESCHED	3	/* rescheduling necessary */
>  #define TIF_MEMDIE		4
> +#define TIF_FREEZE		5
>  
>  
>  #endif /* __KERNEL__ */
> Index: linux-2.6.12/include/asm-alpha/thread_info.h
> ===================================================================
> --- linux-2.6.12.orig/include/asm-alpha/thread_info.h	2005-06-17 19:48:29.000000000 +0000
> +++ linux-2.6.12/include/asm-alpha/thread_info.h	2005-06-27 05:23:06.000000000 +0000
> @@ -78,6 +78,7 @@ register struct thread_info *__current_t
>  #define TIF_UAC_NOFIX		7
>  #define TIF_UAC_SIGBUS		8
>  #define TIF_MEMDIE		9
> +#define TIF_FREEZE		10
>  
>  #define _TIF_SYSCALL_TRACE	(1<<TIF_SYSCALL_TRACE)
>  #define _TIF_NOTIFY_RESUME	(1<<TIF_NOTIFY_RESUME)
> Index: linux-2.6.12/include/asm-sparc/thread_info.h
> ===================================================================
> --- linux-2.6.12.orig/include/asm-sparc/thread_info.h	2005-06-27 02:23:01.000000000 +0000
> +++ linux-2.6.12/include/asm-sparc/thread_info.h	2005-06-27 05:35:23.000000000 +0000
> @@ -139,6 +139,7 @@ BTFIXUPDEF_CALL(void, free_thread_info, 
>  #define TIF_POLLING_NRFLAG	9	/* true if poll_idle() is polling
>  					 * TIF_NEED_RESCHED */
>  #define TIF_MEMDIE		10
> +#define TIF_FREEZE		11
>  
>  /* as above, but as bit values */
>  #define _TIF_SYSCALL_TRACE	(1<<TIF_SYSCALL_TRACE)
> Index: linux-2.6.12/include/asm-frv/thread_info.h
> ===================================================================
> --- linux-2.6.12.orig/include/asm-frv/thread_info.h	2005-06-27 02:23:01.000000000 +0000
> +++ linux-2.6.12/include/asm-frv/thread_info.h	2005-06-27 05:25:02.000000000 +0000
> @@ -133,6 +133,7 @@ register struct thread_info *__current_t
>  #define TIF_IRET		5	/* return with iret */
>  #define TIF_POLLING_NRFLAG	16	/* true if poll_idle() is polling TIF_NEED_RESCHED */
>  #define TIF_MEMDIE		17	/* OOM killer killed process */
> +#define TIF_FREEZE		18
>  
>  #define _TIF_SYSCALL_TRACE	(1 << TIF_SYSCALL_TRACE)
>  #define _TIF_NOTIFY_RESUME	(1 << TIF_NOTIFY_RESUME)
> Index: linux-2.6.12/include/asm-parisc/thread_info.h
> ===================================================================
> --- linux-2.6.12.orig/include/asm-parisc/thread_info.h	2005-06-27 02:23:01.000000000 +0000
> +++ linux-2.6.12/include/asm-parisc/thread_info.h	2005-06-27 05:28:34.000000000 +0000
> @@ -64,6 +64,7 @@ struct thread_info {
>  #define TIF_POLLING_NRFLAG	4	/* true if poll_idle() is polling TIF_NEED_RESCHED */
>  #define TIF_32BIT               5       /* 32 bit binary */
>  #define TIF_MEMDIE		6
> +#define TIF_FREEZE		7
>  
>  #define _TIF_SYSCALL_TRACE	(1 << TIF_SYSCALL_TRACE)
>  #define _TIF_NOTIFY_RESUME	(1 << TIF_NOTIFY_RESUME)
> Index: linux-2.6.12/include/asm-m68knommu/thread_info.h
> ===================================================================
> --- linux-2.6.12.orig/include/asm-m68knommu/thread_info.h	2005-06-27 02:23:01.000000000 +0000
> +++ linux-2.6.12/include/asm-m68knommu/thread_info.h	2005-06-27 05:27:13.000000000 +0000
> @@ -91,6 +91,7 @@ static inline struct thread_info *curren
>  #define TIF_POLLING_NRFLAG	4	/* true if poll_idle() is polling
>  					   TIF_NEED_RESCHED */
>  #define TIF_MEMDIE		5
> +#define TIF_FREEZE		6
>  
>  /* as above, but as bit values */
>  #define _TIF_SYSCALL_TRACE	(1<<TIF_SYSCALL_TRACE)
> Index: linux-2.6.12/include/asm-m68k/thread_info.h
> ===================================================================
> --- linux-2.6.12.orig/include/asm-m68k/thread_info.h	2005-06-27 02:23:01.000000000 +0000
> +++ linux-2.6.12/include/asm-m68k/thread_info.h	2005-06-27 05:26:49.000000000 +0000
> @@ -49,6 +49,7 @@ struct thread_info {
>  #define TIF_SIGPENDING		3	/* signal pending */
>  #define TIF_NEED_RESCHED	4	/* rescheduling necessary */
>  #define TIF_MEMDIE		5
> +#define TIF_FREEZE		6
>  
>  extern int thread_flag_fixme(void);
>  
> Index: linux-2.6.12/include/asm-sh/thread_info.h
> ===================================================================
> --- linux-2.6.12.orig/include/asm-sh/thread_info.h	2005-06-27 02:23:01.000000000 +0000
> +++ linux-2.6.12/include/asm-sh/thread_info.h	2005-06-27 05:34:43.000000000 +0000
> @@ -84,6 +84,7 @@ static inline struct thread_info *curren
>  #define TIF_USEDFPU		16	/* FPU was used by this task this quantum (SMP) */
>  #define TIF_POLLING_NRFLAG	17	/* true if poll_idle() is polling TIF_NEED_RESCHED */
>  #define TIF_MEMDIE		18
> +#define TIF_FREEZE		19
>  #define TIF_USERSPACE		31	/* true if FS sets userspace */
>  
>  #define _TIF_SYSCALL_TRACE	(1<<TIF_SYSCALL_TRACE)
> Index: linux-2.6.12/include/asm-s390/thread_info.h
> ===================================================================
> --- linux-2.6.12.orig/include/asm-s390/thread_info.h	2005-06-27 02:23:01.000000000 +0000
> +++ linux-2.6.12/include/asm-s390/thread_info.h	2005-06-27 05:34:19.000000000 +0000
> @@ -102,6 +102,7 @@ static inline struct thread_info *curren
>  					   TIF_NEED_RESCHED */
>  #define TIF_31BIT		18	/* 32bit process */ 
>  #define TIF_MEMDIE		19
> +#define TIF_FREEZE		20
>  
>  #define _TIF_SYSCALL_TRACE	(1<<TIF_SYSCALL_TRACE)
>  #define _TIF_NOTIFY_RESUME	(1<<TIF_NOTIFY_RESUME)
> Index: linux-2.6.12/include/asm-arm/thread_info.h
> ===================================================================
> --- linux-2.6.12.orig/include/asm-arm/thread_info.h	2005-06-27 02:23:01.000000000 +0000
> +++ linux-2.6.12/include/asm-arm/thread_info.h	2005-06-27 05:23:34.000000000 +0000
> @@ -132,6 +132,7 @@ extern void iwmmxt_task_release(struct t
>  #define TIF_POLLING_NRFLAG	16
>  #define TIF_USING_IWMMXT	17
>  #define TIF_MEMDIE		18
> +#define TIF_FREEZE		19
>  
>  #define _TIF_NOTIFY_RESUME	(1 << TIF_NOTIFY_RESUME)
>  #define _TIF_SIGPENDING		(1 << TIF_SIGPENDING)
> Index: linux-2.6.12/include/asm-v850/thread_info.h
> ===================================================================
> --- linux-2.6.12.orig/include/asm-v850/thread_info.h	2005-06-27 02:23:01.000000000 +0000
> +++ linux-2.6.12/include/asm-v850/thread_info.h	2005-06-27 05:36:25.000000000 +0000
> @@ -85,6 +85,7 @@ struct thread_info {
>  #define TIF_POLLING_NRFLAG	4	/* true if poll_idle() is polling
>  					   TIF_NEED_RESCHED */
>  #define TIF_MEMDIE		5
> +#define TIF_FREEZE		6
>  
>  /* as above, but as bit values */
>  #define _TIF_SYSCALL_TRACE	(1<<TIF_SYSCALL_TRACE)
> Index: linux-2.6.12/include/asm-mips/thread_info.h
> ===================================================================
> --- linux-2.6.12.orig/include/asm-mips/thread_info.h	2005-06-27 02:23:01.000000000 +0000
> +++ linux-2.6.12/include/asm-mips/thread_info.h	2005-06-27 05:27:41.000000000 +0000
> @@ -117,6 +117,7 @@ register struct thread_info *__current_t
>  #define TIF_USEDFPU		16	/* FPU was used by this task this quantum (SMP) */
>  #define TIF_POLLING_NRFLAG	17	/* true if poll_idle() is polling TIF_NEED_RESCHED */
>  #define TIF_MEMDIE		18
> +#define TIF_FREEZE		19
>  #define TIF_SYSCALL_TRACE	31	/* syscall trace active */
>  
>  #define _TIF_SYSCALL_TRACE	(1<<TIF_SYSCALL_TRACE)
> Index: linux-2.6.12/include/asm-cris/thread_info.h
> ===================================================================
> --- linux-2.6.12.orig/include/asm-cris/thread_info.h	2005-06-27 02:23:01.000000000 +0000
> +++ linux-2.6.12/include/asm-cris/thread_info.h	2005-06-27 05:24:28.000000000 +0000
> @@ -86,6 +86,7 @@ struct thread_info {
>  #define TIF_NEED_RESCHED	3	/* rescheduling necessary */
>  #define TIF_POLLING_NRFLAG	16	/* true if poll_idle() is polling TIF_NEED_RESCHED */
>  #define TIF_MEMDIE		17
> +#define TIF_FREEZE		18
>  
>  #define _TIF_SYSCALL_TRACE	(1<<TIF_SYSCALL_TRACE)
>  #define _TIF_NOTIFY_RESUME	(1<<TIF_NOTIFY_RESUME)
> Index: linux-2.6.12/include/asm-arm26/thread_info.h
> ===================================================================
> --- linux-2.6.12.orig/include/asm-arm26/thread_info.h	2005-06-27 02:23:01.000000000 +0000
> +++ linux-2.6.12/include/asm-arm26/thread_info.h	2005-06-27 05:24:02.000000000 +0000
> @@ -127,6 +127,7 @@ extern void free_thread_info(struct thre
>  #define TIF_USED_FPU		16
>  #define TIF_POLLING_NRFLAG	17
>  #define TIF_MEMDIE		18
> +#define TIF_FREEZE		19
>  
>  #define _TIF_NOTIFY_RESUME	(1 << TIF_NOTIFY_RESUME)
>  #define _TIF_SIGPENDING		(1 << TIF_SIGPENDING)
> Index: linux-2.6.12/include/asm-sparc64/thread_info.h
> ===================================================================
> --- linux-2.6.12.orig/include/asm-sparc64/thread_info.h	2005-06-27 02:23:01.000000000 +0000
> +++ linux-2.6.12/include/asm-sparc64/thread_info.h	2005-06-27 05:35:45.000000000 +0000
> @@ -229,6 +229,7 @@ register struct thread_info *current_thr
>   */
>  #define TIF_ABI_PENDING		12
>  #define TIF_MEMDIE		13
> +#define TIF_FREEZE		14
>  
>  #define _TIF_SYSCALL_TRACE	(1<<TIF_SYSCALL_TRACE)
>  #define _TIF_NOTIFY_RESUME	(1<<TIF_NOTIFY_RESUME)
> Index: linux-2.6.12/include/asm-m32r/thread_info.h
> ===================================================================
> --- linux-2.6.12.orig/include/asm-m32r/thread_info.h	2005-06-27 02:23:01.000000000 +0000
> +++ linux-2.6.12/include/asm-m32r/thread_info.h	2005-06-27 05:26:33.000000000 +0000
> @@ -156,6 +156,7 @@ static inline unsigned int get_thread_fa
>  #define TIF_POLLING_NRFLAG	16	/* true if poll_idle() is polling TIF_NEED_RESCHED */
>  					/* 31..28 fault code */
>  #define TIF_MEMDIE		17
> +#define TIF_FREEZE		18
>  
>  #define _TIF_SYSCALL_TRACE	(1<<TIF_SYSCALL_TRACE)
>  #define _TIF_NOTIFY_RESUME	(1<<TIF_NOTIFY_RESUME)
> Index: linux-2.6.12/include/asm-ppc64/thread_info.h
> ===================================================================
> --- linux-2.6.12.orig/include/asm-ppc64/thread_info.h	2005-06-27 02:23:01.000000000 +0000
> +++ linux-2.6.12/include/asm-ppc64/thread_info.h	2005-06-27 05:29:13.000000000 +0000
> @@ -102,6 +102,7 @@ static inline struct thread_info *curren
>  #define TIF_SINGLESTEP		9	/* singlestepping active */
>  #define TIF_MEMDIE		10
>  #define TIF_SECCOMP		11	/* secure computing */
> +#define TIF_FREEZE		12
>  
>  /* as above, but as bit values */
>  #define _TIF_SYSCALL_TRACE	(1<<TIF_SYSCALL_TRACE)
> Index: linux-2.6.12/include/asm-um/thread_info.h
> ===================================================================
> --- linux-2.6.12.orig/include/asm-um/thread_info.h	2005-06-27 02:23:01.000000000 +0000
> +++ linux-2.6.12/include/asm-um/thread_info.h	2005-06-27 05:36:07.000000000 +0000
> @@ -72,6 +72,7 @@ static inline struct thread_info *curren
>  #define TIF_RESTART_BLOCK 	4
>  #define TIF_MEMDIE	 	5
>  #define TIF_SYSCALL_AUDIT	6
> +#define TIF_FREEZE		7
>  
>  #define _TIF_SYSCALL_TRACE	(1 << TIF_SYSCALL_TRACE)
>  #define _TIF_SIGPENDING		(1 << TIF_SIGPENDING)
> Index: linux-2.6.12/kernel/sched.c
> ===================================================================
> --- linux-2.6.12.orig/kernel/sched.c	2005-06-27 02:23:01.000000000 +0000
> +++ linux-2.6.12/kernel/sched.c	2005-06-27 15:08:19.000000000 +0000
> @@ -5203,6 +5203,25 @@ void __init sched_init(void)
>  	init_idle(current, smp_processor_id());
>  }
>  
> +#if defined(CONFIG_PM) || defined(CONFIG_MIGRATE)
> +DECLARE_MUTEX(freezer_sem);
> +DECLARE_COMPLETION(thaw);
> +
> +void refrigerator(void)
> +{
> +	current->flags |= PF_FROZEN;
> +	clear_thread_flag(TIF_FREEZE);
> +	/* A fake signal 0 may have been sent. Recalculate sigpending */
> +	spin_lock_irq(&current->sighand->siglock);
> +	recalc_sigpending();
> +	spin_unlock_irq(&current->sighand->siglock);
> +	wait_for_completion(&thaw);
> +	current->flags &= ~PF_FROZEN;
<<<< I still think this refrigerator is racy with freeze_processes():
<<<< scenarios:
<<<< scenario 1
<<<<
task1 -> freeze_processes():			taskXXX ->refrigerator()
   checked (task->flags & PF_FROZEN) == 0	cur->flags |= PF_FROZEN
						clear TIF_FREEZE
						<sleep on thaw>
   set TIF_FREEZING
						clear PF_FROZEN

<<<< so the task awakes with TIF_FREEZE flag set!!!

<<<< scenario 2
<<<< look at error path in freeze_processes (on timeout), it is broken 
as well. You need to wakeup tasks there...

<<<< ------------------------------
> +}
> +EXPORT_SYMBOL(refrigerator);
> +#endif
> +
> +
>  #ifdef CONFIG_DEBUG_SPINLOCK_SLEEP
>  void __might_sleep(char *file, int line)
>  {
> -
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at  http://www.tux.org/lkml/
> 


--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"aart@kvack.org"> aart@kvack.org </a>

^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: [RFC] Fix SMP brokenness for PF_FREEZE and make freezing usable for other purposes
  2005-06-28  6:18                     ` Kirill Korotaev
@ 2005-06-28  7:01                       ` Christoph Lameter
  2005-06-28  7:30                         ` Kirill Korotaev
  2005-06-28 12:47                       ` Pavel Machek
  1 sibling, 1 reply; 35+ messages in thread
From: Christoph Lameter @ 2005-06-28  7:01 UTC (permalink / raw)
  To: Kirill Korotaev
  Cc: Pavel Machek, Linus Torvalds, linux-mm, linux-kernel, raybry,
	Alexey Kuznetsov

On Tue, 28 Jun 2005, Kirill Korotaev wrote:

> > -static inline int freezing(struct task_struct *p)
> > -{
> > -	return p->flags & PF_FREEZE;
> > -}
> > +#if defined(CONFIG_PM) || defined(CONFIG_MIGRATE)
> <<<< why not to make a single option CONFIG_REFRIGERATOR? It looks to be a
> more robust way, since there are multiple users of it.

Yes. That may be better. We can do that once the migration code is 
finished and when we know what kind of CONFIG_XXX the migration code 
really needs.

> > +#ifdef CONFIG_PM
> <<<< is it intentionaly? or you just lost CONFIG_MIGRATE?

It is intentional. freeze_processes and thaw_processes are only needed 
for suspend. One only needs to freeze a couple of processes for process 
migration.

> <<<< I still think this refrigerator is racy with freeze_processes():
> <<<< scenarios:
> <<<< scenario 1
> <<<<
> task1 -> freeze_processes():			taskXXX ->refrigerator()
>   checked (task->flags & PF_FROZEN) == 0	cur->flags |= PF_FROZEN
> 						clear TIF_FREEZE
> 						<sleep on thaw>
>   set TIF_FREEZING
> 						clear PF_FROZEN
> 
> <<<< so the task awakes with TIF_FREEZE flag set!!!

Hmm... If we wait to clear both flags until after the completion 
notification then we do not have the race right? But then we need to move 
the signal recalc since it tests for TIF_FREEZE too.
 
> <<<< scenario 2
> <<<< look at error path in freeze_processes (on timeout), it is broken as
> well. You need to wakeup tasks there...

Ok. How about this additional patch? This still requires that process 
freezing does not immediately occurr again after the completion 
handler. All of this is iffy due to not having a real lock protecting all 
these values and we may still need to add some barriers.

Index: linux-2.6.12/kernel/power/process.c
===================================================================
--- linux-2.6.12.orig/kernel/power/process.c	2005-06-28 06:34:52.000000000 +0000
+++ linux-2.6.12/kernel/power/process.c	2005-06-28 06:40:28.000000000 +0000
@@ -47,12 +47,13 @@ int freeze_processes(void)
 			unsigned long flags;
 			if (!freezeable(p))
 				continue;
-			if ((p->flags & PF_FROZEN) ||
-			    (p->state == TASK_TRACED) ||
+			if ((p->state == TASK_TRACED) ||
 			    (p->state == TASK_STOPPED))
 				continue;
 
 			set_thread_flag(TIF_FREEZE);
+			if (p->flags & PF_FROZEN)
+				continue;
 			spin_lock_irqsave(&p->sighand->siglock, flags);
 			signal_wake_up(p, 0);
 			spin_unlock_irqrestore(&p->sighand->siglock, flags);
@@ -63,6 +64,8 @@ int freeze_processes(void)
 		if (time_after(jiffies, start_time + TIMEOUT)) {
 			printk( "\n" );
 			printk(KERN_ERR " stopping tasks failed (%d tasks remaining)\n", todo );
+			complete_all(&thaw);
+			up(&freezer_sem);
 			return todo;
 		}
 	} while(todo);
Index: linux-2.6.12/kernel/sched.c
===================================================================
--- linux-2.6.12.orig/kernel/sched.c	2005-06-28 06:34:52.000000000 +0000
+++ linux-2.6.12/kernel/sched.c	2005-06-28 06:37:36.000000000 +0000
@@ -5210,13 +5210,13 @@ DECLARE_COMPLETION(thaw);
 void refrigerator(void)
 {
 	current->flags |= PF_FROZEN;
+	wait_for_completion(&thaw);
 	clear_thread_flag(TIF_FREEZE);
+	current->flags &= ~PF_FROZEN;
 	/* A fake signal 0 may have been sent. Recalculate sigpending */
 	spin_lock_irq(&current->sighand->siglock);
 	recalc_sigpending();
 	spin_unlock_irq(&current->sighand->siglock);
-	wait_for_completion(&thaw);
-	current->flags &= ~PF_FROZEN;
 }
 EXPORT_SYMBOL(refrigerator);
 #endif
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"aart@kvack.org"> aart@kvack.org </a>

^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: [RFC] Fix SMP brokenness for PF_FREEZE and make freezing usable for other purposes
  2005-06-28  7:01                       ` Christoph Lameter
@ 2005-06-28  7:30                         ` Kirill Korotaev
  2005-06-28  8:13                           ` Kirill Korotaev
  2005-06-28 14:01                           ` Christoph Lameter
  0 siblings, 2 replies; 35+ messages in thread
From: Kirill Korotaev @ 2005-06-28  7:30 UTC (permalink / raw)
  To: Christoph Lameter
  Cc: Pavel Machek, Linus Torvalds, linux-mm, linux-kernel, raybry,
	Alexey Kuznetsov

>>>-static inline int freezing(struct task_struct *p)
>>>-{
>>>-	return p->flags & PF_FREEZE;
>>>-}
>>>+#if defined(CONFIG_PM) || defined(CONFIG_MIGRATE)
>>
>><<<< why not to make a single option CONFIG_REFRIGERATOR? It looks to be a
>>more robust way, since there are multiple users of it.
> 
> 
> Yes. That may be better. We can do that once the migration code is 
> finished and when we know what kind of CONFIG_XXX the migration code 
> really needs.
> 
> 
>>>+#ifdef CONFIG_PM
>>
>><<<< is it intentionaly? or you just lost CONFIG_MIGRATE?
> It is intentional. freeze_processes and thaw_processes are only needed 
> for suspend. One only needs to freeze a couple of processes for process 
> migration.
But PM and your migrate code can be not the only users of it.

>><<<< I still think this refrigerator is racy with freeze_processes():
>><<<< scenarios:
>><<<< scenario 1
>><<<<
>>task1 -> freeze_processes():			taskXXX ->refrigerator()
>>  checked (task->flags & PF_FROZEN) == 0	cur->flags |= PF_FROZEN
>>						clear TIF_FREEZE
>>						<sleep on thaw>
>>  set TIF_FREEZING
>>						clear PF_FROZEN
>>
>><<<< so the task awakes with TIF_FREEZE flag set!!!
> 
> 
> Hmm... If we wait to clear both flags until after the completion 
> notification then we do not have the race right? But then we need to move 
> the signal recalc since it tests for TIF_FREEZE too.
It is almost ok, but it is still not fine :)

look what happens if you call freeze/unfreeze in a loop:

refrigerator:
awakes

freezer:
check PF_FROZEN, it is still set, skips task and thinks it is finished 
freezing.

refrigerator:
clears PF_FROZEN and TIF_FREEZE and returns.

I think you can fix this by moving PF_FROZEN check and set in both 
places under siglock.

Kirill


>><<<< scenario 2
>><<<< look at error path in freeze_processes (on timeout), it is broken as
>>well. You need to wakeup tasks there...
> 
> 
> Ok. How about this additional patch? This still requires that process 
> freezing does not immediately occurr again after the completion 
> handler. All of this is iffy due to not having a real lock protecting all 
> these values and we may still need to add some barriers.
> 
> Index: linux-2.6.12/kernel/power/process.c
> ===================================================================
> --- linux-2.6.12.orig/kernel/power/process.c	2005-06-28 06:34:52.000000000 +0000
> +++ linux-2.6.12/kernel/power/process.c	2005-06-28 06:40:28.000000000 +0000
> @@ -47,12 +47,13 @@ int freeze_processes(void)
>  			unsigned long flags;
>  			if (!freezeable(p))
>  				continue;
> -			if ((p->flags & PF_FROZEN) ||
> -			    (p->state == TASK_TRACED) ||
> +			if ((p->state == TASK_TRACED) ||
>  			    (p->state == TASK_STOPPED))
>  				continue;
>  
>  			set_thread_flag(TIF_FREEZE);
> +			if (p->flags & PF_FROZEN)
> +				continue;
>  			spin_lock_irqsave(&p->sighand->siglock, flags);
>  			signal_wake_up(p, 0);
>  			spin_unlock_irqrestore(&p->sighand->siglock, flags);
> @@ -63,6 +64,8 @@ int freeze_processes(void)
>  		if (time_after(jiffies, start_time + TIMEOUT)) {
>  			printk( "\n" );
>  			printk(KERN_ERR " stopping tasks failed (%d tasks remaining)\n", todo );
> +			complete_all(&thaw);
> +			up(&freezer_sem);
>  			return todo;
>  		}
>  	} while(todo);
> Index: linux-2.6.12/kernel/sched.c
> ===================================================================
> --- linux-2.6.12.orig/kernel/sched.c	2005-06-28 06:34:52.000000000 +0000
> +++ linux-2.6.12/kernel/sched.c	2005-06-28 06:37:36.000000000 +0000
> @@ -5210,13 +5210,13 @@ DECLARE_COMPLETION(thaw);
>  void refrigerator(void)
>  {
>  	current->flags |= PF_FROZEN;
> +	wait_for_completion(&thaw);
>  	clear_thread_flag(TIF_FREEZE);
> +	current->flags &= ~PF_FROZEN;
>  	/* A fake signal 0 may have been sent. Recalculate sigpending */
>  	spin_lock_irq(&current->sighand->siglock);
>  	recalc_sigpending();
>  	spin_unlock_irq(&current->sighand->siglock);
> -	wait_for_completion(&thaw);
> -	current->flags &= ~PF_FROZEN;
>  }
>  EXPORT_SYMBOL(refrigerator);
>  #endif
> 


--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"aart@kvack.org"> aart@kvack.org </a>

^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: [RFC] Fix SMP brokenness for PF_FREEZE and make freezing usable for other purposes
  2005-06-28  7:30                         ` Kirill Korotaev
@ 2005-06-28  8:13                           ` Kirill Korotaev
  2005-06-28 14:02                             ` Christoph Lameter
  2005-06-28 14:01                           ` Christoph Lameter
  1 sibling, 1 reply; 35+ messages in thread
From: Kirill Korotaev @ 2005-06-28  8:13 UTC (permalink / raw)
  To: Kirill Korotaev
  Cc: Christoph Lameter, Pavel Machek, Linus Torvalds, linux-mm,
	linux-kernel, raybry, Alexey Kuznetsov

Christoph I was wrong a bit. Due to use of completion you have no one 
race I described before. If the task is leaving refrigarator with 
TIF_FREEZE it will just visit refrigarator() once more, but won't sleep 
there  since completion is done. BTW, I see no place where you 
initialize the completion.

Kirill

>>>> -static inline int freezing(struct task_struct *p)
>>>> -{
>>>> -    return p->flags & PF_FREEZE;
>>>> -}
>>>> +#if defined(CONFIG_PM) || defined(CONFIG_MIGRATE)
>>>
>>>
>>> <<<< why not to make a single option CONFIG_REFRIGERATOR? It looks to 
>>> be a
>>> more robust way, since there are multiple users of it.
>>
>>
>>
>> Yes. That may be better. We can do that once the migration code is 
>> finished and when we know what kind of CONFIG_XXX the migration code 
>> really needs.
>>
>>
>>>> +#ifdef CONFIG_PM
>>>
>>>
>>> <<<< is it intentionaly? or you just lost CONFIG_MIGRATE?
>>
>> It is intentional. freeze_processes and thaw_processes are only needed 
>> for suspend. One only needs to freeze a couple of processes for 
>> process migration.
> 
> But PM and your migrate code can be not the only users of it.
> 
>>> <<<< I still think this refrigerator is racy with freeze_processes():
>>> <<<< scenarios:
>>> <<<< scenario 1
>>> <<<<
>>> task1 -> freeze_processes():            taskXXX ->refrigerator()
>>>  checked (task->flags & PF_FROZEN) == 0    cur->flags |= PF_FROZEN
>>>                         clear TIF_FREEZE
>>>                         <sleep on thaw>
>>>  set TIF_FREEZING
>>>                         clear PF_FROZEN
>>>
>>> <<<< so the task awakes with TIF_FREEZE flag set!!!
>>
>>
>>
>> Hmm... If we wait to clear both flags until after the completion 
>> notification then we do not have the race right? But then we need to 
>> move the signal recalc since it tests for TIF_FREEZE too.
> 
> It is almost ok, but it is still not fine :)
> 
> look what happens if you call freeze/unfreeze in a loop:
> 
> refrigerator:
> awakes
> 
> freezer:
> check PF_FROZEN, it is still set, skips task and thinks it is finished 
> freezing.
> 
> refrigerator:
> clears PF_FROZEN and TIF_FREEZE and returns.
> 
> I think you can fix this by moving PF_FROZEN check and set in both 
> places under siglock.
> 
> Kirill
> 
> 
>>> <<<< scenario 2
>>> <<<< look at error path in freeze_processes (on timeout), it is 
>>> broken as
>>> well. You need to wakeup tasks there...
>>
>>
>>
>> Ok. How about this additional patch? This still requires that process 
>> freezing does not immediately occurr again after the completion 
>> handler. All of this is iffy due to not having a real lock protecting 
>> all these values and we may still need to add some barriers.
>>
>> Index: linux-2.6.12/kernel/power/process.c
>> ===================================================================
>> --- linux-2.6.12.orig/kernel/power/process.c    2005-06-28 
>> 06:34:52.000000000 +0000
>> +++ linux-2.6.12/kernel/power/process.c    2005-06-28 
>> 06:40:28.000000000 +0000
>> @@ -47,12 +47,13 @@ int freeze_processes(void)
>>              unsigned long flags;
>>              if (!freezeable(p))
>>                  continue;
>> -            if ((p->flags & PF_FROZEN) ||
>> -                (p->state == TASK_TRACED) ||
>> +            if ((p->state == TASK_TRACED) ||
>>                  (p->state == TASK_STOPPED))
>>                  continue;
>>  
>>              set_thread_flag(TIF_FREEZE);
>> +            if (p->flags & PF_FROZEN)
>> +                continue;
>>              spin_lock_irqsave(&p->sighand->siglock, flags);
>>              signal_wake_up(p, 0);
>>              spin_unlock_irqrestore(&p->sighand->siglock, flags);
>> @@ -63,6 +64,8 @@ int freeze_processes(void)
>>          if (time_after(jiffies, start_time + TIMEOUT)) {
>>              printk( "\n" );
>>              printk(KERN_ERR " stopping tasks failed (%d tasks 
>> remaining)\n", todo );
>> +            complete_all(&thaw);
>> +            up(&freezer_sem);
>>              return todo;
>>          }
>>      } while(todo);
>> Index: linux-2.6.12/kernel/sched.c
>> ===================================================================
>> --- linux-2.6.12.orig/kernel/sched.c    2005-06-28 06:34:52.000000000 
>> +0000
>> +++ linux-2.6.12/kernel/sched.c    2005-06-28 06:37:36.000000000 +0000
>> @@ -5210,13 +5210,13 @@ DECLARE_COMPLETION(thaw);
>>  void refrigerator(void)
>>  {
>>      current->flags |= PF_FROZEN;
>> +    wait_for_completion(&thaw);
>>      clear_thread_flag(TIF_FREEZE);
>> +    current->flags &= ~PF_FROZEN;
>>      /* A fake signal 0 may have been sent. Recalculate sigpending */
>>      spin_lock_irq(&current->sighand->siglock);
>>      recalc_sigpending();
>>      spin_unlock_irq(&current->sighand->siglock);
>> -    wait_for_completion(&thaw);
>> -    current->flags &= ~PF_FROZEN;
>>  }
>>  EXPORT_SYMBOL(refrigerator);
>>  #endif
>>
> 
> 


--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"aart@kvack.org"> aart@kvack.org </a>

^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: [RFC] Fix SMP brokenness for PF_FREEZE and make freezing usable for other purposes
  2005-06-28  6:18                     ` Kirill Korotaev
  2005-06-28  7:01                       ` Christoph Lameter
@ 2005-06-28 12:47                       ` Pavel Machek
  2005-07-01 17:06                         ` [SUSPEND 1/2]Replace PF_FREEZE with TIF_FREEZE Christoph Lameter
  1 sibling, 1 reply; 35+ messages in thread
From: Pavel Machek @ 2005-06-28 12:47 UTC (permalink / raw)
  To: Kirill Korotaev
  Cc: Christoph Lameter, Linus Torvalds, linux-mm, linux-kernel,
	raybry, Alexey Kuznetsov

Hi!

> <<<< look at error path in freeze_processes (on timeout), it is broken 
> as well. You need to wakeup tasks there...
> 

Yep, and I have this in my tree to fix it:

[word-wrap-warning]

--- a/kernel/power/process.c
+++ b/kernel/power/process.c
@@ -60,6 +60,7 @@ int freeze_processes(void)
        int todo;
        unsigned long start_time;
        struct task_struct *g, *p;
+       unsigned long flags;

        printk( "Stopping tasks: " );
        start_time = jiffies;
@@ -67,12 +68,9 @@ int freeze_processes(void)
                todo = 0;
                read_lock(&tasklist_lock);
                do_each_thread(g, p) {
-                       unsigned long flags;
                        if (!freezeable(p))
                                continue;
-                       if ((p->flags & PF_FROZEN) ||
-                           (p->state == TASK_TRACED) ||
-                           (p->state == TASK_STOPPED))
+                       if (p->flags & PF_FROZEN)
                                continue;

                        /* FIXME: smp problem here: we may not access other process' flags
@@ -85,13 +83,28 @@ int freeze_processes(void)
                } while_each_thread(g, p);
                read_unlock(&tasklist_lock);
                yield();                        /* Yield is okay here */
-               if (time_after(jiffies, start_time + TIMEOUT)) {
+               if (todo && time_after(jiffies, start_time + TIMEOUT)) {
                        printk( "\n" );
                        printk(KERN_ERR " stopping tasks failed (%d tasks remaining)\n", todo );
-                       return todo;
+                       break;
                }
        } while(todo);
-
+
+       if (todo) {
+               read_lock(&tasklist_lock);
+               do_each_thread(g, p)
+                       if (p->flags & PF_FREEZE) {
+                               pr_debug("  clean up: %s\n", p->comm);
+                               p->flags &= ~PF_FREEZE;
+                               spin_lock_irqsave(&p->sighand->siglock, flags);
+                               recalc_sigpending_tsk(p);
+                               spin_unlock_irqrestore(&p->sighand->siglock, flags);
+                       }
+               while_each_thread(g, p);
+               read_unlock(&tasklist_lock);
+               return todo;
+       }
+
        printk( "|\n" );
        BUG_ON(in_atomic());
        return 0;

									Pavel

-- 
Boycott Kodak -- for their patent abuse against Java.
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"aart@kvack.org"> aart@kvack.org </a>

^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: [RFC] Fix SMP brokenness for PF_FREEZE and make freezing usable for other purposes
  2005-06-28  7:30                         ` Kirill Korotaev
  2005-06-28  8:13                           ` Kirill Korotaev
@ 2005-06-28 14:01                           ` Christoph Lameter
  1 sibling, 0 replies; 35+ messages in thread
From: Christoph Lameter @ 2005-06-28 14:01 UTC (permalink / raw)
  To: Kirill Korotaev
  Cc: Pavel Machek, Linus Torvalds, linux-mm, linux-kernel, raybry,
	Alexey Kuznetsov

On Tue, 28 Jun 2005, Kirill Korotaev wrote:

> > > <<<< is it intentionaly? or you just lost CONFIG_MIGRATE?
> > It is intentional. freeze_processes and thaw_processes are only needed for
> > suspend. One only needs to freeze a couple of processes for process
> > migration.
> But PM and your migrate code can be not the only users of it.

freeze_processes and thaw_processes is not needed by the migrate 
code.

> > Hmm... If we wait to clear both flags until after the completion
> > notification then we do not have the race right? But then we need to move
> > the signal recalc since it tests for TIF_FREEZE too.
> It is almost ok, but it is still not fine :)
> 
> look what happens if you call freeze/unfreeze in a loop:
> 
> refrigerator:
> awakes
> 
> freezer:
> check PF_FROZEN, it is still set, skips task and thinks it is finished
> freezing.
> 
> refrigerator:
> clears PF_FROZEN and TIF_FREEZE and returns.
> 
> I think you can fix this by moving PF_FROZEN check and set in both places
> under siglock.

I do not think this is necessary because 
freezing and awakening are not done concurrently. First you will 
freeze a number of processes (and no awakening occurs).

Then some action occurs (migration, suspend). Then complete_all 
is invoked. No freezing occurs during the awakening period.

It would be great if you can fix this issue with a patch. But taking a 
lock only makes sense if you can use it to coordinate multiple updates
of variables. I.e. take siglock for clearing PF_FROZEN and TIF_FREEZE and
then use it while checking the state of PF_FROZEN and TIF_FREEZE.
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"aart@kvack.org"> aart@kvack.org </a>

^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: [RFC] Fix SMP brokenness for PF_FREEZE and make freezing usable for other purposes
  2005-06-28  8:13                           ` Kirill Korotaev
@ 2005-06-28 14:02                             ` Christoph Lameter
  0 siblings, 0 replies; 35+ messages in thread
From: Christoph Lameter @ 2005-06-28 14:02 UTC (permalink / raw)
  To: Kirill Korotaev
  Cc: Pavel Machek, Linus Torvalds, linux-mm, linux-kernel, raybry,
	Alexey Kuznetsov

On Tue, 28 Jun 2005, Kirill Korotaev wrote:

> Christoph I was wrong a bit. Due to use of completion you have no one race I
> described before. If the task is leaving refrigarator with TIF_FREEZE it will
> just visit refrigarator() once more, but won't sleep there  since completion
> is done. BTW, I see no place where you initialize the completion.

It is initialized through the DECLARE_COMPLETION in sched.c.

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"aart@kvack.org"> aart@kvack.org </a>

^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: [RFC] Fix SMP brokenness for PF_FREEZE and make freezing usable for other purposes
  2005-06-27  5:53               ` Christoph Lameter
  2005-06-27 14:13                 ` Pavel Machek
@ 2005-06-28 21:50                 ` Ray Bryant
  2005-06-28 21:54                   ` Christoph Lameter
  1 sibling, 1 reply; 35+ messages in thread
From: Ray Bryant @ 2005-06-28 21:50 UTC (permalink / raw)
  To: Christoph Lameter; +Cc: Linus Torvalds, Pavel Machek, linux-mm, linux-kernel

Christoph Lameter wrote:

<snip>

>  
> Index: linux-2.6.12/kernel/power/process.c
> ===================================================================
> --- linux-2.6.12.orig/kernel/power/process.c	2005-06-27 05:20:15.000000000 +0000
> +++ linux-2.6.12/kernel/power/process.c	2005-06-27 05:22:00.000000000 +0000

<snip>

> @@ -69,12 +63,12 @@ int freeze_processes(void)
>  			unsigned long flags;
>  			if (!freezeable(p))
>  				continue;
> -			if ((frozen(p)) ||
> +			if ((p->flags & PF_FROZEN) ||
>  			    (p->state == TASK_TRACED) ||
>  			    (p->state == TASK_STOPPED))
>  				continue;
>  
> -			freeze(p);
> +			set_thread_flag(TIF_FREEZE);

Shouldn't that be "set_ti_thread_flag(p->thread_info, TIF_FREEZE)"?
Otherwise you freeze current, not the thread "p".

>  			spin_lock_irqsave(&p->sighand->siglock, flags);
>  			signal_wake_up(p, 0);
>  			spin_unlock_irqrestore(&p->sighand->siglock, flags);
>

-- 
Best Regards,
Ray
-----------------------------------------------
                   Ray Bryant
512-453-9679 (work)         512-507-7807 (cell)
raybry@sgi.com             raybry@austin.rr.com
The box said: "Requires Windows 98 or better",
            so I installed Linux.
-----------------------------------------------
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"aart@kvack.org"> aart@kvack.org </a>

^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: [RFC] Fix SMP brokenness for PF_FREEZE and make freezing usable for other purposes
  2005-06-28 21:50                 ` [RFC] Fix SMP brokenness for PF_FREEZE and make freezing usable for other purposes Ray Bryant
@ 2005-06-28 21:54                   ` Christoph Lameter
  2005-07-03 11:06                     ` Pavel Machek
  0 siblings, 1 reply; 35+ messages in thread
From: Christoph Lameter @ 2005-06-28 21:54 UTC (permalink / raw)
  To: Ray Bryant; +Cc: Linus Torvalds, Pavel Machek, linux-mm, linux-kernel

On Tue, 28 Jun 2005, Ray Bryant wrote:

> >  -			freeze(p);
> > +			set_thread_flag(TIF_FREEZE);
> 
> Shouldn't that be "set_ti_thread_flag(p->thread_info, TIF_FREEZE)"?
> Otherwise you freeze current, not the thread "p".

Correct. Which also means that we have not progressed yet beyond an 
academic version of the patch:

---

Revise handling of freezing in the suspend code

The current suspend code modifies thread flags from outside the context of process.
This creates a SMP race.

The patch fixes that by introducing a TIF_FREEZE flag (for all arches). Also

- Uses a completion handler instead of waiting in a schedule loop in the refrigerator.

- Introduces a semaphore freezer_sem to provide a way that multiple kernel
  subsystems can use the freezing ability without interfering with one another.

- Include necessary definitions for the migration code if CONFIG_MIGRATE is set.

- Removes PF_FREEZE

Signed-off-by: Christoph Lameter <christoph@lameter.com>

Index: linux-2.6.12/include/linux/sched.h
===================================================================
--- linux-2.6.12.orig/include/linux/sched.h	2005-06-27 05:20:15.000000000 +0000
+++ linux-2.6.12/include/linux/sched.h	2005-06-28 06:34:52.000000000 +0000
@@ -804,7 +804,6 @@ do { if (atomic_dec_and_test(&(tsk)->usa
 #define PF_MEMALLOC	0x00000800	/* Allocating memory */
 #define PF_FLUSHER	0x00001000	/* responsible for disk writeback */
 #define PF_USED_MATH	0x00002000	/* if unset the fpu must be initialized before use */
-#define PF_FREEZE	0x00004000	/* this task is being frozen for suspend now */
 #define PF_NOFREEZE	0x00008000	/* this thread should not be frozen */
 #define PF_FROZEN	0x00010000	/* frozen for system suspend */
 #define PF_FSTRANS	0x00020000	/* inside a filesystem transaction */
@@ -1265,78 +1264,37 @@ extern void normalize_rt_tasks(void);
 
 #endif
 
-#ifdef CONFIG_PM
-/*
- * 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;
-}
+#if defined(CONFIG_PM) || defined(CONFIG_MIGRATE)
+extern struct semaphore freezer_sem;
+extern struct completion thaw;
 
-/*
- * 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;
-}
+extern void refrigerator(void);
 
-/*
- * freezing is complete, mark process as frozen
- */
-static inline void frozen_process(struct task_struct *p)
+static inline int freezing(struct task_struct *p)
 {
-	p->flags = (p->flags & ~PF_FREEZE) | PF_FROZEN;
+	return test_ti_thread_flag(p->thread_info, TIF_FREEZE);
 }
 
-extern void refrigerator(void);
-extern int freeze_processes(void);
-extern void thaw_processes(void);
-
 static inline int try_to_freeze(void)
 {
-	if (freezing(current)) {
+	if (test_thread_flag(TIF_FREEZE)) {
 		refrigerator();
 		return 1;
 	} else
 		return 0;
 }
 #else
-static inline int frozen(struct task_struct *p) { return 0; }
+static inline void refrigerator(void) {}
 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 int try_to_freeze(void) { return 0; }
+#endif
 
-static inline void refrigerator(void) {}
+#ifdef CONFIG_PM
+extern int freeze_processes(void);
+extern void thaw_processes(void);
+#else
 static inline int freeze_processes(void) { BUG(); return 0; }
 static inline void thaw_processes(void) {}
-
-static inline int try_to_freeze(void) { return 0; }
-
 #endif /* CONFIG_PM */
 #endif /* __KERNEL__ */
 
Index: linux-2.6.12/kernel/power/process.c
===================================================================
--- linux-2.6.12.orig/kernel/power/process.c	2005-06-27 05:20:15.000000000 +0000
+++ linux-2.6.12/kernel/power/process.c	2005-06-28 21:52:47.000000000 +0000
@@ -18,7 +18,6 @@
  */
 #define TIMEOUT	(6 * HZ)
 
-
 static inline int freezeable(struct task_struct * p)
 {
 	if ((p == current) || 
@@ -31,28 +30,6 @@ static inline int freezeable(struct task
 	return 1;
 }
 
-/* Refrigerator is place where frozen processes are stored :-). */
-void refrigerator(void)
-{
-	/* Hmm, should we be allowed to suspend when there are realtime
-	   processes around? */
-	long save;
-	save = current->state;
-	current->state = TASK_UNINTERRUPTIBLE;
-	pr_debug("%s entered refrigerator\n", current->comm);
-	printk("=");
-
-	frozen_process(current);
-	spin_lock_irq(&current->sighand->siglock);
-	recalc_sigpending(); /* We sent fake signal, clean it up */
-	spin_unlock_irq(&current->sighand->siglock);
-
-	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)
 {
@@ -60,6 +37,7 @@ int freeze_processes(void)
 	unsigned long start_time;
 	struct task_struct *g, *p;
 
+	down(&freezer_sem);
 	printk( "Stopping tasks: " );
 	start_time = jiffies;
 	do {
@@ -69,12 +47,13 @@ int freeze_processes(void)
 			unsigned long flags;
 			if (!freezeable(p))
 				continue;
-			if ((frozen(p)) ||
-			    (p->state == TASK_TRACED) ||
+			if ((p->state == TASK_TRACED) ||
 			    (p->state == TASK_STOPPED))
 				continue;
 
-			freeze(p);
+			set_ti_thread_flag(p->thread_info, TIF_FREEZE);
+			if (p->flags & PF_FROZEN)
+				continue;
 			spin_lock_irqsave(&p->sighand->siglock, flags);
 			signal_wake_up(p, 0);
 			spin_unlock_irqrestore(&p->sighand->siglock, flags);
@@ -85,6 +64,8 @@ int freeze_processes(void)
 		if (time_after(jiffies, start_time + TIMEOUT)) {
 			printk( "\n" );
 			printk(KERN_ERR " stopping tasks failed (%d tasks remaining)\n", todo );
+			complete_all(&thaw);
+			up(&freezer_sem);
 			return todo;
 		}
 	} while(todo);
@@ -96,20 +77,6 @@ int freeze_processes(void)
 
 void thaw_processes(void)
 {
-	struct task_struct *g, *p;
-
-	printk( "Restarting tasks..." );
-	read_lock(&tasklist_lock);
-	do_each_thread(g, p) {
-		if (!freezeable(p))
-			continue;
-		if (!thaw_process(p))
-			printk(KERN_INFO " Strange, %s not stopped\n", p->comm );
-	} while_each_thread(g, p);
-
-	read_unlock(&tasklist_lock);
-	schedule();
-	printk( " done\n" );
+	complete_all(&thaw);
+	up(&freezer_sem);
 }
-
-EXPORT_SYMBOL(refrigerator);
Index: linux-2.6.12/include/asm-x86_64/thread_info.h
===================================================================
--- linux-2.6.12.orig/include/asm-x86_64/thread_info.h	2005-06-27 05:20:15.000000000 +0000
+++ linux-2.6.12/include/asm-x86_64/thread_info.h	2005-06-27 05:37:24.000000000 +0000
@@ -108,6 +108,7 @@ static inline struct thread_info *stack_
 #define TIF_FORK		18	/* ret_from_fork */
 #define TIF_ABI_PENDING		19
 #define TIF_MEMDIE		20
+#define TIF_FREEZE		21	/* Freeze process */
 
 #define _TIF_SYSCALL_TRACE	(1<<TIF_SYSCALL_TRACE)
 #define _TIF_NOTIFY_RESUME	(1<<TIF_NOTIFY_RESUME)
Index: linux-2.6.12/include/asm-ia64/thread_info.h
===================================================================
--- linux-2.6.12.orig/include/asm-ia64/thread_info.h	2005-06-27 05:20:15.000000000 +0000
+++ linux-2.6.12/include/asm-ia64/thread_info.h	2005-06-27 05:26:12.000000000 +0000
@@ -76,6 +76,7 @@ struct thread_info {
 #define TIF_SIGDELAYED		5	/* signal delayed from MCA/INIT/NMI/PMI context */
 #define TIF_POLLING_NRFLAG	16	/* true if poll_idle() is polling TIF_NEED_RESCHED */
 #define TIF_MEMDIE		17
+#define TIF_FREEZE		18	/* Freeze process */
 
 #define _TIF_SYSCALL_TRACE	(1 << TIF_SYSCALL_TRACE)
 #define _TIF_SYSCALL_AUDIT	(1 << TIF_SYSCALL_AUDIT)
Index: linux-2.6.12/include/asm-i386/thread_info.h
===================================================================
--- linux-2.6.12.orig/include/asm-i386/thread_info.h	2005-06-27 05:20:15.000000000 +0000
+++ linux-2.6.12/include/asm-i386/thread_info.h	2005-06-27 05:25:49.000000000 +0000
@@ -143,6 +143,7 @@ register unsigned long current_stack_poi
 #define TIF_SECCOMP		8	/* secure computing */
 #define TIF_POLLING_NRFLAG	16	/* true if poll_idle() is polling TIF_NEED_RESCHED */
 #define TIF_MEMDIE		17
+#define TIF_FREEZE		18	/* Freeze thread */
 
 #define _TIF_SYSCALL_TRACE	(1<<TIF_SYSCALL_TRACE)
 #define _TIF_NOTIFY_RESUME	(1<<TIF_NOTIFY_RESUME)
Index: linux-2.6.12/include/asm-xtensa/thread_info.h
===================================================================
--- linux-2.6.12.orig/include/asm-xtensa/thread_info.h	2005-06-27 02:23:01.000000000 +0000
+++ linux-2.6.12/include/asm-xtensa/thread_info.h	2005-06-27 05:36:54.000000000 +0000
@@ -118,6 +118,7 @@ static inline struct thread_info *curren
 #define TIF_SINGLESTEP		4	/* restore singlestep on return to user mode */
 #define TIF_IRET		5	/* return with iret */
 #define TIF_MEMDIE		6
+#define TIF_FREEZE		7
 #define TIF_POLLING_NRFLAG	16	/* true if poll_idle() is polling TIF_NEED_RESCHED */
 
 #define _TIF_SYSCALL_TRACE	(1<<TIF_SYSCALL_TRACE)
Index: linux-2.6.12/include/asm-h8300/thread_info.h
===================================================================
--- linux-2.6.12.orig/include/asm-h8300/thread_info.h	2005-06-27 02:23:01.000000000 +0000
+++ linux-2.6.12/include/asm-h8300/thread_info.h	2005-06-27 05:25:25.000000000 +0000
@@ -94,6 +94,7 @@ static inline struct thread_info *curren
 #define TIF_POLLING_NRFLAG	4	/* true if poll_idle() is polling
 					   TIF_NEED_RESCHED */
 #define TIF_MEMDIE		5
+#define TIF_FREEZE		6
 
 /* as above, but as bit values */
 #define _TIF_SYSCALL_TRACE	(1<<TIF_SYSCALL_TRACE)
Index: linux-2.6.12/include/asm-ppc/thread_info.h
===================================================================
--- linux-2.6.12.orig/include/asm-ppc/thread_info.h	2005-06-27 02:23:01.000000000 +0000
+++ linux-2.6.12/include/asm-ppc/thread_info.h	2005-06-27 05:28:53.000000000 +0000
@@ -80,6 +80,7 @@ static inline struct thread_info *curren
 #define TIF_MEMDIE		5
 #define TIF_SYSCALL_AUDIT       6       /* syscall auditing active */
 #define TIF_SECCOMP             7      /* secure computing */
+#define TIF_FREEZE		8
 
 /* as above, but as bit values */
 #define _TIF_SYSCALL_TRACE	(1<<TIF_SYSCALL_TRACE)
Index: linux-2.6.12/include/asm-sh64/thread_info.h
===================================================================
--- linux-2.6.12.orig/include/asm-sh64/thread_info.h	2005-06-27 02:23:01.000000000 +0000
+++ linux-2.6.12/include/asm-sh64/thread_info.h	2005-06-27 05:35:02.000000000 +0000
@@ -80,6 +80,7 @@ static inline struct thread_info *curren
 #define TIF_SIGPENDING		2	/* signal pending */
 #define TIF_NEED_RESCHED	3	/* rescheduling necessary */
 #define TIF_MEMDIE		4
+#define TIF_FREEZE		5
 
 
 #endif /* __KERNEL__ */
Index: linux-2.6.12/include/asm-alpha/thread_info.h
===================================================================
--- linux-2.6.12.orig/include/asm-alpha/thread_info.h	2005-06-17 19:48:29.000000000 +0000
+++ linux-2.6.12/include/asm-alpha/thread_info.h	2005-06-27 05:23:06.000000000 +0000
@@ -78,6 +78,7 @@ register struct thread_info *__current_t
 #define TIF_UAC_NOFIX		7
 #define TIF_UAC_SIGBUS		8
 #define TIF_MEMDIE		9
+#define TIF_FREEZE		10
 
 #define _TIF_SYSCALL_TRACE	(1<<TIF_SYSCALL_TRACE)
 #define _TIF_NOTIFY_RESUME	(1<<TIF_NOTIFY_RESUME)
Index: linux-2.6.12/include/asm-sparc/thread_info.h
===================================================================
--- linux-2.6.12.orig/include/asm-sparc/thread_info.h	2005-06-27 02:23:01.000000000 +0000
+++ linux-2.6.12/include/asm-sparc/thread_info.h	2005-06-27 05:35:23.000000000 +0000
@@ -139,6 +139,7 @@ BTFIXUPDEF_CALL(void, free_thread_info, 
 #define TIF_POLLING_NRFLAG	9	/* true if poll_idle() is polling
 					 * TIF_NEED_RESCHED */
 #define TIF_MEMDIE		10
+#define TIF_FREEZE		11
 
 /* as above, but as bit values */
 #define _TIF_SYSCALL_TRACE	(1<<TIF_SYSCALL_TRACE)
Index: linux-2.6.12/include/asm-frv/thread_info.h
===================================================================
--- linux-2.6.12.orig/include/asm-frv/thread_info.h	2005-06-27 02:23:01.000000000 +0000
+++ linux-2.6.12/include/asm-frv/thread_info.h	2005-06-27 05:25:02.000000000 +0000
@@ -133,6 +133,7 @@ register struct thread_info *__current_t
 #define TIF_IRET		5	/* return with iret */
 #define TIF_POLLING_NRFLAG	16	/* true if poll_idle() is polling TIF_NEED_RESCHED */
 #define TIF_MEMDIE		17	/* OOM killer killed process */
+#define TIF_FREEZE		18
 
 #define _TIF_SYSCALL_TRACE	(1 << TIF_SYSCALL_TRACE)
 #define _TIF_NOTIFY_RESUME	(1 << TIF_NOTIFY_RESUME)
Index: linux-2.6.12/include/asm-parisc/thread_info.h
===================================================================
--- linux-2.6.12.orig/include/asm-parisc/thread_info.h	2005-06-27 02:23:01.000000000 +0000
+++ linux-2.6.12/include/asm-parisc/thread_info.h	2005-06-27 05:28:34.000000000 +0000
@@ -64,6 +64,7 @@ struct thread_info {
 #define TIF_POLLING_NRFLAG	4	/* true if poll_idle() is polling TIF_NEED_RESCHED */
 #define TIF_32BIT               5       /* 32 bit binary */
 #define TIF_MEMDIE		6
+#define TIF_FREEZE		7
 
 #define _TIF_SYSCALL_TRACE	(1 << TIF_SYSCALL_TRACE)
 #define _TIF_NOTIFY_RESUME	(1 << TIF_NOTIFY_RESUME)
Index: linux-2.6.12/include/asm-m68knommu/thread_info.h
===================================================================
--- linux-2.6.12.orig/include/asm-m68knommu/thread_info.h	2005-06-27 02:23:01.000000000 +0000
+++ linux-2.6.12/include/asm-m68knommu/thread_info.h	2005-06-27 05:27:13.000000000 +0000
@@ -91,6 +91,7 @@ static inline struct thread_info *curren
 #define TIF_POLLING_NRFLAG	4	/* true if poll_idle() is polling
 					   TIF_NEED_RESCHED */
 #define TIF_MEMDIE		5
+#define TIF_FREEZE		6
 
 /* as above, but as bit values */
 #define _TIF_SYSCALL_TRACE	(1<<TIF_SYSCALL_TRACE)
Index: linux-2.6.12/include/asm-m68k/thread_info.h
===================================================================
--- linux-2.6.12.orig/include/asm-m68k/thread_info.h	2005-06-27 02:23:01.000000000 +0000
+++ linux-2.6.12/include/asm-m68k/thread_info.h	2005-06-27 05:26:49.000000000 +0000
@@ -49,6 +49,7 @@ struct thread_info {
 #define TIF_SIGPENDING		3	/* signal pending */
 #define TIF_NEED_RESCHED	4	/* rescheduling necessary */
 #define TIF_MEMDIE		5
+#define TIF_FREEZE		6
 
 extern int thread_flag_fixme(void);
 
Index: linux-2.6.12/include/asm-sh/thread_info.h
===================================================================
--- linux-2.6.12.orig/include/asm-sh/thread_info.h	2005-06-27 02:23:01.000000000 +0000
+++ linux-2.6.12/include/asm-sh/thread_info.h	2005-06-27 05:34:43.000000000 +0000
@@ -84,6 +84,7 @@ static inline struct thread_info *curren
 #define TIF_USEDFPU		16	/* FPU was used by this task this quantum (SMP) */
 #define TIF_POLLING_NRFLAG	17	/* true if poll_idle() is polling TIF_NEED_RESCHED */
 #define TIF_MEMDIE		18
+#define TIF_FREEZE		19
 #define TIF_USERSPACE		31	/* true if FS sets userspace */
 
 #define _TIF_SYSCALL_TRACE	(1<<TIF_SYSCALL_TRACE)
Index: linux-2.6.12/include/asm-s390/thread_info.h
===================================================================
--- linux-2.6.12.orig/include/asm-s390/thread_info.h	2005-06-27 02:23:01.000000000 +0000
+++ linux-2.6.12/include/asm-s390/thread_info.h	2005-06-27 05:34:19.000000000 +0000
@@ -102,6 +102,7 @@ static inline struct thread_info *curren
 					   TIF_NEED_RESCHED */
 #define TIF_31BIT		18	/* 32bit process */ 
 #define TIF_MEMDIE		19
+#define TIF_FREEZE		20
 
 #define _TIF_SYSCALL_TRACE	(1<<TIF_SYSCALL_TRACE)
 #define _TIF_NOTIFY_RESUME	(1<<TIF_NOTIFY_RESUME)
Index: linux-2.6.12/include/asm-arm/thread_info.h
===================================================================
--- linux-2.6.12.orig/include/asm-arm/thread_info.h	2005-06-27 02:23:01.000000000 +0000
+++ linux-2.6.12/include/asm-arm/thread_info.h	2005-06-27 05:23:34.000000000 +0000
@@ -132,6 +132,7 @@ extern void iwmmxt_task_release(struct t
 #define TIF_POLLING_NRFLAG	16
 #define TIF_USING_IWMMXT	17
 #define TIF_MEMDIE		18
+#define TIF_FREEZE		19
 
 #define _TIF_NOTIFY_RESUME	(1 << TIF_NOTIFY_RESUME)
 #define _TIF_SIGPENDING		(1 << TIF_SIGPENDING)
Index: linux-2.6.12/include/asm-v850/thread_info.h
===================================================================
--- linux-2.6.12.orig/include/asm-v850/thread_info.h	2005-06-27 02:23:01.000000000 +0000
+++ linux-2.6.12/include/asm-v850/thread_info.h	2005-06-27 05:36:25.000000000 +0000
@@ -85,6 +85,7 @@ struct thread_info {
 #define TIF_POLLING_NRFLAG	4	/* true if poll_idle() is polling
 					   TIF_NEED_RESCHED */
 #define TIF_MEMDIE		5
+#define TIF_FREEZE		6
 
 /* as above, but as bit values */
 #define _TIF_SYSCALL_TRACE	(1<<TIF_SYSCALL_TRACE)
Index: linux-2.6.12/include/asm-mips/thread_info.h
===================================================================
--- linux-2.6.12.orig/include/asm-mips/thread_info.h	2005-06-27 02:23:01.000000000 +0000
+++ linux-2.6.12/include/asm-mips/thread_info.h	2005-06-27 05:27:41.000000000 +0000
@@ -117,6 +117,7 @@ register struct thread_info *__current_t
 #define TIF_USEDFPU		16	/* FPU was used by this task this quantum (SMP) */
 #define TIF_POLLING_NRFLAG	17	/* true if poll_idle() is polling TIF_NEED_RESCHED */
 #define TIF_MEMDIE		18
+#define TIF_FREEZE		19
 #define TIF_SYSCALL_TRACE	31	/* syscall trace active */
 
 #define _TIF_SYSCALL_TRACE	(1<<TIF_SYSCALL_TRACE)
Index: linux-2.6.12/include/asm-cris/thread_info.h
===================================================================
--- linux-2.6.12.orig/include/asm-cris/thread_info.h	2005-06-27 02:23:01.000000000 +0000
+++ linux-2.6.12/include/asm-cris/thread_info.h	2005-06-27 05:24:28.000000000 +0000
@@ -86,6 +86,7 @@ struct thread_info {
 #define TIF_NEED_RESCHED	3	/* rescheduling necessary */
 #define TIF_POLLING_NRFLAG	16	/* true if poll_idle() is polling TIF_NEED_RESCHED */
 #define TIF_MEMDIE		17
+#define TIF_FREEZE		18
 
 #define _TIF_SYSCALL_TRACE	(1<<TIF_SYSCALL_TRACE)
 #define _TIF_NOTIFY_RESUME	(1<<TIF_NOTIFY_RESUME)
Index: linux-2.6.12/include/asm-arm26/thread_info.h
===================================================================
--- linux-2.6.12.orig/include/asm-arm26/thread_info.h	2005-06-27 02:23:01.000000000 +0000
+++ linux-2.6.12/include/asm-arm26/thread_info.h	2005-06-27 05:24:02.000000000 +0000
@@ -127,6 +127,7 @@ extern void free_thread_info(struct thre
 #define TIF_USED_FPU		16
 #define TIF_POLLING_NRFLAG	17
 #define TIF_MEMDIE		18
+#define TIF_FREEZE		19
 
 #define _TIF_NOTIFY_RESUME	(1 << TIF_NOTIFY_RESUME)
 #define _TIF_SIGPENDING		(1 << TIF_SIGPENDING)
Index: linux-2.6.12/include/asm-sparc64/thread_info.h
===================================================================
--- linux-2.6.12.orig/include/asm-sparc64/thread_info.h	2005-06-27 02:23:01.000000000 +0000
+++ linux-2.6.12/include/asm-sparc64/thread_info.h	2005-06-27 05:35:45.000000000 +0000
@@ -229,6 +229,7 @@ register struct thread_info *current_thr
  */
 #define TIF_ABI_PENDING		12
 #define TIF_MEMDIE		13
+#define TIF_FREEZE		14
 
 #define _TIF_SYSCALL_TRACE	(1<<TIF_SYSCALL_TRACE)
 #define _TIF_NOTIFY_RESUME	(1<<TIF_NOTIFY_RESUME)
Index: linux-2.6.12/include/asm-m32r/thread_info.h
===================================================================
--- linux-2.6.12.orig/include/asm-m32r/thread_info.h	2005-06-27 02:23:01.000000000 +0000
+++ linux-2.6.12/include/asm-m32r/thread_info.h	2005-06-27 05:26:33.000000000 +0000
@@ -156,6 +156,7 @@ static inline unsigned int get_thread_fa
 #define TIF_POLLING_NRFLAG	16	/* true if poll_idle() is polling TIF_NEED_RESCHED */
 					/* 31..28 fault code */
 #define TIF_MEMDIE		17
+#define TIF_FREEZE		18
 
 #define _TIF_SYSCALL_TRACE	(1<<TIF_SYSCALL_TRACE)
 #define _TIF_NOTIFY_RESUME	(1<<TIF_NOTIFY_RESUME)
Index: linux-2.6.12/include/asm-ppc64/thread_info.h
===================================================================
--- linux-2.6.12.orig/include/asm-ppc64/thread_info.h	2005-06-27 02:23:01.000000000 +0000
+++ linux-2.6.12/include/asm-ppc64/thread_info.h	2005-06-27 05:29:13.000000000 +0000
@@ -102,6 +102,7 @@ static inline struct thread_info *curren
 #define TIF_SINGLESTEP		9	/* singlestepping active */
 #define TIF_MEMDIE		10
 #define TIF_SECCOMP		11	/* secure computing */
+#define TIF_FREEZE		12
 
 /* as above, but as bit values */
 #define _TIF_SYSCALL_TRACE	(1<<TIF_SYSCALL_TRACE)
Index: linux-2.6.12/include/asm-um/thread_info.h
===================================================================
--- linux-2.6.12.orig/include/asm-um/thread_info.h	2005-06-27 02:23:01.000000000 +0000
+++ linux-2.6.12/include/asm-um/thread_info.h	2005-06-27 05:36:07.000000000 +0000
@@ -72,6 +72,7 @@ static inline struct thread_info *curren
 #define TIF_RESTART_BLOCK 	4
 #define TIF_MEMDIE	 	5
 #define TIF_SYSCALL_AUDIT	6
+#define TIF_FREEZE		7
 
 #define _TIF_SYSCALL_TRACE	(1 << TIF_SYSCALL_TRACE)
 #define _TIF_SIGPENDING		(1 << TIF_SIGPENDING)
Index: linux-2.6.12/kernel/sched.c
===================================================================
--- linux-2.6.12.orig/kernel/sched.c	2005-06-27 02:23:01.000000000 +0000
+++ linux-2.6.12/kernel/sched.c	2005-06-28 21:51:43.000000000 +0000
@@ -5203,6 +5203,25 @@ void __init sched_init(void)
 	init_idle(current, smp_processor_id());
 }
 
+#if defined(CONFIG_PM) || defined(CONFIG_MIGRATE)
+DECLARE_MUTEX(freezer_sem);
+DECLARE_COMPLETION(thaw);
+
+void refrigerator(void)
+{
+	current->flags |= PF_FROZEN;
+	wait_for_completion(&thaw);
+	clear_thread_flag(TIF_FREEZE);
+	current->flags &= ~PF_FROZEN;
+	/* A fake signal 0 may have been sent. Recalculate sigpending */
+	spin_lock_irq(&current->sighand->siglock);
+	recalc_sigpending();
+	spin_unlock_irq(&current->sighand->siglock);
+}
+EXPORT_SYMBOL(refrigerator);
+#endif
+
+
 #ifdef CONFIG_DEBUG_SPINLOCK_SLEEP
 void __might_sleep(char *file, int line)
 {
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"aart@kvack.org"> aart@kvack.org </a>

^ permalink raw reply	[flat|nested] 35+ messages in thread

* [SUSPEND 1/2]Replace PF_FREEZE with TIF_FREEZE
  2005-06-28 12:47                       ` Pavel Machek
@ 2005-07-01 17:06                         ` Christoph Lameter
  2005-07-01 17:14                           ` [SUSPEND 2/2] Replace PF_FROZEN with TASK_FROZEN Christoph Lameter
  0 siblings, 1 reply; 35+ messages in thread
From: Christoph Lameter @ 2005-07-01 17:06 UTC (permalink / raw)
  To: Pavel Machek
  Cc: Kirill Korotaev, Linus Torvalds, linux-mm, linux-kernel,
	Alexey Kuznetsov

The current suspend code modifies thread->flags from outside the context of the
thread. This creates a SMP race.

This patch fixes that by introducing a TIF_FREEZE flag in thread_info

(This is not the end of the races in the suspend code since TIF_FREEZE is cleared
when setting PF_FROZEN creating a window for freeze_processes())

Signed-off-by: Christoph Lameter <christoph@lameter.com>

Index: linux-2.6.12/include/linux/sched.h
===================================================================
--- linux-2.6.12.orig/include/linux/sched.h	2005-06-30 23:26:07.000000000 +0000
+++ linux-2.6.12/include/linux/sched.h	2005-06-30 23:39:12.000000000 +0000
@@ -807,7 +807,6 @@ do { if (atomic_dec_and_test(&(tsk)->usa
 #define PF_MEMALLOC	0x00000800	/* Allocating memory */
 #define PF_FLUSHER	0x00001000	/* responsible for disk writeback */
 #define PF_USED_MATH	0x00002000	/* if unset the fpu must be initialized before use */
-#define PF_FREEZE	0x00004000	/* this task is being frozen for suspend now */
 #define PF_NOFREEZE	0x00008000	/* this thread should not be frozen */
 #define PF_FROZEN	0x00010000	/* frozen for system suspend */
 #define PF_FSTRANS	0x00020000	/* inside a filesystem transaction */
@@ -1283,16 +1282,15 @@ static inline int frozen(struct task_str
  */
 static inline int freezing(struct task_struct *p)
 {
-	return p->flags & PF_FREEZE;
+	return test_ti_thread_flag(p->thread_info, TIF_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;
+	set_ti_thread_flag(p->thread_info, TIF_FREEZE);
 }
 
 /*
@@ -1313,7 +1311,8 @@ static inline int thaw_process(struct ta
  */
 static inline void frozen_process(struct task_struct *p)
 {
-	p->flags = (p->flags & ~PF_FREEZE) | PF_FROZEN;
+	p->flags |= PF_FROZEN;
+	clear_ti_thread_flag(p->thread_info, TIF_FREEZE);
 }
 
 extern void refrigerator(void);
Index: linux-2.6.12/include/asm-x86_64/thread_info.h
===================================================================
--- linux-2.6.12.orig/include/asm-x86_64/thread_info.h	2005-06-30 23:26:07.000000000 +0000
+++ linux-2.6.12/include/asm-x86_64/thread_info.h	2005-06-30 23:26:35.000000000 +0000
@@ -108,6 +108,7 @@ static inline struct thread_info *stack_
 #define TIF_FORK		18	/* ret_from_fork */
 #define TIF_ABI_PENDING		19
 #define TIF_MEMDIE		20
+#define TIF_FREEZE		21	/* Freeze process */
 
 #define _TIF_SYSCALL_TRACE	(1<<TIF_SYSCALL_TRACE)
 #define _TIF_NOTIFY_RESUME	(1<<TIF_NOTIFY_RESUME)
Index: linux-2.6.12/include/asm-ia64/thread_info.h
===================================================================
--- linux-2.6.12.orig/include/asm-ia64/thread_info.h	2005-06-30 23:26:07.000000000 +0000
+++ linux-2.6.12/include/asm-ia64/thread_info.h	2005-06-30 23:26:35.000000000 +0000
@@ -76,6 +76,7 @@ struct thread_info {
 #define TIF_SIGDELAYED		5	/* signal delayed from MCA/INIT/NMI/PMI context */
 #define TIF_POLLING_NRFLAG	16	/* true if poll_idle() is polling TIF_NEED_RESCHED */
 #define TIF_MEMDIE		17
+#define TIF_FREEZE		18	/* Freeze process */
 
 #define _TIF_SYSCALL_TRACE	(1 << TIF_SYSCALL_TRACE)
 #define _TIF_SYSCALL_AUDIT	(1 << TIF_SYSCALL_AUDIT)
Index: linux-2.6.12/include/asm-i386/thread_info.h
===================================================================
--- linux-2.6.12.orig/include/asm-i386/thread_info.h	2005-06-30 23:26:07.000000000 +0000
+++ linux-2.6.12/include/asm-i386/thread_info.h	2005-06-30 23:26:35.000000000 +0000
@@ -143,6 +143,7 @@ register unsigned long current_stack_poi
 #define TIF_SECCOMP		8	/* secure computing */
 #define TIF_POLLING_NRFLAG	16	/* true if poll_idle() is polling TIF_NEED_RESCHED */
 #define TIF_MEMDIE		17
+#define TIF_FREEZE		18	/* Freeze thread */
 
 #define _TIF_SYSCALL_TRACE	(1<<TIF_SYSCALL_TRACE)
 #define _TIF_NOTIFY_RESUME	(1<<TIF_NOTIFY_RESUME)
Index: linux-2.6.12/include/asm-xtensa/thread_info.h
===================================================================
--- linux-2.6.12.orig/include/asm-xtensa/thread_info.h	2005-06-30 23:26:07.000000000 +0000
+++ linux-2.6.12/include/asm-xtensa/thread_info.h	2005-06-30 23:26:35.000000000 +0000
@@ -118,6 +118,7 @@ static inline struct thread_info *curren
 #define TIF_SINGLESTEP		4	/* restore singlestep on return to user mode */
 #define TIF_IRET		5	/* return with iret */
 #define TIF_MEMDIE		6
+#define TIF_FREEZE		7
 #define TIF_POLLING_NRFLAG	16	/* true if poll_idle() is polling TIF_NEED_RESCHED */
 
 #define _TIF_SYSCALL_TRACE	(1<<TIF_SYSCALL_TRACE)
Index: linux-2.6.12/include/asm-h8300/thread_info.h
===================================================================
--- linux-2.6.12.orig/include/asm-h8300/thread_info.h	2005-06-30 23:26:07.000000000 +0000
+++ linux-2.6.12/include/asm-h8300/thread_info.h	2005-06-30 23:26:35.000000000 +0000
@@ -94,6 +94,7 @@ static inline struct thread_info *curren
 #define TIF_POLLING_NRFLAG	4	/* true if poll_idle() is polling
 					   TIF_NEED_RESCHED */
 #define TIF_MEMDIE		5
+#define TIF_FREEZE		6
 
 /* as above, but as bit values */
 #define _TIF_SYSCALL_TRACE	(1<<TIF_SYSCALL_TRACE)
Index: linux-2.6.12/include/asm-ppc/thread_info.h
===================================================================
--- linux-2.6.12.orig/include/asm-ppc/thread_info.h	2005-06-30 23:26:07.000000000 +0000
+++ linux-2.6.12/include/asm-ppc/thread_info.h	2005-06-30 23:26:35.000000000 +0000
@@ -80,6 +80,7 @@ static inline struct thread_info *curren
 #define TIF_MEMDIE		5
 #define TIF_SYSCALL_AUDIT       6       /* syscall auditing active */
 #define TIF_SECCOMP             7      /* secure computing */
+#define TIF_FREEZE		8
 
 /* as above, but as bit values */
 #define _TIF_SYSCALL_TRACE	(1<<TIF_SYSCALL_TRACE)
Index: linux-2.6.12/include/asm-sh64/thread_info.h
===================================================================
--- linux-2.6.12.orig/include/asm-sh64/thread_info.h	2005-06-30 23:26:07.000000000 +0000
+++ linux-2.6.12/include/asm-sh64/thread_info.h	2005-06-30 23:26:35.000000000 +0000
@@ -80,6 +80,7 @@ static inline struct thread_info *curren
 #define TIF_SIGPENDING		2	/* signal pending */
 #define TIF_NEED_RESCHED	3	/* rescheduling necessary */
 #define TIF_MEMDIE		4
+#define TIF_FREEZE		5
 
 
 #endif /* __KERNEL__ */
Index: linux-2.6.12/include/asm-alpha/thread_info.h
===================================================================
--- linux-2.6.12.orig/include/asm-alpha/thread_info.h	2005-06-30 23:26:07.000000000 +0000
+++ linux-2.6.12/include/asm-alpha/thread_info.h	2005-06-30 23:26:35.000000000 +0000
@@ -78,6 +78,7 @@ register struct thread_info *__current_t
 #define TIF_UAC_NOFIX		7
 #define TIF_UAC_SIGBUS		8
 #define TIF_MEMDIE		9
+#define TIF_FREEZE		10
 
 #define _TIF_SYSCALL_TRACE	(1<<TIF_SYSCALL_TRACE)
 #define _TIF_NOTIFY_RESUME	(1<<TIF_NOTIFY_RESUME)
Index: linux-2.6.12/include/asm-sparc/thread_info.h
===================================================================
--- linux-2.6.12.orig/include/asm-sparc/thread_info.h	2005-06-30 23:26:07.000000000 +0000
+++ linux-2.6.12/include/asm-sparc/thread_info.h	2005-06-30 23:26:35.000000000 +0000
@@ -139,6 +139,7 @@ BTFIXUPDEF_CALL(void, free_thread_info, 
 #define TIF_POLLING_NRFLAG	9	/* true if poll_idle() is polling
 					 * TIF_NEED_RESCHED */
 #define TIF_MEMDIE		10
+#define TIF_FREEZE		11
 
 /* as above, but as bit values */
 #define _TIF_SYSCALL_TRACE	(1<<TIF_SYSCALL_TRACE)
Index: linux-2.6.12/include/asm-frv/thread_info.h
===================================================================
--- linux-2.6.12.orig/include/asm-frv/thread_info.h	2005-06-30 23:26:07.000000000 +0000
+++ linux-2.6.12/include/asm-frv/thread_info.h	2005-06-30 23:26:35.000000000 +0000
@@ -133,6 +133,7 @@ register struct thread_info *__current_t
 #define TIF_IRET		5	/* return with iret */
 #define TIF_POLLING_NRFLAG	16	/* true if poll_idle() is polling TIF_NEED_RESCHED */
 #define TIF_MEMDIE		17	/* OOM killer killed process */
+#define TIF_FREEZE		18
 
 #define _TIF_SYSCALL_TRACE	(1 << TIF_SYSCALL_TRACE)
 #define _TIF_NOTIFY_RESUME	(1 << TIF_NOTIFY_RESUME)
Index: linux-2.6.12/include/asm-parisc/thread_info.h
===================================================================
--- linux-2.6.12.orig/include/asm-parisc/thread_info.h	2005-06-30 23:26:07.000000000 +0000
+++ linux-2.6.12/include/asm-parisc/thread_info.h	2005-06-30 23:26:35.000000000 +0000
@@ -64,6 +64,7 @@ struct thread_info {
 #define TIF_POLLING_NRFLAG	4	/* true if poll_idle() is polling TIF_NEED_RESCHED */
 #define TIF_32BIT               5       /* 32 bit binary */
 #define TIF_MEMDIE		6
+#define TIF_FREEZE		7
 
 #define _TIF_SYSCALL_TRACE	(1 << TIF_SYSCALL_TRACE)
 #define _TIF_NOTIFY_RESUME	(1 << TIF_NOTIFY_RESUME)
Index: linux-2.6.12/include/asm-m68knommu/thread_info.h
===================================================================
--- linux-2.6.12.orig/include/asm-m68knommu/thread_info.h	2005-06-30 23:26:07.000000000 +0000
+++ linux-2.6.12/include/asm-m68knommu/thread_info.h	2005-06-30 23:26:35.000000000 +0000
@@ -91,6 +91,7 @@ static inline struct thread_info *curren
 #define TIF_POLLING_NRFLAG	4	/* true if poll_idle() is polling
 					   TIF_NEED_RESCHED */
 #define TIF_MEMDIE		5
+#define TIF_FREEZE		6
 
 /* as above, but as bit values */
 #define _TIF_SYSCALL_TRACE	(1<<TIF_SYSCALL_TRACE)
Index: linux-2.6.12/include/asm-m68k/thread_info.h
===================================================================
--- linux-2.6.12.orig/include/asm-m68k/thread_info.h	2005-06-30 23:26:07.000000000 +0000
+++ linux-2.6.12/include/asm-m68k/thread_info.h	2005-06-30 23:26:35.000000000 +0000
@@ -49,6 +49,7 @@ struct thread_info {
 #define TIF_SIGPENDING		3	/* signal pending */
 #define TIF_NEED_RESCHED	4	/* rescheduling necessary */
 #define TIF_MEMDIE		5
+#define TIF_FREEZE		6
 
 extern int thread_flag_fixme(void);
 
Index: linux-2.6.12/include/asm-sh/thread_info.h
===================================================================
--- linux-2.6.12.orig/include/asm-sh/thread_info.h	2005-06-30 23:26:07.000000000 +0000
+++ linux-2.6.12/include/asm-sh/thread_info.h	2005-06-30 23:26:35.000000000 +0000
@@ -84,6 +84,7 @@ static inline struct thread_info *curren
 #define TIF_USEDFPU		16	/* FPU was used by this task this quantum (SMP) */
 #define TIF_POLLING_NRFLAG	17	/* true if poll_idle() is polling TIF_NEED_RESCHED */
 #define TIF_MEMDIE		18
+#define TIF_FREEZE		19
 #define TIF_USERSPACE		31	/* true if FS sets userspace */
 
 #define _TIF_SYSCALL_TRACE	(1<<TIF_SYSCALL_TRACE)
Index: linux-2.6.12/include/asm-s390/thread_info.h
===================================================================
--- linux-2.6.12.orig/include/asm-s390/thread_info.h	2005-06-30 23:26:07.000000000 +0000
+++ linux-2.6.12/include/asm-s390/thread_info.h	2005-06-30 23:26:35.000000000 +0000
@@ -102,6 +102,7 @@ static inline struct thread_info *curren
 					   TIF_NEED_RESCHED */
 #define TIF_31BIT		18	/* 32bit process */ 
 #define TIF_MEMDIE		19
+#define TIF_FREEZE		20
 
 #define _TIF_SYSCALL_TRACE	(1<<TIF_SYSCALL_TRACE)
 #define _TIF_NOTIFY_RESUME	(1<<TIF_NOTIFY_RESUME)
Index: linux-2.6.12/include/asm-arm/thread_info.h
===================================================================
--- linux-2.6.12.orig/include/asm-arm/thread_info.h	2005-06-30 23:26:07.000000000 +0000
+++ linux-2.6.12/include/asm-arm/thread_info.h	2005-06-30 23:26:35.000000000 +0000
@@ -132,6 +132,7 @@ extern void iwmmxt_task_release(struct t
 #define TIF_POLLING_NRFLAG	16
 #define TIF_USING_IWMMXT	17
 #define TIF_MEMDIE		18
+#define TIF_FREEZE		19
 
 #define _TIF_NOTIFY_RESUME	(1 << TIF_NOTIFY_RESUME)
 #define _TIF_SIGPENDING		(1 << TIF_SIGPENDING)
Index: linux-2.6.12/include/asm-v850/thread_info.h
===================================================================
--- linux-2.6.12.orig/include/asm-v850/thread_info.h	2005-06-30 23:26:07.000000000 +0000
+++ linux-2.6.12/include/asm-v850/thread_info.h	2005-06-30 23:26:35.000000000 +0000
@@ -85,6 +85,7 @@ struct thread_info {
 #define TIF_POLLING_NRFLAG	4	/* true if poll_idle() is polling
 					   TIF_NEED_RESCHED */
 #define TIF_MEMDIE		5
+#define TIF_FREEZE		6
 
 /* as above, but as bit values */
 #define _TIF_SYSCALL_TRACE	(1<<TIF_SYSCALL_TRACE)
Index: linux-2.6.12/include/asm-mips/thread_info.h
===================================================================
--- linux-2.6.12.orig/include/asm-mips/thread_info.h	2005-06-30 23:26:07.000000000 +0000
+++ linux-2.6.12/include/asm-mips/thread_info.h	2005-06-30 23:26:35.000000000 +0000
@@ -117,6 +117,7 @@ register struct thread_info *__current_t
 #define TIF_USEDFPU		16	/* FPU was used by this task this quantum (SMP) */
 #define TIF_POLLING_NRFLAG	17	/* true if poll_idle() is polling TIF_NEED_RESCHED */
 #define TIF_MEMDIE		18
+#define TIF_FREEZE		19
 #define TIF_SYSCALL_TRACE	31	/* syscall trace active */
 
 #define _TIF_SYSCALL_TRACE	(1<<TIF_SYSCALL_TRACE)
Index: linux-2.6.12/include/asm-cris/thread_info.h
===================================================================
--- linux-2.6.12.orig/include/asm-cris/thread_info.h	2005-06-30 23:26:07.000000000 +0000
+++ linux-2.6.12/include/asm-cris/thread_info.h	2005-06-30 23:26:35.000000000 +0000
@@ -86,6 +86,7 @@ struct thread_info {
 #define TIF_NEED_RESCHED	3	/* rescheduling necessary */
 #define TIF_POLLING_NRFLAG	16	/* true if poll_idle() is polling TIF_NEED_RESCHED */
 #define TIF_MEMDIE		17
+#define TIF_FREEZE		18
 
 #define _TIF_SYSCALL_TRACE	(1<<TIF_SYSCALL_TRACE)
 #define _TIF_NOTIFY_RESUME	(1<<TIF_NOTIFY_RESUME)
Index: linux-2.6.12/include/asm-arm26/thread_info.h
===================================================================
--- linux-2.6.12.orig/include/asm-arm26/thread_info.h	2005-06-30 23:26:07.000000000 +0000
+++ linux-2.6.12/include/asm-arm26/thread_info.h	2005-06-30 23:26:35.000000000 +0000
@@ -127,6 +127,7 @@ extern void free_thread_info(struct thre
 #define TIF_USED_FPU		16
 #define TIF_POLLING_NRFLAG	17
 #define TIF_MEMDIE		18
+#define TIF_FREEZE		19
 
 #define _TIF_NOTIFY_RESUME	(1 << TIF_NOTIFY_RESUME)
 #define _TIF_SIGPENDING		(1 << TIF_SIGPENDING)
Index: linux-2.6.12/include/asm-sparc64/thread_info.h
===================================================================
--- linux-2.6.12.orig/include/asm-sparc64/thread_info.h	2005-06-30 23:26:07.000000000 +0000
+++ linux-2.6.12/include/asm-sparc64/thread_info.h	2005-06-30 23:26:35.000000000 +0000
@@ -229,6 +229,7 @@ register struct thread_info *current_thr
  */
 #define TIF_ABI_PENDING		12
 #define TIF_MEMDIE		13
+#define TIF_FREEZE		14
 
 #define _TIF_SYSCALL_TRACE	(1<<TIF_SYSCALL_TRACE)
 #define _TIF_NOTIFY_RESUME	(1<<TIF_NOTIFY_RESUME)
Index: linux-2.6.12/include/asm-m32r/thread_info.h
===================================================================
--- linux-2.6.12.orig/include/asm-m32r/thread_info.h	2005-06-30 23:26:07.000000000 +0000
+++ linux-2.6.12/include/asm-m32r/thread_info.h	2005-06-30 23:26:35.000000000 +0000
@@ -156,6 +156,7 @@ static inline unsigned int get_thread_fa
 #define TIF_POLLING_NRFLAG	16	/* true if poll_idle() is polling TIF_NEED_RESCHED */
 					/* 31..28 fault code */
 #define TIF_MEMDIE		17
+#define TIF_FREEZE		18
 
 #define _TIF_SYSCALL_TRACE	(1<<TIF_SYSCALL_TRACE)
 #define _TIF_NOTIFY_RESUME	(1<<TIF_NOTIFY_RESUME)
Index: linux-2.6.12/include/asm-ppc64/thread_info.h
===================================================================
--- linux-2.6.12.orig/include/asm-ppc64/thread_info.h	2005-06-30 23:26:07.000000000 +0000
+++ linux-2.6.12/include/asm-ppc64/thread_info.h	2005-06-30 23:26:35.000000000 +0000
@@ -102,6 +102,7 @@ static inline struct thread_info *curren
 #define TIF_SINGLESTEP		9	/* singlestepping active */
 #define TIF_MEMDIE		10
 #define TIF_SECCOMP		11	/* secure computing */
+#define TIF_FREEZE		12
 
 /* as above, but as bit values */
 #define _TIF_SYSCALL_TRACE	(1<<TIF_SYSCALL_TRACE)
Index: linux-2.6.12/include/asm-um/thread_info.h
===================================================================
--- linux-2.6.12.orig/include/asm-um/thread_info.h	2005-06-30 23:26:07.000000000 +0000
+++ linux-2.6.12/include/asm-um/thread_info.h	2005-06-30 23:26:35.000000000 +0000
@@ -72,6 +72,7 @@ static inline struct thread_info *curren
 #define TIF_RESTART_BLOCK 	4
 #define TIF_MEMDIE	 	5
 #define TIF_SYSCALL_AUDIT	6
+#define TIF_FREEZE		7
 
 #define _TIF_SYSCALL_TRACE	(1 << TIF_SYSCALL_TRACE)
 #define _TIF_SIGPENDING		(1 << TIF_SIGPENDING)
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"aart@kvack.org"> aart@kvack.org </a>

^ permalink raw reply	[flat|nested] 35+ messages in thread

* [SUSPEND 2/2] Replace PF_FROZEN with TASK_FROZEN
  2005-07-01 17:06                         ` [SUSPEND 1/2]Replace PF_FREEZE with TIF_FREEZE Christoph Lameter
@ 2005-07-01 17:14                           ` Christoph Lameter
  0 siblings, 0 replies; 35+ messages in thread
From: Christoph Lameter @ 2005-07-01 17:14 UTC (permalink / raw)
  To: Pavel Machek
  Cc: Kirill Korotaev, Linus Torvalds, linux-mm, linux-kernel,
	Alexey Kuznetsov

Removes the PF_FROZEN flag and introduces TASK_FROZEN. This allows a simplification
of the locking for software suspend and helps clean up race conditions.

Also remove many inline functions to follow the coding style in other locations.

Beware: compiles fine not tested since I need to move on to other issues 
now. But this is my best stab at how this could be fixed in the time that 
I could spend with the issue.

Signed-off-by: Christoph Lameter <christoph@lameter.com>

Index: linux-2.6.12/include/linux/sched.h
===================================================================
--- linux-2.6.12.orig/include/linux/sched.h	2005-07-01 04:50:46.000000000 +0000
+++ linux-2.6.12/include/linux/sched.h	2005-07-01 08:58:49.000000000 +0000
@@ -110,8 +110,9 @@ extern unsigned long nr_iowait(void);
 #define TASK_UNINTERRUPTIBLE	2
 #define TASK_STOPPED		4
 #define TASK_TRACED		8
-#define EXIT_ZOMBIE		16
-#define EXIT_DEAD		32
+#define TASK_FROZEN		16
+#define EXIT_ZOMBIE		32
+#define EXIT_DEAD		64
 
 #define __set_task_state(tsk, state_value)		\
 	do { (tsk)->state = (state_value); } while (0)
@@ -808,7 +809,6 @@ do { if (atomic_dec_and_test(&(tsk)->usa
 #define PF_FLUSHER	0x00001000	/* responsible for disk writeback */
 #define PF_USED_MATH	0x00002000	/* if unset the fpu must be initialized before use */
 #define PF_NOFREEZE	0x00008000	/* this thread should not be frozen */
-#define PF_FROZEN	0x00010000	/* frozen for system suspend */
 #define PF_FSTRANS	0x00020000	/* inside a filesystem transaction */
 #define PF_KSWAPD	0x00040000	/* I am kswapd */
 #define PF_SWAPOFF	0x00080000	/* I am in swapoff */
@@ -1270,14 +1270,6 @@ extern void normalize_rt_tasks(void);
 
 #ifdef CONFIG_PM
 /*
- * 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)
@@ -1285,36 +1277,6 @@ static inline int freezing(struct task_s
 	return test_ti_thread_flag(p->thread_info, TIF_FREEZE);
 }
 
-/*
- * Request that a process be frozen
- */
-static inline void freeze(struct task_struct *p)
-{
-	set_ti_thread_flag(p->thread_info, TIF_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 |= PF_FROZEN;
-	clear_ti_thread_flag(p->thread_info, TIF_FREEZE);
-}
-
 extern void refrigerator(void);
 extern int freeze_processes(void);
 extern void thaw_processes(void);
@@ -1328,11 +1290,7 @@ static inline int try_to_freeze(void)
 		return 0;
 }
 #else
-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; }
Index: linux-2.6.12/kernel/power/process.c
===================================================================
--- linux-2.6.12.orig/kernel/power/process.c	2005-07-01 04:50:46.000000000 +0000
+++ linux-2.6.12/kernel/power/process.c	2005-07-01 08:58:49.000000000 +0000
@@ -37,20 +37,21 @@ void refrigerator(void)
 	/* Hmm, should we be allowed to suspend when there are realtime
 	   processes around? */
 	long save;
-	save = current->state;
-	current->state = TASK_UNINTERRUPTIBLE;
+
 	pr_debug("%s entered refrigerator\n", current->comm);
 	printk("=");
 
-	frozen_process(current);
+	save = current->state;
+	current->state = TASK_FROZEN;
+	while (test_thread_flag(TIF_FREEZE))
+		schedule();
+	current->state = save;
+
 	spin_lock_irq(&current->sighand->siglock);
 	recalc_sigpending(); /* We sent fake signal, clean it up */
 	spin_unlock_irq(&current->sighand->siglock);
 
-	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 */
@@ -67,14 +68,12 @@ int freeze_processes(void)
 		read_lock(&tasklist_lock);
 		do_each_thread(g, p) {
 			unsigned long flags;
-			if (!freezeable(p))
-				continue;
-			if ((frozen(p)) ||
-			    (p->state == TASK_TRACED) ||
-			    (p->state == TASK_STOPPED))
+
+			if (!freezeable(p) ||
+			    (p->state & (TASK_FROZEN | TASK_TRACED | TASK_STOPPED)))
 				continue;
 
-			freeze(p);
+			set_tsk_thread_flag(p, TIF_FREEZE);
 			spin_lock_irqsave(&p->sighand->siglock, flags);
 			signal_wake_up(p, 0);
 			spin_unlock_irqrestore(&p->sighand->siglock, flags);
@@ -85,6 +84,7 @@ int freeze_processes(void)
 		if (time_after(jiffies, start_time + TIMEOUT)) {
 			printk( "\n" );
 			printk(KERN_ERR " stopping tasks failed (%d tasks remaining)\n", todo );
+			thaw_processes();
 			return todo;
 		}
 	} while(todo);
@@ -103,8 +103,8 @@ void thaw_processes(void)
 	do_each_thread(g, p) {
 		if (!freezeable(p))
 			continue;
-		if (!thaw_process(p))
-			printk(KERN_INFO " Strange, %s not stopped\n", p->comm );
+		if (test_and_clear_tsk_thread_flag(p, TIF_FREEZE))
+			wake_up_state(p, TASK_FROZEN);
 	} while_each_thread(g, p);
 
 	read_unlock(&tasklist_lock);
Index: linux-2.6.12/fs/proc/array.c
===================================================================
--- linux-2.6.12.orig/fs/proc/array.c	2005-06-17 19:48:29.000000000 +0000
+++ linux-2.6.12/fs/proc/array.c	2005-07-01 09:07:05.000000000 +0000
@@ -133,8 +133,9 @@ static const char *task_state_array[] = 
 	"D (disk sleep)",	/*  2 */
 	"T (stopped)",		/*  4 */
 	"T (tracing stop)",	/*  8 */
-	"Z (zombie)",		/* 16 */
-	"X (dead)"		/* 32 */
+	"F (frozen)",		/* 16 */
+	"Z (zombie)",		/* 32 */
+	"X (dead)"		/* 64 */
 };
 
 static inline const char * get_task_state(struct task_struct *tsk)
@@ -143,7 +144,8 @@ static inline const char * get_task_stat
 					    TASK_INTERRUPTIBLE |
 					    TASK_UNINTERRUPTIBLE |
 					    TASK_STOPPED |
-					    TASK_TRACED)) |
+					    TASK_TRACED |
+					    TASK_FROZEN)) |
 			(tsk->exit_state & (EXIT_ZOMBIE |
 					    EXIT_DEAD));
 	const char **p = &task_state_array[0];

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"aart@kvack.org"> aart@kvack.org </a>

^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: [RFC] Fix SMP brokenness for PF_FREEZE and make freezing usable for other purposes
  2005-06-28 21:54                   ` Christoph Lameter
@ 2005-07-03 11:06                     ` Pavel Machek
  0 siblings, 0 replies; 35+ messages in thread
From: Pavel Machek @ 2005-07-03 11:06 UTC (permalink / raw)
  To: Christoph Lameter; +Cc: Ray Bryant, Linus Torvalds, linux-mm, linux-kernel

Hi!

> > >  -			freeze(p);
> > > +			set_thread_flag(TIF_FREEZE);
> > 
> > Shouldn't that be "set_ti_thread_flag(p->thread_info, TIF_FREEZE)"?
> > Otherwise you freeze current, not the thread "p".
> 
> Correct. Which also means that we have not progressed yet beyond an 
> academic version of the patch:
> 
> ---
> 
> Revise handling of freezing in the suspend code
> 
> The current suspend code modifies thread flags from outside the context of process.
> This creates a SMP race.
> 
> The patch fixes that by introducing a TIF_FREEZE flag (for all arches). Also
> 
> - Uses a completion handler instead of waiting in a schedule loop in the refrigerator.
> 
> - Introduces a semaphore freezer_sem to provide a way that multiple kernel
>   subsystems can use the freezing ability without interfering with one another.
> 
> - Include necessary definitions for the migration code if CONFIG_MIGRATE is set.
> 
> - Removes PF_FREEZE
> 
> Signed-off-by: Christoph Lameter <christoph@lameter.com>

This patch breaks suspend for me (first suspend works, second suspend
fails to freeze processes). [I was offline, that's why it took so
long.]

I see patches 1/2 and 2/2 submitted; if you still feel I should apply
some of them, tell me.
								Pavel

-- 
teflon -- maybe it is a trademark, but it should not be.
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"aart@kvack.org"> aart@kvack.org </a>

^ permalink raw reply	[flat|nested] 35+ messages in thread

end of thread, other threads:[~2005-07-03 11:06 UTC | newest]

Thread overview: 35+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2005-06-24 20:20 [RFC] Fix SMP brokenness for PF_FREEZE and make freezing usable for other purposes Christoph Lameter
2005-06-24 22:25 ` Nigel Cunningham
2005-06-25  2:51 ` Pavel Machek
2005-06-25  4:31   ` Christoph Lameter
2005-06-25  4:46     ` Nigel Cunningham
2005-06-25 22:37     ` Pavel Machek
2005-06-25  6:13   ` Christoph Lameter
2005-06-26  2:30     ` Pavel Machek
2005-06-26  2:55       ` Christoph Lameter
2005-06-26  3:09         ` Pavel Machek
2005-06-27  3:51           ` Christoph Lameter
2005-06-27  4:21             ` Pavel Machek
2005-06-27  4:24             ` Linus Torvalds
2005-06-27  5:53               ` Christoph Lameter
2005-06-27 14:13                 ` Pavel Machek
2005-06-27 15:13                   ` Christoph Lameter
2005-06-28  6:18                     ` Kirill Korotaev
2005-06-28  7:01                       ` Christoph Lameter
2005-06-28  7:30                         ` Kirill Korotaev
2005-06-28  8:13                           ` Kirill Korotaev
2005-06-28 14:02                             ` Christoph Lameter
2005-06-28 14:01                           ` Christoph Lameter
2005-06-28 12:47                       ` Pavel Machek
2005-07-01 17:06                         ` [SUSPEND 1/2]Replace PF_FREEZE with TIF_FREEZE Christoph Lameter
2005-07-01 17:14                           ` [SUSPEND 2/2] Replace PF_FROZEN with TASK_FROZEN Christoph Lameter
2005-06-28 21:50                 ` [RFC] Fix SMP brokenness for PF_FREEZE and make freezing usable for other purposes Ray Bryant
2005-06-28 21:54                   ` Christoph Lameter
2005-07-03 11:06                     ` Pavel Machek
2005-06-26 10:54       ` Nigel Cunningham
2005-06-25  6:18   ` Christoph Lameter
2005-06-25  7:35 ` Kirill Korotaev
2005-06-27  7:06   ` Ray Bryant
2005-06-27 13:17     ` Pavel Machek
2005-06-27 14:59       ` Ray Bryant
2005-06-27 18:05         ` Pavel Machek

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox