The Linux Kernel Mailing List
 help / color / mirror / Atom feed
* [RFC] Thread Migration Preemption
@ 2007-07-05 21:51 Mathieu Desnoyers
  2007-07-05 22:46 ` Steven Rostedt
                   ` (3 more replies)
  0 siblings, 4 replies; 33+ messages in thread
From: Mathieu Desnoyers @ 2007-07-05 21:51 UTC (permalink / raw)
  To: Steven Rostedt, Ingo Molnar; +Cc: linux-kernel

Thread Migration Preemption

This patch adds the ability to protect critical sections from migration to
another CPU without disabling preemption.

This will be useful to minimize the amount of preemption disabling for the -rt
patch. It will help leveraging improvements brought by the local_t types in
asm/local.h (see Documentation/local_ops.txt). Note that the updates done to
variables protected by migration_disable must be either atomic or protected from
concurrent updates done by other threads.

Typical use:

migration_disable();
local_inc(&__get_cpu_var(&my_local_t_var));
migration_enable();

Which will increment the variable atomically wrt the local CPU.

Comments (such as how to integrate this in the already almost full
preempt_count) are welcome.

It applies on 2.6.22-rc6-mm1.

Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@polymtl.ca>
---
 include/asm-alpha/thread_info.h     |    1 +
 include/asm-arm/thread_info.h       |    2 ++
 include/asm-arm26/thread_info.h     |    2 ++
 include/asm-avr32/thread_info.h     |    2 ++
 include/asm-blackfin/thread_info.h  |    2 ++
 include/asm-cris/thread_info.h      |    2 ++
 include/asm-frv/thread_info.h       |    2 ++
 include/asm-h8300/thread_info.h     |    2 ++
 include/asm-i386/thread_info.h      |    4 ++--
 include/asm-ia64/thread_info.h      |    2 ++
 include/asm-m32r/thread_info.h      |    2 ++
 include/asm-m68k/thread_info.h      |    1 +
 include/asm-m68knommu/thread_info.h |    1 +
 include/asm-mips/thread_info.h      |    2 ++
 include/asm-parisc/thread_info.h    |    2 ++
 include/asm-powerpc/thread_info.h   |    2 ++
 include/asm-s390/thread_info.h      |    2 ++
 include/asm-sh/thread_info.h        |    2 ++
 include/asm-sh64/thread_info.h      |    2 ++
 include/asm-sparc/thread_info.h     |    2 ++
 include/asm-sparc64/thread_info.h   |    2 ++
 include/asm-um/thread_info.h        |    2 ++
 include/asm-v850/thread_info.h      |    2 ++
 include/asm-x86_64/thread_info.h    |    2 ++
 include/asm-xtensa/thread_info.h    |    2 ++
 include/linux/preempt.h             |   26 +++++++++++++++++++++++++-
 kernel/sched.c                      |   26 ++++++++++++++++++++++++++
 27 files changed, 98 insertions(+), 3 deletions(-)

Index: linux-2.6-lttng/include/asm-i386/thread_info.h
===================================================================
--- linux-2.6-lttng.orig/include/asm-i386/thread_info.h	2007-07-05 16:23:14.000000000 -0400
+++ linux-2.6-lttng/include/asm-i386/thread_info.h	2007-07-05 17:50:51.000000000 -0400
@@ -31,8 +31,7 @@
 	unsigned long		status;		/* thread-synchronous flags */
 	__u32			cpu;		/* current CPU */
 	int			preempt_count;	/* 0 => preemptable, <0 => BUG */
-
-
+	int			migration_count;/* 0: can migrate, <0: BUG */
 	mm_segment_t		addr_limit;	/* thread address space:
 					 	   0-0xBFFFFFFF for user-thead
 						   0-0xFFFFFFFF for kernel-thread
@@ -74,6 +73,7 @@
 	.flags		= 0,			\
 	.cpu		= 0,			\
 	.preempt_count	= 1,			\
+	.migration_count = 0,			\
 	.addr_limit	= KERNEL_DS,		\
 	.restart_block = {			\
 		.fn = do_no_restart_syscall,	\
Index: linux-2.6-lttng/include/linux/preempt.h
===================================================================
--- linux-2.6-lttng.orig/include/linux/preempt.h	2007-07-05 16:19:00.000000000 -0400
+++ linux-2.6-lttng/include/linux/preempt.h	2007-07-05 16:33:29.000000000 -0400
@@ -12,15 +12,24 @@
 #ifdef CONFIG_DEBUG_PREEMPT
   extern void fastcall add_preempt_count(int val);
   extern void fastcall sub_preempt_count(int val);
+  extern void fastcall add_migration_count(int val);
+  extern void fastcall sub_migration_count(int val);
 #else
 # define add_preempt_count(val)	do { preempt_count() += (val); } while (0)
 # define sub_preempt_count(val)	do { preempt_count() -= (val); } while (0)
+# define add_migration_count(val) do { migration_count() += (val); } while (0)
+# define sub_migration_count(val) do { migration_count() -= (val); } while (0)
 #endif
 
 #define inc_preempt_count() add_preempt_count(1)
 #define dec_preempt_count() sub_preempt_count(1)
 
-#define preempt_count()	(current_thread_info()->preempt_count)
+#define preempt_count() (current_thread_info()->preempt_count)
+
+#define inc_migration_count() add_migration_count(1)
+#define dec_migration_count() sub_migration_count(1)
+
+#define migration_count() (current_thread_info()->migration_count)
 
 #ifdef CONFIG_PREEMPT
 
@@ -51,6 +60,18 @@
 	preempt_check_resched(); \
 } while (0)
 
+#define migration_disable() \
+do { \
+	inc_migration_count(); \
+	barrier(); \
+} while (0)
+
+#define migration_enable() \
+do { \
+	barrier(); \
+	dec_migration_count(); \
+} while (0)
+
 #else
 
 #define preempt_disable()		do { } while (0)
@@ -58,6 +79,9 @@
 #define preempt_enable()		do { } while (0)
 #define preempt_check_resched()		do { } while (0)
 
+#define migration_disable()		do { } while (0)
+#define migration_enable()		do { } while (0)
+
 #endif
 
 #endif /* __LINUX_PREEMPT_H */
Index: linux-2.6-lttng/kernel/sched.c
===================================================================
--- linux-2.6-lttng.orig/kernel/sched.c	2007-07-05 16:28:15.000000000 -0400
+++ linux-2.6-lttng/kernel/sched.c	2007-07-05 16:53:24.000000000 -0400
@@ -1996,6 +1996,7 @@
 	 * 1) running (obviously), or
 	 * 2) cannot be migrated to this CPU due to cpus_allowed, or
 	 * 3) are cache-hot on their current CPU.
+	 * 4) migration preemption is non 0 for this non running task.
 	 */
 	if (!cpu_isset(this_cpu, p->cpus_allowed))
 		return 0;
@@ -2003,6 +2004,8 @@
 
 	if (task_running(rq, p))
 		return 0;
+	if (task_thread_info(p)->migration_count)
+		return 0;
 
 	/*
 	 * Aggressive migration if too many balance attempts have failed:
@@ -3220,6 +3223,29 @@
 }
 EXPORT_SYMBOL(sub_preempt_count);
 
+void fastcall add_migration_count(int val)
+{
+	/*
+	 * Underflow?
+	 */
+	if (DEBUG_LOCKS_WARN_ON((migration_count() < 0)))
+		return;
+	migration_count() += val;
+}
+EXPORT_SYMBOL(add_migration_count);
+
+void fastcall sub_migration_count(int val)
+{
+	/*
+	 * Underflow?
+	 */
+	if (DEBUG_LOCKS_WARN_ON(val > migration_count()))
+		return;
+
+	migration_count() -= val;
+}
+EXPORT_SYMBOL(sub_migration_count);
+
 #endif
 
 /*
Index: linux-2.6-lttng/include/asm-alpha/thread_info.h
===================================================================
--- linux-2.6-lttng.orig/include/asm-alpha/thread_info.h	2007-07-05 16:54:49.000000000 -0400
+++ linux-2.6-lttng/include/asm-alpha/thread_info.h	2007-07-05 16:55:39.000000000 -0400
@@ -21,6 +21,7 @@
 	mm_segment_t		addr_limit;	/* thread address space */
 	unsigned		cpu;		/* current CPU */
 	int			preempt_count; /* 0 => preemptable, <0 => BUG */
+	int			migration_count;/* 0: can migrate, <0 => BUG */
 
 	int bpt_nsaved;
 	unsigned long bpt_addr[2];		/* breakpoint handling  */
Index: linux-2.6-lttng/include/asm-arm/thread_info.h
===================================================================
--- linux-2.6-lttng.orig/include/asm-arm/thread_info.h	2007-07-05 16:54:49.000000000 -0400
+++ linux-2.6-lttng/include/asm-arm/thread_info.h	2007-07-05 17:00:39.000000000 -0400
@@ -51,6 +51,7 @@
 struct thread_info {
 	unsigned long		flags;		/* low level flags */
 	int			preempt_count;	/* 0 => preemptable, <0 => bug */
+	int			migration_count;/* 0: can migrate, <0 => BUG */
 	mm_segment_t		addr_limit;	/* address limit */
 	struct task_struct	*task;		/* main task structure */
 	struct exec_domain	*exec_domain;	/* execution domain */
@@ -72,6 +73,7 @@
 	.exec_domain	= &default_exec_domain,				\
 	.flags		= 0,						\
 	.preempt_count	= 1,						\
+	.migration_count = 0,						\
 	.addr_limit	= KERNEL_DS,					\
 	.cpu_domain	= domain_val(DOMAIN_USER, DOMAIN_MANAGER) |	\
 			  domain_val(DOMAIN_KERNEL, DOMAIN_MANAGER) |	\
Index: linux-2.6-lttng/include/asm-arm26/thread_info.h
===================================================================
--- linux-2.6-lttng.orig/include/asm-arm26/thread_info.h	2007-07-05 16:54:49.000000000 -0400
+++ linux-2.6-lttng/include/asm-arm26/thread_info.h	2007-07-05 16:59:55.000000000 -0400
@@ -45,6 +45,7 @@
 struct thread_info {
 	unsigned long		flags;		/* low level flags */
 	int			preempt_count;	/* 0 => preemptable, <0 => bug */
+	int			migration_count;/* 0: can migrate, <0 => BUG */
 	mm_segment_t		addr_limit;	/* address limit */
 	struct task_struct	*task;		/* main task structure */
 	struct exec_domain      *exec_domain;   /* execution domain */
@@ -60,6 +61,7 @@
 	.exec_domain	&default_exec_domain,	\
 	.flags		0,			\
 	.preempt_count	0,			\
+	.migration_count 0,			\
 	.addr_limit	KERNEL_DS,		\
 	.restart_block  = {                             \
 		.fn     = do_no_restart_syscall,        \
Index: linux-2.6-lttng/include/asm-avr32/thread_info.h
===================================================================
--- linux-2.6-lttng.orig/include/asm-avr32/thread_info.h	2007-07-05 16:54:49.000000000 -0400
+++ linux-2.6-lttng/include/asm-avr32/thread_info.h	2007-07-05 17:00:52.000000000 -0400
@@ -25,6 +25,7 @@
 	unsigned long		flags;		/* low level flags */
 	__u32			cpu;
 	__s32			preempt_count;	/* 0 => preemptable, <0 => BUG */
+	int			migration_count;/* 0: can migrate, <0 => BUG */
 	struct restart_block	restart_block;
 	__u8			supervisor_stack[0];
 };
@@ -36,6 +37,7 @@
 	.flags		= 0,						\
 	.cpu		= 0,						\
 	.preempt_count	= 1,						\
+	.migration_count = 0,						\
 	.restart_block	= {						\
 		.fn	= do_no_restart_syscall				\
 	}								\
Index: linux-2.6-lttng/include/asm-blackfin/thread_info.h
===================================================================
--- linux-2.6-lttng.orig/include/asm-blackfin/thread_info.h	2007-07-05 16:54:49.000000000 -0400
+++ linux-2.6-lttng/include/asm-blackfin/thread_info.h	2007-07-05 17:00:58.000000000 -0400
@@ -54,6 +54,7 @@
 	unsigned long flags;	/* low level flags */
 	int cpu;		/* cpu we're on */
 	int preempt_count;	/* 0 => preemptable, <0 => BUG */
+	int migration_count;	/* 0: can migrate, <0 => BUG */
 	mm_segment_t addr_limit;	/* address limit */
 	struct restart_block restart_block;
 	struct l1_scratch_task_info l1_task_info;
@@ -69,6 +70,7 @@
 	.flags		= 0,			\
 	.cpu		= 0,			\
 	.preempt_count  = 1,                    \
+	.migration_count = 0,			\
 	.restart_block	= {			\
 		.fn = do_no_restart_syscall,	\
 	},					\
Index: linux-2.6-lttng/include/asm-cris/thread_info.h
===================================================================
--- linux-2.6-lttng.orig/include/asm-cris/thread_info.h	2007-07-05 16:54:49.000000000 -0400
+++ linux-2.6-lttng/include/asm-cris/thread_info.h	2007-07-05 17:01:16.000000000 -0400
@@ -32,6 +32,7 @@
 	unsigned long		flags;		/* low level flags */
 	__u32			cpu;		/* current CPU */
 	int			preempt_count;	/* 0 => preemptable, <0 => BUG */
+	int			migration_count;/* 0: can migrate, <0 => BUG */
 
 	mm_segment_t		addr_limit;	/* thread address space:
 					 	   0-0xBFFFFFFF for user-thead
@@ -58,6 +59,7 @@
 	.flags		= 0,				\
 	.cpu		= 0,				\
 	.preempt_count	= 1,				\
+	.migration_count = 0,				\
 	.addr_limit	= KERNEL_DS,			\
 	.restart_block = {				\
 		       .fn = do_no_restart_syscall,	\
Index: linux-2.6-lttng/include/asm-frv/thread_info.h
===================================================================
--- linux-2.6-lttng.orig/include/asm-frv/thread_info.h	2007-07-05 16:54:49.000000000 -0400
+++ linux-2.6-lttng/include/asm-frv/thread_info.h	2007-07-05 17:01:28.000000000 -0400
@@ -36,6 +36,7 @@
 	unsigned long		status;		/* thread-synchronous flags */
 	__u32			cpu;		/* current CPU */
 	int			preempt_count;	/* 0 => preemptable, <0 => BUG */
+	int			migration_count;/* 0: can migrate, <0 => BUG */
 
 	mm_segment_t		addr_limit;	/* thread address space:
 					 	   0-0xBFFFFFFF for user-thead
@@ -68,6 +69,7 @@
 	.flags		= 0,			\
 	.cpu		= 0,			\
 	.preempt_count	= 1,			\
+	.migration_count = 0,			\
 	.addr_limit	= KERNEL_DS,		\
 	.restart_block = {			\
 		.fn = do_no_restart_syscall,	\
Index: linux-2.6-lttng/include/asm-h8300/thread_info.h
===================================================================
--- linux-2.6-lttng.orig/include/asm-h8300/thread_info.h	2007-07-05 16:54:49.000000000 -0400
+++ linux-2.6-lttng/include/asm-h8300/thread_info.h	2007-07-05 17:01:52.000000000 -0400
@@ -24,6 +24,7 @@
 	unsigned long	   flags;		/* low level flags */
 	int		   cpu;			/* cpu we're on */
 	int		   preempt_count;	/* 0 => preemptable, <0 => BUG */
+	int			migration_count;/* 0: can migrate, <0 => BUG */
 	struct restart_block restart_block;
 };
 
@@ -37,6 +38,7 @@
 	.flags =	0,			\
 	.cpu =		0,			\
 	.preempt_count = 1,			\
+	.migration_count = 0,			\
 	.restart_block	= {			\
 		.fn = do_no_restart_syscall,	\
 	},					\
Index: linux-2.6-lttng/include/asm-ia64/thread_info.h
===================================================================
--- linux-2.6-lttng.orig/include/asm-ia64/thread_info.h	2007-07-05 16:54:49.000000000 -0400
+++ linux-2.6-lttng/include/asm-ia64/thread_info.h	2007-07-05 17:02:31.000000000 -0400
@@ -30,6 +30,7 @@
 	__u32 status;			/* Thread synchronous flags */
 	mm_segment_t addr_limit;	/* user-level address space limit */
 	int preempt_count;		/* 0=premptable, <0=BUG; will also serve as bh-counter */
+	int migration_count;		/* 0: can migrate, <0 => BUG */
 	struct restart_block restart_block;
 };
 
@@ -43,6 +44,7 @@
 	.cpu		= 0,			\
 	.addr_limit	= KERNEL_DS,		\
 	.preempt_count	= 0,			\
+	.migration_count = 0,			\
 	.restart_block = {			\
 		.fn = do_no_restart_syscall,	\
 	},					\
Index: linux-2.6-lttng/include/asm-m32r/thread_info.h
===================================================================
--- linux-2.6-lttng.orig/include/asm-m32r/thread_info.h	2007-07-05 16:54:49.000000000 -0400
+++ linux-2.6-lttng/include/asm-m32r/thread_info.h	2007-07-05 17:02:44.000000000 -0400
@@ -29,6 +29,7 @@
 	unsigned long		status;		/* thread-synchronous flags */
 	__u32			cpu;		/* current CPU */
 	int			preempt_count;	/* 0 => preemptable, <0 => BUG */
+	int			migration_count;/* 0: can migrate, <0 => BUG */
 
 	mm_segment_t		addr_limit;	/* thread address space:
 					 	   0-0xBFFFFFFF for user-thread
@@ -69,6 +70,7 @@
 	.flags		= 0,			\
 	.cpu		= 0,			\
 	.preempt_count	= 1,			\
+	.migration_count = 0,			\
 	.addr_limit	= KERNEL_DS,		\
 	.restart_block = {			\
 		.fn = do_no_restart_syscall,	\
Index: linux-2.6-lttng/include/asm-m68k/thread_info.h
===================================================================
--- linux-2.6-lttng.orig/include/asm-m68k/thread_info.h	2007-07-05 16:54:50.000000000 -0400
+++ linux-2.6-lttng/include/asm-m68k/thread_info.h	2007-07-05 17:02:59.000000000 -0400
@@ -9,6 +9,7 @@
 	unsigned long		flags;
 	struct exec_domain	*exec_domain;	/* execution domain */
 	int			preempt_count;	/* 0 => preemptable, <0 => BUG */
+	int			migration_count;/* 0: can migrate, <0 => BUG */
 	__u32 cpu; /* should always be 0 on m68k */
 	struct restart_block    restart_block;
 };
Index: linux-2.6-lttng/include/asm-m68knommu/thread_info.h
===================================================================
--- linux-2.6-lttng.orig/include/asm-m68knommu/thread_info.h	2007-07-05 16:54:50.000000000 -0400
+++ linux-2.6-lttng/include/asm-m68knommu/thread_info.h	2007-07-05 17:02:56.000000000 -0400
@@ -37,6 +37,7 @@
 	unsigned long	   flags;		/* low level flags */
 	int		   cpu;			/* cpu we're on */
 	int		   preempt_count;	/* 0 => preemptable, <0 => BUG */
+	int		   migration_count;	/* 0: can migrate, <0 => BUG */
 	struct restart_block restart_block;
 };
 
Index: linux-2.6-lttng/include/asm-mips/thread_info.h
===================================================================
--- linux-2.6-lttng.orig/include/asm-mips/thread_info.h	2007-07-05 16:54:50.000000000 -0400
+++ linux-2.6-lttng/include/asm-mips/thread_info.h	2007-07-05 17:03:14.000000000 -0400
@@ -28,6 +28,7 @@
 	unsigned long		tp_value;	/* thread pointer */
 	__u32			cpu;		/* current CPU */
 	int			preempt_count;	/* 0 => preemptable, <0 => BUG */
+	int			migration_count;/* 0: can migrate, <0 => BUG */
 
 	mm_segment_t		addr_limit;	/* thread address space:
 						   0-0xBFFFFFFF for user-thead
@@ -49,6 +50,7 @@
 	.flags		= 0,			\
 	.cpu		= 0,			\
 	.preempt_count	= 1,			\
+	.migration_count = 0,			\
 	.addr_limit	= KERNEL_DS,		\
 	.restart_block	= {			\
 		.fn = do_no_restart_syscall,	\
Index: linux-2.6-lttng/include/asm-parisc/thread_info.h
===================================================================
--- linux-2.6-lttng.orig/include/asm-parisc/thread_info.h	2007-07-05 16:54:50.000000000 -0400
+++ linux-2.6-lttng/include/asm-parisc/thread_info.h	2007-07-05 17:03:27.000000000 -0400
@@ -13,6 +13,7 @@
 	mm_segment_t addr_limit;	/* user-level address space limit */
 	__u32 cpu;			/* current CPU */
 	int preempt_count;		/* 0=premptable, <0=BUG; will also serve as bh-counter */
+	int migration_count;		/* 0: can migrate, <0 => BUG */
 	struct restart_block restart_block;
 };
 
@@ -24,6 +25,7 @@
 	.cpu		= 0,			\
 	.addr_limit	= KERNEL_DS,		\
 	.preempt_count	= 1,			\
+	.migration_count = 0,			\
   	.restart_block	= {			\
 		.fn = do_no_restart_syscall	\
 	}					\
Index: linux-2.6-lttng/include/asm-powerpc/thread_info.h
===================================================================
--- linux-2.6-lttng.orig/include/asm-powerpc/thread_info.h	2007-07-05 16:54:50.000000000 -0400
+++ linux-2.6-lttng/include/asm-powerpc/thread_info.h	2007-07-05 17:03:47.000000000 -0400
@@ -35,6 +35,7 @@
 	int		cpu;			/* cpu we're on */
 	int		preempt_count;		/* 0 => preemptable,
 						   <0 => BUG */
+	int		migration_count;	/* 0: can migrate, <0 => BUG */
 	struct restart_block restart_block;
 	unsigned long	local_flags;		/* private flags for thread */
 
@@ -53,6 +54,7 @@
 	.exec_domain =	&default_exec_domain,	\
 	.cpu =		0,			\
 	.preempt_count = 1,			\
+	.migration_count = 0,			\
 	.restart_block = {			\
 		.fn = do_no_restart_syscall,	\
 	},					\
Index: linux-2.6-lttng/include/asm-s390/thread_info.h
===================================================================
--- linux-2.6-lttng.orig/include/asm-s390/thread_info.h	2007-07-05 16:54:50.000000000 -0400
+++ linux-2.6-lttng/include/asm-s390/thread_info.h	2007-07-05 17:04:04.000000000 -0400
@@ -51,6 +51,7 @@
 	unsigned long		flags;		/* low level flags */
 	unsigned int		cpu;		/* current CPU */
 	int			preempt_count;	/* 0 => preemptable, <0 => BUG */
+	int			migration_count;/* 0: can migrate, <0 => BUG */
 	struct restart_block	restart_block;
 };
 
@@ -64,6 +65,7 @@
 	.flags		= 0,			\
 	.cpu		= 0,			\
 	.preempt_count	= 1,			\
+	.migration_count = 0,			\
 	.restart_block	= {			\
 		.fn = do_no_restart_syscall,	\
 	},					\
Index: linux-2.6-lttng/include/asm-sh/thread_info.h
===================================================================
--- linux-2.6-lttng.orig/include/asm-sh/thread_info.h	2007-07-05 16:54:50.000000000 -0400
+++ linux-2.6-lttng/include/asm-sh/thread_info.h	2007-07-05 17:04:32.000000000 -0400
@@ -21,6 +21,7 @@
 	unsigned long		flags;		/* low level flags */
 	__u32			cpu;
 	int			preempt_count; /* 0 => preemptable, <0 => BUG */
+	int			migration_count;/* 0: can migrate, <0 => BUG */
 	mm_segment_t		addr_limit;	/* thread address space */
 	struct restart_block	restart_block;
 	unsigned long		previous_sp;	/* sp of previous stack in case
@@ -58,6 +59,7 @@
 	.flags		= 0,			\
 	.cpu		= 0,			\
 	.preempt_count	= 1,			\
+	.migration_count = 0,			\
 	.addr_limit	= KERNEL_DS,		\
 	.restart_block	= {			\
 		.fn = do_no_restart_syscall,	\
Index: linux-2.6-lttng/include/asm-sh64/thread_info.h
===================================================================
--- linux-2.6-lttng.orig/include/asm-sh64/thread_info.h	2007-07-05 16:54:50.000000000 -0400
+++ linux-2.6-lttng/include/asm-sh64/thread_info.h	2007-07-05 17:04:18.000000000 -0400
@@ -23,6 +23,7 @@
 	unsigned long		flags;		/* low level flags */
 	/* Put the 4 32-bit fields together to make asm offsetting easier. */
 	int			preempt_count;	/* 0 => preemptable, <0 => BUG */
+	int			migration_count;/* 0: can migrate, <0 => BUG */
 	__u16			cpu;
 
 	mm_segment_t		addr_limit;
@@ -41,6 +42,7 @@
 	.flags		= 0,			\
 	.cpu		= 0,			\
 	.preempt_count	= 1,			\
+	.migration_count = 0,			\
 	.addr_limit     = KERNEL_DS,            \
 	.restart_block	= {			\
 		.fn = do_no_restart_syscall,	\
Index: linux-2.6-lttng/include/asm-sparc/thread_info.h
===================================================================
--- linux-2.6-lttng.orig/include/asm-sparc/thread_info.h	2007-07-05 16:54:50.000000000 -0400
+++ linux-2.6-lttng/include/asm-sparc/thread_info.h	2007-07-05 17:05:16.000000000 -0400
@@ -33,6 +33,7 @@
 	int			cpu;		/* cpu we're on */
 	int			preempt_count;	/* 0 => preemptable,
 						   <0 => BUG */
+	int			migration_count;/* 0: can migrate, <0 => BUG */
 	int			softirq_count;
 	int			hardirq_count;
 
@@ -65,6 +66,7 @@
 	.flags		=	0,			\
 	.cpu		=	0,			\
 	.preempt_count	=	1,			\
+	.migration_count =	0,			\
 	.restart_block	= {				\
 		.fn	=	do_no_restart_syscall,	\
 	},						\
Index: linux-2.6-lttng/include/asm-sparc64/thread_info.h
===================================================================
--- linux-2.6-lttng.orig/include/asm-sparc64/thread_info.h	2007-07-05 16:54:50.000000000 -0400
+++ linux-2.6-lttng/include/asm-sparc64/thread_info.h	2007-07-05 17:05:00.000000000 -0400
@@ -47,6 +47,7 @@
 	struct pt_regs		*kregs;
 	struct exec_domain	*exec_domain;
 	int			preempt_count;	/* 0 => preemptable, <0 => BUG */
+	int			migration_count;/* 0: can migrate, <0 => BUG */
 	__u8			new_child;
 	__u8			syscall_noerror;
 	__u16			cpu;
@@ -137,6 +138,7 @@
 	.flags		= ((unsigned long)ASI_P) << TI_FLAG_CURRENT_DS_SHIFT,	\
 	.exec_domain	=	&default_exec_domain,	\
 	.preempt_count	=	1,			\
+	.migration_count =	0,			\
 	.restart_block	= {				\
 		.fn	=	do_no_restart_syscall,	\
 	},						\
Index: linux-2.6-lttng/include/asm-um/thread_info.h
===================================================================
--- linux-2.6-lttng.orig/include/asm-um/thread_info.h	2007-07-05 16:54:50.000000000 -0400
+++ linux-2.6-lttng/include/asm-um/thread_info.h	2007-07-05 17:05:30.000000000 -0400
@@ -18,6 +18,7 @@
 	__u32			cpu;		/* current CPU */
 	int			preempt_count;  /* 0 => preemptable,
 						   <0 => BUG */
+	int			migration_count;/* 0: can migrate, <0 => BUG */
 	mm_segment_t		addr_limit;	/* thread address space:
 					 	   0-0xBFFFFFFF for user
 						   0-0xFFFFFFFF for kernel */
@@ -32,6 +33,7 @@
 	.flags =		0,		\
 	.cpu =		0,			\
 	.preempt_count =	1,		\
+	.migration_count =	0,		\
 	.addr_limit =	KERNEL_DS,		\
 	.restart_block =  {			\
 		.fn =  do_no_restart_syscall,	\
Index: linux-2.6-lttng/include/asm-v850/thread_info.h
===================================================================
--- linux-2.6-lttng.orig/include/asm-v850/thread_info.h	2007-07-05 16:54:50.000000000 -0400
+++ linux-2.6-lttng/include/asm-v850/thread_info.h	2007-07-05 17:05:41.000000000 -0400
@@ -32,6 +32,7 @@
 	int			cpu;		/* cpu we're on */
 	int			preempt_count;	/* 0 => preemptable,
 						   <0 => BUG */
+	int			migration_count;/* 0: can migrate, <0 => BUG */
 	struct restart_block	restart_block;
 };
 
@@ -42,6 +43,7 @@
 	.flags =	0,						      \
 	.cpu =		0,						      \
 	.preempt_count = 1,						      \
+	.migration_count = 0,						      \
 	.restart_block = {						      \
 		.fn = do_no_restart_syscall,				      \
 	},								      \
Index: linux-2.6-lttng/include/asm-x86_64/thread_info.h
===================================================================
--- linux-2.6-lttng.orig/include/asm-x86_64/thread_info.h	2007-07-05 16:54:50.000000000 -0400
+++ linux-2.6-lttng/include/asm-x86_64/thread_info.h	2007-07-05 17:05:49.000000000 -0400
@@ -30,6 +30,7 @@
 	__u32			status;		/* thread synchronous flags */
 	__u32			cpu;		/* current CPU */
 	int 			preempt_count;	/* 0 => preemptable, <0 => BUG */
+	int			migration_count;/* 0: can migrate, <0 => BUG */
 
 	mm_segment_t		addr_limit;	
 	struct restart_block    restart_block;
@@ -48,6 +49,7 @@
 	.flags	       = 0,			\
 	.cpu	       = 0,			\
 	.preempt_count = 1,			\
+	.migration_count = 0,			\
 	.addr_limit     = KERNEL_DS,		\
 	.restart_block = {			\
 		.fn = do_no_restart_syscall,	\
Index: linux-2.6-lttng/include/asm-xtensa/thread_info.h
===================================================================
--- linux-2.6-lttng.orig/include/asm-xtensa/thread_info.h	2007-07-05 16:54:50.000000000 -0400
+++ linux-2.6-lttng/include/asm-xtensa/thread_info.h	2007-07-05 17:06:07.000000000 -0400
@@ -34,6 +34,7 @@
 	unsigned long		status;		/* thread-synchronous flags */
 	__u32			cpu;		/* current CPU */
 	__s32			preempt_count;	/* 0 => preemptable,< 0 => BUG*/
+	__s32			migration_count;/* 0: can migrate, <0 => BUG */
 
 	mm_segment_t		addr_limit;	/* thread address space */
 	struct restart_block    restart_block;
@@ -72,6 +73,7 @@
 	.flags		= 0,			\
 	.cpu		= 0,			\
 	.preempt_count	= 1,			\
+	.migration_count = 0,			\
 	.addr_limit	= KERNEL_DS,		\
 	.restart_block = {			\
 		.fn = do_no_restart_syscall,	\

-- 
Mathieu Desnoyers
Computer Engineering Ph.D. Student, Ecole Polytechnique de Montreal
OpenPGP key fingerprint: 8CD5 52C3 8E3C 4140 715F  BA06 3F25 A8FE 3BAE 9A68

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

* Re: [RFC] Thread Migration Preemption
  2007-07-05 21:51 [RFC] Thread Migration Preemption Mathieu Desnoyers
@ 2007-07-05 22:46 ` Steven Rostedt
  2007-07-06  6:12 ` Nick Piggin
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 33+ messages in thread
From: Steven Rostedt @ 2007-07-05 22:46 UTC (permalink / raw)
  To: Mathieu Desnoyers; +Cc: Ingo Molnar, linux-kernel, Thomas Gleixner

On Thu, 2007-07-05 at 17:51 -0400, Mathieu Desnoyers wrote:
> Thread Migration Preemption
> 
> This patch adds the ability to protect critical sections from migration to
> another CPU without disabling preemption.
> 
> This will be useful to minimize the amount of preemption disabling for the -rt
> patch. It will help leveraging improvements brought by the local_t types in
> asm/local.h (see Documentation/local_ops.txt). Note that the updates done to
> variables protected by migration_disable must be either atomic or protected from
> concurrent updates done by other threads.
> 
> Typical use:
> 
> migration_disable();
> local_inc(&__get_cpu_var(&my_local_t_var));
> migration_enable();
> 
> Which will increment the variable atomically wrt the local CPU.
> 
> Comments (such as how to integrate this in the already almost full
> preempt_count) are welcome.

Ingo and Thomas, this also would help with the IRQ thread running a
softirq issue.  We wouldn't need to bind to a CPU the thread. We could
simply disable the ability to migrate while the IRQ thread was handling
the softirqs.

-- Steve



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

* Re: [RFC] Thread Migration Preemption
@ 2007-07-06  6:02 Oleg Nesterov
  2007-07-06 14:23 ` Mathieu Desnoyers
  0 siblings, 1 reply; 33+ messages in thread
From: Oleg Nesterov @ 2007-07-06  6:02 UTC (permalink / raw)
  To: Mathieu Desnoyers; +Cc: Ingo Molnar, Steven Rostedt, linux-kernel

Mathieu Desnoyers wrote:
>
> This patch adds the ability to protect critical sections from migration to
> another CPU without disabling preemption.
>
> Typical use:
>
> migration_disable();
> local_inc(&__get_cpu_var(&my_local_t_var));
> migration_enable();
>
> --- linux-2.6-lttng.orig/kernel/sched.c	2007-07-05 16:28:15.000000000 -0400
> +++ linux-2.6-lttng/kernel/sched.c	2007-07-05 16:53:24.000000000 -0400
> @@ -1996,6 +1996,7 @@
>  	 * 1) running (obviously), or
>  	 * 2) cannot be migrated to this CPU due to cpus_allowed, or
>  	 * 3) are cache-hot on their current CPU.
> +	 * 4) migration preemption is non 0 for this non running task.
>  	 */
>  	if (!cpu_isset(this_cpu, p->cpus_allowed))
>  		return 0;
> @@ -2003,6 +2004,8 @@
>
>  	if (task_running(rq, p))
>  		return 0;
> +	if (task_thread_info(p)->migration_count)
> +		return 0;

Question: This means that the task could be preempted, but can't sleep, yes?

Because try_to_wake_up() can change ->cpu. Shouldn't might_sleep() check
->migration_count then? Or we can change try_to_wake_up().

What if the task does copy_process() under migration_disable() ? Child
gets a copy of ->migration_count.

Also, cpu_down() still can migrate this task to another CPU.

Oleg.


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

* Re: [RFC] Thread Migration Preemption
  2007-07-05 21:51 [RFC] Thread Migration Preemption Mathieu Desnoyers
  2007-07-05 22:46 ` Steven Rostedt
@ 2007-07-06  6:12 ` Nick Piggin
  2007-07-06 14:34   ` Mathieu Desnoyers
                     ` (2 more replies)
  2007-07-06 11:59 ` Andi Kleen
  2007-07-23 18:33 ` Ingo Molnar
  3 siblings, 3 replies; 33+ messages in thread
From: Nick Piggin @ 2007-07-06  6:12 UTC (permalink / raw)
  To: Mathieu Desnoyers; +Cc: Steven Rostedt, Ingo Molnar, linux-kernel

Mathieu Desnoyers wrote:
> Thread Migration Preemption
> 
> This patch adds the ability to protect critical sections from migration to
> another CPU without disabling preemption.
> 
> This will be useful to minimize the amount of preemption disabling for the -rt
> patch. It will help leveraging improvements brought by the local_t types in
> asm/local.h (see Documentation/local_ops.txt). Note that the updates done to
> variables protected by migration_disable must be either atomic or protected from
> concurrent updates done by other threads.
> 
> Typical use:
> 
> migration_disable();
> local_inc(&__get_cpu_var(&my_local_t_var));
> migration_enable();
> 
> Which will increment the variable atomically wrt the local CPU.
> 
> Comments (such as how to integrate this in the already almost full
> preempt_count) are welcome.

This seems like way too much stuff to add just for this type of thing. Why
not just disable and reenable preempt? Surely local_inc is not going to take
so long that disabling preemption matters.

The task struct is not something we should just be carefree putting crap
into because it is seemingly free :(

-- 
SUSE Labs, Novell Inc.

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

* Re: [RFC] Thread Migration Preemption
  2007-07-05 21:51 [RFC] Thread Migration Preemption Mathieu Desnoyers
  2007-07-05 22:46 ` Steven Rostedt
  2007-07-06  6:12 ` Nick Piggin
@ 2007-07-06 11:59 ` Andi Kleen
  2007-07-06 14:41   ` Mathieu Desnoyers
  2007-07-23 18:33 ` Ingo Molnar
  3 siblings, 1 reply; 33+ messages in thread
From: Andi Kleen @ 2007-07-06 11:59 UTC (permalink / raw)
  To: Mathieu Desnoyers; +Cc: Steven Rostedt, Ingo Molnar, linux-kernel

Mathieu Desnoyers <mathieu.desnoyers@polymtl.ca> writes:

> Thread Migration Preemption
> 
> This patch adds the ability to protect critical sections from migration to
> another CPU without disabling preemption.

Good idea.

I sometimes think we could have avoided _much_ trouble
if that had been always default for processes running 
in kernel space.
 
> This will be useful to minimize the amount of preemption disabling for the -rt
> patch. It will help leveraging improvements brought by the local_t types in
> asm/local.h (see Documentation/local_ops.txt). Note that the updates done to
> variables protected by migration_disable must be either atomic or protected from
> concurrent updates done by other threads.
> 
> Typical use:
> 
> migration_disable();
> local_inc(&__get_cpu_var(&my_local_t_var));
> migration_enable();

It seems strange to have a new interface for this. We already 
have get_cpu()/put_cpu(). So why not use that?

>  	unsigned long		flags;		/* low level flags */
>  	__u32			cpu;
>  	__s32			preempt_count;	/* 0 => preemptable, <0 => BUG */
> +	int			migration_count;/* 0: can migrate, <0 => BUG */

Can you turn preempt_count into a short first and use a short? That should be enough
and cache line usage wouldn't be increased. That's ok on x86; on RISCs 
int might be faster


-Andi

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

* Re: [RFC] Thread Migration Preemption
  2007-07-06  6:02 [RFC] Thread Migration Preemption Oleg Nesterov
@ 2007-07-06 14:23 ` Mathieu Desnoyers
  2007-07-06 14:56   ` Oleg Nesterov
  0 siblings, 1 reply; 33+ messages in thread
From: Mathieu Desnoyers @ 2007-07-06 14:23 UTC (permalink / raw)
  To: Oleg Nesterov; +Cc: Ingo Molnar, Steven Rostedt, linux-kernel

* Oleg Nesterov (oleg@tv-sign.ru) wrote:
> Mathieu Desnoyers wrote:
> >
> > This patch adds the ability to protect critical sections from migration to
> > another CPU without disabling preemption.
> >
> > Typical use:
> >
> > migration_disable();
> > local_inc(&__get_cpu_var(&my_local_t_var));
> > migration_enable();
> >
> > --- linux-2.6-lttng.orig/kernel/sched.c	2007-07-05 16:28:15.000000000 -0400
> > +++ linux-2.6-lttng/kernel/sched.c	2007-07-05 16:53:24.000000000 -0400
> > @@ -1996,6 +1996,7 @@
> >  	 * 1) running (obviously), or
> >  	 * 2) cannot be migrated to this CPU due to cpus_allowed, or
> >  	 * 3) are cache-hot on their current CPU.
> > +	 * 4) migration preemption is non 0 for this non running task.
> >  	 */
> >  	if (!cpu_isset(this_cpu, p->cpus_allowed))
> >  		return 0;
> > @@ -2003,6 +2004,8 @@
> >
> >  	if (task_running(rq, p))
> >  		return 0;
> > +	if (task_thread_info(p)->migration_count)
> > +		return 0;
> 

Hi Oleg,

> Question: This means that the task could be preempted, but can't sleep, yes?
> 

No exactly. This means that the task can be preempted, and can therefore
sleep, but we do not allow this sleeping task to be migrated to a
different CPU.

> Because try_to_wake_up() can change ->cpu. Shouldn't might_sleep() check
> ->migration_count then? Or we can change try_to_wake_up().
> 

If we look at try_to_wake_up, it seems to take the new_cpu from
task_cpu(), which comes from the thread info ->cpu, updated by
set_task_cpu(). The *_move_tasks seems to be responsible for calling
can_migrate_task() to see if, in a deferred way, the migration_thread
can use set_task_cpu() to change the task's cpu.

move_task_off_dead_cpu() does not seem to respect this though: it could
potentially move away a process while it is in a critical section by
forcing a __migrate_task. I guess I should put a test in __migrate_task
also so move_task_off_dead_cpu() can try to repeat the migration.

> What if the task does copy_process() under migration_disable() ? Child
> gets a copy of ->migration_count.
> 

Right. Neighter does copy_process set the preemption count. It seems to
be dealt by sched_fork() when the thread is first scheduled in to make
sure that the preempt count is 1. I guess is would be safer to set the
migration count to 0 there too. (or set it to one if we ever decide to
make it the kernel default).

> Also, cpu_down() still can migrate this task to another CPU.
> 

Yes, just noted this earlier. I first thought it was using
can_migrate_task(), but it does not seem so.

Thanks,

Mathieu

> Oleg.
> 

-- 
Mathieu Desnoyers
Computer Engineering Ph.D. Student, Ecole Polytechnique de Montreal
OpenPGP key fingerprint: 8CD5 52C3 8E3C 4140 715F  BA06 3F25 A8FE 3BAE 9A68

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

* Re: [RFC] Thread Migration Preemption
  2007-07-06  6:12 ` Nick Piggin
@ 2007-07-06 14:34   ` Mathieu Desnoyers
  2007-07-06 14:34   ` Steven Rostedt
  2007-07-10 23:39   ` Matt Mackall
  2 siblings, 0 replies; 33+ messages in thread
From: Mathieu Desnoyers @ 2007-07-06 14:34 UTC (permalink / raw)
  To: Nick Piggin; +Cc: Steven Rostedt, Ingo Molnar, linux-kernel

* Nick Piggin (nickpiggin@yahoo.com.au) wrote:
> Mathieu Desnoyers wrote:
> >Thread Migration Preemption
> >
> >This patch adds the ability to protect critical sections from migration to
> >another CPU without disabling preemption.
> >
> >This will be useful to minimize the amount of preemption disabling for the 
> >-rt
> >patch. It will help leveraging improvements brought by the local_t types in
> >asm/local.h (see Documentation/local_ops.txt). Note that the updates done 
> >to
> >variables protected by migration_disable must be either atomic or 
> >protected from
> >concurrent updates done by other threads.
> >
> >Typical use:
> >
> >migration_disable();
> >local_inc(&__get_cpu_var(&my_local_t_var));
> >migration_enable();
> >
> >Which will increment the variable atomically wrt the local CPU.
> >
> >Comments (such as how to integrate this in the already almost full
> >preempt_count) are welcome.
> 
> This seems like way too much stuff to add just for this type of thing. Why
> not just disable and reenable preempt? Surely local_inc is not going to take
> so long that disabling preemption matters.
> 

Disabling preemption seems to cause some discomfort in the RT community.
Steven already noticed that they could leverage migration disabling to
enhance the way they deal with softirqs. Basically, anything that must
be tied to a CPU for a short time, can deal with concurrency from other
threads running on the same CPU, but where we do not want to add to the
scheduler latency would be a good prospect for the migration_disable().

> The task struct is not something we should just be carefree putting crap
> into because it is seemingly free :(
> 

I agree. I added it knowing that we could either pack this in the
preempt_count (using masks, if there is still room, which does not seem
to be the case) or, if not, people who could make extensive use of this
could justify adding this field to the thread_info struct. I am barely
sending the idea out there so it can be helpful for the RT team.

Mathieu

-- 
Mathieu Desnoyers
Computer Engineering Ph.D. Student, Ecole Polytechnique de Montreal
OpenPGP key fingerprint: 8CD5 52C3 8E3C 4140 715F  BA06 3F25 A8FE 3BAE 9A68

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

* Re: [RFC] Thread Migration Preemption
  2007-07-06  6:12 ` Nick Piggin
  2007-07-06 14:34   ` Mathieu Desnoyers
@ 2007-07-06 14:34   ` Steven Rostedt
  2007-07-06 15:43     ` Daniel Walker
  2007-07-08  9:05     ` Nick Piggin
  2007-07-10 23:39   ` Matt Mackall
  2 siblings, 2 replies; 33+ messages in thread
From: Steven Rostedt @ 2007-07-06 14:34 UTC (permalink / raw)
  To: Nick Piggin; +Cc: Mathieu Desnoyers, Ingo Molnar, linux-kernel

On Fri, 2007-07-06 at 16:12 +1000, Nick Piggin wrote:
> Mathieu Desnoyers wrote:

> > migration_disable();
> > local_inc(&__get_cpu_var(&my_local_t_var));
> > migration_enable();
> > 

[...]

> This seems like way too much stuff to add just for this type of thing. Why
> not just disable and reenable preempt? Surely local_inc is not going to take
> so long that disabling preemption matters.

For this given example, it may be too much fine tuning. But there are
other things (at least in RT) where this would be very helpful. One
thing is that in RT an IRQ thread might service a softirq if that
softirq thread is of the same priority as the IRQ thread. The difference
between an IRQ thread and a softirq thread is that the IRQ thread may
migrate but the softirq thread may not. So to do this performance
enhancement, we need to temporarily pin the IRQ thread to the CPU, which
is expensive (set_cpus_allowed).  This would make it much simpler and
light weight to implement.

> 
> The task struct is not something we should just be carefree putting crap
> into because it is seemingly free :(
> 

Agreed, but as the subject says "RFC".  Perhaps we can make it a bit
more complex and put this as one of the most significant bits in the
preempt_count. We would just need to mask off that bit in all the archs
when determining if we should preempt or not.  That's more complex, but
keeps the task struct free from more luggage.

-- Steve



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

* Re: [RFC] Thread Migration Preemption
  2007-07-06 11:59 ` Andi Kleen
@ 2007-07-06 14:41   ` Mathieu Desnoyers
  2007-07-06 17:11     ` Andi Kleen
  0 siblings, 1 reply; 33+ messages in thread
From: Mathieu Desnoyers @ 2007-07-06 14:41 UTC (permalink / raw)
  To: Andi Kleen; +Cc: Steven Rostedt, Ingo Molnar, linux-kernel

* Andi Kleen (andi@firstfloor.org) wrote:
> Mathieu Desnoyers <mathieu.desnoyers@polymtl.ca> writes:
> 
> > Thread Migration Preemption
> > 
> > This patch adds the ability to protect critical sections from migration to
> > another CPU without disabling preemption.
> 
> Good idea.
> 
> I sometimes think we could have avoided _much_ trouble
> if that had been always default for processes running 
> in kernel space.
>  

I haven't thought about making it the default for kernel space
preemption, but yes, it would make sense.

> > This will be useful to minimize the amount of preemption disabling for the -rt
> > patch. It will help leveraging improvements brought by the local_t types in
> > asm/local.h (see Documentation/local_ops.txt). Note that the updates done to
> > variables protected by migration_disable must be either atomic or protected from
> > concurrent updates done by other threads.
> > 
> > Typical use:
> > 
> > migration_disable();
> > local_inc(&__get_cpu_var(&my_local_t_var));
> > migration_enable();
> 
> It seems strange to have a new interface for this. We already 
> have get_cpu()/put_cpu(). So why not use that?
> 

Because get/put_cpu() implicitly insure mutual exclusion between threads
on the same CPU by disabling preemption. migration_disable() does not:
this is why I only do local atomic operations on these variables.


> >  	unsigned long		flags;		/* low level flags */
> >  	__u32			cpu;
> >  	__s32			preempt_count;	/* 0 => preemptable, <0 => BUG */
> > +	int			migration_count;/* 0: can migrate, <0 => BUG */
> 
> Can you turn preempt_count into a short first and use a short? That should be enough
> and cache line usage wouldn't be increased. That's ok on x86; on RISCs 
> int might be faster
> 

using a short instead of an int on modern x86 will cause pipeline stalls
due to partial register use. Also, it won't really reduce the cache line
usage, since it is followed by an unsigned long; gcc structure alignment
will put padding instead of the integer, which does not buy us anything
space-wise. If you find me a case on some architectures where it
improves performances, I will be more than happy to change it, but as
things are, an int seems as efficient, and even more due to partial
register stalls on x86, than a short.

Regards,

Mathieu

> 
> -Andi

-- 
Mathieu Desnoyers
Computer Engineering Ph.D. Student, Ecole Polytechnique de Montreal
OpenPGP key fingerprint: 8CD5 52C3 8E3C 4140 715F  BA06 3F25 A8FE 3BAE 9A68

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

* Re: [RFC] Thread Migration Preemption
  2007-07-06 14:23 ` Mathieu Desnoyers
@ 2007-07-06 14:56   ` Oleg Nesterov
  2007-07-11  4:49     ` [RFC] Thread Migration Preemption - v2 Mathieu Desnoyers
  0 siblings, 1 reply; 33+ messages in thread
From: Oleg Nesterov @ 2007-07-06 14:56 UTC (permalink / raw)
  To: Mathieu Desnoyers; +Cc: Ingo Molnar, Steven Rostedt, linux-kernel

On 07/06, Mathieu Desnoyers wrote:
>
> * Oleg Nesterov (oleg@tv-sign.ru) wrote:
> > Mathieu Desnoyers wrote:
> > >
> > > This patch adds the ability to protect critical sections from migration to
> > > another CPU without disabling preemption.
> > >
> > > Typical use:
> > >
> > > migration_disable();
> > > local_inc(&__get_cpu_var(&my_local_t_var));
> > > migration_enable();
> > >
> > > --- linux-2.6-lttng.orig/kernel/sched.c	2007-07-05 16:28:15.000000000 -0400
> > > +++ linux-2.6-lttng/kernel/sched.c	2007-07-05 16:53:24.000000000 -0400
> > > @@ -1996,6 +1996,7 @@
> > >  	 * 1) running (obviously), or
> > >  	 * 2) cannot be migrated to this CPU due to cpus_allowed, or
> > >  	 * 3) are cache-hot on their current CPU.
> > > +	 * 4) migration preemption is non 0 for this non running task.
> > >  	 */
> > >  	if (!cpu_isset(this_cpu, p->cpus_allowed))
> > >  		return 0;
> > > @@ -2003,6 +2004,8 @@
> > >
> > >  	if (task_running(rq, p))
> > >  		return 0;
> > > +	if (task_thread_info(p)->migration_count)
> > > +		return 0;
> > 
> 
> Hi Oleg,
> 
> > Question: This means that the task could be preempted, but can't sleep, yes?
> > 
> 
> No exactly. This means that the task can be preempted, and can therefore
> sleep, but we do not allow this sleeping task to be migrated to a
> different CPU.
> 
> > Because try_to_wake_up() can change ->cpu. Shouldn't might_sleep() check
> > ->migration_count then? Or we can change try_to_wake_up().
> > 
> 
> If we look at try_to_wake_up, it seems to take the new_cpu from
> task_cpu(), which comes from the thread info ->cpu, updated by
> set_task_cpu(). The *_move_tasks seems to be responsible for calling
> can_migrate_task() to see if, in a deferred way, the migration_thread
> can use set_task_cpu() to change the task's cpu.

Hmm. Perhaps I missed something, perhaps you... Or we both :)

try_to_wake_up() can choose new_cpu which differs from initial ->cpu.
Then it does set_task_cpu() which just sets ->cpu, it doesn't check
can_migrate_task(). This means that the task could be waken on another
CPU, even if it sleeps under migration_disable().


Btw, I think you should also fix debug_smp_processor_id(), it won't
like  migration_disable() + __get_cpu_var().

Oleg.


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

* Re: [RFC] Thread Migration Preemption
  2007-07-06 14:34   ` Steven Rostedt
@ 2007-07-06 15:43     ` Daniel Walker
  2007-07-08  9:05     ` Nick Piggin
  1 sibling, 0 replies; 33+ messages in thread
From: Daniel Walker @ 2007-07-06 15:43 UTC (permalink / raw)
  To: Steven Rostedt; +Cc: Nick Piggin, Mathieu Desnoyers, Ingo Molnar, linux-kernel

On Fri, 2007-07-06 at 10:34 -0400, Steven Rostedt wrote:

> thing is that in RT an IRQ thread might service a softirq if that
> softirq thread is of the same priority as the IRQ thread. The difference
> between an IRQ thread and a softirq thread is that the IRQ thread may
> migrate but the softirq thread may not. So to do this performance
> enhancement, we need to temporarily pin the IRQ thread to the CPU, which
> is expensive (set_cpus_allowed).  This would make it much simpler and
> light weight to implement.

Are there any other reasons?

Daniel


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

* Re: [RFC] Thread Migration Preemption
  2007-07-06 14:41   ` Mathieu Desnoyers
@ 2007-07-06 17:11     ` Andi Kleen
  2007-07-11  4:57       ` Mathieu Desnoyers
  0 siblings, 1 reply; 33+ messages in thread
From: Andi Kleen @ 2007-07-06 17:11 UTC (permalink / raw)
  To: Mathieu Desnoyers; +Cc: Andi Kleen, Steven Rostedt, Ingo Molnar, linux-kernel

On Fri, Jul 06, 2007 at 10:41:44AM -0400, Mathieu Desnoyers wrote:
> I haven't thought about making it the default for kernel space
> preemption, but yes, it would make sense.

Now it's too late -- getcpu() has infected the kernel everywhere.
It would have made sense a few years ago.


> ... getcpu()...

Hmm ok, although i suspect it's rare to assume that. But understood
you don't want to audit all getcpu users because of this.

> using a short instead of an int on modern x86 will cause pipeline stalls
> due to partial register use.

Sorry, that's totally bogus. Primarily because the access would be directly
on memory and there is no partial register tracking there.

Besides pipeline stall is not the correct description on what would
happen if you used a register, the worst you get is a single false dependency
but no pipeline flush.

Besides the latest x86 cpus (C2, K8) don't have much trouble with these
false dependencies in general.

> usage, since it is followed by an unsigned long; gcc structure alignment


> will put padding instead of the integer, which does not buy us anything

on i386 unsigned long is 4 bytes.

-Andi

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

* Re: [RFC] Thread Migration Preemption
  2007-07-06 14:34   ` Steven Rostedt
  2007-07-06 15:43     ` Daniel Walker
@ 2007-07-08  9:05     ` Nick Piggin
  1 sibling, 0 replies; 33+ messages in thread
From: Nick Piggin @ 2007-07-08  9:05 UTC (permalink / raw)
  To: Steven Rostedt; +Cc: Mathieu Desnoyers, Ingo Molnar, linux-kernel

Steven Rostedt wrote:
> On Fri, 2007-07-06 at 16:12 +1000, Nick Piggin wrote:
> 
>>Mathieu Desnoyers wrote:
> 
> 
>>>migration_disable();
>>>local_inc(&__get_cpu_var(&my_local_t_var));
>>>migration_enable();
>>>
> 
> 
> [...]
> 
> 
>>This seems like way too much stuff to add just for this type of thing. Why
>>not just disable and reenable preempt? Surely local_inc is not going to take
>>so long that disabling preemption matters.
> 
> 
> For this given example, it may be too much fine tuning. But there are
> other things (at least in RT) where this would be very helpful. One
> thing is that in RT an IRQ thread might service a softirq if that
> softirq thread is of the same priority as the IRQ thread. The difference
> between an IRQ thread and a softirq thread is that the IRQ thread may
> migrate but the softirq thread may not. So to do this performance
> enhancement, we need to temporarily pin the IRQ thread to the CPU, which
> is expensive (set_cpus_allowed).  This would make it much simpler and
> light weight to implement.

Well if this was just intended for -rt, then OK.


>>The task struct is not something we should just be carefree putting crap
>>into because it is seemingly free :(
>>
> 
> 
> Agreed, but as the subject says "RFC".  Perhaps we can make it a bit
> more complex and put this as one of the most significant bits in the
> preempt_count. We would just need to mask off that bit in all the archs
> when determining if we should preempt or not.  That's more complex, but
> keeps the task struct free from more luggage.

Just so long as it stays out of mainline without a good reason
that's fine.

-- 
SUSE Labs, Novell Inc.

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

* Re: [RFC] Thread Migration Preemption
  2007-07-06  6:12 ` Nick Piggin
  2007-07-06 14:34   ` Mathieu Desnoyers
  2007-07-06 14:34   ` Steven Rostedt
@ 2007-07-10 23:39   ` Matt Mackall
  2007-07-11  0:02     ` Nick Piggin
  2 siblings, 1 reply; 33+ messages in thread
From: Matt Mackall @ 2007-07-10 23:39 UTC (permalink / raw)
  To: Nick Piggin; +Cc: Mathieu Desnoyers, Steven Rostedt, Ingo Molnar, linux-kernel

On Fri, Jul 06, 2007 at 04:12:10PM +1000, Nick Piggin wrote:
> Mathieu Desnoyers wrote:
> >Thread Migration Preemption
> >
> >This patch adds the ability to protect critical sections from migration to
> >another CPU without disabling preemption.
> >
> >This will be useful to minimize the amount of preemption disabling for the 
> >-rt
> >patch. It will help leveraging improvements brought by the local_t types in
> >asm/local.h (see Documentation/local_ops.txt). Note that the updates done 
> >to
> >variables protected by migration_disable must be either atomic or 
> >protected from
> >concurrent updates done by other threads.
> >
> >Typical use:
> >
> >migration_disable();
> >local_inc(&__get_cpu_var(&my_local_t_var));
> >migration_enable();
> >
> >Which will increment the variable atomically wrt the local CPU.
> >
> >Comments (such as how to integrate this in the already almost full
> >preempt_count) are welcome.
> 
> This seems like way too much stuff to add just for this type of thing. Why
> not just disable and reenable preempt? Surely local_inc is not going to take
> so long that disabling preemption matters.

I like this patch a lot. Even if we don't add the underlying mechanism
right now, adding migration_disable as an alias for preempt_disable
will much better document quite a number of the users.
 
> The task struct is not something we should just be carefree putting crap
> into because it is seemingly free :(

Sadly, it is free at the moment. We can only fit 3 task_structs in an order-1 SLAB,
with lots of slop.

-- 
Mathematics is the supreme nostalgia of our time.

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

* Re: [RFC] Thread Migration Preemption
  2007-07-10 23:39   ` Matt Mackall
@ 2007-07-11  0:02     ` Nick Piggin
  2007-07-11  0:36       ` Matt Mackall
  0 siblings, 1 reply; 33+ messages in thread
From: Nick Piggin @ 2007-07-11  0:02 UTC (permalink / raw)
  To: Matt Mackall; +Cc: Mathieu Desnoyers, Steven Rostedt, Ingo Molnar, linux-kernel

Matt Mackall wrote:
> On Fri, Jul 06, 2007 at 04:12:10PM +1000, Nick Piggin wrote:
> 
>>Mathieu Desnoyers wrote:
>>
>>>Thread Migration Preemption
>>>
>>>This patch adds the ability to protect critical sections from migration to
>>>another CPU without disabling preemption.
>>>
>>>This will be useful to minimize the amount of preemption disabling for the 
>>>-rt
>>>patch. It will help leveraging improvements brought by the local_t types in
>>>asm/local.h (see Documentation/local_ops.txt). Note that the updates done 
>>>to
>>>variables protected by migration_disable must be either atomic or 
>>>protected from
>>>concurrent updates done by other threads.
>>>
>>>Typical use:
>>>
>>>migration_disable();
>>>local_inc(&__get_cpu_var(&my_local_t_var));
>>>migration_enable();
>>>
>>>Which will increment the variable atomically wrt the local CPU.
>>>
>>>Comments (such as how to integrate this in the already almost full
>>>preempt_count) are welcome.
>>
>>This seems like way too much stuff to add just for this type of thing. Why
>>not just disable and reenable preempt? Surely local_inc is not going to take
>>so long that disabling preemption matters.
> 
> 
> I like this patch a lot. Even if we don't add the underlying mechanism
> right now, adding migration_disable as an alias for preempt_disable
> will much better document quite a number of the users.

I'd have no problem with that, and it might make it easier in future to
justify a more complex scheme.


>>The task struct is not something we should just be carefree putting crap
>>into because it is seemingly free :(
> 
> 
> Sadly, it is free at the moment. We can only fit 3 task_structs in an order-1 SLAB,
> with lots of slop.

Well apart from more cacheline access, that's why I say seemingly free. But
actually it uses up space we may like for something else in future and/or
makes it harder to shrink down if any effort ever goes into that.

-- 
SUSE Labs, Novell Inc.

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

* Re: [RFC] Thread Migration Preemption
  2007-07-11  0:02     ` Nick Piggin
@ 2007-07-11  0:36       ` Matt Mackall
  2007-07-11  0:55         ` Mathieu Desnoyers
  0 siblings, 1 reply; 33+ messages in thread
From: Matt Mackall @ 2007-07-11  0:36 UTC (permalink / raw)
  To: Nick Piggin; +Cc: Mathieu Desnoyers, Steven Rostedt, Ingo Molnar, linux-kernel

On Wed, Jul 11, 2007 at 10:02:23AM +1000, Nick Piggin wrote:
> >I like this patch a lot. Even if we don't add the underlying mechanism
> >right now, adding migration_disable as an alias for preempt_disable
> >will much better document quite a number of the users.
> 
> I'd have no problem with that, and it might make it easier in future to
> justify a more complex scheme.

What do you think, Mathieu?

Also, small nit: it ought to be migrate_disable to match the form of
preempt_disable.
 
> >>The task struct is not something we should just be carefree putting crap
> >>into because it is seemingly free :(
> >
> >Sadly, it is free at the moment. We can only fit 3 task_structs in an 
> >order-1 SLAB,
> >with lots of slop.
> 
> Well apart from more cacheline access, that's why I say seemingly free. But
> actually it uses up space we may like for something else in future and/or
> makes it harder to shrink down if any effort ever goes into that.

Yes, I'm just trying to draw the sad state of task_struct to people's
attention.

-- 
Mathematics is the supreme nostalgia of our time.

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

* Re: [RFC] Thread Migration Preemption
  2007-07-11  0:36       ` Matt Mackall
@ 2007-07-11  0:55         ` Mathieu Desnoyers
  2007-07-11  1:15           ` Nick Piggin
  0 siblings, 1 reply; 33+ messages in thread
From: Mathieu Desnoyers @ 2007-07-11  0:55 UTC (permalink / raw)
  To: Matt Mackall; +Cc: Nick Piggin, Steven Rostedt, Ingo Molnar, linux-kernel

* Matt Mackall (mpm@selenic.com) wrote:
> On Wed, Jul 11, 2007 at 10:02:23AM +1000, Nick Piggin wrote:
> > >I like this patch a lot. Even if we don't add the underlying mechanism
> > >right now, adding migration_disable as an alias for preempt_disable
> > >will much better document quite a number of the users.
> > 
> > I'd have no problem with that, and it might make it easier in future to
> > justify a more complex scheme.
> 
> What do you think, Mathieu?
> 

That's an excellent idea. It should probably come with some
documentation explaining what difference should be expected between
preempt_disable and migrate_disable in the future so that people can
choose the right alternative for their code.

> Also, small nit: it ought to be migrate_disable to match the form of
> preempt_disable.

Yes, that's fine with me. :)

I though a little more about this whole concept of migrate_disable, and
I think it could be brought further. One of the main problems with per
cpu variables is that this concept cannot be ported to this grey place
called "user-space" because preemption cannot be disabled. The
equivalent (kind of) is currently per thread variables, but it can
consume a lot of space if many threads are running.

However, it could be possible, if we implement a vsyscall based
migration preemption counter accessible with read/write access from
user-space, to tie a thread to a CPU during a user-space critical path.
If we combine this with local atomic operations done in user-space, we
could have highly scalable access to per cpu data structures reentrant
with respect to signal handlers.

Mathieu

-- 
Mathieu Desnoyers
Computer Engineering Ph.D. Student, Ecole Polytechnique de Montreal
OpenPGP key fingerprint: 8CD5 52C3 8E3C 4140 715F  BA06 3F25 A8FE 3BAE 9A68

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

* Re: [RFC] Thread Migration Preemption
  2007-07-11  0:55         ` Mathieu Desnoyers
@ 2007-07-11  1:15           ` Nick Piggin
  0 siblings, 0 replies; 33+ messages in thread
From: Nick Piggin @ 2007-07-11  1:15 UTC (permalink / raw)
  To: Mathieu Desnoyers; +Cc: Matt Mackall, Steven Rostedt, Ingo Molnar, linux-kernel

Mathieu Desnoyers wrote:
> * Matt Mackall (mpm@selenic.com) wrote:
> 
>>On Wed, Jul 11, 2007 at 10:02:23AM +1000, Nick Piggin wrote:
>>
>>>>I like this patch a lot. Even if we don't add the underlying mechanism
>>>>right now, adding migration_disable as an alias for preempt_disable
>>>>will much better document quite a number of the users.
>>>
>>>I'd have no problem with that, and it might make it easier in future to
>>>justify a more complex scheme.
>>
>>What do you think, Mathieu?
>>
> 
> 
> That's an excellent idea. It should probably come with some
> documentation explaining what difference should be expected between
> preempt_disable and migrate_disable in the future so that people can
> choose the right alternative for their code.
> 
> 
>>Also, small nit: it ought to be migrate_disable to match the form of
>>preempt_disable.
> 
> 
> Yes, that's fine with me. :)
> 
> I though a little more about this whole concept of migrate_disable, and
> I think it could be brought further. One of the main problems with per
> cpu variables is that this concept cannot be ported to this grey place
> called "user-space" because preemption cannot be disabled. The
> equivalent (kind of) is currently per thread variables, but it can
> consume a lot of space if many threads are running.
> 
> However, it could be possible, if we implement a vsyscall based
> migration preemption counter accessible with read/write access from
> user-space, to tie a thread to a CPU during a user-space critical path.
> If we combine this with local atomic operations done in user-space, we
> could have highly scalable access to per cpu data structures reentrant
> with respect to signal handlers.

That's all well and good, but for most non-trivial stuff, you
have to disable preemption as well which you cannot do in
userspace. Which I suspect is why there is not a great deal
that can use it in kernelspace either.

So it will remain to be seen what kind of per-cpu data structures
you can access in a highly scalable way, and how big the niche is
between real per-thread data structures and real locking. I'm
skeptical :)

-- 
SUSE Labs, Novell Inc.

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

* Re: [RFC] Thread Migration Preemption - v2
  2007-07-06 14:56   ` Oleg Nesterov
@ 2007-07-11  4:49     ` Mathieu Desnoyers
  2007-07-11 16:36       ` Oleg Nesterov
  0 siblings, 1 reply; 33+ messages in thread
From: Mathieu Desnoyers @ 2007-07-11  4:49 UTC (permalink / raw)
  To: linux-kernel; +Cc: Ingo Molnar, Steven Rostedt, linux-kernel, Oleg Nesterov

Hi,

Still as an RFC, here is an updated version of the migration handling
code in sched.c that supports migrate_disable()/migrate_enable().

I have taken care of the comments I received, thanks. I switched to
migrate_enable/disable following Matt Mackall's comments. He also
suggested to create, for now, an alias of migrate_disable/enable() to
preempt_disable/enable() so that people could better identify what
protection their code requires. This transition phase makes perfect
sense to me.

A case study of scenarios where migration disabling without preemption
disabling is useful must still be done, both for mainline kernel and for
the -rt patch case. It basically involves any case where per-cpu data
can be atomically updated using local atomic operations or where being
tied to a CPU is important due to usage of its specific resources
(performance counters could be a good example of this). We can also
find, in the -rt kernel, the exemple of the threaded softirqs which must
stay binded on a specific CPU and, due to performance reasons, cannot
set the cpu affinity.

A new idea came to me recently: using migration disabling from
user-space through a vsyscall page to protect accesses to per-cpu data
in a locally atomic manner, which would be reentrant wrt signals and use
less space than per thread data. I clearly see an interest for
user-space tracing, where duplicating buffers per thread would be a
waste of ressources. Since it is not possible to disable preemption from
user-space context, disabling migration efficiently would be the
solution that could provide critical regions bound to a CPU to
user-space programs.

Mathieu


Thread Migration Preemption - v2

This patch adds the ability to protect critical sections from migration to
another CPU without disabling preemption.

This will be useful to minimize the amount of preemption disabling for the -rt
patch. It will help leveraging improvements brought by the local_t types in
asm/local.h (see Documentation/local_ops.txt). Note that the updates done to
variables protected by migrate_disable must be either atomic or protected from
concurrent updates done by other threads.

Typical use:

migrate_disable();
local_inc(&__get_cpu_var(&my_local_t_var));
migrate_enable();

Which will increment the variable atomically wrt the local CPU.

Changes:

Do a check_migrate() upon migrate_enable() to answer to the migration
thread waiting for us to exit the migration disabled critical section. Use a
NEED_MIGRATE thread flag for this.

Note: (or we could say FIXME)
Is we ever want to check migration pending in assembly code, we will have to
make sure we test the right thread flag bits on each architectures. Care should
also be taken to check that the thread flags used won't trigger false positives
in non selective asm thread flag checks.

Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@polymtl.ca>
---
 include/asm-alpha/thread_info.h     |    3 +
 include/asm-arm/thread_info.h       |    5 +
 include/asm-arm26/thread_info.h     |    5 +
 include/asm-avr32/thread_info.h     |    4 +
 include/asm-blackfin/thread_info.h  |    4 +
 include/asm-cris/thread_info.h      |    4 +
 include/asm-frv/thread_info.h       |    4 +
 include/asm-h8300/thread_info.h     |    4 +
 include/asm-i386/thread_info.h      |    6 +-
 include/asm-ia64/thread_info.h      |    4 +
 include/asm-m32r/thread_info.h      |    4 +
 include/asm-m68k/thread_info.h      |    2 
 include/asm-m68knommu/thread_info.h |    3 +
 include/asm-mips/thread_info.h      |    4 +
 include/asm-parisc/thread_info.h    |    4 +
 include/asm-powerpc/thread_info.h   |    4 +
 include/asm-s390/thread_info.h      |    4 +
 include/asm-sh/thread_info.h        |    4 +
 include/asm-sh64/thread_info.h      |    4 +
 include/asm-sparc/thread_info.h     |    4 +
 include/asm-sparc64/thread_info.h   |    5 +
 include/asm-um/thread_info.h        |    4 +
 include/asm-v850/thread_info.h      |    4 +
 include/asm-x86_64/thread_info.h    |    4 +
 include/asm-xtensa/thread_info.h    |    4 +
 include/linux/preempt.h             |   43 ++++++++++++++++
 kernel/sched.c                      |   92 +++++++++++++++++++++++++++++++++---
 lib/smp_processor_id.c              |    6 +-
 28 files changed, 230 insertions(+), 12 deletions(-)

Index: linux-2.6-lttng/include/asm-i386/thread_info.h
===================================================================
--- linux-2.6-lttng.orig/include/asm-i386/thread_info.h	2007-07-10 02:29:10.000000000 -0400
+++ linux-2.6-lttng/include/asm-i386/thread_info.h	2007-07-11 00:43:03.000000000 -0400
@@ -31,8 +31,7 @@
 	unsigned long		status;		/* thread-synchronous flags */
 	__u32			cpu;		/* current CPU */
 	int			preempt_count;	/* 0 => preemptable, <0 => BUG */
-
-
+	int			migrate_count;/* 0: can migrate, <0: BUG */
 	mm_segment_t		addr_limit;	/* thread address space:
 					 	   0-0xBFFFFFFF for user-thead
 						   0-0xFFFFFFFF for kernel-thread
@@ -74,6 +73,7 @@
 	.flags		= 0,			\
 	.cpu		= 0,			\
 	.preempt_count	= 1,			\
+	.migrate_count = 0,			\
 	.addr_limit	= KERNEL_DS,		\
 	.restart_block = {			\
 		.fn = do_no_restart_syscall,	\
@@ -132,6 +132,7 @@
 #define TIF_SYSCALL_AUDIT	6	/* syscall auditing active */
 #define TIF_SECCOMP		7	/* secure computing */
 #define TIF_RESTORE_SIGMASK	8	/* restore signal mask in do_signal() */
+#define TIF_NEED_MIGRATE	9	/* migration necessary */
 #define TIF_MEMDIE		16
 #define TIF_DEBUG		17	/* uses debug registers */
 #define TIF_IO_BITMAP		18	/* uses I/O bitmap */
@@ -147,6 +148,7 @@
 #define _TIF_SYSCALL_AUDIT	(1<<TIF_SYSCALL_AUDIT)
 #define _TIF_SECCOMP		(1<<TIF_SECCOMP)
 #define _TIF_RESTORE_SIGMASK	(1<<TIF_RESTORE_SIGMASK)
+#define _TIF_NEED_MIGRATE	(1<<TIF_NEED_MIGRATE)
 #define _TIF_DEBUG		(1<<TIF_DEBUG)
 #define _TIF_IO_BITMAP		(1<<TIF_IO_BITMAP)
 #define _TIF_FREEZE		(1<<TIF_FREEZE)
Index: linux-2.6-lttng/include/linux/preempt.h
===================================================================
--- linux-2.6-lttng.orig/include/linux/preempt.h	2007-07-10 02:29:10.000000000 -0400
+++ linux-2.6-lttng/include/linux/preempt.h	2007-07-11 00:43:03.000000000 -0400
@@ -12,15 +12,24 @@
 #ifdef CONFIG_DEBUG_PREEMPT
   extern void fastcall add_preempt_count(int val);
   extern void fastcall sub_preempt_count(int val);
+  extern void fastcall add_migrate_count(int val);
+  extern void fastcall sub_migrate_count(int val);
 #else
 # define add_preempt_count(val)	do { preempt_count() += (val); } while (0)
 # define sub_preempt_count(val)	do { preempt_count() -= (val); } while (0)
+# define add_migrate_count(val) do { migrate_count() += (val); } while (0)
+# define sub_migrate_count(val) do { migrate_count() -= (val); } while (0)
 #endif
 
 #define inc_preempt_count() add_preempt_count(1)
 #define dec_preempt_count() sub_preempt_count(1)
 
-#define preempt_count()	(current_thread_info()->preempt_count)
+#define preempt_count() (current_thread_info()->preempt_count)
+
+#define inc_migrate_count() add_migrate_count(1)
+#define dec_migrate_count() sub_migrate_count(1)
+
+#define migrate_count() (current_thread_info()->migrate_count)
 
 #ifdef CONFIG_PREEMPT
 
@@ -51,6 +60,35 @@
 	preempt_check_resched(); \
 } while (0)
 
+#define migrate_disable() \
+do { \
+	inc_migrate_count(); \
+	barrier(); \
+} while (0)
+
+#define migrate_enable_no_check() \
+do { \
+	barrier(); \
+	dec_migrate_count(); \
+} while (0)
+
+#ifdef CONFIG_SMP
+#define check_migrate() \
+do { \
+	if (unlikely(test_thread_flag(TIF_NEED_MIGRATE))) \
+		do_check_migrate(); \
+} while (0)
+#else
+#define check_migrate()
+#endif
+
+#define migrate_enable() \
+do { \
+	migrate_enable_no_check(); \
+	barrier(); \
+	check_migrate(); \
+} while (0)
+
 #else
 
 #define preempt_disable()		do { } while (0)
@@ -58,6 +96,9 @@
 #define preempt_enable()		do { } while (0)
 #define preempt_check_resched()		do { } while (0)
 
+#define migrate_disable()		do { } while (0)
+#define migrate_enable()		do { } while (0)
+
 #endif
 
 #endif /* __LINUX_PREEMPT_H */
Index: linux-2.6-lttng/kernel/sched.c
===================================================================
--- linux-2.6-lttng.orig/kernel/sched.c	2007-07-11 00:43:02.000000000 -0400
+++ linux-2.6-lttng/kernel/sched.c	2007-07-11 00:43:03.000000000 -0400
@@ -946,7 +946,8 @@
 	 * If the task is not on a runqueue (and not running), then
 	 * it is sufficient to simply update the task's cpu field.
 	 */
-	if (!p->se.on_rq && !task_running(rq, p)) {
+	if (!p->se.on_rq && !task_running(rq, p)
+			&& !task_thread_info(p)->migrate_count) {
 		set_task_cpu(p, dest_cpu);
 		return 0;
 	}
@@ -1347,7 +1348,10 @@
 #ifdef CONFIG_SMP
 	if (unlikely(task_running(rq, p)))
 		goto out_activate;
-
+#ifdef CONFIG_PREEMPT
+	if (task_thread_info(p)->migrate_count)
+		goto out_activate;
+#endif
 	new_cpu = cpu;
 
 	schedstat_inc(rq, ttwu_cnt);
@@ -1534,6 +1538,7 @@
 #ifdef CONFIG_PREEMPT
 	/* Want to start with kernel preemption disabled. */
 	task_thread_info(p)->preempt_count = 1;
+	task_thread_info(p)->migrate_count = 0;
 #endif
 	put_cpu();
 }
@@ -1933,6 +1938,10 @@
 	if (!cpu_isset(dest_cpu, p->cpus_allowed)
 	    || unlikely(cpu_is_offline(dest_cpu)))
 		goto out;
+#ifdef CONFIG_PREEMPT
+	if (task_thread_info(p)->migrate_count)
+		goto out;
+#endif
 
 	trace_mark(kernel_sched_migrate_task, "%d %ld %d",
 		p->pid, p->state, dest_cpu);
@@ -1996,6 +2005,7 @@
 	 * 1) running (obviously), or
 	 * 2) cannot be migrated to this CPU due to cpus_allowed, or
 	 * 3) are cache-hot on their current CPU.
+	 * 4) migration preemption is non 0 for this non running task.
 	 */
 	if (!cpu_isset(this_cpu, p->cpus_allowed))
 		return 0;
@@ -2003,6 +2013,10 @@
 
 	if (task_running(rq, p))
 		return 0;
+#ifdef CONFIG_PREEMPT
+	if (task_thread_info(p)->migrate_count)
+		return 0;
+#endif
 
 	/*
 	 * Aggressive migration if too many balance attempts have failed:
@@ -3220,6 +3234,29 @@
 }
 EXPORT_SYMBOL(sub_preempt_count);
 
+void fastcall add_migrate_count(int val)
+{
+	/*
+	 * Underflow?
+	 */
+	if (DEBUG_LOCKS_WARN_ON((migrate_count() < 0)))
+		return;
+	migrate_count() += val;
+}
+EXPORT_SYMBOL(add_migrate_count);
+
+void fastcall sub_migrate_count(int val)
+{
+	/*
+	 * Underflow?
+	 */
+	if (DEBUG_LOCKS_WARN_ON(val > migrate_count()))
+		return;
+
+	migrate_count() -= val;
+}
+EXPORT_SYMBOL(sub_migrate_count);
+
 #endif
 
 /*
@@ -3353,6 +3390,28 @@
 EXPORT_SYMBOL(schedule);
 
 #ifdef CONFIG_PREEMPT
+
+#ifdef CONFIG_SMP
+/*
+ * Wake up the migration thread to deal with our pending migration.
+ * If we have been moved since, we will just wake up the migration thread from
+ * the wrong CPU, which does not hurt anyone. (that's why we use
+ * raw_smp_processor_id()).
+ */
+void __sched do_check_migrate(void)
+{
+	struct rq *rq;
+
+	if (migrate_count())
+		return;
+
+	clear_thread_flag(TIF_NEED_MIGRATE);
+	rq = cpu_rq(raw_smp_processor_id());
+	wake_up_process(rq->migration_thread);
+}
+EXPORT_SYMBOL(do_check_migrate);
+#endif
+
 /*
  * this is the entry point to schedule() from in-kernel preemption
  * off of preempt_enable.  Kernel preemptions off return from interrupt
@@ -4814,7 +4873,7 @@
  * So we race with normal scheduler movements, but that's OK, as long
  * as the task is no longer on this CPU.
  *
- * Returns non-zero if task was successfully migrated.
+ * Returns non-zero if task is on dest_cpu when this function ends.
  */
 static int __migrate_task(struct task_struct *p, int src_cpu, int dest_cpu)
 {
@@ -4829,13 +4888,19 @@
 
 	double_rq_lock(rq_src, rq_dest);
 	/* Already moved. */
-	if (task_cpu(p) != src_cpu)
+	if (task_cpu(p) != src_cpu) {
+		ret = 1;
 		goto out;
+	}
 	/* Affinity changed (again). */
 	if (!cpu_isset(dest_cpu, p->cpus_allowed))
 		goto out;
 
 	on_rq = p->se.on_rq;
+#ifdef CONFIG_PREEMPT
+	if (!on_rq && task_thread_info(p)->migrate_count)
+		goto out;
+#endif
 	if (on_rq)
 		deactivate_task(rq_src, p, 0);
 	set_task_cpu(p, dest_cpu);
@@ -4858,6 +4923,7 @@
 {
 	int cpu = (long)data;
 	struct rq *rq;
+	int migrated;
 
 	rq = cpu_rq(cpu);
 	BUG_ON(rq->migration_thread != current);
@@ -4891,10 +4957,22 @@
 		list_del_init(head->next);
 
 		spin_unlock(&rq->lock);
-		__migrate_task(req->task, cpu, req->dest_cpu);
+		migrated = __migrate_task(req->task, cpu, req->dest_cpu);
 		local_irq_enable();
-
-		complete(&req->done);
+		if (!migrated) {
+			/*
+			 * If the process has not been migrated, let it run
+			 * until it reaches a migration_check() so it can
+			 * wake us up.
+			 */
+			spin_lock_irq(&rq->lock);
+			head = &rq->migration_queue;
+			list_add(&req->list, head);
+			set_tsk_thread_flag(req->task, TIF_NEED_MIGRATE);
+			spin_unlock_irq(&rq->lock);
+			wake_up_process(req->task);
+		} else
+			complete(&req->done);
 	}
 	__set_current_state(TASK_RUNNING);
 	return 0;
Index: linux-2.6-lttng/include/asm-alpha/thread_info.h
===================================================================
--- linux-2.6-lttng.orig/include/asm-alpha/thread_info.h	2007-07-11 00:43:02.000000000 -0400
+++ linux-2.6-lttng/include/asm-alpha/thread_info.h	2007-07-11 00:43:03.000000000 -0400
@@ -21,6 +21,7 @@
 	mm_segment_t		addr_limit;	/* thread address space */
 	unsigned		cpu;		/* current CPU */
 	int			preempt_count; /* 0 => preemptable, <0 => BUG */
+	int			migrate_count;/* 0: can migrate, <0 => BUG */
 
 	int bpt_nsaved;
 	unsigned long bpt_addr[2];		/* breakpoint handling  */
@@ -77,6 +78,7 @@
 #define TIF_MEMDIE		8
 #define TIF_RESTORE_SIGMASK	9	/* restore signal mask in do_signal */
 #define	TIF_SYSCALL_AUDIT	10
+#define TIF_NEED_MIGRATE	11	/* migration necessary */
 
 #define _TIF_SYSCALL_TRACE	(1<<TIF_SYSCALL_TRACE)
 #define _TIF_SIGPENDING		(1<<TIF_SIGPENDING)
@@ -84,6 +86,7 @@
 #define _TIF_POLLING_NRFLAG	(1<<TIF_POLLING_NRFLAG)
 #define _TIF_RESTORE_SIGMASK	(1<<TIF_RESTORE_SIGMASK)
 #define _TIF_SYSCALL_AUDIT	(1<<TIF_SYSCALL_AUDIT)
+#define _TIF_NEED_MIGRATE	(1<<TIF_NEED_MIGRATE)
 
 /* Work to do on interrupt/exception return.  */
 #define _TIF_WORK_MASK		(_TIF_SIGPENDING | _TIF_NEED_RESCHED)
Index: linux-2.6-lttng/include/asm-arm/thread_info.h
===================================================================
--- linux-2.6-lttng.orig/include/asm-arm/thread_info.h	2007-07-11 00:43:00.000000000 -0400
+++ linux-2.6-lttng/include/asm-arm/thread_info.h	2007-07-11 00:43:03.000000000 -0400
@@ -51,6 +51,7 @@
 struct thread_info {
 	unsigned long		flags;		/* low level flags */
 	int			preempt_count;	/* 0 => preemptable, <0 => bug */
+	int			migrate_count;/* 0: can migrate, <0 => BUG */
 	mm_segment_t		addr_limit;	/* address limit */
 	struct task_struct	*task;		/* main task structure */
 	struct exec_domain	*exec_domain;	/* execution domain */
@@ -72,6 +73,7 @@
 	.exec_domain	= &default_exec_domain,				\
 	.flags		= 0,						\
 	.preempt_count	= 1,						\
+	.migrate_count = 0,						\
 	.addr_limit	= KERNEL_DS,					\
 	.cpu_domain	= domain_val(DOMAIN_USER, DOMAIN_MANAGER) |	\
 			  domain_val(DOMAIN_KERNEL, DOMAIN_MANAGER) |	\
@@ -137,12 +139,14 @@
  *  TIF_SYSCALL_TRACE	- syscall trace active
  *  TIF_SIGPENDING	- signal pending
  *  TIF_NEED_RESCHED	- rescheduling necessary
+ *  TIF_NEED_MIGRATE	- migration necessary
  *  TIF_USEDFPU		- FPU was used by this task this quantum (SMP)
  *  TIF_POLLING_NRFLAG	- true if poll_idle() is polling TIF_NEED_RESCHED
  *  TIF_SYSCALL_AUDIT	- Syscall audting active - LTTng
  */
 #define TIF_SIGPENDING		0
 #define TIF_NEED_RESCHED	1
+#define TIF_NEED_MIGRATE	2
 #define	TIF_SYSCALL_AUDIT	7
 #define TIF_SYSCALL_TRACE	8
 #define TIF_POLLING_NRFLAG	16
@@ -152,6 +156,7 @@
 
 #define _TIF_SIGPENDING		(1 << TIF_SIGPENDING)
 #define _TIF_NEED_RESCHED	(1 << TIF_NEED_RESCHED)
+#define _TIF_NEED_MIGRATE	(1 << TIF_NEED_MIGRATE)
 #define _TIF_SYSCALL_TRACE	(1 << TIF_SYSCALL_TRACE)
 #define	_TIF_SYSCALL_AUDIT	(1 << TIF_SYSCALL_AUDIT)
 #define _TIF_POLLING_NRFLAG	(1 << TIF_POLLING_NRFLAG)
Index: linux-2.6-lttng/include/asm-arm26/thread_info.h
===================================================================
--- linux-2.6-lttng.orig/include/asm-arm26/thread_info.h	2007-07-10 02:29:10.000000000 -0400
+++ linux-2.6-lttng/include/asm-arm26/thread_info.h	2007-07-11 00:43:03.000000000 -0400
@@ -45,6 +45,7 @@
 struct thread_info {
 	unsigned long		flags;		/* low level flags */
 	int			preempt_count;	/* 0 => preemptable, <0 => bug */
+	int			migrate_count;/* 0: can migrate, <0 => BUG */
 	mm_segment_t		addr_limit;	/* address limit */
 	struct task_struct	*task;		/* main task structure */
 	struct exec_domain      *exec_domain;   /* execution domain */
@@ -60,6 +61,7 @@
 	.exec_domain	&default_exec_domain,	\
 	.flags		0,			\
 	.preempt_count	0,			\
+	.migrate_count 0,			\
 	.addr_limit	KERNEL_DS,		\
 	.restart_block  = {                             \
 		.fn     = do_no_restart_syscall,        \
@@ -112,11 +114,13 @@
  *  TIF_SYSCALL_TRACE	- syscall trace active
  *  TIF_SIGPENDING	- signal pending
  *  TIF_NEED_RESCHED	- rescheduling necessary
+ *  TIF_NEED_MIGRATE	- migration necessary
  *  TIF_USEDFPU		- FPU was used by this task this quantum (SMP)
  *  TIF_POLLING_NRFLAG	- true if poll_idle() is polling TIF_NEED_RESCHED
  */
 #define TIF_SIGPENDING		0
 #define TIF_NEED_RESCHED	1
+#define TIF_NEED_MIGRATE	2
 #define TIF_SYSCALL_TRACE	8
 #define TIF_USED_FPU		16
 #define TIF_POLLING_NRFLAG	17
@@ -124,6 +128,7 @@
 
 #define _TIF_SIGPENDING		(1 << TIF_SIGPENDING)
 #define _TIF_NEED_RESCHED	(1 << TIF_NEED_RESCHED)
+#define _TIF_NEED_MIGRATE	(1 << TIF_NEED_MIGRATE)
 #define _TIF_SYSCALL_TRACE	(1 << TIF_SYSCALL_TRACE)
 #define _TIF_USED_FPU		(1 << TIF_USED_FPU)
 #define _TIF_POLLING_NRFLAG	(1 << TIF_POLLING_NRFLAG)
Index: linux-2.6-lttng/include/asm-avr32/thread_info.h
===================================================================
--- linux-2.6-lttng.orig/include/asm-avr32/thread_info.h	2007-07-10 02:29:10.000000000 -0400
+++ linux-2.6-lttng/include/asm-avr32/thread_info.h	2007-07-11 00:43:03.000000000 -0400
@@ -25,6 +25,7 @@
 	unsigned long		flags;		/* low level flags */
 	__u32			cpu;
 	__s32			preempt_count;	/* 0 => preemptable, <0 => BUG */
+	int			migrate_count;/* 0: can migrate, <0 => BUG */
 	struct restart_block	restart_block;
 	__u8			supervisor_stack[0];
 };
@@ -36,6 +37,7 @@
 	.flags		= 0,						\
 	.cpu		= 0,						\
 	.preempt_count	= 1,						\
+	.migrate_count = 0,						\
 	.restart_block	= {						\
 		.fn	= do_no_restart_syscall				\
 	}								\
@@ -83,6 +85,7 @@
 #define TIF_MEMDIE		6
 #define TIF_RESTORE_SIGMASK	7	/* restore signal mask in do_signal */
 #define TIF_CPU_GOING_TO_SLEEP	8	/* CPU is entering sleep 0 mode */
+#define TIF_NEED_MIGRATE      9       /* migration necessary */
 #define TIF_USERSPACE		31      /* true if FS sets userspace */
 
 #define _TIF_SYSCALL_TRACE	(1 << TIF_SYSCALL_TRACE)
@@ -94,6 +97,7 @@
 #define _TIF_MEMDIE		(1 << TIF_MEMDIE)
 #define _TIF_RESTORE_SIGMASK	(1 << TIF_RESTORE_SIGMASK)
 #define _TIF_CPU_GOING_TO_SLEEP (1 << TIF_CPU_GOING_TO_SLEEP)
+#define _TIF_NEED_MIGRATE	(1 << TIF_NEED_MIGRATE)
 
 /* XXX: These two masks must never span more than 16 bits! */
 /* work to do on interrupt/exception return */
Index: linux-2.6-lttng/include/asm-blackfin/thread_info.h
===================================================================
--- linux-2.6-lttng.orig/include/asm-blackfin/thread_info.h	2007-07-10 02:29:10.000000000 -0400
+++ linux-2.6-lttng/include/asm-blackfin/thread_info.h	2007-07-11 00:43:03.000000000 -0400
@@ -54,6 +54,7 @@
 	unsigned long flags;	/* low level flags */
 	int cpu;		/* cpu we're on */
 	int preempt_count;	/* 0 => preemptable, <0 => BUG */
+	int migrate_count;	/* 0: can migrate, <0 => BUG */
 	mm_segment_t addr_limit;	/* address limit */
 	struct restart_block restart_block;
 	struct l1_scratch_task_info l1_task_info;
@@ -69,6 +70,7 @@
 	.flags		= 0,			\
 	.cpu		= 0,			\
 	.preempt_count  = 1,                    \
+	.migrate_count = 0,			\
 	.restart_block	= {			\
 		.fn = do_no_restart_syscall,	\
 	},					\
@@ -125,6 +127,7 @@
 #define TIF_MEMDIE              4
 #define TIF_RESTORE_SIGMASK	5	/* restore signal mask in do_signal() */
 #define TIF_FREEZE              6       /* is freezing for suspend */
+#define TIF_NEED_MIGRATE	7	/* migration necessary */
 
 /* as above, but as bit values */
 #define _TIF_SYSCALL_TRACE	(1<<TIF_SYSCALL_TRACE)
@@ -133,6 +136,7 @@
 #define _TIF_POLLING_NRFLAG	(1<<TIF_POLLING_NRFLAG)
 #define _TIF_RESTORE_SIGMASK	(1<<TIF_RESTORE_SIGMASK)
 #define _TIF_FREEZE             (1<<TIF_FREEZE)
+#define _TIF_NEED_MIGRATE	(1<<TIF_NEED_MIGRATE)
 
 #define _TIF_WORK_MASK		0x0000FFFE	/* work to do on interrupt/exception return */
 
Index: linux-2.6-lttng/include/asm-cris/thread_info.h
===================================================================
--- linux-2.6-lttng.orig/include/asm-cris/thread_info.h	2007-07-10 02:29:10.000000000 -0400
+++ linux-2.6-lttng/include/asm-cris/thread_info.h	2007-07-11 00:43:03.000000000 -0400
@@ -32,6 +32,7 @@
 	unsigned long		flags;		/* low level flags */
 	__u32			cpu;		/* current CPU */
 	int			preempt_count;	/* 0 => preemptable, <0 => BUG */
+	int			migrate_count;/* 0: can migrate, <0 => BUG */
 
 	mm_segment_t		addr_limit;	/* thread address space:
 					 	   0-0xBFFFFFFF for user-thead
@@ -58,6 +59,7 @@
 	.flags		= 0,				\
 	.cpu		= 0,				\
 	.preempt_count	= 1,				\
+	.migrate_count = 0,				\
 	.addr_limit	= KERNEL_DS,			\
 	.restart_block = {				\
 		       .fn = do_no_restart_syscall,	\
@@ -81,6 +83,7 @@
 #define TIF_SYSCALL_TRACE	0	/* syscall trace active */
 #define TIF_SIGPENDING		1	/* signal pending */
 #define TIF_NEED_RESCHED	2	/* rescheduling necessary */
+#define TIF_NEED_MIGRATE	3	/* migration necessary */
 #define TIF_POLLING_NRFLAG	16	/* true if poll_idle() is polling TIF_NEED_RESCHED */
 #define TIF_MEMDIE		17
 
@@ -88,6 +91,7 @@
 #define _TIF_SIGPENDING		(1<<TIF_SIGPENDING)
 #define _TIF_NEED_RESCHED	(1<<TIF_NEED_RESCHED)
 #define _TIF_POLLING_NRFLAG	(1<<TIF_POLLING_NRFLAG)
+#define _TIF_NEED_MIGRATE	(1<<TIF_NEED_MIGRATE)
 
 #define _TIF_WORK_MASK		0x0000FFFE	/* work to do on interrupt/exception return */
 #define _TIF_ALLWORK_MASK	0x0000FFFF	/* work to do on any return to u-space */
Index: linux-2.6-lttng/include/asm-frv/thread_info.h
===================================================================
--- linux-2.6-lttng.orig/include/asm-frv/thread_info.h	2007-07-10 02:29:10.000000000 -0400
+++ linux-2.6-lttng/include/asm-frv/thread_info.h	2007-07-11 00:43:03.000000000 -0400
@@ -36,6 +36,7 @@
 	unsigned long		status;		/* thread-synchronous flags */
 	__u32			cpu;		/* current CPU */
 	int			preempt_count;	/* 0 => preemptable, <0 => BUG */
+	int			migrate_count;/* 0: can migrate, <0 => BUG */
 
 	mm_segment_t		addr_limit;	/* thread address space:
 					 	   0-0xBFFFFFFF for user-thead
@@ -68,6 +69,7 @@
 	.flags		= 0,			\
 	.cpu		= 0,			\
 	.preempt_count	= 1,			\
+	.migrate_count = 0,			\
 	.addr_limit	= KERNEL_DS,		\
 	.restart_block = {			\
 		.fn = do_no_restart_syscall,	\
@@ -113,6 +115,7 @@
 #define TIF_SINGLESTEP		3	/* restore singlestep on return to user mode */
 #define TIF_IRET		4	/* return with iret */
 #define TIF_RESTORE_SIGMASK	5	/* restore signal mask in do_signal() */
+#define TIF_NEED_MIGRATE	6	/* migration necessary */
 #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	/* freezing for suspend */
@@ -125,6 +128,7 @@
 #define _TIF_RESTORE_SIGMASK	(1 << TIF_RESTORE_SIGMASK)
 #define _TIF_POLLING_NRFLAG	(1 << TIF_POLLING_NRFLAG)
 #define _TIF_FREEZE		(1 << TIF_FREEZE)
+#define _TIF_NEED_MIGRATE	(1 << TIF_NEED_MIGRATE)
 
 #define _TIF_WORK_MASK		0x0000FFFE	/* work to do on interrupt/exception return */
 #define _TIF_ALLWORK_MASK	0x0000FFFF	/* work to do on any return to u-space */
Index: linux-2.6-lttng/include/asm-h8300/thread_info.h
===================================================================
--- linux-2.6-lttng.orig/include/asm-h8300/thread_info.h	2007-07-10 02:29:10.000000000 -0400
+++ linux-2.6-lttng/include/asm-h8300/thread_info.h	2007-07-11 00:43:03.000000000 -0400
@@ -24,6 +24,7 @@
 	unsigned long	   flags;		/* low level flags */
 	int		   cpu;			/* cpu we're on */
 	int		   preempt_count;	/* 0 => preemptable, <0 => BUG */
+	int			migrate_count;/* 0: can migrate, <0 => BUG */
 	struct restart_block restart_block;
 };
 
@@ -37,6 +38,7 @@
 	.flags =	0,			\
 	.cpu =		0,			\
 	.preempt_count = 1,			\
+	.migrate_count = 0,			\
 	.restart_block	= {			\
 		.fn = do_no_restart_syscall,	\
 	},					\
@@ -91,12 +93,14 @@
 #define TIF_POLLING_NRFLAG	3	/* true if poll_idle() is polling
 					   TIF_NEED_RESCHED */
 #define TIF_MEMDIE		4
+#define TIF_NEED_MIGRATE	5	/* migration necessary */
 
 /* as above, but as bit values */
 #define _TIF_SYSCALL_TRACE	(1<<TIF_SYSCALL_TRACE)
 #define _TIF_SIGPENDING		(1<<TIF_SIGPENDING)
 #define _TIF_NEED_RESCHED	(1<<TIF_NEED_RESCHED)
 #define _TIF_POLLING_NRFLAG	(1<<TIF_POLLING_NRFLAG)
+#define _TIF_NEED_MIGRATE	(1<<TIF_NEED_MIGRATE)
 
 #define _TIF_WORK_MASK		0x0000FFFE	/* work to do on interrupt/exception return */
 
Index: linux-2.6-lttng/include/asm-ia64/thread_info.h
===================================================================
--- linux-2.6-lttng.orig/include/asm-ia64/thread_info.h	2007-07-10 02:29:10.000000000 -0400
+++ linux-2.6-lttng/include/asm-ia64/thread_info.h	2007-07-11 00:43:03.000000000 -0400
@@ -30,6 +30,7 @@
 	__u32 status;			/* Thread synchronous flags */
 	mm_segment_t addr_limit;	/* user-level address space limit */
 	int preempt_count;		/* 0=premptable, <0=BUG; will also serve as bh-counter */
+	int migrate_count;		/* 0: can migrate, <0 => BUG */
 	struct restart_block restart_block;
 };
 
@@ -43,6 +44,7 @@
 	.cpu		= 0,			\
 	.addr_limit	= KERNEL_DS,		\
 	.preempt_count	= 0,			\
+	.migrate_count = 0,			\
 	.restart_block = {			\
 		.fn = do_no_restart_syscall,	\
 	},					\
@@ -86,6 +88,7 @@
 #define TIF_SINGLESTEP		4	/* restore singlestep on return to user mode */
 #define TIF_RESTORE_SIGMASK	5	/* restore signal mask in do_signal() */
 #define TIF_PERFMON_WORK	6	/* work for pfm_handle_work() */
+#define TIF_NEED_MIGRATE	7	/* migration necessary */
 #define TIF_POLLING_NRFLAG	16	/* true if poll_idle() is polling TIF_NEED_RESCHED */
 #define TIF_MEMDIE		17
 #define TIF_MCA_INIT		18	/* this task is processing MCA or INIT */
@@ -98,6 +101,7 @@
 #define _TIF_SYSCALL_TRACEAUDIT	(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SINGLESTEP)
 #define _TIF_RESTORE_SIGMASK	(1 << TIF_RESTORE_SIGMASK)
 #define _TIF_PERFMON_WORK	(1 << TIF_PERFMON_WORK)
+#define _TIF_NEED_MIGRATE	(1 << TIF_NEED_MIGRATE)
 #define _TIF_SIGPENDING		(1 << TIF_SIGPENDING)
 #define _TIF_NEED_RESCHED	(1 << TIF_NEED_RESCHED)
 #define _TIF_POLLING_NRFLAG	(1 << TIF_POLLING_NRFLAG)
Index: linux-2.6-lttng/include/asm-m32r/thread_info.h
===================================================================
--- linux-2.6-lttng.orig/include/asm-m32r/thread_info.h	2007-07-10 02:29:10.000000000 -0400
+++ linux-2.6-lttng/include/asm-m32r/thread_info.h	2007-07-11 00:43:03.000000000 -0400
@@ -29,6 +29,7 @@
 	unsigned long		status;		/* thread-synchronous flags */
 	__u32			cpu;		/* current CPU */
 	int			preempt_count;	/* 0 => preemptable, <0 => BUG */
+	int			migrate_count;/* 0: can migrate, <0 => BUG */
 
 	mm_segment_t		addr_limit;	/* thread address space:
 					 	   0-0xBFFFFFFF for user-thread
@@ -69,6 +70,7 @@
 	.flags		= 0,			\
 	.cpu		= 0,			\
 	.preempt_count	= 1,			\
+	.migrate_count = 0,			\
 	.addr_limit	= KERNEL_DS,		\
 	.restart_block = {			\
 		.fn = do_no_restart_syscall,	\
@@ -150,6 +152,7 @@
 #define TIF_NEED_RESCHED	2	/* rescheduling necessary */
 #define TIF_SINGLESTEP		3	/* restore singlestep on return to user mode */
 #define TIF_IRET		4	/* return with iret */
+#define TIF_NEED_MIGRATE	5	/* migration necessary */
 #define TIF_POLLING_NRFLAG	16	/* true if poll_idle() is polling TIF_NEED_RESCHED */
 					/* 31..28 fault code */
 #define TIF_MEMDIE		17
@@ -160,6 +163,7 @@
 #define _TIF_SINGLESTEP		(1<<TIF_SINGLESTEP)
 #define _TIF_IRET		(1<<TIF_IRET)
 #define _TIF_POLLING_NRFLAG	(1<<TIF_POLLING_NRFLAG)
+#define _TIF_NEED_MIGRATE	(1<<TIF_NEED_MIGRATE)
 
 #define _TIF_WORK_MASK		0x0000FFFE	/* work to do on interrupt/exception return */
 #define _TIF_ALLWORK_MASK	0x0000FFFF	/* work to do on any return to u-space */
Index: linux-2.6-lttng/include/asm-m68k/thread_info.h
===================================================================
--- linux-2.6-lttng.orig/include/asm-m68k/thread_info.h	2007-07-11 00:43:01.000000000 -0400
+++ linux-2.6-lttng/include/asm-m68k/thread_info.h	2007-07-11 00:43:03.000000000 -0400
@@ -9,6 +9,7 @@
 	unsigned long		flags;
 	struct exec_domain	*exec_domain;	/* execution domain */
 	int			preempt_count;	/* 0 => preemptable, <0 => BUG */
+	int			migrate_count;/* 0: can migrate, <0 => BUG */
 	__u32 cpu; /* should always be 0 on m68k */
 	struct restart_block    restart_block;
 };
@@ -59,5 +60,6 @@
 #define TIF_DELAYED_TRACE	14	/* single step a syscall */
 #define TIF_SYSCALL_TRACE	15	/* syscall trace active */
 #define TIF_MEMDIE		16
+#define TIF_NEED_MIGRATE	17	/* migration necessary */
 
 #endif	/* _ASM_M68K_THREAD_INFO_H */
Index: linux-2.6-lttng/include/asm-m68knommu/thread_info.h
===================================================================
--- linux-2.6-lttng.orig/include/asm-m68knommu/thread_info.h	2007-07-11 00:43:01.000000000 -0400
+++ linux-2.6-lttng/include/asm-m68knommu/thread_info.h	2007-07-11 00:43:03.000000000 -0400
@@ -37,6 +37,7 @@
 	unsigned long	   flags;		/* low level flags */
 	int		   cpu;			/* cpu we're on */
 	int		   preempt_count;	/* 0 => preemptable, <0 => BUG */
+	int		   migrate_count;	/* 0: can migrate, <0 => BUG */
 	struct restart_block restart_block;
 };
 
@@ -88,6 +89,7 @@
 #define TIF_POLLING_NRFLAG	3	/* true if poll_idle() is polling
 					   TIF_NEED_RESCHED */
 #define TIF_MEMDIE		4
+#define TIF_NEED_MIGRATE	5	/* migration necessary */
 #define	TIF_SYSCALL_AUDIT	7	/* syscall auditing active */
 
 /* as above, but as bit values */
@@ -96,6 +98,7 @@
 #define _TIF_NEED_RESCHED	(1<<TIF_NEED_RESCHED)
 #define _TIF_POLLING_NRFLAG	(1<<TIF_POLLING_NRFLAG)
 #define _TIF_MEMDIE		(1<<TIF_MEMDIE)
+#define _TIF_NEED_MIGRATE	(1<<TIF_NEED_MIGRATE)
 #define _TIF_SYSCALL_AUDIT	(1<<TIF_SYSCALL_AUDIT)
 
 #define _TIF_WORK_MASK		0x0000FFFE	/* work to do on interrupt/exception return */
Index: linux-2.6-lttng/include/asm-mips/thread_info.h
===================================================================
--- linux-2.6-lttng.orig/include/asm-mips/thread_info.h	2007-07-10 02:29:10.000000000 -0400
+++ linux-2.6-lttng/include/asm-mips/thread_info.h	2007-07-11 00:43:03.000000000 -0400
@@ -28,6 +28,7 @@
 	unsigned long		tp_value;	/* thread pointer */
 	__u32			cpu;		/* current CPU */
 	int			preempt_count;	/* 0 => preemptable, <0 => BUG */
+	int			migrate_count;/* 0: can migrate, <0 => BUG */
 
 	mm_segment_t		addr_limit;	/* thread address space:
 						   0-0xBFFFFFFF for user-thead
@@ -49,6 +50,7 @@
 	.flags		= 0,			\
 	.cpu		= 0,			\
 	.preempt_count	= 1,			\
+	.migrate_count = 0,			\
 	.addr_limit	= KERNEL_DS,		\
 	.restart_block	= {			\
 		.fn = do_no_restart_syscall,	\
@@ -113,6 +115,7 @@
 #define TIF_NEED_RESCHED	2	/* rescheduling necessary */
 #define TIF_SYSCALL_AUDIT	3	/* syscall auditing active */
 #define TIF_SECCOMP		4	/* secure computing */
+#define TIF_NEED_MIGRATE	5	/* migration necessary */
 #define TIF_RESTORE_SIGMASK	9	/* restore signal mask in do_signal() */
 #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 */
@@ -125,6 +128,7 @@
 #define _TIF_NEED_RESCHED	(1<<TIF_NEED_RESCHED)
 #define _TIF_SYSCALL_AUDIT	(1<<TIF_SYSCALL_AUDIT)
 #define _TIF_SECCOMP		(1<<TIF_SECCOMP)
+#define _TIF_NEED_MIGRATE	(1<<TIF_NEED_MIGRATE)
 #define _TIF_RESTORE_SIGMASK	(1<<TIF_RESTORE_SIGMASK)
 #define _TIF_USEDFPU		(1<<TIF_USEDFPU)
 #define _TIF_POLLING_NRFLAG	(1<<TIF_POLLING_NRFLAG)
Index: linux-2.6-lttng/include/asm-parisc/thread_info.h
===================================================================
--- linux-2.6-lttng.orig/include/asm-parisc/thread_info.h	2007-07-10 02:29:10.000000000 -0400
+++ linux-2.6-lttng/include/asm-parisc/thread_info.h	2007-07-11 00:43:03.000000000 -0400
@@ -13,6 +13,7 @@
 	mm_segment_t addr_limit;	/* user-level address space limit */
 	__u32 cpu;			/* current CPU */
 	int preempt_count;		/* 0=premptable, <0=BUG; will also serve as bh-counter */
+	int migrate_count;		/* 0: can migrate, <0 => BUG */
 	struct restart_block restart_block;
 };
 
@@ -24,6 +25,7 @@
 	.cpu		= 0,			\
 	.addr_limit	= KERNEL_DS,		\
 	.preempt_count	= 1,			\
+	.migrate_count = 0,			\
   	.restart_block	= {			\
 		.fn = do_no_restart_syscall	\
 	}					\
@@ -62,6 +64,7 @@
 #define TIF_32BIT               4       /* 32 bit binary */
 #define TIF_MEMDIE		5
 #define TIF_RESTORE_SIGMASK	6	/* restore saved signal mask */
+#define TIF_NEED_MIGRATE	7	/* migration necessary */
 
 #define _TIF_SYSCALL_TRACE	(1 << TIF_SYSCALL_TRACE)
 #define _TIF_SIGPENDING		(1 << TIF_SIGPENDING)
@@ -69,6 +72,7 @@
 #define _TIF_POLLING_NRFLAG	(1 << TIF_POLLING_NRFLAG)
 #define _TIF_32BIT		(1 << TIF_32BIT)
 #define _TIF_RESTORE_SIGMASK	(1 << TIF_RESTORE_SIGMASK)
+#define _TIF_NEED_MIGRATE	(1 << TIF_NEED_MIGRATE)
 
 #define _TIF_USER_WORK_MASK     (_TIF_SIGPENDING | \
                                  _TIF_NEED_RESCHED | _TIF_RESTORE_SIGMASK)
Index: linux-2.6-lttng/include/asm-powerpc/thread_info.h
===================================================================
--- linux-2.6-lttng.orig/include/asm-powerpc/thread_info.h	2007-07-10 02:29:10.000000000 -0400
+++ linux-2.6-lttng/include/asm-powerpc/thread_info.h	2007-07-11 00:43:03.000000000 -0400
@@ -35,6 +35,7 @@
 	int		cpu;			/* cpu we're on */
 	int		preempt_count;		/* 0 => preemptable,
 						   <0 => BUG */
+	int		migrate_count;	/* 0: can migrate, <0 => BUG */
 	struct restart_block restart_block;
 	unsigned long	local_flags;		/* private flags for thread */
 
@@ -53,6 +54,7 @@
 	.exec_domain =	&default_exec_domain,	\
 	.cpu =		0,			\
 	.preempt_count = 1,			\
+	.migrate_count = 0,			\
 	.restart_block = {			\
 		.fn = do_no_restart_syscall,	\
 	},					\
@@ -124,6 +126,7 @@
 #define TIF_FREEZE		14	/* Freezing for suspend */
 #define TIF_RUNLATCH		15	/* Is the runlatch enabled? */
 #define TIF_ABI_PENDING		16	/* 32/64 bit switch needed */
+#define TIF_NEED_MIGRATE	17	/* migration necessary */
 
 /* as above, but as bit values */
 #define _TIF_SYSCALL_TRACE	(1<<TIF_SYSCALL_TRACE)
@@ -142,6 +145,7 @@
 #define _TIF_FREEZE		(1<<TIF_FREEZE)
 #define _TIF_RUNLATCH		(1<<TIF_RUNLATCH)
 #define _TIF_ABI_PENDING	(1<<TIF_ABI_PENDING)
+#define _TIF_NEED_MIGRATE	(1<<TIF_NEED_MIGRATE)
 #define _TIF_SYSCALL_T_OR_A	(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SECCOMP)
 
 #define _TIF_USER_WORK_MASK	( _TIF_SIGPENDING | \
Index: linux-2.6-lttng/include/asm-s390/thread_info.h
===================================================================
--- linux-2.6-lttng.orig/include/asm-s390/thread_info.h	2007-07-10 02:29:10.000000000 -0400
+++ linux-2.6-lttng/include/asm-s390/thread_info.h	2007-07-11 00:43:03.000000000 -0400
@@ -51,6 +51,7 @@
 	unsigned long		flags;		/* low level flags */
 	unsigned int		cpu;		/* current CPU */
 	int			preempt_count;	/* 0 => preemptable, <0 => BUG */
+	int			migrate_count;/* 0: can migrate, <0 => BUG */
 	struct restart_block	restart_block;
 };
 
@@ -64,6 +65,7 @@
 	.flags		= 0,			\
 	.cpu		= 0,			\
 	.preempt_count	= 1,			\
+	.migrate_count = 0,			\
 	.restart_block	= {			\
 		.fn = do_no_restart_syscall,	\
 	},					\
@@ -96,6 +98,7 @@
 #define TIF_SYSCALL_AUDIT	5	/* syscall auditing active */
 #define TIF_SINGLE_STEP		6	/* deliver sigtrap on return to user */
 #define TIF_MCCK_PENDING	7	/* machine check handling is pending */
+#define TIF_NEED_MIGRATE	8	/* migration necessary */
 #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 */
@@ -110,6 +113,7 @@
 #define _TIF_SYSCALL_AUDIT	(1<<TIF_SYSCALL_AUDIT)
 #define _TIF_SINGLE_STEP	(1<<TIF_SINGLE_STEP)
 #define _TIF_MCCK_PENDING	(1<<TIF_MCCK_PENDING)
+#define _TIF_NEED_MIGRATE	(1<<TIF_NEED_MIGRATE)
 #define _TIF_USEDFPU		(1<<TIF_USEDFPU)
 #define _TIF_POLLING_NRFLAG	(1<<TIF_POLLING_NRFLAG)
 #define _TIF_31BIT		(1<<TIF_31BIT)
Index: linux-2.6-lttng/include/asm-sh/thread_info.h
===================================================================
--- linux-2.6-lttng.orig/include/asm-sh/thread_info.h	2007-07-11 00:43:01.000000000 -0400
+++ linux-2.6-lttng/include/asm-sh/thread_info.h	2007-07-11 00:43:03.000000000 -0400
@@ -21,6 +21,7 @@
 	unsigned long		flags;		/* low level flags */
 	__u32			cpu;
 	int			preempt_count; /* 0 => preemptable, <0 => BUG */
+	int			migrate_count;/* 0: can migrate, <0 => BUG */
 	mm_segment_t		addr_limit;	/* thread address space */
 	struct restart_block	restart_block;
 	unsigned long		previous_sp;	/* sp of previous stack in case
@@ -58,6 +59,7 @@
 	.flags		= 0,			\
 	.cpu		= 0,			\
 	.preempt_count	= 1,			\
+	.migrate_count = 0,			\
 	.addr_limit	= KERNEL_DS,		\
 	.restart_block	= {			\
 		.fn = do_no_restart_syscall,	\
@@ -112,6 +114,7 @@
 #define TIF_RESTORE_SIGMASK	3	/* restore signal mask in do_signal() */
 #define TIF_SINGLESTEP		4	/* singlestepping active */
 #define	TIF_SYSCALL_AUDIT	6	/* syscall audit active */
+#define TIF_NEED_MIGRATE	7	/* migration necessary */
 #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
@@ -123,6 +126,7 @@
 #define _TIF_RESTORE_SIGMASK	(1<<TIF_RESTORE_SIGMASK)
 #define _TIF_SINGLESTEP		(1<<TIF_SINGLESTEP)
 #define _TIF_SYSCALL_AUDIT	(1<<TIF_SYSCALL_AUDIT)
+#define _TIF_NEED_MIGRATE	(1<<TIF_NEED_MIGRATE)
 #define _TIF_USEDFPU		(1<<TIF_USEDFPU)
 #define _TIF_POLLING_NRFLAG	(1<<TIF_POLLING_NRFLAG)
 #define _TIF_FREEZE		(1<<TIF_FREEZE)
Index: linux-2.6-lttng/include/asm-sh64/thread_info.h
===================================================================
--- linux-2.6-lttng.orig/include/asm-sh64/thread_info.h	2007-07-11 00:43:01.000000000 -0400
+++ linux-2.6-lttng/include/asm-sh64/thread_info.h	2007-07-11 00:43:03.000000000 -0400
@@ -23,6 +23,7 @@
 	unsigned long		flags;		/* low level flags */
 	/* Put the 4 32-bit fields together to make asm offsetting easier. */
 	int			preempt_count;	/* 0 => preemptable, <0 => BUG */
+	int			migrate_count;/* 0: can migrate, <0 => BUG */
 	__u16			cpu;
 
 	mm_segment_t		addr_limit;
@@ -41,6 +42,7 @@
 	.flags		= 0,			\
 	.cpu		= 0,			\
 	.preempt_count	= 1,			\
+	.migrate_count = 0,			\
 	.addr_limit     = KERNEL_DS,            \
 	.restart_block	= {			\
 		.fn = do_no_restart_syscall,	\
@@ -80,12 +82,14 @@
 #define TIF_NEED_RESCHED	3	/* rescheduling necessary */
 #define TIF_MEMDIE		4
 #define TIF_RESTORE_SIGMASK	5	/* Restore signal mask in do_signal */
+#define TIF_NEED_MIGRATE	6	/* migration necessary */
 
 #define _TIF_SYSCALL_TRACE	(1 << TIF_SYSCALL_TRACE)
 #define _TIF_SIGPENDING		(1 << TIF_SIGPENDING)
 #define _TIF_NEED_RESCHED	(1 << TIF_NEED_RESCHED)
 #define _TIF_MEMDIE		(1 << TIF_MEMDIE)
 #define _TIF_RESTORE_SIGMASK	(1 << TIF_RESTORE_SIGMASK)
+#define _TIF_NEED_MIGRATE	(1 << TIF_NEED_MIGRATE)
 
 #endif /* __KERNEL__ */
 
Index: linux-2.6-lttng/include/asm-sparc/thread_info.h
===================================================================
--- linux-2.6-lttng.orig/include/asm-sparc/thread_info.h	2007-07-11 00:43:01.000000000 -0400
+++ linux-2.6-lttng/include/asm-sparc/thread_info.h	2007-07-11 00:43:03.000000000 -0400
@@ -33,6 +33,7 @@
 	int			cpu;		/* cpu we're on */
 	int			preempt_count;	/* 0 => preemptable,
 						   <0 => BUG */
+	int			migrate_count;/* 0: can migrate, <0 => BUG */
 	int			softirq_count;
 	int			hardirq_count;
 
@@ -65,6 +66,7 @@
 	.flags		=	0,			\
 	.cpu		=	0,			\
 	.preempt_count	=	1,			\
+	.migrate_count =	0,			\
 	.restart_block	= {				\
 		.fn	=	do_no_restart_syscall,	\
 	},						\
@@ -132,6 +134,7 @@
 #define TIF_SIGPENDING		2	/* signal pending */
 #define TIF_NEED_RESCHED	3	/* rescheduling necessary */
 #define TIF_RESTORE_SIGMASK	4	/* restore signal mask in do_signal() */
+#define TIF_NEED_MIGRATE	5	/* migration necessary */
 #define TIF_USEDFPU		8	/* FPU was used by this task
 					 * this quantum (SMP) */
 #define TIF_POLLING_NRFLAG	9	/* true if poll_idle() is polling
@@ -144,6 +147,7 @@
 #define _TIF_SIGPENDING		(1<<TIF_SIGPENDING)
 #define _TIF_NEED_RESCHED	(1<<TIF_NEED_RESCHED)
 #define _TIF_RESTORE_SIGMASK	(1<<TIF_RESTORE_SIGMASK)
+#define _TIF_NEED_MIGRATE	(1<<TIF_NEED_MIGRATE)
 #define _TIF_USEDFPU		(1<<TIF_USEDFPU)
 #define _TIF_POLLING_NRFLAG	(1<<TIF_POLLING_NRFLAG)
 
Index: linux-2.6-lttng/include/asm-sparc64/thread_info.h
===================================================================
--- linux-2.6-lttng.orig/include/asm-sparc64/thread_info.h	2007-07-10 02:29:10.000000000 -0400
+++ linux-2.6-lttng/include/asm-sparc64/thread_info.h	2007-07-11 00:43:03.000000000 -0400
@@ -47,6 +47,7 @@
 	struct pt_regs		*kregs;
 	struct exec_domain	*exec_domain;
 	int			preempt_count;	/* 0 => preemptable, <0 => BUG */
+	int			migrate_count;/* 0: can migrate, <0 => BUG */
 	__u8			new_child;
 	__u8			syscall_noerror;
 	__u16			cpu;
@@ -137,6 +138,7 @@
 	.flags		= ((unsigned long)ASI_P) << TI_FLAG_CURRENT_DS_SHIFT,	\
 	.exec_domain	=	&default_exec_domain,	\
 	.preempt_count	=	1,			\
+	.migrate_count =	0,			\
 	.restart_block	= {				\
 		.fn	=	do_no_restart_syscall,	\
 	},						\
@@ -225,7 +227,7 @@
 #define TIF_UNALIGNED		5	/* allowed to do unaligned accesses */
 #define TIF_NEWSIGNALS		6	/* wants new-style signals */
 #define TIF_32BIT		7	/* 32-bit binary */
-/* flag bit 8 is available */
+#define TIF_NEED_MIGRATE	8	/* migration necessary */
 #define TIF_SECCOMP		9	/* secure computing */
 #define TIF_SYSCALL_AUDIT	10	/* syscall auditing active */
 /* flag bit 11 is available */
@@ -244,6 +246,7 @@
 #define _TIF_UNALIGNED		(1<<TIF_UNALIGNED)
 #define _TIF_NEWSIGNALS		(1<<TIF_NEWSIGNALS)
 #define _TIF_32BIT		(1<<TIF_32BIT)
+#define _TIF_NEED_MIGRATE	(1<<TIF_NEED_MIGRATE)
 #define _TIF_SECCOMP		(1<<TIF_SECCOMP)
 #define _TIF_SYSCALL_AUDIT	(1<<TIF_SYSCALL_AUDIT)
 #define _TIF_RESTORE_SIGMASK	(1<<TIF_RESTORE_SIGMASK)
Index: linux-2.6-lttng/include/asm-um/thread_info.h
===================================================================
--- linux-2.6-lttng.orig/include/asm-um/thread_info.h	2007-07-10 02:29:10.000000000 -0400
+++ linux-2.6-lttng/include/asm-um/thread_info.h	2007-07-11 00:43:03.000000000 -0400
@@ -18,6 +18,7 @@
 	__u32			cpu;		/* current CPU */
 	int			preempt_count;  /* 0 => preemptable,
 						   <0 => BUG */
+	int			migrate_count;/* 0: can migrate, <0 => BUG */
 	mm_segment_t		addr_limit;	/* thread address space:
 					 	   0-0xBFFFFFFF for user
 						   0-0xFFFFFFFF for kernel */
@@ -32,6 +33,7 @@
 	.flags =		0,		\
 	.cpu =		0,			\
 	.preempt_count =	1,		\
+	.migrate_count =	0,		\
 	.addr_limit =	KERNEL_DS,		\
 	.restart_block =  {			\
 		.fn =  do_no_restart_syscall,	\
@@ -82,6 +84,7 @@
 #define TIF_MEMDIE	 	5
 #define TIF_SYSCALL_AUDIT	6
 #define TIF_RESTORE_SIGMASK	7
+#define TIF_NEED_MIGRATE	8	/* migration necessary */
 
 #define _TIF_SYSCALL_TRACE	(1 << TIF_SYSCALL_TRACE)
 #define _TIF_SIGPENDING		(1 << TIF_SIGPENDING)
@@ -90,5 +93,6 @@
 #define _TIF_MEMDIE		(1 << TIF_MEMDIE)
 #define _TIF_SYSCALL_AUDIT	(1 << TIF_SYSCALL_AUDIT)
 #define _TIF_RESTORE_SIGMASK	(1 << TIF_RESTORE_SIGMASK)
+#define _TIF_NEED_MIGRATE	(1 << TIF_NEED_MIGRATE)
 
 #endif
Index: linux-2.6-lttng/include/asm-v850/thread_info.h
===================================================================
--- linux-2.6-lttng.orig/include/asm-v850/thread_info.h	2007-07-10 02:29:10.000000000 -0400
+++ linux-2.6-lttng/include/asm-v850/thread_info.h	2007-07-11 00:43:03.000000000 -0400
@@ -32,6 +32,7 @@
 	int			cpu;		/* cpu we're on */
 	int			preempt_count;	/* 0 => preemptable,
 						   <0 => BUG */
+	int			migrate_count;/* 0: can migrate, <0 => BUG */
 	struct restart_block	restart_block;
 };
 
@@ -42,6 +43,7 @@
 	.flags =	0,						      \
 	.cpu =		0,						      \
 	.preempt_count = 1,						      \
+	.migrate_count = 0,						      \
 	.restart_block = {						      \
 		.fn = do_no_restart_syscall,				      \
 	},								      \
@@ -82,12 +84,14 @@
 #define TIF_POLLING_NRFLAG	3	/* true if poll_idle() is polling
 					   TIF_NEED_RESCHED */
 #define TIF_MEMDIE		4
+#define TIF_NEED_MIGRATE	5	/* migration necessary */
 
 /* as above, but as bit values */
 #define _TIF_SYSCALL_TRACE	(1<<TIF_SYSCALL_TRACE)
 #define _TIF_SIGPENDING		(1<<TIF_SIGPENDING)
 #define _TIF_NEED_RESCHED	(1<<TIF_NEED_RESCHED)
 #define _TIF_POLLING_NRFLAG	(1<<TIF_POLLING_NRFLAG)
+#define _TIF_NEED_MIGRATE	(1<<TIF_NEED_MIGRATE)
 
 
 /* Size of kernel stack for each process.  */
Index: linux-2.6-lttng/include/asm-x86_64/thread_info.h
===================================================================
--- linux-2.6-lttng.orig/include/asm-x86_64/thread_info.h	2007-07-10 02:29:10.000000000 -0400
+++ linux-2.6-lttng/include/asm-x86_64/thread_info.h	2007-07-11 00:43:03.000000000 -0400
@@ -30,6 +30,7 @@
 	__u32			status;		/* thread synchronous flags */
 	__u32			cpu;		/* current CPU */
 	int 			preempt_count;	/* 0 => preemptable, <0 => BUG */
+	int			migrate_count;/* 0: can migrate, <0 => BUG */
 
 	mm_segment_t		addr_limit;	
 	struct restart_block    restart_block;
@@ -48,6 +49,7 @@
 	.flags	       = 0,			\
 	.cpu	       = 0,			\
 	.preempt_count = 1,			\
+	.migrate_count = 0,			\
 	.addr_limit     = KERNEL_DS,		\
 	.restart_block = {			\
 		.fn = do_no_restart_syscall,	\
@@ -115,6 +117,7 @@
 #define TIF_SECCOMP		8	/* secure computing */
 #define TIF_RESTORE_SIGMASK	9	/* restore signal mask in do_signal */
 #define TIF_MCE_NOTIFY		10	/* notify userspace of an MCE */
+#define TIF_NEED_MIGRATE	11	/* migration necessary */
 /* 16 free */
 #define TIF_IA32		17	/* 32bit process */ 
 #define TIF_FORK		18	/* ret_from_fork */
@@ -133,6 +136,7 @@
 #define _TIF_SECCOMP		(1<<TIF_SECCOMP)
 #define _TIF_RESTORE_SIGMASK	(1<<TIF_RESTORE_SIGMASK)
 #define _TIF_MCE_NOTIFY		(1<<TIF_MCE_NOTIFY)
+#define _TIF_NEED_MIGRATE	(1<<TIF_NEED_MIGRATE)
 #define _TIF_IA32		(1<<TIF_IA32)
 #define _TIF_FORK		(1<<TIF_FORK)
 #define _TIF_ABI_PENDING	(1<<TIF_ABI_PENDING)
Index: linux-2.6-lttng/include/asm-xtensa/thread_info.h
===================================================================
--- linux-2.6-lttng.orig/include/asm-xtensa/thread_info.h	2007-07-10 02:29:10.000000000 -0400
+++ linux-2.6-lttng/include/asm-xtensa/thread_info.h	2007-07-11 00:43:03.000000000 -0400
@@ -34,6 +34,7 @@
 	unsigned long		status;		/* thread-synchronous flags */
 	__u32			cpu;		/* current CPU */
 	__s32			preempt_count;	/* 0 => preemptable,< 0 => BUG*/
+	__s32			migrate_count;/* 0: can migrate, <0 => BUG */
 
 	mm_segment_t		addr_limit;	/* thread address space */
 	struct restart_block    restart_block;
@@ -72,6 +73,7 @@
 	.flags		= 0,			\
 	.cpu		= 0,			\
 	.preempt_count	= 1,			\
+	.migrate_count = 0,			\
 	.addr_limit	= KERNEL_DS,		\
 	.restart_block = {			\
 		.fn = do_no_restart_syscall,	\
@@ -116,6 +118,7 @@
 #define TIF_IRET		4	/* return with iret */
 #define TIF_MEMDIE		5
 #define TIF_RESTORE_SIGMASK	6	/* restore signal mask in do_signal() */
+#define TIF_NEED_MIGRATE	7	/* migration necessary */
 #define TIF_POLLING_NRFLAG	16	/* true if poll_idle() is polling TIF_NEED_RESCHED */
 
 #define _TIF_SYSCALL_TRACE	(1<<TIF_SYSCALL_TRACE)
@@ -123,6 +126,7 @@
 #define _TIF_NEED_RESCHED	(1<<TIF_NEED_RESCHED)
 #define _TIF_SINGLESTEP		(1<<TIF_SINGLESTEP)
 #define _TIF_IRET		(1<<TIF_IRET)
+#define _TIF_NEED_MIGRATE	(1<<TIF_NEED_MIGRATE)
 #define _TIF_POLLING_NRFLAG	(1<<TIF_POLLING_NRFLAG)
 #define _TIF_RESTORE_SIGMASK	(1<<TIF_RESTORE_SIGMASK)
 
Index: linux-2.6-lttng/lib/smp_processor_id.c
===================================================================
--- linux-2.6-lttng.orig/lib/smp_processor_id.c	2007-07-10 02:29:10.000000000 -0400
+++ linux-2.6-lttng/lib/smp_processor_id.c	2007-07-11 00:43:03.000000000 -0400
@@ -10,12 +10,16 @@
 unsigned int debug_smp_processor_id(void)
 {
 	unsigned long preempt_count = preempt_count();
+	unsigned long migrate_count = migrate_count();
 	int this_cpu = raw_smp_processor_id();
 	cpumask_t this_mask;
 
 	if (likely(preempt_count))
 		goto out;
 
+	if (likely(migrate_count))
+		goto out;
+
 	if (irqs_disabled())
 		goto out;
 
@@ -42,7 +46,7 @@
 	if (!printk_ratelimit())
 		goto out_enable;
 
-	printk(KERN_ERR "BUG: using smp_processor_id() in preemptible [%08x] code: %s/%d\n", preempt_count(), current->comm, current->pid);
+	printk(KERN_ERR "BUG: using smp_processor_id() in preemptible [%08x] migration [%08x] code: %s/%d\n", preempt_count(), migrate_count(), current->comm, current->pid);
 	print_symbol("caller is %s\n", (long)__builtin_return_address(0));
 	dump_stack();
 

-- 
Mathieu Desnoyers
Computer Engineering Ph.D. Student, Ecole Polytechnique de Montreal
OpenPGP key fingerprint: 8CD5 52C3 8E3C 4140 715F  BA06 3F25 A8FE 3BAE 9A68

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

* Re: [RFC] Thread Migration Preemption
  2007-07-06 17:11     ` Andi Kleen
@ 2007-07-11  4:57       ` Mathieu Desnoyers
  0 siblings, 0 replies; 33+ messages in thread
From: Mathieu Desnoyers @ 2007-07-11  4:57 UTC (permalink / raw)
  To: Andi Kleen; +Cc: Steven Rostedt, Ingo Molnar, linux-kernel

* Andi Kleen (andi@firstfloor.org) wrote:
> On Fri, Jul 06, 2007 at 10:41:44AM -0400, Mathieu Desnoyers wrote:
> > I haven't thought about making it the default for kernel space
> > preemption, but yes, it would make sense.
> 
> Now it's too late -- getcpu() has infected the kernel everywhere.
> It would have made sense a few years ago.
> 
> 
> > ... getcpu()...
> 
> Hmm ok, although i suspect it's rare to assume that. But understood
> you don't want to audit all getcpu users because of this.
> 
> > using a short instead of an int on modern x86 will cause pipeline stalls
> > due to partial register use.
> 
> Sorry, that's totally bogus. Primarily because the access would be directly
> on memory and there is no partial register tracking there.
> 
> Besides pipeline stall is not the correct description on what would
> happen if you used a register, the worst you get is a single false dependency
> but no pipeline flush.
> 
> Besides the latest x86 cpus (C2, K8) don't have much trouble with these
> false dependencies in general.
> 

Yes, false dependency is what I meant. And hrm, yeah I guess that mostly
movzbl would be used to get the byte from memory and zero-extend, making
sure there is no false dependency.

> > usage, since it is followed by an unsigned long; gcc structure alignment
> 
> 
> > will put padding instead of the integer, which does not buy us anything
> 
> on i386 unsigned long is 4 bytes.
> 

Since we have, on i386:

        int                     preempt_count;  /* 0 => preemptable, <0 => BUG */
        int                     migrate_count;/* 0: can migrate, <0: BUG */
        mm_segment_t            addr_limit;     /* thread address space:

and:

typedef struct {
        unsigned long seg;
} mm_segment_t;

Turning migrate_count into a char would only put padding between
migrate_count and addr_limit. So I still do not see a clear improvement
in memory usage there... but I don't specially care about it being an
integer or a byte though :)

Mathieu


> -Andi

-- 
Mathieu Desnoyers
Computer Engineering Ph.D. Student, Ecole Polytechnique de Montreal
OpenPGP key fingerprint: 8CD5 52C3 8E3C 4140 715F  BA06 3F25 A8FE 3BAE 9A68

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

* Re: [RFC] Thread Migration Preemption - v2
  2007-07-11  4:49     ` [RFC] Thread Migration Preemption - v2 Mathieu Desnoyers
@ 2007-07-11 16:36       ` Oleg Nesterov
  2007-07-14 18:27         ` Mathieu Desnoyers
                           ` (2 more replies)
  0 siblings, 3 replies; 33+ messages in thread
From: Oleg Nesterov @ 2007-07-11 16:36 UTC (permalink / raw)
  To: Mathieu Desnoyers; +Cc: linux-kernel, Ingo Molnar, Steven Rostedt

On 07/11, Mathieu Desnoyers wrote:
> 
> This patch adds the ability to protect critical sections from migration to
> another CPU without disabling preemption.
> 
> This will be useful to minimize the amount of preemption disabling for the -rt
> patch. It will help leveraging improvements brought by the local_t types in
> asm/local.h (see Documentation/local_ops.txt). Note that the updates done to
> variables protected by migrate_disable must be either atomic or protected from
> concurrent updates done by other threads.
> 
> Typical use:
> 
> migrate_disable();
> local_inc(&__get_cpu_var(&my_local_t_var));
> migrate_enable();
> 
> Which will increment the variable atomically wrt the local CPU.

Well, I am not a maintainer, but I personally think this patch is too complex.

Mathieu, please use "diff -p", it is very difficult to read it. I am not sure
I understand this patch correctly, I don't have a -git tree.

>  static int __migrate_task(struct task_struct *p, int src_cpu, int dest_cpu)
>  {
> @@ -4829,13 +4888,19 @@
>  
>  	double_rq_lock(rq_src, rq_dest);
>  	/* Already moved. */
> -	if (task_cpu(p) != src_cpu)
> +	if (task_cpu(p) != src_cpu) {
> +		ret = 1;
>  		goto out;
> +	}

This is a strange change. Why we return success when migration failed ?
OK, I guess this is a special hack for the modified migration_thread()...

>  	/* Affinity changed (again). */
>  	if (!cpu_isset(dest_cpu, p->cpus_allowed))
>  		goto out;
>  
>  	on_rq = p->se.on_rq;
> +#ifdef CONFIG_PREEMPT
> +	if (!on_rq && task_thread_info(p)->migrate_count)
> +		goto out;
> +#endif

This means that move_task_off_dead_cpu() will spin until the task will be scheduled
on the dead CPU. Given that we hold tasklist_lock and irqs are disabled, this may
never happen.

(This patch adds a lot of #ifdef's, I think it could be simplified if you add
 get_migrate_count() which is defined as 0 when !CONFIG_PREEMPT).

> @@ -4891,10 +4957,22 @@
>  		list_del_init(head->next);
>  
>  		spin_unlock(&rq->lock);
> -		__migrate_task(req->task, cpu, req->dest_cpu);
> +		migrated = __migrate_task(req->task, cpu, req->dest_cpu);
>  		local_irq_enable();
> -
> -		complete(&req->done);
> +		if (!migrated) {
> +			/*
> +			 * If the process has not been migrated, let it run
> +			 * until it reaches a migration_check() so it can
> +			 * wake us up.
> +			 */
> +			spin_lock_irq(&rq->lock);
> +			head = &rq->migration_queue;
> +			list_add(&req->list, head);
> +			set_tsk_thread_flag(req->task, TIF_NEED_MIGRATE);
> +			spin_unlock_irq(&rq->lock);
> +			wake_up_process(req->task);
> +		} else
> +			complete(&req->done);

I guess this is migration_thread(). The wake_up_process(req->task) looks strange,
why? It can't help if the task waits for the event/mutex.

And this is racy. What if check_migrate() is in progress, and the task has already
checked TIF_NEED_MIGRATE?

Hm. We re-add "req" to rq->migration_queue. This means that migration_thread() will
do a busy-wait loop. Not good and deadlockable, migration/X is SCHED_FIFO.
And what if __migrate_task() failed because ->cpus_allowed was changed in between?

Oleg.


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

* Re: [RFC] Thread Migration Preemption - v2
  2007-07-11 16:36       ` Oleg Nesterov
@ 2007-07-14 18:27         ` Mathieu Desnoyers
  2007-07-14 19:56           ` Oleg Nesterov
  2007-07-14 18:40         ` [RFC] Thread Migration Preemption - v3 Mathieu Desnoyers
  2007-07-14 18:42         ` [RFC] Thread Migration Preemption - v4 Mathieu Desnoyers
  2 siblings, 1 reply; 33+ messages in thread
From: Mathieu Desnoyers @ 2007-07-14 18:27 UTC (permalink / raw)
  To: Oleg Nesterov; +Cc: linux-kernel, Ingo Molnar, Steven Rostedt

* Oleg Nesterov (oleg@tv-sign.ru) wrote:
> On 07/11, Mathieu Desnoyers wrote:
> > 
> > This patch adds the ability to protect critical sections from migration to
> > another CPU without disabling preemption.
> > 
> > This will be useful to minimize the amount of preemption disabling for the -rt
> > patch. It will help leveraging improvements brought by the local_t types in
> > asm/local.h (see Documentation/local_ops.txt). Note that the updates done to
> > variables protected by migrate_disable must be either atomic or protected from
> > concurrent updates done by other threads.
> > 
> > Typical use:
> > 
> > migrate_disable();
> > local_inc(&__get_cpu_var(&my_local_t_var));
> > migrate_enable();
> > 
> > Which will increment the variable atomically wrt the local CPU.
> 
> Well, I am not a maintainer, but I personally think this patch is too complex.
> 
> Mathieu, please use "diff -p", it is very difficult to read it. I am not sure
> I understand this patch correctly, I don't have a -git tree.
> 

man quilt... echo "QUILT_DIFF_OPTS="-p" > ~/.quiltrc. done. :) Thanks
for pointing this out, the next patches should include this.


> >  static int __migrate_task(struct task_struct *p, int src_cpu, int dest_cpu)
> >  {
> > @@ -4829,13 +4888,19 @@
> >  
> >  	double_rq_lock(rq_src, rq_dest);
> >  	/* Already moved. */
> > -	if (task_cpu(p) != src_cpu)
> > +	if (task_cpu(p) != src_cpu) {
> > +		ret = 1;
> >  		goto out;
> > +	}
> 
> This is a strange change. Why we return success when migration failed ?
> OK, I guess this is a special hack for the modified migration_thread()...
> 

Yes, I wanted to change __migrate_task so it returns true if, after it
has been called to migrate a task out of a source CPU, the task is
indeed now migrated out the this CPU.

It follows a comment already at the beginning of this function:

  * So we race with normal scheduler movements, but that's OK, as long
  * as the task is no longer on this CPU.

The comment at the beginning explains the new convention:

- * Returns non-zero if task was successfully migrated.
+ * Returns non-zero if task is on dest_cpu when this function ends.

Well.. my comment is not perfect. It should read:

- * Returns non-zero if task was successfully migrated.
+ * Returns non-zero if task is not on src_cpu when this function ends.

My assumption is that if migrate_task races with the scheduler movement
to move a task out of a CPU, it should return non-zero in every case
when the task has been migrated out of the src_cpu.


> >  	/* Affinity changed (again). */
> >  	if (!cpu_isset(dest_cpu, p->cpus_allowed))
> >  		goto out;
> >  
> >  	on_rq = p->se.on_rq;
> > +#ifdef CONFIG_PREEMPT
> > +	if (!on_rq && task_thread_info(p)->migrate_count)
> > +		goto out;
> > +#endif
> 
> This means that move_task_off_dead_cpu() will spin until the task will be scheduled
> on the dead CPU. Given that we hold tasklist_lock and irqs are disabled, this may
> never happen.
> 

Yes. My idea to fix this issue is the following:

If a thread has non zero migrate_count, we should still move it to a
different CPU upon hotplug cpu removal, even if this thread resists
migration. Care should be taken to send _all_ such threads to the _same_
CPU so they don't race for the per-cpu ressources. Does it make sense ?

We would have to keep the CPU affinity of the threads running on the
wrong CPU until they end their migrate disabled section, so that we can
put them back on their original CPU if it goes back online, otherwise we
could end up with concurrent per-cpu variables accesses.

(I'll wait for reply before coding a solution for this CPU HOTPLUG
related problem)

> (This patch adds a lot of #ifdef's, I think it could be simplified if you add
>  get_migrate_count() which is defined as 0 when !CONFIG_PREEMPT).

Sure. Added migrate_count() and task_migrate_count(task).

> 
> > @@ -4891,10 +4957,22 @@
> >  		list_del_init(head->next);
> >  
> >  		spin_unlock(&rq->lock);
> > -		__migrate_task(req->task, cpu, req->dest_cpu);
> > +		migrated = __migrate_task(req->task, cpu, req->dest_cpu);
> >  		local_irq_enable();
> > -
> > -		complete(&req->done);
> > +		if (!migrated) {
> > +			/*
> > +			 * If the process has not been migrated, let it run
> > +			 * until it reaches a migration_check() so it can
> > +			 * wake us up.
> > +			 */
> > +			spin_lock_irq(&rq->lock);
> > +			head = &rq->migration_queue;
> > +			list_add(&req->list, head);
> > +			set_tsk_thread_flag(req->task, TIF_NEED_MIGRATE);
> > +			spin_unlock_irq(&rq->lock);
> > +			wake_up_process(req->task);
> > +		} else
> > +			complete(&req->done);
> 
> I guess this is migration_thread(). The wake_up_process(req->task) looks strange,
> why? It can't help if the task waits for the event/mutex.
> 

Hrm, the idea was to wake up the thread that is in the migrate disabled
section, which is what I seem to do req->task points to the process we
try to migrate. We poke it like this until is ends its critical
section. At that moment, the thread will wake up the migration thread,
and only then do we let sched_migrate_task, which is waiting for
completion, finish.

> And this is racy. What if check_migrate() is in progress, and the task has already
> checked TIF_NEED_MIGRATE?
> 

The idea is to take the rq->lock to make sure the thread is not running
when we do this. Since the runqueue lock is released between the tests
in __migrate_task and this code, I should test again to see if it is
running. Currently, the migration thread retries actively if the thread
we are trying to migrate is in its critical section. The change I am
about to do does 2 things:

If the thread is on the runqueue, retry actively.
If the thread is not on the runqueue, set the NEED MIGRATE flag and go
to sleep, waiting for it to wake us up.

> Hm. We re-add "req" to rq->migration_queue. This means that migration_thread() will
> do a busy-wait loop. Not good and deadlockable, migration/X is SCHED_FIFO.

Yup. The comment above should hopefully fix it.

> And what if __migrate_task() failed because ->cpus_allowed was changed in between?
> 

Right, we should check for this. Will fix.

Thanks for the thorough review.

Mathieu

> Oleg.
> 

-- 
Mathieu Desnoyers
Computer Engineering Ph.D. Student, Ecole Polytechnique de Montreal
OpenPGP key fingerprint: 8CD5 52C3 8E3C 4140 715F  BA06 3F25 A8FE 3BAE 9A68

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

* [RFC] Thread Migration Preemption - v3
  2007-07-11 16:36       ` Oleg Nesterov
  2007-07-14 18:27         ` Mathieu Desnoyers
@ 2007-07-14 18:40         ` Mathieu Desnoyers
  2007-07-14 18:42         ` [RFC] Thread Migration Preemption - v4 Mathieu Desnoyers
  2 siblings, 0 replies; 33+ messages in thread
From: Mathieu Desnoyers @ 2007-07-14 18:40 UTC (permalink / raw)
  To: Oleg Nesterov; +Cc: linux-kernel, Ingo Molnar, Steven Rostedt

Thread Migration Preemption

This patch adds the ability to protect critical sections from migration to
another CPU without disabling preemption.

This will be useful to minimize the amount of preemption disabling for the -rt
patch. It will help leveraging improvements brought by the local_t types in
asm/local.h (see Documentation/local_ops.txt). Note that the updates done to
variables protected by migrate_disable must be either atomic or protected from
concurrent updates done by other threads.

Typical use:

migrate_disable();
local_inc(&__get_cpu_var(&my_local_t_var));
migrate_enable();

Which will increment the variable atomically wrt the local CPU.

Changes:

Do a check_migrate() upon migrate_enable() to answer to the migration
thread waiting for us to exit the migration disabled critical section. Use a
NEED_MIGRATE thread flag for this.

Note: (or we could say FIXME)
Is we ever want to check migration pending in assembly code, we will have to
make sure we test the right thread flag bits on each architectures. Care should
also be taken to check that the thread flags used won't trigger false positives
in non selective asm thread flag checks.

FIXME (HOTPLUG) :

> >     /* Affinity changed (again). */
> >     if (!cpu_isset(dest_cpu, p->cpus_allowed))
> >             goto out;
> >  
> >     on_rq = p->se.on_rq;
> > +#ifdef CONFIG_PREEMPT
> > +   if (!on_rq && task_thread_info(p)->migrate_count)
> > +           goto out;
> > +#endif
> 
> This means that move_task_off_dead_cpu() will spin until the task will be
> scheduled
> on the dead CPU. Given that we hold tasklist_lock and irqs are disabled, this
> may
> never happen.
>

Yes. My idea to fix this issue is the following:

If a thread has non zero migrate_count, we should still move it to a
different CPU upon hotplug cpu removal, even if this thread resists
migration. Care should be taken to send _all_ such threads to the _same_
CPU so they don't race for the per-cpu ressources. Does it make sense ?

We would have to keep the CPU affinity of the threads running on the
wrong CPU until they end their migrate disabled section, so that we can
put them back on their original CPU if it goes back online, otherwise we
could end up with concurrent per-cpu variables accesses.

(I'll wait for reply before coding a solution for this CPU HOTPLUG
related problem)


Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@polymtl.ca>
---
 include/asm-alpha/thread_info.h     |    3 +
 include/asm-arm/thread_info.h       |    5 +
 include/asm-arm26/thread_info.h     |    5 +
 include/asm-avr32/thread_info.h     |    4 +
 include/asm-blackfin/thread_info.h  |    4 +
 include/asm-cris/thread_info.h      |    4 +
 include/asm-frv/thread_info.h       |    4 +
 include/asm-h8300/thread_info.h     |    4 +
 include/asm-i386/thread_info.h      |    6 +-
 include/asm-ia64/thread_info.h      |    4 +
 include/asm-m32r/thread_info.h      |    4 +
 include/asm-m68k/thread_info.h      |    2 
 include/asm-m68knommu/thread_info.h |    3 +
 include/asm-mips/thread_info.h      |    4 +
 include/asm-parisc/thread_info.h    |    4 +
 include/asm-powerpc/thread_info.h   |    4 +
 include/asm-s390/thread_info.h      |    4 +
 include/asm-sh/thread_info.h        |    4 +
 include/asm-sh64/thread_info.h      |    4 +
 include/asm-sparc/thread_info.h     |    4 +
 include/asm-sparc64/thread_info.h   |    5 +
 include/asm-um/thread_info.h        |    4 +
 include/asm-v850/thread_info.h      |    4 +
 include/asm-x86_64/thread_info.h    |    4 +
 include/asm-xtensa/thread_info.h    |    4 +
 include/linux/preempt.h             |   47 ++++++++++++++++-
 kernel/sched.c                      |   98 +++++++++++++++++++++++++++++++++---
 lib/smp_processor_id.c              |    6 +-
 28 files changed, 240 insertions(+), 12 deletions(-)

Index: linux-2.6-lttng/include/asm-i386/thread_info.h
===================================================================
--- linux-2.6-lttng.orig/include/asm-i386/thread_info.h	2007-07-13 14:18:26.000000000 -0400
+++ linux-2.6-lttng/include/asm-i386/thread_info.h	2007-07-14 13:20:12.000000000 -0400
@@ -31,8 +31,7 @@ struct thread_info {
 	unsigned long		status;		/* thread-synchronous flags */
 	__u32			cpu;		/* current CPU */
 	int			preempt_count;	/* 0 => preemptable, <0 => BUG */
-
-
+	int			migrate_count;/* 0: can migrate, <0: BUG */
 	mm_segment_t		addr_limit;	/* thread address space:
 					 	   0-0xBFFFFFFF for user-thead
 						   0-0xFFFFFFFF for kernel-thread
@@ -74,6 +73,7 @@ struct thread_info {
 	.flags		= 0,			\
 	.cpu		= 0,			\
 	.preempt_count	= 1,			\
+	.migrate_count = 0,			\
 	.addr_limit	= KERNEL_DS,		\
 	.restart_block = {			\
 		.fn = do_no_restart_syscall,	\
@@ -132,6 +132,7 @@ static inline struct thread_info *curren
 #define TIF_SYSCALL_AUDIT	6	/* syscall auditing active */
 #define TIF_SECCOMP		7	/* secure computing */
 #define TIF_RESTORE_SIGMASK	8	/* restore signal mask in do_signal() */
+#define TIF_NEED_MIGRATE	9	/* migration necessary */
 #define TIF_MEMDIE		16
 #define TIF_DEBUG		17	/* uses debug registers */
 #define TIF_IO_BITMAP		18	/* uses I/O bitmap */
@@ -147,6 +148,7 @@ static inline struct thread_info *curren
 #define _TIF_SYSCALL_AUDIT	(1<<TIF_SYSCALL_AUDIT)
 #define _TIF_SECCOMP		(1<<TIF_SECCOMP)
 #define _TIF_RESTORE_SIGMASK	(1<<TIF_RESTORE_SIGMASK)
+#define _TIF_NEED_MIGRATE	(1<<TIF_NEED_MIGRATE)
 #define _TIF_DEBUG		(1<<TIF_DEBUG)
 #define _TIF_IO_BITMAP		(1<<TIF_IO_BITMAP)
 #define _TIF_FREEZE		(1<<TIF_FREEZE)
Index: linux-2.6-lttng/include/linux/preempt.h
===================================================================
--- linux-2.6-lttng.orig/include/linux/preempt.h	2007-07-13 14:18:26.000000000 -0400
+++ linux-2.6-lttng/include/linux/preempt.h	2007-07-14 13:45:10.000000000 -0400
@@ -12,15 +12,22 @@
 #ifdef CONFIG_DEBUG_PREEMPT
   extern void fastcall add_preempt_count(int val);
   extern void fastcall sub_preempt_count(int val);
+  extern void fastcall add_migrate_count(int val);
+  extern void fastcall sub_migrate_count(int val);
 #else
 # define add_preempt_count(val)	do { preempt_count() += (val); } while (0)
 # define sub_preempt_count(val)	do { preempt_count() -= (val); } while (0)
+# define add_migrate_count(val) do { migrate_count() += (val); } while (0)
+# define sub_migrate_count(val) do { migrate_count() -= (val); } while (0)
 #endif
 
 #define inc_preempt_count() add_preempt_count(1)
 #define dec_preempt_count() sub_preempt_count(1)
 
-#define preempt_count()	(current_thread_info()->preempt_count)
+#define preempt_count() (current_thread_info()->preempt_count)
+
+#define inc_migrate_count() add_migrate_count(1)
+#define dec_migrate_count() sub_migrate_count(1)
 
 #ifdef CONFIG_PREEMPT
 
@@ -51,6 +58,38 @@ do { \
 	preempt_check_resched(); \
 } while (0)
 
+#define migrate_count()			(current_thread_info()->migrate_count)
+#define task_migrate_count(task)	(task_thread_info(task)->migrate_count)
+
+#define migrate_disable() \
+do { \
+	inc_migrate_count(); \
+	barrier(); \
+} while (0)
+
+#define migrate_enable_no_check() \
+do { \
+	barrier(); \
+	dec_migrate_count(); \
+} while (0)
+
+#ifdef CONFIG_SMP
+#define check_migrate() \
+do { \
+	if (unlikely(test_thread_flag(TIF_NEED_MIGRATE))) \
+		do_check_migrate(); \
+} while (0)
+#else
+#define check_migrate()
+#endif
+
+#define migrate_enable() \
+do { \
+	migrate_enable_no_check(); \
+	barrier(); \
+	check_migrate(); \
+} while (0)
+
 #else
 
 #define preempt_disable()		do { } while (0)
@@ -58,6 +97,12 @@ do { \
 #define preempt_enable()		do { } while (0)
 #define preempt_check_resched()		do { } while (0)
 
+#define migrate_count()					0
+#define task_migrate_count(task)			0
+
+#define migrate_disable()		do { } while (0)
+#define migrate_enable()		do { } while (0)
+
 #endif
 
 #endif /* __LINUX_PREEMPT_H */
Index: linux-2.6-lttng/kernel/sched.c
===================================================================
--- linux-2.6-lttng.orig/kernel/sched.c	2007-07-14 13:20:11.000000000 -0400
+++ linux-2.6-lttng/kernel/sched.c	2007-07-14 14:18:07.000000000 -0400
@@ -946,7 +946,7 @@ migrate_task(struct task_struct *p, int 
 	 * If the task is not on a runqueue (and not running), then
 	 * it is sufficient to simply update the task's cpu field.
 	 */
-	if (!p->se.on_rq && !task_running(rq, p)) {
+	if (!p->se.on_rq && !task_running(rq, p) && !task_migrate_count(p)) {
 		set_task_cpu(p, dest_cpu);
 		return 0;
 	}
@@ -1347,7 +1347,8 @@ static int try_to_wake_up(struct task_st
 #ifdef CONFIG_SMP
 	if (unlikely(task_running(rq, p)))
 		goto out_activate;
-
+	if (task_migrate_count(p))
+		goto out_activate;
 	new_cpu = cpu;
 
 	schedstat_inc(rq, ttwu_cnt);
@@ -1534,6 +1535,7 @@ void sched_fork(struct task_struct *p, i
 #ifdef CONFIG_PREEMPT
 	/* Want to start with kernel preemption disabled. */
 	task_thread_info(p)->preempt_count = 1;
+	task_thread_info(p)->migrate_count = 0;
 #endif
 	put_cpu();
 }
@@ -1933,6 +1935,8 @@ static void sched_migrate_task(struct ta
 	if (!cpu_isset(dest_cpu, p->cpus_allowed)
 	    || unlikely(cpu_is_offline(dest_cpu)))
 		goto out;
+	if (task_migrate_count(p))
+		goto out;
 
 	trace_mark(kernel_sched_migrate_task, "%d %ld %d",
 		p->pid, p->state, dest_cpu);
@@ -1996,6 +2000,7 @@ int can_migrate_task(struct task_struct 
 	 * 1) running (obviously), or
 	 * 2) cannot be migrated to this CPU due to cpus_allowed, or
 	 * 3) are cache-hot on their current CPU.
+	 * 4) migration preemption is non 0 for this non running task.
 	 */
 	if (!cpu_isset(this_cpu, p->cpus_allowed))
 		return 0;
@@ -2003,6 +2008,8 @@ int can_migrate_task(struct task_struct 
 
 	if (task_running(rq, p))
 		return 0;
+	if (task_migrate_count(p))
+		return 0;
 
 	/*
 	 * Aggressive migration if too many balance attempts have failed:
@@ -3220,6 +3227,29 @@ void fastcall sub_preempt_count(int val)
 }
 EXPORT_SYMBOL(sub_preempt_count);
 
+void fastcall add_migrate_count(int val)
+{
+	/*
+	 * Underflow?
+	 */
+	if (DEBUG_LOCKS_WARN_ON((migrate_count() < 0)))
+		return;
+	migrate_count() += val;
+}
+EXPORT_SYMBOL(add_migrate_count);
+
+void fastcall sub_migrate_count(int val)
+{
+	/*
+	 * Underflow?
+	 */
+	if (DEBUG_LOCKS_WARN_ON(val > migrate_count()))
+		return;
+
+	migrate_count() -= val;
+}
+EXPORT_SYMBOL(sub_migrate_count);
+
 #endif
 
 /*
@@ -3353,6 +3383,28 @@ need_resched_nonpreemptible:
 EXPORT_SYMBOL(schedule);
 
 #ifdef CONFIG_PREEMPT
+
+#ifdef CONFIG_SMP
+/*
+ * Wake up the migration thread to deal with our pending migration.
+ * If we have been moved since, we will just wake up the migration thread from
+ * the wrong CPU, which does not hurt anyone. (that's why we use
+ * raw_smp_processor_id()).
+ */
+void __sched do_check_migrate(void)
+{
+	struct rq *rq;
+
+	if (migrate_count())
+		return;
+
+	clear_thread_flag(TIF_NEED_MIGRATE);
+	rq = cpu_rq(raw_smp_processor_id());
+	wake_up_process(rq->migration_thread);
+}
+EXPORT_SYMBOL(do_check_migrate);
+#endif
+
 /*
  * this is the entry point to schedule() from in-kernel preemption
  * off of preempt_enable.  Kernel preemptions off return from interrupt
@@ -4814,7 +4866,7 @@ EXPORT_SYMBOL_GPL(set_cpus_allowed);
  * So we race with normal scheduler movements, but that's OK, as long
  * as the task is no longer on this CPU.
  *
- * Returns non-zero if task was successfully migrated.
+ * Returns non-zero if task is not on src_cpu when this function ends.
  */
 static int __migrate_task(struct task_struct *p, int src_cpu, int dest_cpu)
 {
@@ -4829,13 +4881,17 @@ static int __migrate_task(struct task_st
 
 	double_rq_lock(rq_src, rq_dest);
 	/* Already moved. */
-	if (task_cpu(p) != src_cpu)
+	if (task_cpu(p) != src_cpu) {
+		ret = 1;
 		goto out;
+	}
 	/* Affinity changed (again). */
 	if (!cpu_isset(dest_cpu, p->cpus_allowed))
 		goto out;
 
 	on_rq = p->se.on_rq;
+	if (!on_rq && task_migrate_count(p))
+		goto out;
 	if (on_rq)
 		deactivate_task(rq_src, p, 0);
 	set_task_cpu(p, dest_cpu);
@@ -4858,6 +4914,7 @@ static int migration_thread(void *data)
 {
 	int cpu = (long)data;
 	struct rq *rq;
+	int migrated;
 
 	rq = cpu_rq(cpu);
 	BUG_ON(rq->migration_thread != current);
@@ -4891,10 +4948,37 @@ static int migration_thread(void *data)
 		list_del_init(head->next);
 
 		spin_unlock(&rq->lock);
-		__migrate_task(req->task, cpu, req->dest_cpu);
+		migrated = __migrate_task(req->task, cpu, req->dest_cpu);
 		local_irq_enable();
-
-		complete(&req->done);
+		if (!migrated) {
+			/*
+			 * If the process has not been migrated, let it run
+			 * until it reaches a migration_check() so it can
+			 * wake us up.
+			 */
+			spin_lock_irq(&rq->lock);
+			head = &rq->migration_queue;
+			list_add(&req->list, head);
+			if (p->se.on_rq) {
+				/*
+				 * The process is on the runqueue, it could
+				 * exit its critical section at any moment,
+				 * don't race with it and retry actively.
+				 */
+				spin_unlock_irq(&rq->lock);
+				continue;
+			}
+			set_tsk_thread_flag(req->task, TIF_NEED_MIGRATE);
+			set_current_state(TASK_INTERRUPTIBLE);
+			spin_unlock_irq(&rq->lock);
+			/*
+			 * Wait for the process currently in its critical
+			 * section.
+			 */
+			wake_up_process(req->task);
+			schedule();
+		} else
+			complete(&req->done);
 	}
 	__set_current_state(TASK_RUNNING);
 	return 0;
Index: linux-2.6-lttng/include/asm-alpha/thread_info.h
===================================================================
--- linux-2.6-lttng.orig/include/asm-alpha/thread_info.h	2007-07-14 13:20:11.000000000 -0400
+++ linux-2.6-lttng/include/asm-alpha/thread_info.h	2007-07-14 13:20:12.000000000 -0400
@@ -21,6 +21,7 @@ struct thread_info {
 	mm_segment_t		addr_limit;	/* thread address space */
 	unsigned		cpu;		/* current CPU */
 	int			preempt_count; /* 0 => preemptable, <0 => BUG */
+	int			migrate_count;/* 0: can migrate, <0 => BUG */
 
 	int bpt_nsaved;
 	unsigned long bpt_addr[2];		/* breakpoint handling  */
@@ -77,6 +78,7 @@ register struct thread_info *__current_t
 #define TIF_MEMDIE		8
 #define TIF_RESTORE_SIGMASK	9	/* restore signal mask in do_signal */
 #define	TIF_SYSCALL_AUDIT	10
+#define TIF_NEED_MIGRATE	11	/* migration necessary */
 
 #define _TIF_SYSCALL_TRACE	(1<<TIF_SYSCALL_TRACE)
 #define _TIF_SIGPENDING		(1<<TIF_SIGPENDING)
@@ -84,6 +86,7 @@ register struct thread_info *__current_t
 #define _TIF_POLLING_NRFLAG	(1<<TIF_POLLING_NRFLAG)
 #define _TIF_RESTORE_SIGMASK	(1<<TIF_RESTORE_SIGMASK)
 #define _TIF_SYSCALL_AUDIT	(1<<TIF_SYSCALL_AUDIT)
+#define _TIF_NEED_MIGRATE	(1<<TIF_NEED_MIGRATE)
 
 /* Work to do on interrupt/exception return.  */
 #define _TIF_WORK_MASK		(_TIF_SIGPENDING | _TIF_NEED_RESCHED)
Index: linux-2.6-lttng/include/asm-arm/thread_info.h
===================================================================
--- linux-2.6-lttng.orig/include/asm-arm/thread_info.h	2007-07-14 13:20:10.000000000 -0400
+++ linux-2.6-lttng/include/asm-arm/thread_info.h	2007-07-14 13:20:12.000000000 -0400
@@ -51,6 +51,7 @@ struct cpu_context_save {
 struct thread_info {
 	unsigned long		flags;		/* low level flags */
 	int			preempt_count;	/* 0 => preemptable, <0 => bug */
+	int			migrate_count;/* 0: can migrate, <0 => BUG */
 	mm_segment_t		addr_limit;	/* address limit */
 	struct task_struct	*task;		/* main task structure */
 	struct exec_domain	*exec_domain;	/* execution domain */
@@ -72,6 +73,7 @@ struct thread_info {
 	.exec_domain	= &default_exec_domain,				\
 	.flags		= 0,						\
 	.preempt_count	= 1,						\
+	.migrate_count = 0,						\
 	.addr_limit	= KERNEL_DS,					\
 	.cpu_domain	= domain_val(DOMAIN_USER, DOMAIN_MANAGER) |	\
 			  domain_val(DOMAIN_KERNEL, DOMAIN_MANAGER) |	\
@@ -137,12 +139,14 @@ extern void iwmmxt_task_switch(struct th
  *  TIF_SYSCALL_TRACE	- syscall trace active
  *  TIF_SIGPENDING	- signal pending
  *  TIF_NEED_RESCHED	- rescheduling necessary
+ *  TIF_NEED_MIGRATE	- migration necessary
  *  TIF_USEDFPU		- FPU was used by this task this quantum (SMP)
  *  TIF_POLLING_NRFLAG	- true if poll_idle() is polling TIF_NEED_RESCHED
  *  TIF_SYSCALL_AUDIT	- Syscall audting active - LTTng
  */
 #define TIF_SIGPENDING		0
 #define TIF_NEED_RESCHED	1
+#define TIF_NEED_MIGRATE	2
 #define	TIF_SYSCALL_AUDIT	7
 #define TIF_SYSCALL_TRACE	8
 #define TIF_POLLING_NRFLAG	16
@@ -152,6 +156,7 @@ extern void iwmmxt_task_switch(struct th
 
 #define _TIF_SIGPENDING		(1 << TIF_SIGPENDING)
 #define _TIF_NEED_RESCHED	(1 << TIF_NEED_RESCHED)
+#define _TIF_NEED_MIGRATE	(1 << TIF_NEED_MIGRATE)
 #define _TIF_SYSCALL_TRACE	(1 << TIF_SYSCALL_TRACE)
 #define	_TIF_SYSCALL_AUDIT	(1 << TIF_SYSCALL_AUDIT)
 #define _TIF_POLLING_NRFLAG	(1 << TIF_POLLING_NRFLAG)
Index: linux-2.6-lttng/include/asm-arm26/thread_info.h
===================================================================
--- linux-2.6-lttng.orig/include/asm-arm26/thread_info.h	2007-07-13 14:18:26.000000000 -0400
+++ linux-2.6-lttng/include/asm-arm26/thread_info.h	2007-07-14 13:20:12.000000000 -0400
@@ -45,6 +45,7 @@ struct cpu_context_save {
 struct thread_info {
 	unsigned long		flags;		/* low level flags */
 	int			preempt_count;	/* 0 => preemptable, <0 => bug */
+	int			migrate_count;/* 0: can migrate, <0 => BUG */
 	mm_segment_t		addr_limit;	/* address limit */
 	struct task_struct	*task;		/* main task structure */
 	struct exec_domain      *exec_domain;   /* execution domain */
@@ -60,6 +61,7 @@ struct thread_info {
 	.exec_domain	&default_exec_domain,	\
 	.flags		0,			\
 	.preempt_count	0,			\
+	.migrate_count 0,			\
 	.addr_limit	KERNEL_DS,		\
 	.restart_block  = {                             \
 		.fn     = do_no_restart_syscall,        \
@@ -112,11 +114,13 @@ extern void free_thread_info(struct thre
  *  TIF_SYSCALL_TRACE	- syscall trace active
  *  TIF_SIGPENDING	- signal pending
  *  TIF_NEED_RESCHED	- rescheduling necessary
+ *  TIF_NEED_MIGRATE	- migration necessary
  *  TIF_USEDFPU		- FPU was used by this task this quantum (SMP)
  *  TIF_POLLING_NRFLAG	- true if poll_idle() is polling TIF_NEED_RESCHED
  */
 #define TIF_SIGPENDING		0
 #define TIF_NEED_RESCHED	1
+#define TIF_NEED_MIGRATE	2
 #define TIF_SYSCALL_TRACE	8
 #define TIF_USED_FPU		16
 #define TIF_POLLING_NRFLAG	17
@@ -124,6 +128,7 @@ extern void free_thread_info(struct thre
 
 #define _TIF_SIGPENDING		(1 << TIF_SIGPENDING)
 #define _TIF_NEED_RESCHED	(1 << TIF_NEED_RESCHED)
+#define _TIF_NEED_MIGRATE	(1 << TIF_NEED_MIGRATE)
 #define _TIF_SYSCALL_TRACE	(1 << TIF_SYSCALL_TRACE)
 #define _TIF_USED_FPU		(1 << TIF_USED_FPU)
 #define _TIF_POLLING_NRFLAG	(1 << TIF_POLLING_NRFLAG)
Index: linux-2.6-lttng/include/asm-avr32/thread_info.h
===================================================================
--- linux-2.6-lttng.orig/include/asm-avr32/thread_info.h	2007-07-13 14:18:26.000000000 -0400
+++ linux-2.6-lttng/include/asm-avr32/thread_info.h	2007-07-14 13:20:12.000000000 -0400
@@ -25,6 +25,7 @@ struct thread_info {
 	unsigned long		flags;		/* low level flags */
 	__u32			cpu;
 	__s32			preempt_count;	/* 0 => preemptable, <0 => BUG */
+	int			migrate_count;/* 0: can migrate, <0 => BUG */
 	struct restart_block	restart_block;
 	__u8			supervisor_stack[0];
 };
@@ -36,6 +37,7 @@ struct thread_info {
 	.flags		= 0,						\
 	.cpu		= 0,						\
 	.preempt_count	= 1,						\
+	.migrate_count = 0,						\
 	.restart_block	= {						\
 		.fn	= do_no_restart_syscall				\
 	}								\
@@ -83,6 +85,7 @@ static inline struct thread_info *curren
 #define TIF_MEMDIE		6
 #define TIF_RESTORE_SIGMASK	7	/* restore signal mask in do_signal */
 #define TIF_CPU_GOING_TO_SLEEP	8	/* CPU is entering sleep 0 mode */
+#define TIF_NEED_MIGRATE      9       /* migration necessary */
 #define TIF_USERSPACE		31      /* true if FS sets userspace */
 
 #define _TIF_SYSCALL_TRACE	(1 << TIF_SYSCALL_TRACE)
@@ -94,6 +97,7 @@ static inline struct thread_info *curren
 #define _TIF_MEMDIE		(1 << TIF_MEMDIE)
 #define _TIF_RESTORE_SIGMASK	(1 << TIF_RESTORE_SIGMASK)
 #define _TIF_CPU_GOING_TO_SLEEP (1 << TIF_CPU_GOING_TO_SLEEP)
+#define _TIF_NEED_MIGRATE	(1 << TIF_NEED_MIGRATE)
 
 /* XXX: These two masks must never span more than 16 bits! */
 /* work to do on interrupt/exception return */
Index: linux-2.6-lttng/include/asm-blackfin/thread_info.h
===================================================================
--- linux-2.6-lttng.orig/include/asm-blackfin/thread_info.h	2007-07-13 14:18:26.000000000 -0400
+++ linux-2.6-lttng/include/asm-blackfin/thread_info.h	2007-07-14 13:20:12.000000000 -0400
@@ -54,6 +54,7 @@ struct thread_info {
 	unsigned long flags;	/* low level flags */
 	int cpu;		/* cpu we're on */
 	int preempt_count;	/* 0 => preemptable, <0 => BUG */
+	int migrate_count;	/* 0: can migrate, <0 => BUG */
 	mm_segment_t addr_limit;	/* address limit */
 	struct restart_block restart_block;
 	struct l1_scratch_task_info l1_task_info;
@@ -69,6 +70,7 @@ struct thread_info {
 	.flags		= 0,			\
 	.cpu		= 0,			\
 	.preempt_count  = 1,                    \
+	.migrate_count = 0,			\
 	.restart_block	= {			\
 		.fn = do_no_restart_syscall,	\
 	},					\
@@ -125,6 +127,7 @@ static inline struct thread_info *curren
 #define TIF_MEMDIE              4
 #define TIF_RESTORE_SIGMASK	5	/* restore signal mask in do_signal() */
 #define TIF_FREEZE              6       /* is freezing for suspend */
+#define TIF_NEED_MIGRATE	7	/* migration necessary */
 
 /* as above, but as bit values */
 #define _TIF_SYSCALL_TRACE	(1<<TIF_SYSCALL_TRACE)
@@ -133,6 +136,7 @@ static inline struct thread_info *curren
 #define _TIF_POLLING_NRFLAG	(1<<TIF_POLLING_NRFLAG)
 #define _TIF_RESTORE_SIGMASK	(1<<TIF_RESTORE_SIGMASK)
 #define _TIF_FREEZE             (1<<TIF_FREEZE)
+#define _TIF_NEED_MIGRATE	(1<<TIF_NEED_MIGRATE)
 
 #define _TIF_WORK_MASK		0x0000FFFE	/* work to do on interrupt/exception return */
 
Index: linux-2.6-lttng/include/asm-cris/thread_info.h
===================================================================
--- linux-2.6-lttng.orig/include/asm-cris/thread_info.h	2007-07-13 14:18:26.000000000 -0400
+++ linux-2.6-lttng/include/asm-cris/thread_info.h	2007-07-14 13:20:12.000000000 -0400
@@ -32,6 +32,7 @@ struct thread_info {
 	unsigned long		flags;		/* low level flags */
 	__u32			cpu;		/* current CPU */
 	int			preempt_count;	/* 0 => preemptable, <0 => BUG */
+	int			migrate_count;/* 0: can migrate, <0 => BUG */
 
 	mm_segment_t		addr_limit;	/* thread address space:
 					 	   0-0xBFFFFFFF for user-thead
@@ -58,6 +59,7 @@ struct thread_info {
 	.flags		= 0,				\
 	.cpu		= 0,				\
 	.preempt_count	= 1,				\
+	.migrate_count = 0,				\
 	.addr_limit	= KERNEL_DS,			\
 	.restart_block = {				\
 		       .fn = do_no_restart_syscall,	\
@@ -81,6 +83,7 @@ struct thread_info {
 #define TIF_SYSCALL_TRACE	0	/* syscall trace active */
 #define TIF_SIGPENDING		1	/* signal pending */
 #define TIF_NEED_RESCHED	2	/* rescheduling necessary */
+#define TIF_NEED_MIGRATE	3	/* migration necessary */
 #define TIF_POLLING_NRFLAG	16	/* true if poll_idle() is polling TIF_NEED_RESCHED */
 #define TIF_MEMDIE		17
 
@@ -88,6 +91,7 @@ struct thread_info {
 #define _TIF_SIGPENDING		(1<<TIF_SIGPENDING)
 #define _TIF_NEED_RESCHED	(1<<TIF_NEED_RESCHED)
 #define _TIF_POLLING_NRFLAG	(1<<TIF_POLLING_NRFLAG)
+#define _TIF_NEED_MIGRATE	(1<<TIF_NEED_MIGRATE)
 
 #define _TIF_WORK_MASK		0x0000FFFE	/* work to do on interrupt/exception return */
 #define _TIF_ALLWORK_MASK	0x0000FFFF	/* work to do on any return to u-space */
Index: linux-2.6-lttng/include/asm-frv/thread_info.h
===================================================================
--- linux-2.6-lttng.orig/include/asm-frv/thread_info.h	2007-07-13 14:18:26.000000000 -0400
+++ linux-2.6-lttng/include/asm-frv/thread_info.h	2007-07-14 13:20:12.000000000 -0400
@@ -36,6 +36,7 @@ struct thread_info {
 	unsigned long		status;		/* thread-synchronous flags */
 	__u32			cpu;		/* current CPU */
 	int			preempt_count;	/* 0 => preemptable, <0 => BUG */
+	int			migrate_count;/* 0: can migrate, <0 => BUG */
 
 	mm_segment_t		addr_limit;	/* thread address space:
 					 	   0-0xBFFFFFFF for user-thead
@@ -68,6 +69,7 @@ struct thread_info {
 	.flags		= 0,			\
 	.cpu		= 0,			\
 	.preempt_count	= 1,			\
+	.migrate_count = 0,			\
 	.addr_limit	= KERNEL_DS,		\
 	.restart_block = {			\
 		.fn = do_no_restart_syscall,	\
@@ -113,6 +115,7 @@ register struct thread_info *__current_t
 #define TIF_SINGLESTEP		3	/* restore singlestep on return to user mode */
 #define TIF_IRET		4	/* return with iret */
 #define TIF_RESTORE_SIGMASK	5	/* restore signal mask in do_signal() */
+#define TIF_NEED_MIGRATE	6	/* migration necessary */
 #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	/* freezing for suspend */
@@ -125,6 +128,7 @@ register struct thread_info *__current_t
 #define _TIF_RESTORE_SIGMASK	(1 << TIF_RESTORE_SIGMASK)
 #define _TIF_POLLING_NRFLAG	(1 << TIF_POLLING_NRFLAG)
 #define _TIF_FREEZE		(1 << TIF_FREEZE)
+#define _TIF_NEED_MIGRATE	(1 << TIF_NEED_MIGRATE)
 
 #define _TIF_WORK_MASK		0x0000FFFE	/* work to do on interrupt/exception return */
 #define _TIF_ALLWORK_MASK	0x0000FFFF	/* work to do on any return to u-space */
Index: linux-2.6-lttng/include/asm-h8300/thread_info.h
===================================================================
--- linux-2.6-lttng.orig/include/asm-h8300/thread_info.h	2007-07-13 14:18:26.000000000 -0400
+++ linux-2.6-lttng/include/asm-h8300/thread_info.h	2007-07-14 13:20:12.000000000 -0400
@@ -24,6 +24,7 @@ struct thread_info {
 	unsigned long	   flags;		/* low level flags */
 	int		   cpu;			/* cpu we're on */
 	int		   preempt_count;	/* 0 => preemptable, <0 => BUG */
+	int			migrate_count;/* 0: can migrate, <0 => BUG */
 	struct restart_block restart_block;
 };
 
@@ -37,6 +38,7 @@ struct thread_info {
 	.flags =	0,			\
 	.cpu =		0,			\
 	.preempt_count = 1,			\
+	.migrate_count = 0,			\
 	.restart_block	= {			\
 		.fn = do_no_restart_syscall,	\
 	},					\
@@ -91,12 +93,14 @@ static inline struct thread_info *curren
 #define TIF_POLLING_NRFLAG	3	/* true if poll_idle() is polling
 					   TIF_NEED_RESCHED */
 #define TIF_MEMDIE		4
+#define TIF_NEED_MIGRATE	5	/* migration necessary */
 
 /* as above, but as bit values */
 #define _TIF_SYSCALL_TRACE	(1<<TIF_SYSCALL_TRACE)
 #define _TIF_SIGPENDING		(1<<TIF_SIGPENDING)
 #define _TIF_NEED_RESCHED	(1<<TIF_NEED_RESCHED)
 #define _TIF_POLLING_NRFLAG	(1<<TIF_POLLING_NRFLAG)
+#define _TIF_NEED_MIGRATE	(1<<TIF_NEED_MIGRATE)
 
 #define _TIF_WORK_MASK		0x0000FFFE	/* work to do on interrupt/exception return */
 
Index: linux-2.6-lttng/include/asm-ia64/thread_info.h
===================================================================
--- linux-2.6-lttng.orig/include/asm-ia64/thread_info.h	2007-07-13 14:18:26.000000000 -0400
+++ linux-2.6-lttng/include/asm-ia64/thread_info.h	2007-07-14 13:20:12.000000000 -0400
@@ -30,6 +30,7 @@ struct thread_info {
 	__u32 status;			/* Thread synchronous flags */
 	mm_segment_t addr_limit;	/* user-level address space limit */
 	int preempt_count;		/* 0=premptable, <0=BUG; will also serve as bh-counter */
+	int migrate_count;		/* 0: can migrate, <0 => BUG */
 	struct restart_block restart_block;
 };
 
@@ -43,6 +44,7 @@ struct thread_info {
 	.cpu		= 0,			\
 	.addr_limit	= KERNEL_DS,		\
 	.preempt_count	= 0,			\
+	.migrate_count = 0,			\
 	.restart_block = {			\
 		.fn = do_no_restart_syscall,	\
 	},					\
@@ -86,6 +88,7 @@ struct thread_info {
 #define TIF_SINGLESTEP		4	/* restore singlestep on return to user mode */
 #define TIF_RESTORE_SIGMASK	5	/* restore signal mask in do_signal() */
 #define TIF_PERFMON_WORK	6	/* work for pfm_handle_work() */
+#define TIF_NEED_MIGRATE	7	/* migration necessary */
 #define TIF_POLLING_NRFLAG	16	/* true if poll_idle() is polling TIF_NEED_RESCHED */
 #define TIF_MEMDIE		17
 #define TIF_MCA_INIT		18	/* this task is processing MCA or INIT */
@@ -98,6 +101,7 @@ struct thread_info {
 #define _TIF_SYSCALL_TRACEAUDIT	(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SINGLESTEP)
 #define _TIF_RESTORE_SIGMASK	(1 << TIF_RESTORE_SIGMASK)
 #define _TIF_PERFMON_WORK	(1 << TIF_PERFMON_WORK)
+#define _TIF_NEED_MIGRATE	(1 << TIF_NEED_MIGRATE)
 #define _TIF_SIGPENDING		(1 << TIF_SIGPENDING)
 #define _TIF_NEED_RESCHED	(1 << TIF_NEED_RESCHED)
 #define _TIF_POLLING_NRFLAG	(1 << TIF_POLLING_NRFLAG)
Index: linux-2.6-lttng/include/asm-m32r/thread_info.h
===================================================================
--- linux-2.6-lttng.orig/include/asm-m32r/thread_info.h	2007-07-13 14:18:26.000000000 -0400
+++ linux-2.6-lttng/include/asm-m32r/thread_info.h	2007-07-14 13:20:12.000000000 -0400
@@ -29,6 +29,7 @@ struct thread_info {
 	unsigned long		status;		/* thread-synchronous flags */
 	__u32			cpu;		/* current CPU */
 	int			preempt_count;	/* 0 => preemptable, <0 => BUG */
+	int			migrate_count;/* 0: can migrate, <0 => BUG */
 
 	mm_segment_t		addr_limit;	/* thread address space:
 					 	   0-0xBFFFFFFF for user-thread
@@ -69,6 +70,7 @@ struct thread_info {
 	.flags		= 0,			\
 	.cpu		= 0,			\
 	.preempt_count	= 1,			\
+	.migrate_count = 0,			\
 	.addr_limit	= KERNEL_DS,		\
 	.restart_block = {			\
 		.fn = do_no_restart_syscall,	\
@@ -150,6 +152,7 @@ static inline unsigned int get_thread_fa
 #define TIF_NEED_RESCHED	2	/* rescheduling necessary */
 #define TIF_SINGLESTEP		3	/* restore singlestep on return to user mode */
 #define TIF_IRET		4	/* return with iret */
+#define TIF_NEED_MIGRATE	5	/* migration necessary */
 #define TIF_POLLING_NRFLAG	16	/* true if poll_idle() is polling TIF_NEED_RESCHED */
 					/* 31..28 fault code */
 #define TIF_MEMDIE		17
@@ -160,6 +163,7 @@ static inline unsigned int get_thread_fa
 #define _TIF_SINGLESTEP		(1<<TIF_SINGLESTEP)
 #define _TIF_IRET		(1<<TIF_IRET)
 #define _TIF_POLLING_NRFLAG	(1<<TIF_POLLING_NRFLAG)
+#define _TIF_NEED_MIGRATE	(1<<TIF_NEED_MIGRATE)
 
 #define _TIF_WORK_MASK		0x0000FFFE	/* work to do on interrupt/exception return */
 #define _TIF_ALLWORK_MASK	0x0000FFFF	/* work to do on any return to u-space */
Index: linux-2.6-lttng/include/asm-m68k/thread_info.h
===================================================================
--- linux-2.6-lttng.orig/include/asm-m68k/thread_info.h	2007-07-14 13:20:11.000000000 -0400
+++ linux-2.6-lttng/include/asm-m68k/thread_info.h	2007-07-14 13:20:12.000000000 -0400
@@ -9,6 +9,7 @@ struct thread_info {
 	unsigned long		flags;
 	struct exec_domain	*exec_domain;	/* execution domain */
 	int			preempt_count;	/* 0 => preemptable, <0 => BUG */
+	int			migrate_count;/* 0: can migrate, <0 => BUG */
 	__u32 cpu; /* should always be 0 on m68k */
 	struct restart_block    restart_block;
 };
@@ -59,5 +60,6 @@ struct thread_info {
 #define TIF_DELAYED_TRACE	14	/* single step a syscall */
 #define TIF_SYSCALL_TRACE	15	/* syscall trace active */
 #define TIF_MEMDIE		16
+#define TIF_NEED_MIGRATE	17	/* migration necessary */
 
 #endif	/* _ASM_M68K_THREAD_INFO_H */
Index: linux-2.6-lttng/include/asm-m68knommu/thread_info.h
===================================================================
--- linux-2.6-lttng.orig/include/asm-m68knommu/thread_info.h	2007-07-14 13:20:11.000000000 -0400
+++ linux-2.6-lttng/include/asm-m68knommu/thread_info.h	2007-07-14 13:20:12.000000000 -0400
@@ -37,6 +37,7 @@ struct thread_info {
 	unsigned long	   flags;		/* low level flags */
 	int		   cpu;			/* cpu we're on */
 	int		   preempt_count;	/* 0 => preemptable, <0 => BUG */
+	int		   migrate_count;	/* 0: can migrate, <0 => BUG */
 	struct restart_block restart_block;
 };
 
@@ -88,6 +89,7 @@ static inline struct thread_info *curren
 #define TIF_POLLING_NRFLAG	3	/* true if poll_idle() is polling
 					   TIF_NEED_RESCHED */
 #define TIF_MEMDIE		4
+#define TIF_NEED_MIGRATE	5	/* migration necessary */
 #define	TIF_SYSCALL_AUDIT	7	/* syscall auditing active */
 
 /* as above, but as bit values */
@@ -96,6 +98,7 @@ static inline struct thread_info *curren
 #define _TIF_NEED_RESCHED	(1<<TIF_NEED_RESCHED)
 #define _TIF_POLLING_NRFLAG	(1<<TIF_POLLING_NRFLAG)
 #define _TIF_MEMDIE		(1<<TIF_MEMDIE)
+#define _TIF_NEED_MIGRATE	(1<<TIF_NEED_MIGRATE)
 #define _TIF_SYSCALL_AUDIT	(1<<TIF_SYSCALL_AUDIT)
 
 #define _TIF_WORK_MASK		0x0000FFFE	/* work to do on interrupt/exception return */
Index: linux-2.6-lttng/include/asm-mips/thread_info.h
===================================================================
--- linux-2.6-lttng.orig/include/asm-mips/thread_info.h	2007-07-13 14:18:26.000000000 -0400
+++ linux-2.6-lttng/include/asm-mips/thread_info.h	2007-07-14 13:20:12.000000000 -0400
@@ -28,6 +28,7 @@ struct thread_info {
 	unsigned long		tp_value;	/* thread pointer */
 	__u32			cpu;		/* current CPU */
 	int			preempt_count;	/* 0 => preemptable, <0 => BUG */
+	int			migrate_count;/* 0: can migrate, <0 => BUG */
 
 	mm_segment_t		addr_limit;	/* thread address space:
 						   0-0xBFFFFFFF for user-thead
@@ -49,6 +50,7 @@ struct thread_info {
 	.flags		= 0,			\
 	.cpu		= 0,			\
 	.preempt_count	= 1,			\
+	.migrate_count = 0,			\
 	.addr_limit	= KERNEL_DS,		\
 	.restart_block	= {			\
 		.fn = do_no_restart_syscall,	\
@@ -113,6 +115,7 @@ register struct thread_info *__current_t
 #define TIF_NEED_RESCHED	2	/* rescheduling necessary */
 #define TIF_SYSCALL_AUDIT	3	/* syscall auditing active */
 #define TIF_SECCOMP		4	/* secure computing */
+#define TIF_NEED_MIGRATE	5	/* migration necessary */
 #define TIF_RESTORE_SIGMASK	9	/* restore signal mask in do_signal() */
 #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 */
@@ -125,6 +128,7 @@ register struct thread_info *__current_t
 #define _TIF_NEED_RESCHED	(1<<TIF_NEED_RESCHED)
 #define _TIF_SYSCALL_AUDIT	(1<<TIF_SYSCALL_AUDIT)
 #define _TIF_SECCOMP		(1<<TIF_SECCOMP)
+#define _TIF_NEED_MIGRATE	(1<<TIF_NEED_MIGRATE)
 #define _TIF_RESTORE_SIGMASK	(1<<TIF_RESTORE_SIGMASK)
 #define _TIF_USEDFPU		(1<<TIF_USEDFPU)
 #define _TIF_POLLING_NRFLAG	(1<<TIF_POLLING_NRFLAG)
Index: linux-2.6-lttng/include/asm-parisc/thread_info.h
===================================================================
--- linux-2.6-lttng.orig/include/asm-parisc/thread_info.h	2007-07-13 14:18:26.000000000 -0400
+++ linux-2.6-lttng/include/asm-parisc/thread_info.h	2007-07-14 13:20:12.000000000 -0400
@@ -13,6 +13,7 @@ struct thread_info {
 	mm_segment_t addr_limit;	/* user-level address space limit */
 	__u32 cpu;			/* current CPU */
 	int preempt_count;		/* 0=premptable, <0=BUG; will also serve as bh-counter */
+	int migrate_count;		/* 0: can migrate, <0 => BUG */
 	struct restart_block restart_block;
 };
 
@@ -24,6 +25,7 @@ struct thread_info {
 	.cpu		= 0,			\
 	.addr_limit	= KERNEL_DS,		\
 	.preempt_count	= 1,			\
+	.migrate_count = 0,			\
   	.restart_block	= {			\
 		.fn = do_no_restart_syscall	\
 	}					\
@@ -62,6 +64,7 @@ struct thread_info {
 #define TIF_32BIT               4       /* 32 bit binary */
 #define TIF_MEMDIE		5
 #define TIF_RESTORE_SIGMASK	6	/* restore saved signal mask */
+#define TIF_NEED_MIGRATE	7	/* migration necessary */
 
 #define _TIF_SYSCALL_TRACE	(1 << TIF_SYSCALL_TRACE)
 #define _TIF_SIGPENDING		(1 << TIF_SIGPENDING)
@@ -69,6 +72,7 @@ struct thread_info {
 #define _TIF_POLLING_NRFLAG	(1 << TIF_POLLING_NRFLAG)
 #define _TIF_32BIT		(1 << TIF_32BIT)
 #define _TIF_RESTORE_SIGMASK	(1 << TIF_RESTORE_SIGMASK)
+#define _TIF_NEED_MIGRATE	(1 << TIF_NEED_MIGRATE)
 
 #define _TIF_USER_WORK_MASK     (_TIF_SIGPENDING | \
                                  _TIF_NEED_RESCHED | _TIF_RESTORE_SIGMASK)
Index: linux-2.6-lttng/include/asm-powerpc/thread_info.h
===================================================================
--- linux-2.6-lttng.orig/include/asm-powerpc/thread_info.h	2007-07-13 14:18:26.000000000 -0400
+++ linux-2.6-lttng/include/asm-powerpc/thread_info.h	2007-07-14 13:20:12.000000000 -0400
@@ -35,6 +35,7 @@ struct thread_info {
 	int		cpu;			/* cpu we're on */
 	int		preempt_count;		/* 0 => preemptable,
 						   <0 => BUG */
+	int		migrate_count;	/* 0: can migrate, <0 => BUG */
 	struct restart_block restart_block;
 	unsigned long	local_flags;		/* private flags for thread */
 
@@ -53,6 +54,7 @@ struct thread_info {
 	.exec_domain =	&default_exec_domain,	\
 	.cpu =		0,			\
 	.preempt_count = 1,			\
+	.migrate_count = 0,			\
 	.restart_block = {			\
 		.fn = do_no_restart_syscall,	\
 	},					\
@@ -124,6 +126,7 @@ static inline struct thread_info *curren
 #define TIF_FREEZE		14	/* Freezing for suspend */
 #define TIF_RUNLATCH		15	/* Is the runlatch enabled? */
 #define TIF_ABI_PENDING		16	/* 32/64 bit switch needed */
+#define TIF_NEED_MIGRATE	17	/* migration necessary */
 
 /* as above, but as bit values */
 #define _TIF_SYSCALL_TRACE	(1<<TIF_SYSCALL_TRACE)
@@ -142,6 +145,7 @@ static inline struct thread_info *curren
 #define _TIF_FREEZE		(1<<TIF_FREEZE)
 #define _TIF_RUNLATCH		(1<<TIF_RUNLATCH)
 #define _TIF_ABI_PENDING	(1<<TIF_ABI_PENDING)
+#define _TIF_NEED_MIGRATE	(1<<TIF_NEED_MIGRATE)
 #define _TIF_SYSCALL_T_OR_A	(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SECCOMP)
 
 #define _TIF_USER_WORK_MASK	( _TIF_SIGPENDING | \
Index: linux-2.6-lttng/include/asm-s390/thread_info.h
===================================================================
--- linux-2.6-lttng.orig/include/asm-s390/thread_info.h	2007-07-13 14:18:26.000000000 -0400
+++ linux-2.6-lttng/include/asm-s390/thread_info.h	2007-07-14 13:20:12.000000000 -0400
@@ -51,6 +51,7 @@ struct thread_info {
 	unsigned long		flags;		/* low level flags */
 	unsigned int		cpu;		/* current CPU */
 	int			preempt_count;	/* 0 => preemptable, <0 => BUG */
+	int			migrate_count;/* 0: can migrate, <0 => BUG */
 	struct restart_block	restart_block;
 };
 
@@ -64,6 +65,7 @@ struct thread_info {
 	.flags		= 0,			\
 	.cpu		= 0,			\
 	.preempt_count	= 1,			\
+	.migrate_count = 0,			\
 	.restart_block	= {			\
 		.fn = do_no_restart_syscall,	\
 	},					\
@@ -96,6 +98,7 @@ static inline struct thread_info *curren
 #define TIF_SYSCALL_AUDIT	5	/* syscall auditing active */
 #define TIF_SINGLE_STEP		6	/* deliver sigtrap on return to user */
 #define TIF_MCCK_PENDING	7	/* machine check handling is pending */
+#define TIF_NEED_MIGRATE	8	/* migration necessary */
 #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 */
@@ -110,6 +113,7 @@ static inline struct thread_info *curren
 #define _TIF_SYSCALL_AUDIT	(1<<TIF_SYSCALL_AUDIT)
 #define _TIF_SINGLE_STEP	(1<<TIF_SINGLE_STEP)
 #define _TIF_MCCK_PENDING	(1<<TIF_MCCK_PENDING)
+#define _TIF_NEED_MIGRATE	(1<<TIF_NEED_MIGRATE)
 #define _TIF_USEDFPU		(1<<TIF_USEDFPU)
 #define _TIF_POLLING_NRFLAG	(1<<TIF_POLLING_NRFLAG)
 #define _TIF_31BIT		(1<<TIF_31BIT)
Index: linux-2.6-lttng/include/asm-sh/thread_info.h
===================================================================
--- linux-2.6-lttng.orig/include/asm-sh/thread_info.h	2007-07-14 13:20:11.000000000 -0400
+++ linux-2.6-lttng/include/asm-sh/thread_info.h	2007-07-14 13:20:12.000000000 -0400
@@ -21,6 +21,7 @@ struct thread_info {
 	unsigned long		flags;		/* low level flags */
 	__u32			cpu;
 	int			preempt_count; /* 0 => preemptable, <0 => BUG */
+	int			migrate_count;/* 0: can migrate, <0 => BUG */
 	mm_segment_t		addr_limit;	/* thread address space */
 	struct restart_block	restart_block;
 	unsigned long		previous_sp;	/* sp of previous stack in case
@@ -58,6 +59,7 @@ struct thread_info {
 	.flags		= 0,			\
 	.cpu		= 0,			\
 	.preempt_count	= 1,			\
+	.migrate_count = 0,			\
 	.addr_limit	= KERNEL_DS,		\
 	.restart_block	= {			\
 		.fn = do_no_restart_syscall,	\
@@ -112,6 +114,7 @@ static inline struct thread_info *curren
 #define TIF_RESTORE_SIGMASK	3	/* restore signal mask in do_signal() */
 #define TIF_SINGLESTEP		4	/* singlestepping active */
 #define	TIF_SYSCALL_AUDIT	6	/* syscall audit active */
+#define TIF_NEED_MIGRATE	7	/* migration necessary */
 #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
@@ -123,6 +126,7 @@ static inline struct thread_info *curren
 #define _TIF_RESTORE_SIGMASK	(1<<TIF_RESTORE_SIGMASK)
 #define _TIF_SINGLESTEP		(1<<TIF_SINGLESTEP)
 #define _TIF_SYSCALL_AUDIT	(1<<TIF_SYSCALL_AUDIT)
+#define _TIF_NEED_MIGRATE	(1<<TIF_NEED_MIGRATE)
 #define _TIF_USEDFPU		(1<<TIF_USEDFPU)
 #define _TIF_POLLING_NRFLAG	(1<<TIF_POLLING_NRFLAG)
 #define _TIF_FREEZE		(1<<TIF_FREEZE)
Index: linux-2.6-lttng/include/asm-sh64/thread_info.h
===================================================================
--- linux-2.6-lttng.orig/include/asm-sh64/thread_info.h	2007-07-14 13:20:11.000000000 -0400
+++ linux-2.6-lttng/include/asm-sh64/thread_info.h	2007-07-14 13:20:12.000000000 -0400
@@ -23,6 +23,7 @@ struct thread_info {
 	unsigned long		flags;		/* low level flags */
 	/* Put the 4 32-bit fields together to make asm offsetting easier. */
 	int			preempt_count;	/* 0 => preemptable, <0 => BUG */
+	int			migrate_count;/* 0: can migrate, <0 => BUG */
 	__u16			cpu;
 
 	mm_segment_t		addr_limit;
@@ -41,6 +42,7 @@ struct thread_info {
 	.flags		= 0,			\
 	.cpu		= 0,			\
 	.preempt_count	= 1,			\
+	.migrate_count = 0,			\
 	.addr_limit     = KERNEL_DS,            \
 	.restart_block	= {			\
 		.fn = do_no_restart_syscall,	\
@@ -80,12 +82,14 @@ static inline struct thread_info *curren
 #define TIF_NEED_RESCHED	3	/* rescheduling necessary */
 #define TIF_MEMDIE		4
 #define TIF_RESTORE_SIGMASK	5	/* Restore signal mask in do_signal */
+#define TIF_NEED_MIGRATE	6	/* migration necessary */
 
 #define _TIF_SYSCALL_TRACE	(1 << TIF_SYSCALL_TRACE)
 #define _TIF_SIGPENDING		(1 << TIF_SIGPENDING)
 #define _TIF_NEED_RESCHED	(1 << TIF_NEED_RESCHED)
 #define _TIF_MEMDIE		(1 << TIF_MEMDIE)
 #define _TIF_RESTORE_SIGMASK	(1 << TIF_RESTORE_SIGMASK)
+#define _TIF_NEED_MIGRATE	(1 << TIF_NEED_MIGRATE)
 
 #endif /* __KERNEL__ */
 
Index: linux-2.6-lttng/include/asm-sparc/thread_info.h
===================================================================
--- linux-2.6-lttng.orig/include/asm-sparc/thread_info.h	2007-07-14 13:20:11.000000000 -0400
+++ linux-2.6-lttng/include/asm-sparc/thread_info.h	2007-07-14 13:20:12.000000000 -0400
@@ -33,6 +33,7 @@ struct thread_info {
 	int			cpu;		/* cpu we're on */
 	int			preempt_count;	/* 0 => preemptable,
 						   <0 => BUG */
+	int			migrate_count;/* 0: can migrate, <0 => BUG */
 	int			softirq_count;
 	int			hardirq_count;
 
@@ -65,6 +66,7 @@ struct thread_info {
 	.flags		=	0,			\
 	.cpu		=	0,			\
 	.preempt_count	=	1,			\
+	.migrate_count =	0,			\
 	.restart_block	= {				\
 		.fn	=	do_no_restart_syscall,	\
 	},						\
@@ -132,6 +134,7 @@ BTFIXUPDEF_CALL(void, free_thread_info, 
 #define TIF_SIGPENDING		2	/* signal pending */
 #define TIF_NEED_RESCHED	3	/* rescheduling necessary */
 #define TIF_RESTORE_SIGMASK	4	/* restore signal mask in do_signal() */
+#define TIF_NEED_MIGRATE	5	/* migration necessary */
 #define TIF_USEDFPU		8	/* FPU was used by this task
 					 * this quantum (SMP) */
 #define TIF_POLLING_NRFLAG	9	/* true if poll_idle() is polling
@@ -144,6 +147,7 @@ BTFIXUPDEF_CALL(void, free_thread_info, 
 #define _TIF_SIGPENDING		(1<<TIF_SIGPENDING)
 #define _TIF_NEED_RESCHED	(1<<TIF_NEED_RESCHED)
 #define _TIF_RESTORE_SIGMASK	(1<<TIF_RESTORE_SIGMASK)
+#define _TIF_NEED_MIGRATE	(1<<TIF_NEED_MIGRATE)
 #define _TIF_USEDFPU		(1<<TIF_USEDFPU)
 #define _TIF_POLLING_NRFLAG	(1<<TIF_POLLING_NRFLAG)
 
Index: linux-2.6-lttng/include/asm-sparc64/thread_info.h
===================================================================
--- linux-2.6-lttng.orig/include/asm-sparc64/thread_info.h	2007-07-13 14:18:26.000000000 -0400
+++ linux-2.6-lttng/include/asm-sparc64/thread_info.h	2007-07-14 13:20:12.000000000 -0400
@@ -47,6 +47,7 @@ struct thread_info {
 	struct pt_regs		*kregs;
 	struct exec_domain	*exec_domain;
 	int			preempt_count;	/* 0 => preemptable, <0 => BUG */
+	int			migrate_count;/* 0: can migrate, <0 => BUG */
 	__u8			new_child;
 	__u8			syscall_noerror;
 	__u16			cpu;
@@ -137,6 +138,7 @@ struct thread_info {
 	.flags		= ((unsigned long)ASI_P) << TI_FLAG_CURRENT_DS_SHIFT,	\
 	.exec_domain	=	&default_exec_domain,	\
 	.preempt_count	=	1,			\
+	.migrate_count =	0,			\
 	.restart_block	= {				\
 		.fn	=	do_no_restart_syscall,	\
 	},						\
@@ -225,7 +227,7 @@ register struct thread_info *current_thr
 #define TIF_UNALIGNED		5	/* allowed to do unaligned accesses */
 #define TIF_NEWSIGNALS		6	/* wants new-style signals */
 #define TIF_32BIT		7	/* 32-bit binary */
-/* flag bit 8 is available */
+#define TIF_NEED_MIGRATE	8	/* migration necessary */
 #define TIF_SECCOMP		9	/* secure computing */
 #define TIF_SYSCALL_AUDIT	10	/* syscall auditing active */
 /* flag bit 11 is available */
@@ -244,6 +246,7 @@ register struct thread_info *current_thr
 #define _TIF_UNALIGNED		(1<<TIF_UNALIGNED)
 #define _TIF_NEWSIGNALS		(1<<TIF_NEWSIGNALS)
 #define _TIF_32BIT		(1<<TIF_32BIT)
+#define _TIF_NEED_MIGRATE	(1<<TIF_NEED_MIGRATE)
 #define _TIF_SECCOMP		(1<<TIF_SECCOMP)
 #define _TIF_SYSCALL_AUDIT	(1<<TIF_SYSCALL_AUDIT)
 #define _TIF_RESTORE_SIGMASK	(1<<TIF_RESTORE_SIGMASK)
Index: linux-2.6-lttng/include/asm-um/thread_info.h
===================================================================
--- linux-2.6-lttng.orig/include/asm-um/thread_info.h	2007-07-13 14:18:26.000000000 -0400
+++ linux-2.6-lttng/include/asm-um/thread_info.h	2007-07-14 13:20:12.000000000 -0400
@@ -18,6 +18,7 @@ struct thread_info {
 	__u32			cpu;		/* current CPU */
 	int			preempt_count;  /* 0 => preemptable,
 						   <0 => BUG */
+	int			migrate_count;/* 0: can migrate, <0 => BUG */
 	mm_segment_t		addr_limit;	/* thread address space:
 					 	   0-0xBFFFFFFF for user
 						   0-0xFFFFFFFF for kernel */
@@ -32,6 +33,7 @@ struct thread_info {
 	.flags =		0,		\
 	.cpu =		0,			\
 	.preempt_count =	1,		\
+	.migrate_count =	0,		\
 	.addr_limit =	KERNEL_DS,		\
 	.restart_block =  {			\
 		.fn =  do_no_restart_syscall,	\
@@ -82,6 +84,7 @@ static inline struct thread_info *curren
 #define TIF_MEMDIE	 	5
 #define TIF_SYSCALL_AUDIT	6
 #define TIF_RESTORE_SIGMASK	7
+#define TIF_NEED_MIGRATE	8	/* migration necessary */
 
 #define _TIF_SYSCALL_TRACE	(1 << TIF_SYSCALL_TRACE)
 #define _TIF_SIGPENDING		(1 << TIF_SIGPENDING)
@@ -90,5 +93,6 @@ static inline struct thread_info *curren
 #define _TIF_MEMDIE		(1 << TIF_MEMDIE)
 #define _TIF_SYSCALL_AUDIT	(1 << TIF_SYSCALL_AUDIT)
 #define _TIF_RESTORE_SIGMASK	(1 << TIF_RESTORE_SIGMASK)
+#define _TIF_NEED_MIGRATE	(1 << TIF_NEED_MIGRATE)
 
 #endif
Index: linux-2.6-lttng/include/asm-v850/thread_info.h
===================================================================
--- linux-2.6-lttng.orig/include/asm-v850/thread_info.h	2007-07-13 14:18:26.000000000 -0400
+++ linux-2.6-lttng/include/asm-v850/thread_info.h	2007-07-14 13:20:12.000000000 -0400
@@ -32,6 +32,7 @@ struct thread_info {
 	int			cpu;		/* cpu we're on */
 	int			preempt_count;	/* 0 => preemptable,
 						   <0 => BUG */
+	int			migrate_count;/* 0: can migrate, <0 => BUG */
 	struct restart_block	restart_block;
 };
 
@@ -42,6 +43,7 @@ struct thread_info {
 	.flags =	0,						      \
 	.cpu =		0,						      \
 	.preempt_count = 1,						      \
+	.migrate_count = 0,						      \
 	.restart_block = {						      \
 		.fn = do_no_restart_syscall,				      \
 	},								      \
@@ -82,12 +84,14 @@ struct thread_info {
 #define TIF_POLLING_NRFLAG	3	/* true if poll_idle() is polling
 					   TIF_NEED_RESCHED */
 #define TIF_MEMDIE		4
+#define TIF_NEED_MIGRATE	5	/* migration necessary */
 
 /* as above, but as bit values */
 #define _TIF_SYSCALL_TRACE	(1<<TIF_SYSCALL_TRACE)
 #define _TIF_SIGPENDING		(1<<TIF_SIGPENDING)
 #define _TIF_NEED_RESCHED	(1<<TIF_NEED_RESCHED)
 #define _TIF_POLLING_NRFLAG	(1<<TIF_POLLING_NRFLAG)
+#define _TIF_NEED_MIGRATE	(1<<TIF_NEED_MIGRATE)
 
 
 /* Size of kernel stack for each process.  */
Index: linux-2.6-lttng/include/asm-x86_64/thread_info.h
===================================================================
--- linux-2.6-lttng.orig/include/asm-x86_64/thread_info.h	2007-07-13 14:18:26.000000000 -0400
+++ linux-2.6-lttng/include/asm-x86_64/thread_info.h	2007-07-14 13:20:12.000000000 -0400
@@ -30,6 +30,7 @@ struct thread_info {
 	__u32			status;		/* thread synchronous flags */
 	__u32			cpu;		/* current CPU */
 	int 			preempt_count;	/* 0 => preemptable, <0 => BUG */
+	int			migrate_count;/* 0: can migrate, <0 => BUG */
 
 	mm_segment_t		addr_limit;	
 	struct restart_block    restart_block;
@@ -48,6 +49,7 @@ struct thread_info {
 	.flags	       = 0,			\
 	.cpu	       = 0,			\
 	.preempt_count = 1,			\
+	.migrate_count = 0,			\
 	.addr_limit     = KERNEL_DS,		\
 	.restart_block = {			\
 		.fn = do_no_restart_syscall,	\
@@ -115,6 +117,7 @@ static inline struct thread_info *stack_
 #define TIF_SECCOMP		8	/* secure computing */
 #define TIF_RESTORE_SIGMASK	9	/* restore signal mask in do_signal */
 #define TIF_MCE_NOTIFY		10	/* notify userspace of an MCE */
+#define TIF_NEED_MIGRATE	11	/* migration necessary */
 /* 16 free */
 #define TIF_IA32		17	/* 32bit process */ 
 #define TIF_FORK		18	/* ret_from_fork */
@@ -133,6 +136,7 @@ static inline struct thread_info *stack_
 #define _TIF_SECCOMP		(1<<TIF_SECCOMP)
 #define _TIF_RESTORE_SIGMASK	(1<<TIF_RESTORE_SIGMASK)
 #define _TIF_MCE_NOTIFY		(1<<TIF_MCE_NOTIFY)
+#define _TIF_NEED_MIGRATE	(1<<TIF_NEED_MIGRATE)
 #define _TIF_IA32		(1<<TIF_IA32)
 #define _TIF_FORK		(1<<TIF_FORK)
 #define _TIF_ABI_PENDING	(1<<TIF_ABI_PENDING)
Index: linux-2.6-lttng/include/asm-xtensa/thread_info.h
===================================================================
--- linux-2.6-lttng.orig/include/asm-xtensa/thread_info.h	2007-07-13 14:18:26.000000000 -0400
+++ linux-2.6-lttng/include/asm-xtensa/thread_info.h	2007-07-14 13:20:12.000000000 -0400
@@ -34,6 +34,7 @@ struct thread_info {
 	unsigned long		status;		/* thread-synchronous flags */
 	__u32			cpu;		/* current CPU */
 	__s32			preempt_count;	/* 0 => preemptable,< 0 => BUG*/
+	__s32			migrate_count;/* 0: can migrate, <0 => BUG */
 
 	mm_segment_t		addr_limit;	/* thread address space */
 	struct restart_block    restart_block;
@@ -72,6 +73,7 @@ struct thread_info {
 	.flags		= 0,			\
 	.cpu		= 0,			\
 	.preempt_count	= 1,			\
+	.migrate_count = 0,			\
 	.addr_limit	= KERNEL_DS,		\
 	.restart_block = {			\
 		.fn = do_no_restart_syscall,	\
@@ -116,6 +118,7 @@ static inline struct thread_info *curren
 #define TIF_IRET		4	/* return with iret */
 #define TIF_MEMDIE		5
 #define TIF_RESTORE_SIGMASK	6	/* restore signal mask in do_signal() */
+#define TIF_NEED_MIGRATE	7	/* migration necessary */
 #define TIF_POLLING_NRFLAG	16	/* true if poll_idle() is polling TIF_NEED_RESCHED */
 
 #define _TIF_SYSCALL_TRACE	(1<<TIF_SYSCALL_TRACE)
@@ -123,6 +126,7 @@ static inline struct thread_info *curren
 #define _TIF_NEED_RESCHED	(1<<TIF_NEED_RESCHED)
 #define _TIF_SINGLESTEP		(1<<TIF_SINGLESTEP)
 #define _TIF_IRET		(1<<TIF_IRET)
+#define _TIF_NEED_MIGRATE	(1<<TIF_NEED_MIGRATE)
 #define _TIF_POLLING_NRFLAG	(1<<TIF_POLLING_NRFLAG)
 #define _TIF_RESTORE_SIGMASK	(1<<TIF_RESTORE_SIGMASK)
 
Index: linux-2.6-lttng/lib/smp_processor_id.c
===================================================================
--- linux-2.6-lttng.orig/lib/smp_processor_id.c	2007-07-13 14:18:26.000000000 -0400
+++ linux-2.6-lttng/lib/smp_processor_id.c	2007-07-14 13:20:12.000000000 -0400
@@ -10,12 +10,16 @@
 unsigned int debug_smp_processor_id(void)
 {
 	unsigned long preempt_count = preempt_count();
+	unsigned long migrate_count = migrate_count();
 	int this_cpu = raw_smp_processor_id();
 	cpumask_t this_mask;
 
 	if (likely(preempt_count))
 		goto out;
 
+	if (likely(migrate_count))
+		goto out;
+
 	if (irqs_disabled())
 		goto out;
 
@@ -42,7 +46,7 @@ unsigned int debug_smp_processor_id(void
 	if (!printk_ratelimit())
 		goto out_enable;
 
-	printk(KERN_ERR "BUG: using smp_processor_id() in preemptible [%08x] code: %s/%d\n", preempt_count(), current->comm, current->pid);
+	printk(KERN_ERR "BUG: using smp_processor_id() in preemptible [%08x] migration [%08x] code: %s/%d\n", preempt_count(), migrate_count(), current->comm, current->pid);
 	print_symbol("caller is %s\n", (long)__builtin_return_address(0));
 	dump_stack();
 

-- 
Mathieu Desnoyers
Computer Engineering Ph.D. Student, Ecole Polytechnique de Montreal
OpenPGP key fingerprint: 8CD5 52C3 8E3C 4140 715F  BA06 3F25 A8FE 3BAE 9A68

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

* [RFC] Thread Migration Preemption - v4
  2007-07-11 16:36       ` Oleg Nesterov
  2007-07-14 18:27         ` Mathieu Desnoyers
  2007-07-14 18:40         ` [RFC] Thread Migration Preemption - v3 Mathieu Desnoyers
@ 2007-07-14 18:42         ` Mathieu Desnoyers
  2007-07-14 19:14           ` Peter Zijlstra
                             ` (2 more replies)
  2 siblings, 3 replies; 33+ messages in thread
From: Mathieu Desnoyers @ 2007-07-14 18:42 UTC (permalink / raw)
  To: Oleg Nesterov; +Cc: linux-kernel, Ingo Molnar, Steven Rostedt

Thread Migration Preemption

(v3 did not have the latest updates from Oleg review)

This patch adds the ability to protect critical sections from migration to
another CPU without disabling preemption.

This will be useful to minimize the amount of preemption disabling for the -rt
patch. It will help leveraging improvements brought by the local_t types in
asm/local.h (see Documentation/local_ops.txt). Note that the updates done to
variables protected by migrate_disable must be either atomic or protected from
concurrent updates done by other threads.

Typical use:

migrate_disable();
local_inc(&__get_cpu_var(&my_local_t_var));
migrate_enable();

Which will increment the variable atomically wrt the local CPU.

Changes:

Do a check_migrate() upon migrate_enable() to answer to the migration
thread waiting for us to exit the migration disabled critical section. Use a
NEED_MIGRATE thread flag for this.

Note: (or we could say FIXME)
Is we ever want to check migration pending in assembly code, we will have to
make sure we test the right thread flag bits on each architectures. Care should
also be taken to check that the thread flags used won't trigger false positives
in non selective asm thread flag checks.

FIXME (HOTPLUG) :

> >     /* Affinity changed (again). */
> >     if (!cpu_isset(dest_cpu, p->cpus_allowed))
> >             goto out;
> >  
> >     on_rq = p->se.on_rq;
> > +#ifdef CONFIG_PREEMPT
> > +   if (!on_rq && task_thread_info(p)->migrate_count)
> > +           goto out;
> > +#endif
> 
> This means that move_task_off_dead_cpu() will spin until the task will be
> scheduled
> on the dead CPU. Given that we hold tasklist_lock and irqs are disabled, this
> may
> never happen.
>

Yes. My idea to fix this issue is the following:

If a thread has non zero migrate_count, we should still move it to a
different CPU upon hotplug cpu removal, even if this thread resists
migration. Care should be taken to send _all_ such threads to the _same_
CPU so they don't race for the per-cpu ressources. Does it make sense ?

We would have to keep the CPU affinity of the threads running on the
wrong CPU until they end their migrate disabled section, so that we can
put them back on their original CPU if it goes back online, otherwise we
could end up with concurrent per-cpu variables accesses.

(I'll wait for reply before coding a solution for this CPU HOTPLUG
related problem)


Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@polymtl.ca>
---
 include/asm-alpha/thread_info.h     |    3 +
 include/asm-arm/thread_info.h       |    5 +
 include/asm-arm26/thread_info.h     |    5 +
 include/asm-avr32/thread_info.h     |    4 +
 include/asm-blackfin/thread_info.h  |    4 +
 include/asm-cris/thread_info.h      |    4 +
 include/asm-frv/thread_info.h       |    4 +
 include/asm-h8300/thread_info.h     |    4 +
 include/asm-i386/thread_info.h      |    6 +-
 include/asm-ia64/thread_info.h      |    4 +
 include/asm-m32r/thread_info.h      |    4 +
 include/asm-m68k/thread_info.h      |    2 
 include/asm-m68knommu/thread_info.h |    3 +
 include/asm-mips/thread_info.h      |    4 +
 include/asm-parisc/thread_info.h    |    4 +
 include/asm-powerpc/thread_info.h   |    4 +
 include/asm-s390/thread_info.h      |    4 +
 include/asm-sh/thread_info.h        |    4 +
 include/asm-sh64/thread_info.h      |    4 +
 include/asm-sparc/thread_info.h     |    4 +
 include/asm-sparc64/thread_info.h   |    5 +
 include/asm-um/thread_info.h        |    4 +
 include/asm-v850/thread_info.h      |    4 +
 include/asm-x86_64/thread_info.h    |    4 +
 include/asm-xtensa/thread_info.h    |    4 +
 include/linux/preempt.h             |   47 ++++++++++++++++
 kernel/sched.c                      |  103 +++++++++++++++++++++++++++++++++---
 lib/smp_processor_id.c              |    6 +-
 28 files changed, 245 insertions(+), 12 deletions(-)

Index: linux-2.6-lttng/include/asm-i386/thread_info.h
===================================================================
--- linux-2.6-lttng.orig/include/asm-i386/thread_info.h	2007-07-13 14:18:26.000000000 -0400
+++ linux-2.6-lttng/include/asm-i386/thread_info.h	2007-07-14 13:20:12.000000000 -0400
@@ -31,8 +31,7 @@ struct thread_info {
 	unsigned long		status;		/* thread-synchronous flags */
 	__u32			cpu;		/* current CPU */
 	int			preempt_count;	/* 0 => preemptable, <0 => BUG */
-
-
+	int			migrate_count;/* 0: can migrate, <0: BUG */
 	mm_segment_t		addr_limit;	/* thread address space:
 					 	   0-0xBFFFFFFF for user-thead
 						   0-0xFFFFFFFF for kernel-thread
@@ -74,6 +73,7 @@ struct thread_info {
 	.flags		= 0,			\
 	.cpu		= 0,			\
 	.preempt_count	= 1,			\
+	.migrate_count = 0,			\
 	.addr_limit	= KERNEL_DS,		\
 	.restart_block = {			\
 		.fn = do_no_restart_syscall,	\
@@ -132,6 +132,7 @@ static inline struct thread_info *curren
 #define TIF_SYSCALL_AUDIT	6	/* syscall auditing active */
 #define TIF_SECCOMP		7	/* secure computing */
 #define TIF_RESTORE_SIGMASK	8	/* restore signal mask in do_signal() */
+#define TIF_NEED_MIGRATE	9	/* migration necessary */
 #define TIF_MEMDIE		16
 #define TIF_DEBUG		17	/* uses debug registers */
 #define TIF_IO_BITMAP		18	/* uses I/O bitmap */
@@ -147,6 +148,7 @@ static inline struct thread_info *curren
 #define _TIF_SYSCALL_AUDIT	(1<<TIF_SYSCALL_AUDIT)
 #define _TIF_SECCOMP		(1<<TIF_SECCOMP)
 #define _TIF_RESTORE_SIGMASK	(1<<TIF_RESTORE_SIGMASK)
+#define _TIF_NEED_MIGRATE	(1<<TIF_NEED_MIGRATE)
 #define _TIF_DEBUG		(1<<TIF_DEBUG)
 #define _TIF_IO_BITMAP		(1<<TIF_IO_BITMAP)
 #define _TIF_FREEZE		(1<<TIF_FREEZE)
Index: linux-2.6-lttng/include/linux/preempt.h
===================================================================
--- linux-2.6-lttng.orig/include/linux/preempt.h	2007-07-13 14:18:26.000000000 -0400
+++ linux-2.6-lttng/include/linux/preempt.h	2007-07-14 13:45:10.000000000 -0400
@@ -12,15 +12,22 @@
 #ifdef CONFIG_DEBUG_PREEMPT
   extern void fastcall add_preempt_count(int val);
   extern void fastcall sub_preempt_count(int val);
+  extern void fastcall add_migrate_count(int val);
+  extern void fastcall sub_migrate_count(int val);
 #else
 # define add_preempt_count(val)	do { preempt_count() += (val); } while (0)
 # define sub_preempt_count(val)	do { preempt_count() -= (val); } while (0)
+# define add_migrate_count(val) do { migrate_count() += (val); } while (0)
+# define sub_migrate_count(val) do { migrate_count() -= (val); } while (0)
 #endif
 
 #define inc_preempt_count() add_preempt_count(1)
 #define dec_preempt_count() sub_preempt_count(1)
 
-#define preempt_count()	(current_thread_info()->preempt_count)
+#define preempt_count() (current_thread_info()->preempt_count)
+
+#define inc_migrate_count() add_migrate_count(1)
+#define dec_migrate_count() sub_migrate_count(1)
 
 #ifdef CONFIG_PREEMPT
 
@@ -51,6 +58,38 @@ do { \
 	preempt_check_resched(); \
 } while (0)
 
+#define migrate_count()			(current_thread_info()->migrate_count)
+#define task_migrate_count(task)	(task_thread_info(task)->migrate_count)
+
+#define migrate_disable() \
+do { \
+	inc_migrate_count(); \
+	barrier(); \
+} while (0)
+
+#define migrate_enable_no_check() \
+do { \
+	barrier(); \
+	dec_migrate_count(); \
+} while (0)
+
+#ifdef CONFIG_SMP
+#define check_migrate() \
+do { \
+	if (unlikely(test_thread_flag(TIF_NEED_MIGRATE))) \
+		do_check_migrate(); \
+} while (0)
+#else
+#define check_migrate()
+#endif
+
+#define migrate_enable() \
+do { \
+	migrate_enable_no_check(); \
+	barrier(); \
+	check_migrate(); \
+} while (0)
+
 #else
 
 #define preempt_disable()		do { } while (0)
@@ -58,6 +97,12 @@ do { \
 #define preempt_enable()		do { } while (0)
 #define preempt_check_resched()		do { } while (0)
 
+#define migrate_count()					0
+#define task_migrate_count(task)			0
+
+#define migrate_disable()		do { } while (0)
+#define migrate_enable()		do { } while (0)
+
 #endif
 
 #endif /* __LINUX_PREEMPT_H */
Index: linux-2.6-lttng/kernel/sched.c
===================================================================
--- linux-2.6-lttng.orig/kernel/sched.c	2007-07-14 13:20:11.000000000 -0400
+++ linux-2.6-lttng/kernel/sched.c	2007-07-14 14:25:33.000000000 -0400
@@ -946,7 +946,7 @@ migrate_task(struct task_struct *p, int 
 	 * If the task is not on a runqueue (and not running), then
 	 * it is sufficient to simply update the task's cpu field.
 	 */
-	if (!p->se.on_rq && !task_running(rq, p)) {
+	if (!p->se.on_rq && !task_running(rq, p) && !task_migrate_count(p)) {
 		set_task_cpu(p, dest_cpu);
 		return 0;
 	}
@@ -1347,7 +1347,8 @@ static int try_to_wake_up(struct task_st
 #ifdef CONFIG_SMP
 	if (unlikely(task_running(rq, p)))
 		goto out_activate;
-
+	if (task_migrate_count(p))
+		goto out_activate;
 	new_cpu = cpu;
 
 	schedstat_inc(rq, ttwu_cnt);
@@ -1534,6 +1535,7 @@ void sched_fork(struct task_struct *p, i
 #ifdef CONFIG_PREEMPT
 	/* Want to start with kernel preemption disabled. */
 	task_thread_info(p)->preempt_count = 1;
+	task_thread_info(p)->migrate_count = 0;
 #endif
 	put_cpu();
 }
@@ -1933,6 +1935,8 @@ static void sched_migrate_task(struct ta
 	if (!cpu_isset(dest_cpu, p->cpus_allowed)
 	    || unlikely(cpu_is_offline(dest_cpu)))
 		goto out;
+	if (task_migrate_count(p))
+		goto out;
 
 	trace_mark(kernel_sched_migrate_task, "%d %ld %d",
 		p->pid, p->state, dest_cpu);
@@ -1996,6 +2000,7 @@ int can_migrate_task(struct task_struct 
 	 * 1) running (obviously), or
 	 * 2) cannot be migrated to this CPU due to cpus_allowed, or
 	 * 3) are cache-hot on their current CPU.
+	 * 4) migration preemption is non 0 for this non running task.
 	 */
 	if (!cpu_isset(this_cpu, p->cpus_allowed))
 		return 0;
@@ -2003,6 +2008,8 @@ int can_migrate_task(struct task_struct 
 
 	if (task_running(rq, p))
 		return 0;
+	if (task_migrate_count(p))
+		return 0;
 
 	/*
 	 * Aggressive migration if too many balance attempts have failed:
@@ -3220,6 +3227,29 @@ void fastcall sub_preempt_count(int val)
 }
 EXPORT_SYMBOL(sub_preempt_count);
 
+void fastcall add_migrate_count(int val)
+{
+	/*
+	 * Underflow?
+	 */
+	if (DEBUG_LOCKS_WARN_ON((migrate_count() < 0)))
+		return;
+	migrate_count() += val;
+}
+EXPORT_SYMBOL(add_migrate_count);
+
+void fastcall sub_migrate_count(int val)
+{
+	/*
+	 * Underflow?
+	 */
+	if (DEBUG_LOCKS_WARN_ON(val > migrate_count()))
+		return;
+
+	migrate_count() -= val;
+}
+EXPORT_SYMBOL(sub_migrate_count);
+
 #endif
 
 /*
@@ -3353,6 +3383,28 @@ need_resched_nonpreemptible:
 EXPORT_SYMBOL(schedule);
 
 #ifdef CONFIG_PREEMPT
+
+#ifdef CONFIG_SMP
+/*
+ * Wake up the migration thread to deal with our pending migration.
+ * If we have been moved since, we will just wake up the migration thread from
+ * the wrong CPU, which does not hurt anyone. (that's why we use
+ * raw_smp_processor_id()).
+ */
+void __sched do_check_migrate(void)
+{
+	struct rq *rq;
+
+	if (migrate_count())
+		return;
+
+	clear_thread_flag(TIF_NEED_MIGRATE);
+	rq = cpu_rq(raw_smp_processor_id());
+	wake_up_process(rq->migration_thread);
+}
+EXPORT_SYMBOL(do_check_migrate);
+#endif
+
 /*
  * this is the entry point to schedule() from in-kernel preemption
  * off of preempt_enable.  Kernel preemptions off return from interrupt
@@ -4814,7 +4866,7 @@ EXPORT_SYMBOL_GPL(set_cpus_allowed);
  * So we race with normal scheduler movements, but that's OK, as long
  * as the task is no longer on this CPU.
  *
- * Returns non-zero if task was successfully migrated.
+ * Returns non-zero if task is not on src_cpu when this function ends.
  */
 static int __migrate_task(struct task_struct *p, int src_cpu, int dest_cpu)
 {
@@ -4829,13 +4881,17 @@ static int __migrate_task(struct task_st
 
 	double_rq_lock(rq_src, rq_dest);
 	/* Already moved. */
-	if (task_cpu(p) != src_cpu)
+	if (task_cpu(p) != src_cpu) {
+		ret = 1;
 		goto out;
+	}
 	/* Affinity changed (again). */
 	if (!cpu_isset(dest_cpu, p->cpus_allowed))
 		goto out;
 
 	on_rq = p->se.on_rq;
+	if (!on_rq && task_migrate_count(p))
+		goto out;
 	if (on_rq)
 		deactivate_task(rq_src, p, 0);
 	set_task_cpu(p, dest_cpu);
@@ -4858,6 +4914,7 @@ static int migration_thread(void *data)
 {
 	int cpu = (long)data;
 	struct rq *rq;
+	int migrated;
 
 	rq = cpu_rq(cpu);
 	BUG_ON(rq->migration_thread != current);
@@ -4891,10 +4948,42 @@ static int migration_thread(void *data)
 		list_del_init(head->next);
 
 		spin_unlock(&rq->lock);
-		__migrate_task(req->task, cpu, req->dest_cpu);
+		migrated = __migrate_task(req->task, cpu, req->dest_cpu);
 		local_irq_enable();
-
-		complete(&req->done);
+		if (!migrated) {
+			/*
+			 * If the process has not been migrated, let it run
+			 * until it reaches a migration_check() so it can
+			 * wake us up.
+			 */
+			spin_lock_irq(&rq->lock);
+			head = &rq->migration_queue;
+			list_add(&req->list, head);
+			if (req->task->se.on_rq
+					|| !task_migrate_count(req->task)) {
+				/*
+				 * The process is on the runqueue, it could
+				 * exit its critical section at any moment,
+				 * don't race with it and retry actively.
+				 * Also, if the thread is not on the runqueue
+				 * and has a zero migration count
+				 * (__migrate_task failed because cpus allowed
+				 * changed), just retry.
+				 */
+				spin_unlock_irq(&rq->lock);
+				continue;
+			}
+			set_tsk_thread_flag(req->task, TIF_NEED_MIGRATE);
+			set_current_state(TASK_INTERRUPTIBLE);
+			spin_unlock_irq(&rq->lock);
+			/*
+			 * Wait for the process currently in its critical
+			 * section.
+			 */
+			wake_up_process(req->task);
+			schedule();
+		} else
+			complete(&req->done);
 	}
 	__set_current_state(TASK_RUNNING);
 	return 0;
Index: linux-2.6-lttng/include/asm-alpha/thread_info.h
===================================================================
--- linux-2.6-lttng.orig/include/asm-alpha/thread_info.h	2007-07-14 13:20:11.000000000 -0400
+++ linux-2.6-lttng/include/asm-alpha/thread_info.h	2007-07-14 13:20:12.000000000 -0400
@@ -21,6 +21,7 @@ struct thread_info {
 	mm_segment_t		addr_limit;	/* thread address space */
 	unsigned		cpu;		/* current CPU */
 	int			preempt_count; /* 0 => preemptable, <0 => BUG */
+	int			migrate_count;/* 0: can migrate, <0 => BUG */
 
 	int bpt_nsaved;
 	unsigned long bpt_addr[2];		/* breakpoint handling  */
@@ -77,6 +78,7 @@ register struct thread_info *__current_t
 #define TIF_MEMDIE		8
 #define TIF_RESTORE_SIGMASK	9	/* restore signal mask in do_signal */
 #define	TIF_SYSCALL_AUDIT	10
+#define TIF_NEED_MIGRATE	11	/* migration necessary */
 
 #define _TIF_SYSCALL_TRACE	(1<<TIF_SYSCALL_TRACE)
 #define _TIF_SIGPENDING		(1<<TIF_SIGPENDING)
@@ -84,6 +86,7 @@ register struct thread_info *__current_t
 #define _TIF_POLLING_NRFLAG	(1<<TIF_POLLING_NRFLAG)
 #define _TIF_RESTORE_SIGMASK	(1<<TIF_RESTORE_SIGMASK)
 #define _TIF_SYSCALL_AUDIT	(1<<TIF_SYSCALL_AUDIT)
+#define _TIF_NEED_MIGRATE	(1<<TIF_NEED_MIGRATE)
 
 /* Work to do on interrupt/exception return.  */
 #define _TIF_WORK_MASK		(_TIF_SIGPENDING | _TIF_NEED_RESCHED)
Index: linux-2.6-lttng/include/asm-arm/thread_info.h
===================================================================
--- linux-2.6-lttng.orig/include/asm-arm/thread_info.h	2007-07-14 13:20:10.000000000 -0400
+++ linux-2.6-lttng/include/asm-arm/thread_info.h	2007-07-14 13:20:12.000000000 -0400
@@ -51,6 +51,7 @@ struct cpu_context_save {
 struct thread_info {
 	unsigned long		flags;		/* low level flags */
 	int			preempt_count;	/* 0 => preemptable, <0 => bug */
+	int			migrate_count;/* 0: can migrate, <0 => BUG */
 	mm_segment_t		addr_limit;	/* address limit */
 	struct task_struct	*task;		/* main task structure */
 	struct exec_domain	*exec_domain;	/* execution domain */
@@ -72,6 +73,7 @@ struct thread_info {
 	.exec_domain	= &default_exec_domain,				\
 	.flags		= 0,						\
 	.preempt_count	= 1,						\
+	.migrate_count = 0,						\
 	.addr_limit	= KERNEL_DS,					\
 	.cpu_domain	= domain_val(DOMAIN_USER, DOMAIN_MANAGER) |	\
 			  domain_val(DOMAIN_KERNEL, DOMAIN_MANAGER) |	\
@@ -137,12 +139,14 @@ extern void iwmmxt_task_switch(struct th
  *  TIF_SYSCALL_TRACE	- syscall trace active
  *  TIF_SIGPENDING	- signal pending
  *  TIF_NEED_RESCHED	- rescheduling necessary
+ *  TIF_NEED_MIGRATE	- migration necessary
  *  TIF_USEDFPU		- FPU was used by this task this quantum (SMP)
  *  TIF_POLLING_NRFLAG	- true if poll_idle() is polling TIF_NEED_RESCHED
  *  TIF_SYSCALL_AUDIT	- Syscall audting active - LTTng
  */
 #define TIF_SIGPENDING		0
 #define TIF_NEED_RESCHED	1
+#define TIF_NEED_MIGRATE	2
 #define	TIF_SYSCALL_AUDIT	7
 #define TIF_SYSCALL_TRACE	8
 #define TIF_POLLING_NRFLAG	16
@@ -152,6 +156,7 @@ extern void iwmmxt_task_switch(struct th
 
 #define _TIF_SIGPENDING		(1 << TIF_SIGPENDING)
 #define _TIF_NEED_RESCHED	(1 << TIF_NEED_RESCHED)
+#define _TIF_NEED_MIGRATE	(1 << TIF_NEED_MIGRATE)
 #define _TIF_SYSCALL_TRACE	(1 << TIF_SYSCALL_TRACE)
 #define	_TIF_SYSCALL_AUDIT	(1 << TIF_SYSCALL_AUDIT)
 #define _TIF_POLLING_NRFLAG	(1 << TIF_POLLING_NRFLAG)
Index: linux-2.6-lttng/include/asm-arm26/thread_info.h
===================================================================
--- linux-2.6-lttng.orig/include/asm-arm26/thread_info.h	2007-07-13 14:18:26.000000000 -0400
+++ linux-2.6-lttng/include/asm-arm26/thread_info.h	2007-07-14 13:20:12.000000000 -0400
@@ -45,6 +45,7 @@ struct cpu_context_save {
 struct thread_info {
 	unsigned long		flags;		/* low level flags */
 	int			preempt_count;	/* 0 => preemptable, <0 => bug */
+	int			migrate_count;/* 0: can migrate, <0 => BUG */
 	mm_segment_t		addr_limit;	/* address limit */
 	struct task_struct	*task;		/* main task structure */
 	struct exec_domain      *exec_domain;   /* execution domain */
@@ -60,6 +61,7 @@ struct thread_info {
 	.exec_domain	&default_exec_domain,	\
 	.flags		0,			\
 	.preempt_count	0,			\
+	.migrate_count 0,			\
 	.addr_limit	KERNEL_DS,		\
 	.restart_block  = {                             \
 		.fn     = do_no_restart_syscall,        \
@@ -112,11 +114,13 @@ extern void free_thread_info(struct thre
  *  TIF_SYSCALL_TRACE	- syscall trace active
  *  TIF_SIGPENDING	- signal pending
  *  TIF_NEED_RESCHED	- rescheduling necessary
+ *  TIF_NEED_MIGRATE	- migration necessary
  *  TIF_USEDFPU		- FPU was used by this task this quantum (SMP)
  *  TIF_POLLING_NRFLAG	- true if poll_idle() is polling TIF_NEED_RESCHED
  */
 #define TIF_SIGPENDING		0
 #define TIF_NEED_RESCHED	1
+#define TIF_NEED_MIGRATE	2
 #define TIF_SYSCALL_TRACE	8
 #define TIF_USED_FPU		16
 #define TIF_POLLING_NRFLAG	17
@@ -124,6 +128,7 @@ extern void free_thread_info(struct thre
 
 #define _TIF_SIGPENDING		(1 << TIF_SIGPENDING)
 #define _TIF_NEED_RESCHED	(1 << TIF_NEED_RESCHED)
+#define _TIF_NEED_MIGRATE	(1 << TIF_NEED_MIGRATE)
 #define _TIF_SYSCALL_TRACE	(1 << TIF_SYSCALL_TRACE)
 #define _TIF_USED_FPU		(1 << TIF_USED_FPU)
 #define _TIF_POLLING_NRFLAG	(1 << TIF_POLLING_NRFLAG)
Index: linux-2.6-lttng/include/asm-avr32/thread_info.h
===================================================================
--- linux-2.6-lttng.orig/include/asm-avr32/thread_info.h	2007-07-13 14:18:26.000000000 -0400
+++ linux-2.6-lttng/include/asm-avr32/thread_info.h	2007-07-14 13:20:12.000000000 -0400
@@ -25,6 +25,7 @@ struct thread_info {
 	unsigned long		flags;		/* low level flags */
 	__u32			cpu;
 	__s32			preempt_count;	/* 0 => preemptable, <0 => BUG */
+	int			migrate_count;/* 0: can migrate, <0 => BUG */
 	struct restart_block	restart_block;
 	__u8			supervisor_stack[0];
 };
@@ -36,6 +37,7 @@ struct thread_info {
 	.flags		= 0,						\
 	.cpu		= 0,						\
 	.preempt_count	= 1,						\
+	.migrate_count = 0,						\
 	.restart_block	= {						\
 		.fn	= do_no_restart_syscall				\
 	}								\
@@ -83,6 +85,7 @@ static inline struct thread_info *curren
 #define TIF_MEMDIE		6
 #define TIF_RESTORE_SIGMASK	7	/* restore signal mask in do_signal */
 #define TIF_CPU_GOING_TO_SLEEP	8	/* CPU is entering sleep 0 mode */
+#define TIF_NEED_MIGRATE      9       /* migration necessary */
 #define TIF_USERSPACE		31      /* true if FS sets userspace */
 
 #define _TIF_SYSCALL_TRACE	(1 << TIF_SYSCALL_TRACE)
@@ -94,6 +97,7 @@ static inline struct thread_info *curren
 #define _TIF_MEMDIE		(1 << TIF_MEMDIE)
 #define _TIF_RESTORE_SIGMASK	(1 << TIF_RESTORE_SIGMASK)
 #define _TIF_CPU_GOING_TO_SLEEP (1 << TIF_CPU_GOING_TO_SLEEP)
+#define _TIF_NEED_MIGRATE	(1 << TIF_NEED_MIGRATE)
 
 /* XXX: These two masks must never span more than 16 bits! */
 /* work to do on interrupt/exception return */
Index: linux-2.6-lttng/include/asm-blackfin/thread_info.h
===================================================================
--- linux-2.6-lttng.orig/include/asm-blackfin/thread_info.h	2007-07-13 14:18:26.000000000 -0400
+++ linux-2.6-lttng/include/asm-blackfin/thread_info.h	2007-07-14 13:20:12.000000000 -0400
@@ -54,6 +54,7 @@ struct thread_info {
 	unsigned long flags;	/* low level flags */
 	int cpu;		/* cpu we're on */
 	int preempt_count;	/* 0 => preemptable, <0 => BUG */
+	int migrate_count;	/* 0: can migrate, <0 => BUG */
 	mm_segment_t addr_limit;	/* address limit */
 	struct restart_block restart_block;
 	struct l1_scratch_task_info l1_task_info;
@@ -69,6 +70,7 @@ struct thread_info {
 	.flags		= 0,			\
 	.cpu		= 0,			\
 	.preempt_count  = 1,                    \
+	.migrate_count = 0,			\
 	.restart_block	= {			\
 		.fn = do_no_restart_syscall,	\
 	},					\
@@ -125,6 +127,7 @@ static inline struct thread_info *curren
 #define TIF_MEMDIE              4
 #define TIF_RESTORE_SIGMASK	5	/* restore signal mask in do_signal() */
 #define TIF_FREEZE              6       /* is freezing for suspend */
+#define TIF_NEED_MIGRATE	7	/* migration necessary */
 
 /* as above, but as bit values */
 #define _TIF_SYSCALL_TRACE	(1<<TIF_SYSCALL_TRACE)
@@ -133,6 +136,7 @@ static inline struct thread_info *curren
 #define _TIF_POLLING_NRFLAG	(1<<TIF_POLLING_NRFLAG)
 #define _TIF_RESTORE_SIGMASK	(1<<TIF_RESTORE_SIGMASK)
 #define _TIF_FREEZE             (1<<TIF_FREEZE)
+#define _TIF_NEED_MIGRATE	(1<<TIF_NEED_MIGRATE)
 
 #define _TIF_WORK_MASK		0x0000FFFE	/* work to do on interrupt/exception return */
 
Index: linux-2.6-lttng/include/asm-cris/thread_info.h
===================================================================
--- linux-2.6-lttng.orig/include/asm-cris/thread_info.h	2007-07-13 14:18:26.000000000 -0400
+++ linux-2.6-lttng/include/asm-cris/thread_info.h	2007-07-14 13:20:12.000000000 -0400
@@ -32,6 +32,7 @@ struct thread_info {
 	unsigned long		flags;		/* low level flags */
 	__u32			cpu;		/* current CPU */
 	int			preempt_count;	/* 0 => preemptable, <0 => BUG */
+	int			migrate_count;/* 0: can migrate, <0 => BUG */
 
 	mm_segment_t		addr_limit;	/* thread address space:
 					 	   0-0xBFFFFFFF for user-thead
@@ -58,6 +59,7 @@ struct thread_info {
 	.flags		= 0,				\
 	.cpu		= 0,				\
 	.preempt_count	= 1,				\
+	.migrate_count = 0,				\
 	.addr_limit	= KERNEL_DS,			\
 	.restart_block = {				\
 		       .fn = do_no_restart_syscall,	\
@@ -81,6 +83,7 @@ struct thread_info {
 #define TIF_SYSCALL_TRACE	0	/* syscall trace active */
 #define TIF_SIGPENDING		1	/* signal pending */
 #define TIF_NEED_RESCHED	2	/* rescheduling necessary */
+#define TIF_NEED_MIGRATE	3	/* migration necessary */
 #define TIF_POLLING_NRFLAG	16	/* true if poll_idle() is polling TIF_NEED_RESCHED */
 #define TIF_MEMDIE		17
 
@@ -88,6 +91,7 @@ struct thread_info {
 #define _TIF_SIGPENDING		(1<<TIF_SIGPENDING)
 #define _TIF_NEED_RESCHED	(1<<TIF_NEED_RESCHED)
 #define _TIF_POLLING_NRFLAG	(1<<TIF_POLLING_NRFLAG)
+#define _TIF_NEED_MIGRATE	(1<<TIF_NEED_MIGRATE)
 
 #define _TIF_WORK_MASK		0x0000FFFE	/* work to do on interrupt/exception return */
 #define _TIF_ALLWORK_MASK	0x0000FFFF	/* work to do on any return to u-space */
Index: linux-2.6-lttng/include/asm-frv/thread_info.h
===================================================================
--- linux-2.6-lttng.orig/include/asm-frv/thread_info.h	2007-07-13 14:18:26.000000000 -0400
+++ linux-2.6-lttng/include/asm-frv/thread_info.h	2007-07-14 13:20:12.000000000 -0400
@@ -36,6 +36,7 @@ struct thread_info {
 	unsigned long		status;		/* thread-synchronous flags */
 	__u32			cpu;		/* current CPU */
 	int			preempt_count;	/* 0 => preemptable, <0 => BUG */
+	int			migrate_count;/* 0: can migrate, <0 => BUG */
 
 	mm_segment_t		addr_limit;	/* thread address space:
 					 	   0-0xBFFFFFFF for user-thead
@@ -68,6 +69,7 @@ struct thread_info {
 	.flags		= 0,			\
 	.cpu		= 0,			\
 	.preempt_count	= 1,			\
+	.migrate_count = 0,			\
 	.addr_limit	= KERNEL_DS,		\
 	.restart_block = {			\
 		.fn = do_no_restart_syscall,	\
@@ -113,6 +115,7 @@ register struct thread_info *__current_t
 #define TIF_SINGLESTEP		3	/* restore singlestep on return to user mode */
 #define TIF_IRET		4	/* return with iret */
 #define TIF_RESTORE_SIGMASK	5	/* restore signal mask in do_signal() */
+#define TIF_NEED_MIGRATE	6	/* migration necessary */
 #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	/* freezing for suspend */
@@ -125,6 +128,7 @@ register struct thread_info *__current_t
 #define _TIF_RESTORE_SIGMASK	(1 << TIF_RESTORE_SIGMASK)
 #define _TIF_POLLING_NRFLAG	(1 << TIF_POLLING_NRFLAG)
 #define _TIF_FREEZE		(1 << TIF_FREEZE)
+#define _TIF_NEED_MIGRATE	(1 << TIF_NEED_MIGRATE)
 
 #define _TIF_WORK_MASK		0x0000FFFE	/* work to do on interrupt/exception return */
 #define _TIF_ALLWORK_MASK	0x0000FFFF	/* work to do on any return to u-space */
Index: linux-2.6-lttng/include/asm-h8300/thread_info.h
===================================================================
--- linux-2.6-lttng.orig/include/asm-h8300/thread_info.h	2007-07-13 14:18:26.000000000 -0400
+++ linux-2.6-lttng/include/asm-h8300/thread_info.h	2007-07-14 13:20:12.000000000 -0400
@@ -24,6 +24,7 @@ struct thread_info {
 	unsigned long	   flags;		/* low level flags */
 	int		   cpu;			/* cpu we're on */
 	int		   preempt_count;	/* 0 => preemptable, <0 => BUG */
+	int			migrate_count;/* 0: can migrate, <0 => BUG */
 	struct restart_block restart_block;
 };
 
@@ -37,6 +38,7 @@ struct thread_info {
 	.flags =	0,			\
 	.cpu =		0,			\
 	.preempt_count = 1,			\
+	.migrate_count = 0,			\
 	.restart_block	= {			\
 		.fn = do_no_restart_syscall,	\
 	},					\
@@ -91,12 +93,14 @@ static inline struct thread_info *curren
 #define TIF_POLLING_NRFLAG	3	/* true if poll_idle() is polling
 					   TIF_NEED_RESCHED */
 #define TIF_MEMDIE		4
+#define TIF_NEED_MIGRATE	5	/* migration necessary */
 
 /* as above, but as bit values */
 #define _TIF_SYSCALL_TRACE	(1<<TIF_SYSCALL_TRACE)
 #define _TIF_SIGPENDING		(1<<TIF_SIGPENDING)
 #define _TIF_NEED_RESCHED	(1<<TIF_NEED_RESCHED)
 #define _TIF_POLLING_NRFLAG	(1<<TIF_POLLING_NRFLAG)
+#define _TIF_NEED_MIGRATE	(1<<TIF_NEED_MIGRATE)
 
 #define _TIF_WORK_MASK		0x0000FFFE	/* work to do on interrupt/exception return */
 
Index: linux-2.6-lttng/include/asm-ia64/thread_info.h
===================================================================
--- linux-2.6-lttng.orig/include/asm-ia64/thread_info.h	2007-07-13 14:18:26.000000000 -0400
+++ linux-2.6-lttng/include/asm-ia64/thread_info.h	2007-07-14 13:20:12.000000000 -0400
@@ -30,6 +30,7 @@ struct thread_info {
 	__u32 status;			/* Thread synchronous flags */
 	mm_segment_t addr_limit;	/* user-level address space limit */
 	int preempt_count;		/* 0=premptable, <0=BUG; will also serve as bh-counter */
+	int migrate_count;		/* 0: can migrate, <0 => BUG */
 	struct restart_block restart_block;
 };
 
@@ -43,6 +44,7 @@ struct thread_info {
 	.cpu		= 0,			\
 	.addr_limit	= KERNEL_DS,		\
 	.preempt_count	= 0,			\
+	.migrate_count = 0,			\
 	.restart_block = {			\
 		.fn = do_no_restart_syscall,	\
 	},					\
@@ -86,6 +88,7 @@ struct thread_info {
 #define TIF_SINGLESTEP		4	/* restore singlestep on return to user mode */
 #define TIF_RESTORE_SIGMASK	5	/* restore signal mask in do_signal() */
 #define TIF_PERFMON_WORK	6	/* work for pfm_handle_work() */
+#define TIF_NEED_MIGRATE	7	/* migration necessary */
 #define TIF_POLLING_NRFLAG	16	/* true if poll_idle() is polling TIF_NEED_RESCHED */
 #define TIF_MEMDIE		17
 #define TIF_MCA_INIT		18	/* this task is processing MCA or INIT */
@@ -98,6 +101,7 @@ struct thread_info {
 #define _TIF_SYSCALL_TRACEAUDIT	(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SINGLESTEP)
 #define _TIF_RESTORE_SIGMASK	(1 << TIF_RESTORE_SIGMASK)
 #define _TIF_PERFMON_WORK	(1 << TIF_PERFMON_WORK)
+#define _TIF_NEED_MIGRATE	(1 << TIF_NEED_MIGRATE)
 #define _TIF_SIGPENDING		(1 << TIF_SIGPENDING)
 #define _TIF_NEED_RESCHED	(1 << TIF_NEED_RESCHED)
 #define _TIF_POLLING_NRFLAG	(1 << TIF_POLLING_NRFLAG)
Index: linux-2.6-lttng/include/asm-m32r/thread_info.h
===================================================================
--- linux-2.6-lttng.orig/include/asm-m32r/thread_info.h	2007-07-13 14:18:26.000000000 -0400
+++ linux-2.6-lttng/include/asm-m32r/thread_info.h	2007-07-14 13:20:12.000000000 -0400
@@ -29,6 +29,7 @@ struct thread_info {
 	unsigned long		status;		/* thread-synchronous flags */
 	__u32			cpu;		/* current CPU */
 	int			preempt_count;	/* 0 => preemptable, <0 => BUG */
+	int			migrate_count;/* 0: can migrate, <0 => BUG */
 
 	mm_segment_t		addr_limit;	/* thread address space:
 					 	   0-0xBFFFFFFF for user-thread
@@ -69,6 +70,7 @@ struct thread_info {
 	.flags		= 0,			\
 	.cpu		= 0,			\
 	.preempt_count	= 1,			\
+	.migrate_count = 0,			\
 	.addr_limit	= KERNEL_DS,		\
 	.restart_block = {			\
 		.fn = do_no_restart_syscall,	\
@@ -150,6 +152,7 @@ static inline unsigned int get_thread_fa
 #define TIF_NEED_RESCHED	2	/* rescheduling necessary */
 #define TIF_SINGLESTEP		3	/* restore singlestep on return to user mode */
 #define TIF_IRET		4	/* return with iret */
+#define TIF_NEED_MIGRATE	5	/* migration necessary */
 #define TIF_POLLING_NRFLAG	16	/* true if poll_idle() is polling TIF_NEED_RESCHED */
 					/* 31..28 fault code */
 #define TIF_MEMDIE		17
@@ -160,6 +163,7 @@ static inline unsigned int get_thread_fa
 #define _TIF_SINGLESTEP		(1<<TIF_SINGLESTEP)
 #define _TIF_IRET		(1<<TIF_IRET)
 #define _TIF_POLLING_NRFLAG	(1<<TIF_POLLING_NRFLAG)
+#define _TIF_NEED_MIGRATE	(1<<TIF_NEED_MIGRATE)
 
 #define _TIF_WORK_MASK		0x0000FFFE	/* work to do on interrupt/exception return */
 #define _TIF_ALLWORK_MASK	0x0000FFFF	/* work to do on any return to u-space */
Index: linux-2.6-lttng/include/asm-m68k/thread_info.h
===================================================================
--- linux-2.6-lttng.orig/include/asm-m68k/thread_info.h	2007-07-14 13:20:11.000000000 -0400
+++ linux-2.6-lttng/include/asm-m68k/thread_info.h	2007-07-14 13:20:12.000000000 -0400
@@ -9,6 +9,7 @@ struct thread_info {
 	unsigned long		flags;
 	struct exec_domain	*exec_domain;	/* execution domain */
 	int			preempt_count;	/* 0 => preemptable, <0 => BUG */
+	int			migrate_count;/* 0: can migrate, <0 => BUG */
 	__u32 cpu; /* should always be 0 on m68k */
 	struct restart_block    restart_block;
 };
@@ -59,5 +60,6 @@ struct thread_info {
 #define TIF_DELAYED_TRACE	14	/* single step a syscall */
 #define TIF_SYSCALL_TRACE	15	/* syscall trace active */
 #define TIF_MEMDIE		16
+#define TIF_NEED_MIGRATE	17	/* migration necessary */
 
 #endif	/* _ASM_M68K_THREAD_INFO_H */
Index: linux-2.6-lttng/include/asm-m68knommu/thread_info.h
===================================================================
--- linux-2.6-lttng.orig/include/asm-m68knommu/thread_info.h	2007-07-14 13:20:11.000000000 -0400
+++ linux-2.6-lttng/include/asm-m68knommu/thread_info.h	2007-07-14 13:20:12.000000000 -0400
@@ -37,6 +37,7 @@ struct thread_info {
 	unsigned long	   flags;		/* low level flags */
 	int		   cpu;			/* cpu we're on */
 	int		   preempt_count;	/* 0 => preemptable, <0 => BUG */
+	int		   migrate_count;	/* 0: can migrate, <0 => BUG */
 	struct restart_block restart_block;
 };
 
@@ -88,6 +89,7 @@ static inline struct thread_info *curren
 #define TIF_POLLING_NRFLAG	3	/* true if poll_idle() is polling
 					   TIF_NEED_RESCHED */
 #define TIF_MEMDIE		4
+#define TIF_NEED_MIGRATE	5	/* migration necessary */
 #define	TIF_SYSCALL_AUDIT	7	/* syscall auditing active */
 
 /* as above, but as bit values */
@@ -96,6 +98,7 @@ static inline struct thread_info *curren
 #define _TIF_NEED_RESCHED	(1<<TIF_NEED_RESCHED)
 #define _TIF_POLLING_NRFLAG	(1<<TIF_POLLING_NRFLAG)
 #define _TIF_MEMDIE		(1<<TIF_MEMDIE)
+#define _TIF_NEED_MIGRATE	(1<<TIF_NEED_MIGRATE)
 #define _TIF_SYSCALL_AUDIT	(1<<TIF_SYSCALL_AUDIT)
 
 #define _TIF_WORK_MASK		0x0000FFFE	/* work to do on interrupt/exception return */
Index: linux-2.6-lttng/include/asm-mips/thread_info.h
===================================================================
--- linux-2.6-lttng.orig/include/asm-mips/thread_info.h	2007-07-13 14:18:26.000000000 -0400
+++ linux-2.6-lttng/include/asm-mips/thread_info.h	2007-07-14 13:20:12.000000000 -0400
@@ -28,6 +28,7 @@ struct thread_info {
 	unsigned long		tp_value;	/* thread pointer */
 	__u32			cpu;		/* current CPU */
 	int			preempt_count;	/* 0 => preemptable, <0 => BUG */
+	int			migrate_count;/* 0: can migrate, <0 => BUG */
 
 	mm_segment_t		addr_limit;	/* thread address space:
 						   0-0xBFFFFFFF for user-thead
@@ -49,6 +50,7 @@ struct thread_info {
 	.flags		= 0,			\
 	.cpu		= 0,			\
 	.preempt_count	= 1,			\
+	.migrate_count = 0,			\
 	.addr_limit	= KERNEL_DS,		\
 	.restart_block	= {			\
 		.fn = do_no_restart_syscall,	\
@@ -113,6 +115,7 @@ register struct thread_info *__current_t
 #define TIF_NEED_RESCHED	2	/* rescheduling necessary */
 #define TIF_SYSCALL_AUDIT	3	/* syscall auditing active */
 #define TIF_SECCOMP		4	/* secure computing */
+#define TIF_NEED_MIGRATE	5	/* migration necessary */
 #define TIF_RESTORE_SIGMASK	9	/* restore signal mask in do_signal() */
 #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 */
@@ -125,6 +128,7 @@ register struct thread_info *__current_t
 #define _TIF_NEED_RESCHED	(1<<TIF_NEED_RESCHED)
 #define _TIF_SYSCALL_AUDIT	(1<<TIF_SYSCALL_AUDIT)
 #define _TIF_SECCOMP		(1<<TIF_SECCOMP)
+#define _TIF_NEED_MIGRATE	(1<<TIF_NEED_MIGRATE)
 #define _TIF_RESTORE_SIGMASK	(1<<TIF_RESTORE_SIGMASK)
 #define _TIF_USEDFPU		(1<<TIF_USEDFPU)
 #define _TIF_POLLING_NRFLAG	(1<<TIF_POLLING_NRFLAG)
Index: linux-2.6-lttng/include/asm-parisc/thread_info.h
===================================================================
--- linux-2.6-lttng.orig/include/asm-parisc/thread_info.h	2007-07-13 14:18:26.000000000 -0400
+++ linux-2.6-lttng/include/asm-parisc/thread_info.h	2007-07-14 13:20:12.000000000 -0400
@@ -13,6 +13,7 @@ struct thread_info {
 	mm_segment_t addr_limit;	/* user-level address space limit */
 	__u32 cpu;			/* current CPU */
 	int preempt_count;		/* 0=premptable, <0=BUG; will also serve as bh-counter */
+	int migrate_count;		/* 0: can migrate, <0 => BUG */
 	struct restart_block restart_block;
 };
 
@@ -24,6 +25,7 @@ struct thread_info {
 	.cpu		= 0,			\
 	.addr_limit	= KERNEL_DS,		\
 	.preempt_count	= 1,			\
+	.migrate_count = 0,			\
   	.restart_block	= {			\
 		.fn = do_no_restart_syscall	\
 	}					\
@@ -62,6 +64,7 @@ struct thread_info {
 #define TIF_32BIT               4       /* 32 bit binary */
 #define TIF_MEMDIE		5
 #define TIF_RESTORE_SIGMASK	6	/* restore saved signal mask */
+#define TIF_NEED_MIGRATE	7	/* migration necessary */
 
 #define _TIF_SYSCALL_TRACE	(1 << TIF_SYSCALL_TRACE)
 #define _TIF_SIGPENDING		(1 << TIF_SIGPENDING)
@@ -69,6 +72,7 @@ struct thread_info {
 #define _TIF_POLLING_NRFLAG	(1 << TIF_POLLING_NRFLAG)
 #define _TIF_32BIT		(1 << TIF_32BIT)
 #define _TIF_RESTORE_SIGMASK	(1 << TIF_RESTORE_SIGMASK)
+#define _TIF_NEED_MIGRATE	(1 << TIF_NEED_MIGRATE)
 
 #define _TIF_USER_WORK_MASK     (_TIF_SIGPENDING | \
                                  _TIF_NEED_RESCHED | _TIF_RESTORE_SIGMASK)
Index: linux-2.6-lttng/include/asm-powerpc/thread_info.h
===================================================================
--- linux-2.6-lttng.orig/include/asm-powerpc/thread_info.h	2007-07-13 14:18:26.000000000 -0400
+++ linux-2.6-lttng/include/asm-powerpc/thread_info.h	2007-07-14 13:20:12.000000000 -0400
@@ -35,6 +35,7 @@ struct thread_info {
 	int		cpu;			/* cpu we're on */
 	int		preempt_count;		/* 0 => preemptable,
 						   <0 => BUG */
+	int		migrate_count;	/* 0: can migrate, <0 => BUG */
 	struct restart_block restart_block;
 	unsigned long	local_flags;		/* private flags for thread */
 
@@ -53,6 +54,7 @@ struct thread_info {
 	.exec_domain =	&default_exec_domain,	\
 	.cpu =		0,			\
 	.preempt_count = 1,			\
+	.migrate_count = 0,			\
 	.restart_block = {			\
 		.fn = do_no_restart_syscall,	\
 	},					\
@@ -124,6 +126,7 @@ static inline struct thread_info *curren
 #define TIF_FREEZE		14	/* Freezing for suspend */
 #define TIF_RUNLATCH		15	/* Is the runlatch enabled? */
 #define TIF_ABI_PENDING		16	/* 32/64 bit switch needed */
+#define TIF_NEED_MIGRATE	17	/* migration necessary */
 
 /* as above, but as bit values */
 #define _TIF_SYSCALL_TRACE	(1<<TIF_SYSCALL_TRACE)
@@ -142,6 +145,7 @@ static inline struct thread_info *curren
 #define _TIF_FREEZE		(1<<TIF_FREEZE)
 #define _TIF_RUNLATCH		(1<<TIF_RUNLATCH)
 #define _TIF_ABI_PENDING	(1<<TIF_ABI_PENDING)
+#define _TIF_NEED_MIGRATE	(1<<TIF_NEED_MIGRATE)
 #define _TIF_SYSCALL_T_OR_A	(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SECCOMP)
 
 #define _TIF_USER_WORK_MASK	( _TIF_SIGPENDING | \
Index: linux-2.6-lttng/include/asm-s390/thread_info.h
===================================================================
--- linux-2.6-lttng.orig/include/asm-s390/thread_info.h	2007-07-13 14:18:26.000000000 -0400
+++ linux-2.6-lttng/include/asm-s390/thread_info.h	2007-07-14 13:20:12.000000000 -0400
@@ -51,6 +51,7 @@ struct thread_info {
 	unsigned long		flags;		/* low level flags */
 	unsigned int		cpu;		/* current CPU */
 	int			preempt_count;	/* 0 => preemptable, <0 => BUG */
+	int			migrate_count;/* 0: can migrate, <0 => BUG */
 	struct restart_block	restart_block;
 };
 
@@ -64,6 +65,7 @@ struct thread_info {
 	.flags		= 0,			\
 	.cpu		= 0,			\
 	.preempt_count	= 1,			\
+	.migrate_count = 0,			\
 	.restart_block	= {			\
 		.fn = do_no_restart_syscall,	\
 	},					\
@@ -96,6 +98,7 @@ static inline struct thread_info *curren
 #define TIF_SYSCALL_AUDIT	5	/* syscall auditing active */
 #define TIF_SINGLE_STEP		6	/* deliver sigtrap on return to user */
 #define TIF_MCCK_PENDING	7	/* machine check handling is pending */
+#define TIF_NEED_MIGRATE	8	/* migration necessary */
 #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 */
@@ -110,6 +113,7 @@ static inline struct thread_info *curren
 #define _TIF_SYSCALL_AUDIT	(1<<TIF_SYSCALL_AUDIT)
 #define _TIF_SINGLE_STEP	(1<<TIF_SINGLE_STEP)
 #define _TIF_MCCK_PENDING	(1<<TIF_MCCK_PENDING)
+#define _TIF_NEED_MIGRATE	(1<<TIF_NEED_MIGRATE)
 #define _TIF_USEDFPU		(1<<TIF_USEDFPU)
 #define _TIF_POLLING_NRFLAG	(1<<TIF_POLLING_NRFLAG)
 #define _TIF_31BIT		(1<<TIF_31BIT)
Index: linux-2.6-lttng/include/asm-sh/thread_info.h
===================================================================
--- linux-2.6-lttng.orig/include/asm-sh/thread_info.h	2007-07-14 13:20:11.000000000 -0400
+++ linux-2.6-lttng/include/asm-sh/thread_info.h	2007-07-14 13:20:12.000000000 -0400
@@ -21,6 +21,7 @@ struct thread_info {
 	unsigned long		flags;		/* low level flags */
 	__u32			cpu;
 	int			preempt_count; /* 0 => preemptable, <0 => BUG */
+	int			migrate_count;/* 0: can migrate, <0 => BUG */
 	mm_segment_t		addr_limit;	/* thread address space */
 	struct restart_block	restart_block;
 	unsigned long		previous_sp;	/* sp of previous stack in case
@@ -58,6 +59,7 @@ struct thread_info {
 	.flags		= 0,			\
 	.cpu		= 0,			\
 	.preempt_count	= 1,			\
+	.migrate_count = 0,			\
 	.addr_limit	= KERNEL_DS,		\
 	.restart_block	= {			\
 		.fn = do_no_restart_syscall,	\
@@ -112,6 +114,7 @@ static inline struct thread_info *curren
 #define TIF_RESTORE_SIGMASK	3	/* restore signal mask in do_signal() */
 #define TIF_SINGLESTEP		4	/* singlestepping active */
 #define	TIF_SYSCALL_AUDIT	6	/* syscall audit active */
+#define TIF_NEED_MIGRATE	7	/* migration necessary */
 #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
@@ -123,6 +126,7 @@ static inline struct thread_info *curren
 #define _TIF_RESTORE_SIGMASK	(1<<TIF_RESTORE_SIGMASK)
 #define _TIF_SINGLESTEP		(1<<TIF_SINGLESTEP)
 #define _TIF_SYSCALL_AUDIT	(1<<TIF_SYSCALL_AUDIT)
+#define _TIF_NEED_MIGRATE	(1<<TIF_NEED_MIGRATE)
 #define _TIF_USEDFPU		(1<<TIF_USEDFPU)
 #define _TIF_POLLING_NRFLAG	(1<<TIF_POLLING_NRFLAG)
 #define _TIF_FREEZE		(1<<TIF_FREEZE)
Index: linux-2.6-lttng/include/asm-sh64/thread_info.h
===================================================================
--- linux-2.6-lttng.orig/include/asm-sh64/thread_info.h	2007-07-14 13:20:11.000000000 -0400
+++ linux-2.6-lttng/include/asm-sh64/thread_info.h	2007-07-14 13:20:12.000000000 -0400
@@ -23,6 +23,7 @@ struct thread_info {
 	unsigned long		flags;		/* low level flags */
 	/* Put the 4 32-bit fields together to make asm offsetting easier. */
 	int			preempt_count;	/* 0 => preemptable, <0 => BUG */
+	int			migrate_count;/* 0: can migrate, <0 => BUG */
 	__u16			cpu;
 
 	mm_segment_t		addr_limit;
@@ -41,6 +42,7 @@ struct thread_info {
 	.flags		= 0,			\
 	.cpu		= 0,			\
 	.preempt_count	= 1,			\
+	.migrate_count = 0,			\
 	.addr_limit     = KERNEL_DS,            \
 	.restart_block	= {			\
 		.fn = do_no_restart_syscall,	\
@@ -80,12 +82,14 @@ static inline struct thread_info *curren
 #define TIF_NEED_RESCHED	3	/* rescheduling necessary */
 #define TIF_MEMDIE		4
 #define TIF_RESTORE_SIGMASK	5	/* Restore signal mask in do_signal */
+#define TIF_NEED_MIGRATE	6	/* migration necessary */
 
 #define _TIF_SYSCALL_TRACE	(1 << TIF_SYSCALL_TRACE)
 #define _TIF_SIGPENDING		(1 << TIF_SIGPENDING)
 #define _TIF_NEED_RESCHED	(1 << TIF_NEED_RESCHED)
 #define _TIF_MEMDIE		(1 << TIF_MEMDIE)
 #define _TIF_RESTORE_SIGMASK	(1 << TIF_RESTORE_SIGMASK)
+#define _TIF_NEED_MIGRATE	(1 << TIF_NEED_MIGRATE)
 
 #endif /* __KERNEL__ */
 
Index: linux-2.6-lttng/include/asm-sparc/thread_info.h
===================================================================
--- linux-2.6-lttng.orig/include/asm-sparc/thread_info.h	2007-07-14 13:20:11.000000000 -0400
+++ linux-2.6-lttng/include/asm-sparc/thread_info.h	2007-07-14 13:20:12.000000000 -0400
@@ -33,6 +33,7 @@ struct thread_info {
 	int			cpu;		/* cpu we're on */
 	int			preempt_count;	/* 0 => preemptable,
 						   <0 => BUG */
+	int			migrate_count;/* 0: can migrate, <0 => BUG */
 	int			softirq_count;
 	int			hardirq_count;
 
@@ -65,6 +66,7 @@ struct thread_info {
 	.flags		=	0,			\
 	.cpu		=	0,			\
 	.preempt_count	=	1,			\
+	.migrate_count =	0,			\
 	.restart_block	= {				\
 		.fn	=	do_no_restart_syscall,	\
 	},						\
@@ -132,6 +134,7 @@ BTFIXUPDEF_CALL(void, free_thread_info, 
 #define TIF_SIGPENDING		2	/* signal pending */
 #define TIF_NEED_RESCHED	3	/* rescheduling necessary */
 #define TIF_RESTORE_SIGMASK	4	/* restore signal mask in do_signal() */
+#define TIF_NEED_MIGRATE	5	/* migration necessary */
 #define TIF_USEDFPU		8	/* FPU was used by this task
 					 * this quantum (SMP) */
 #define TIF_POLLING_NRFLAG	9	/* true if poll_idle() is polling
@@ -144,6 +147,7 @@ BTFIXUPDEF_CALL(void, free_thread_info, 
 #define _TIF_SIGPENDING		(1<<TIF_SIGPENDING)
 #define _TIF_NEED_RESCHED	(1<<TIF_NEED_RESCHED)
 #define _TIF_RESTORE_SIGMASK	(1<<TIF_RESTORE_SIGMASK)
+#define _TIF_NEED_MIGRATE	(1<<TIF_NEED_MIGRATE)
 #define _TIF_USEDFPU		(1<<TIF_USEDFPU)
 #define _TIF_POLLING_NRFLAG	(1<<TIF_POLLING_NRFLAG)
 
Index: linux-2.6-lttng/include/asm-sparc64/thread_info.h
===================================================================
--- linux-2.6-lttng.orig/include/asm-sparc64/thread_info.h	2007-07-13 14:18:26.000000000 -0400
+++ linux-2.6-lttng/include/asm-sparc64/thread_info.h	2007-07-14 13:20:12.000000000 -0400
@@ -47,6 +47,7 @@ struct thread_info {
 	struct pt_regs		*kregs;
 	struct exec_domain	*exec_domain;
 	int			preempt_count;	/* 0 => preemptable, <0 => BUG */
+	int			migrate_count;/* 0: can migrate, <0 => BUG */
 	__u8			new_child;
 	__u8			syscall_noerror;
 	__u16			cpu;
@@ -137,6 +138,7 @@ struct thread_info {
 	.flags		= ((unsigned long)ASI_P) << TI_FLAG_CURRENT_DS_SHIFT,	\
 	.exec_domain	=	&default_exec_domain,	\
 	.preempt_count	=	1,			\
+	.migrate_count =	0,			\
 	.restart_block	= {				\
 		.fn	=	do_no_restart_syscall,	\
 	},						\
@@ -225,7 +227,7 @@ register struct thread_info *current_thr
 #define TIF_UNALIGNED		5	/* allowed to do unaligned accesses */
 #define TIF_NEWSIGNALS		6	/* wants new-style signals */
 #define TIF_32BIT		7	/* 32-bit binary */
-/* flag bit 8 is available */
+#define TIF_NEED_MIGRATE	8	/* migration necessary */
 #define TIF_SECCOMP		9	/* secure computing */
 #define TIF_SYSCALL_AUDIT	10	/* syscall auditing active */
 /* flag bit 11 is available */
@@ -244,6 +246,7 @@ register struct thread_info *current_thr
 #define _TIF_UNALIGNED		(1<<TIF_UNALIGNED)
 #define _TIF_NEWSIGNALS		(1<<TIF_NEWSIGNALS)
 #define _TIF_32BIT		(1<<TIF_32BIT)
+#define _TIF_NEED_MIGRATE	(1<<TIF_NEED_MIGRATE)
 #define _TIF_SECCOMP		(1<<TIF_SECCOMP)
 #define _TIF_SYSCALL_AUDIT	(1<<TIF_SYSCALL_AUDIT)
 #define _TIF_RESTORE_SIGMASK	(1<<TIF_RESTORE_SIGMASK)
Index: linux-2.6-lttng/include/asm-um/thread_info.h
===================================================================
--- linux-2.6-lttng.orig/include/asm-um/thread_info.h	2007-07-13 14:18:26.000000000 -0400
+++ linux-2.6-lttng/include/asm-um/thread_info.h	2007-07-14 13:20:12.000000000 -0400
@@ -18,6 +18,7 @@ struct thread_info {
 	__u32			cpu;		/* current CPU */
 	int			preempt_count;  /* 0 => preemptable,
 						   <0 => BUG */
+	int			migrate_count;/* 0: can migrate, <0 => BUG */
 	mm_segment_t		addr_limit;	/* thread address space:
 					 	   0-0xBFFFFFFF for user
 						   0-0xFFFFFFFF for kernel */
@@ -32,6 +33,7 @@ struct thread_info {
 	.flags =		0,		\
 	.cpu =		0,			\
 	.preempt_count =	1,		\
+	.migrate_count =	0,		\
 	.addr_limit =	KERNEL_DS,		\
 	.restart_block =  {			\
 		.fn =  do_no_restart_syscall,	\
@@ -82,6 +84,7 @@ static inline struct thread_info *curren
 #define TIF_MEMDIE	 	5
 #define TIF_SYSCALL_AUDIT	6
 #define TIF_RESTORE_SIGMASK	7
+#define TIF_NEED_MIGRATE	8	/* migration necessary */
 
 #define _TIF_SYSCALL_TRACE	(1 << TIF_SYSCALL_TRACE)
 #define _TIF_SIGPENDING		(1 << TIF_SIGPENDING)
@@ -90,5 +93,6 @@ static inline struct thread_info *curren
 #define _TIF_MEMDIE		(1 << TIF_MEMDIE)
 #define _TIF_SYSCALL_AUDIT	(1 << TIF_SYSCALL_AUDIT)
 #define _TIF_RESTORE_SIGMASK	(1 << TIF_RESTORE_SIGMASK)
+#define _TIF_NEED_MIGRATE	(1 << TIF_NEED_MIGRATE)
 
 #endif
Index: linux-2.6-lttng/include/asm-v850/thread_info.h
===================================================================
--- linux-2.6-lttng.orig/include/asm-v850/thread_info.h	2007-07-13 14:18:26.000000000 -0400
+++ linux-2.6-lttng/include/asm-v850/thread_info.h	2007-07-14 13:20:12.000000000 -0400
@@ -32,6 +32,7 @@ struct thread_info {
 	int			cpu;		/* cpu we're on */
 	int			preempt_count;	/* 0 => preemptable,
 						   <0 => BUG */
+	int			migrate_count;/* 0: can migrate, <0 => BUG */
 	struct restart_block	restart_block;
 };
 
@@ -42,6 +43,7 @@ struct thread_info {
 	.flags =	0,						      \
 	.cpu =		0,						      \
 	.preempt_count = 1,						      \
+	.migrate_count = 0,						      \
 	.restart_block = {						      \
 		.fn = do_no_restart_syscall,				      \
 	},								      \
@@ -82,12 +84,14 @@ struct thread_info {
 #define TIF_POLLING_NRFLAG	3	/* true if poll_idle() is polling
 					   TIF_NEED_RESCHED */
 #define TIF_MEMDIE		4
+#define TIF_NEED_MIGRATE	5	/* migration necessary */
 
 /* as above, but as bit values */
 #define _TIF_SYSCALL_TRACE	(1<<TIF_SYSCALL_TRACE)
 #define _TIF_SIGPENDING		(1<<TIF_SIGPENDING)
 #define _TIF_NEED_RESCHED	(1<<TIF_NEED_RESCHED)
 #define _TIF_POLLING_NRFLAG	(1<<TIF_POLLING_NRFLAG)
+#define _TIF_NEED_MIGRATE	(1<<TIF_NEED_MIGRATE)
 
 
 /* Size of kernel stack for each process.  */
Index: linux-2.6-lttng/include/asm-x86_64/thread_info.h
===================================================================
--- linux-2.6-lttng.orig/include/asm-x86_64/thread_info.h	2007-07-13 14:18:26.000000000 -0400
+++ linux-2.6-lttng/include/asm-x86_64/thread_info.h	2007-07-14 13:20:12.000000000 -0400
@@ -30,6 +30,7 @@ struct thread_info {
 	__u32			status;		/* thread synchronous flags */
 	__u32			cpu;		/* current CPU */
 	int 			preempt_count;	/* 0 => preemptable, <0 => BUG */
+	int			migrate_count;/* 0: can migrate, <0 => BUG */
 
 	mm_segment_t		addr_limit;	
 	struct restart_block    restart_block;
@@ -48,6 +49,7 @@ struct thread_info {
 	.flags	       = 0,			\
 	.cpu	       = 0,			\
 	.preempt_count = 1,			\
+	.migrate_count = 0,			\
 	.addr_limit     = KERNEL_DS,		\
 	.restart_block = {			\
 		.fn = do_no_restart_syscall,	\
@@ -115,6 +117,7 @@ static inline struct thread_info *stack_
 #define TIF_SECCOMP		8	/* secure computing */
 #define TIF_RESTORE_SIGMASK	9	/* restore signal mask in do_signal */
 #define TIF_MCE_NOTIFY		10	/* notify userspace of an MCE */
+#define TIF_NEED_MIGRATE	11	/* migration necessary */
 /* 16 free */
 #define TIF_IA32		17	/* 32bit process */ 
 #define TIF_FORK		18	/* ret_from_fork */
@@ -133,6 +136,7 @@ static inline struct thread_info *stack_
 #define _TIF_SECCOMP		(1<<TIF_SECCOMP)
 #define _TIF_RESTORE_SIGMASK	(1<<TIF_RESTORE_SIGMASK)
 #define _TIF_MCE_NOTIFY		(1<<TIF_MCE_NOTIFY)
+#define _TIF_NEED_MIGRATE	(1<<TIF_NEED_MIGRATE)
 #define _TIF_IA32		(1<<TIF_IA32)
 #define _TIF_FORK		(1<<TIF_FORK)
 #define _TIF_ABI_PENDING	(1<<TIF_ABI_PENDING)
Index: linux-2.6-lttng/include/asm-xtensa/thread_info.h
===================================================================
--- linux-2.6-lttng.orig/include/asm-xtensa/thread_info.h	2007-07-13 14:18:26.000000000 -0400
+++ linux-2.6-lttng/include/asm-xtensa/thread_info.h	2007-07-14 13:20:12.000000000 -0400
@@ -34,6 +34,7 @@ struct thread_info {
 	unsigned long		status;		/* thread-synchronous flags */
 	__u32			cpu;		/* current CPU */
 	__s32			preempt_count;	/* 0 => preemptable,< 0 => BUG*/
+	__s32			migrate_count;/* 0: can migrate, <0 => BUG */
 
 	mm_segment_t		addr_limit;	/* thread address space */
 	struct restart_block    restart_block;
@@ -72,6 +73,7 @@ struct thread_info {
 	.flags		= 0,			\
 	.cpu		= 0,			\
 	.preempt_count	= 1,			\
+	.migrate_count = 0,			\
 	.addr_limit	= KERNEL_DS,		\
 	.restart_block = {			\
 		.fn = do_no_restart_syscall,	\
@@ -116,6 +118,7 @@ static inline struct thread_info *curren
 #define TIF_IRET		4	/* return with iret */
 #define TIF_MEMDIE		5
 #define TIF_RESTORE_SIGMASK	6	/* restore signal mask in do_signal() */
+#define TIF_NEED_MIGRATE	7	/* migration necessary */
 #define TIF_POLLING_NRFLAG	16	/* true if poll_idle() is polling TIF_NEED_RESCHED */
 
 #define _TIF_SYSCALL_TRACE	(1<<TIF_SYSCALL_TRACE)
@@ -123,6 +126,7 @@ static inline struct thread_info *curren
 #define _TIF_NEED_RESCHED	(1<<TIF_NEED_RESCHED)
 #define _TIF_SINGLESTEP		(1<<TIF_SINGLESTEP)
 #define _TIF_IRET		(1<<TIF_IRET)
+#define _TIF_NEED_MIGRATE	(1<<TIF_NEED_MIGRATE)
 #define _TIF_POLLING_NRFLAG	(1<<TIF_POLLING_NRFLAG)
 #define _TIF_RESTORE_SIGMASK	(1<<TIF_RESTORE_SIGMASK)
 
Index: linux-2.6-lttng/lib/smp_processor_id.c
===================================================================
--- linux-2.6-lttng.orig/lib/smp_processor_id.c	2007-07-13 14:18:26.000000000 -0400
+++ linux-2.6-lttng/lib/smp_processor_id.c	2007-07-14 13:20:12.000000000 -0400
@@ -10,12 +10,16 @@
 unsigned int debug_smp_processor_id(void)
 {
 	unsigned long preempt_count = preempt_count();
+	unsigned long migrate_count = migrate_count();
 	int this_cpu = raw_smp_processor_id();
 	cpumask_t this_mask;
 
 	if (likely(preempt_count))
 		goto out;
 
+	if (likely(migrate_count))
+		goto out;
+
 	if (irqs_disabled())
 		goto out;
 
@@ -42,7 +46,7 @@ unsigned int debug_smp_processor_id(void
 	if (!printk_ratelimit())
 		goto out_enable;
 
-	printk(KERN_ERR "BUG: using smp_processor_id() in preemptible [%08x] code: %s/%d\n", preempt_count(), current->comm, current->pid);
+	printk(KERN_ERR "BUG: using smp_processor_id() in preemptible [%08x] migration [%08x] code: %s/%d\n", preempt_count(), migrate_count(), current->comm, current->pid);
 	print_symbol("caller is %s\n", (long)__builtin_return_address(0));
 	dump_stack();
 
-- 
Mathieu Desnoyers
Computer Engineering Ph.D. Student, Ecole Polytechnique de Montreal
OpenPGP key fingerprint: 8CD5 52C3 8E3C 4140 715F  BA06 3F25 A8FE 3BAE 9A68

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

* Re: [RFC] Thread Migration Preemption - v4
  2007-07-14 18:42         ` [RFC] Thread Migration Preemption - v4 Mathieu Desnoyers
@ 2007-07-14 19:14           ` Peter Zijlstra
  2007-07-14 20:25             ` Mathieu Desnoyers
  2007-07-14 19:30           ` Peter Zijlstra
  2007-07-14 20:23           ` Oleg Nesterov
  2 siblings, 1 reply; 33+ messages in thread
From: Peter Zijlstra @ 2007-07-14 19:14 UTC (permalink / raw)
  To: Mathieu Desnoyers
  Cc: Oleg Nesterov, linux-kernel, Ingo Molnar, Steven Rostedt

Would have been nice if you'd CC'ed me :-/

On Sat, 2007-07-14 at 14:42 -0400, Mathieu Desnoyers wrote:

> @@ -4891,10 +4948,42 @@ static int migration_thread(void *data)
>  		list_del_init(head->next);
>  
>  		spin_unlock(&rq->lock);
> -		__migrate_task(req->task, cpu, req->dest_cpu);
> +		migrated = __migrate_task(req->task, cpu, req->dest_cpu);
>  		local_irq_enable();
> -
> -		complete(&req->done);
> +		if (!migrated) {
> +			/*
> +			 * If the process has not been migrated, let it run
> +			 * until it reaches a migration_check() so it can
> +			 * wake us up.
> +			 */
> +			spin_lock_irq(&rq->lock);
> +			head = &rq->migration_queue;
> +			list_add(&req->list, head);
> +			if (req->task->se.on_rq
> +					|| !task_migrate_count(req->task)) {
> +				/*
> +				 * The process is on the runqueue, it could
> +				 * exit its critical section at any moment,
> +				 * don't race with it and retry actively.
> +				 * Also, if the thread is not on the runqueue
> +				 * and has a zero migration count
> +				 * (__migrate_task failed because cpus allowed
> +				 * changed), just retry.
> +				 */
> +				spin_unlock_irq(&rq->lock);
> +				continue;
> +			}
> +			set_tsk_thread_flag(req->task, TIF_NEED_MIGRATE);
> +			set_current_state(TASK_INTERRUPTIBLE);
> +			spin_unlock_irq(&rq->lock);
> +			/*
> +			 * Wait for the process currently in its critical
> +			 * section.
> +			 */
> +			wake_up_process(req->task);
> +			schedule();
> +		} else
> +			complete(&req->done);
>  	}
>  	__set_current_state(TASK_RUNNING);
>  	return 0;

I'm not really liking this, this way we hold up all other migration
requests.


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

* Re: [RFC] Thread Migration Preemption - v4
  2007-07-14 18:42         ` [RFC] Thread Migration Preemption - v4 Mathieu Desnoyers
  2007-07-14 19:14           ` Peter Zijlstra
@ 2007-07-14 19:30           ` Peter Zijlstra
  2007-07-14 20:26             ` Mathieu Desnoyers
  2007-07-14 20:23           ` Oleg Nesterov
  2 siblings, 1 reply; 33+ messages in thread
From: Peter Zijlstra @ 2007-07-14 19:30 UTC (permalink / raw)
  To: Mathieu Desnoyers
  Cc: Oleg Nesterov, linux-kernel, Ingo Molnar, Steven Rostedt

On Sat, 2007-07-14 at 14:42 -0400, Mathieu Desnoyers wrote:

> Note: (or we could say FIXME)
> Is we ever want to check migration pending in assembly code, we will have to
> make sure we test the right thread flag bits on each architectures. Care should
> also be taken to check that the thread flags used won't trigger false positives
> in non selective asm thread flag checks.
> 
> FIXME (HOTPLUG) :
> 
> > >     /* Affinity changed (again). */
> > >     if (!cpu_isset(dest_cpu, p->cpus_allowed))
> > >             goto out;
> > >  
> > >     on_rq = p->se.on_rq;
> > > +#ifdef CONFIG_PREEMPT
> > > +   if (!on_rq && task_thread_info(p)->migrate_count)
> > > +           goto out;
> > > +#endif
> > 
> > This means that move_task_off_dead_cpu() will spin until the task will be
> > scheduled
> > on the dead CPU. Given that we hold tasklist_lock and irqs are disabled, this
> > may
> > never happen.
> >
> 
> Yes. My idea to fix this issue is the following:
> 
> If a thread has non zero migrate_count, we should still move it to a
> different CPU upon hotplug cpu removal, even if this thread resists
> migration. Care should be taken to send _all_ such threads to the _same_
> CPU so they don't race for the per-cpu ressources. Does it make sense ?
> 
> We would have to keep the CPU affinity of the threads running on the
> wrong CPU until they end their migrate disabled section, so that we can
> put them back on their original CPU if it goes back online, otherwise we
> could end up with concurrent per-cpu variables accesses.
> 
> (I'll wait for reply before coding a solution for this CPU HOTPLUG
> related problem)

What would, aside from technical issues, be the problem with making
migration_disable() delay CPU_DOWN until migration_enable()?


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

* Re: [RFC] Thread Migration Preemption - v2
  2007-07-14 18:27         ` Mathieu Desnoyers
@ 2007-07-14 19:56           ` Oleg Nesterov
  0 siblings, 0 replies; 33+ messages in thread
From: Oleg Nesterov @ 2007-07-14 19:56 UTC (permalink / raw)
  To: Mathieu Desnoyers; +Cc: linux-kernel, Ingo Molnar, Steven Rostedt

On 07/14, Mathieu Desnoyers wrote:
>
> * Oleg Nesterov (oleg@tv-sign.ru) wrote:
> > >  	/* Affinity changed (again). */
> > >  	if (!cpu_isset(dest_cpu, p->cpus_allowed))
> > >  		goto out;
> > >  
> > >  	on_rq = p->se.on_rq;
> > > +#ifdef CONFIG_PREEMPT
> > > +	if (!on_rq && task_thread_info(p)->migrate_count)
> > > +		goto out;
> > > +#endif
> > 
> > This means that move_task_off_dead_cpu() will spin until the task will be scheduled
> > on the dead CPU. Given that we hold tasklist_lock and irqs are disabled, this may
> > never happen.
> > 
> 
> Yes. My idea to fix this issue is the following:
> 
> If a thread has non zero migrate_count, we should still move it to a
> different CPU upon hotplug cpu removal, even if this thread resists
> migration. Care should be taken to send _all_ such threads to the _same_
> CPU so they don't race for the per-cpu ressources. Does it make sense ?
> 
> We would have to keep the CPU affinity of the threads running on the
> wrong CPU until they end their migrate disabled section, so that we can
> put them back on their original CPU if it goes back online, otherwise we
> could end up with concurrent per-cpu variables accesses.

Well, this means that migrate_disable() doesn't guarantee a stable
smp_processor_id(), not good.

> > > @@ -4891,10 +4957,22 @@
> > >  		list_del_init(head->next);
> > >  
> > >  		spin_unlock(&rq->lock);
> > > -		__migrate_task(req->task, cpu, req->dest_cpu);
> > > +		migrated = __migrate_task(req->task, cpu, req->dest_cpu);
> > >  		local_irq_enable();
> > > -
> > > -		complete(&req->done);
> > > +		if (!migrated) {
> > > +			/*
> > > +			 * If the process has not been migrated, let it run
> > > +			 * until it reaches a migration_check() so it can
> > > +			 * wake us up.
> > > +			 */
> > > +			spin_lock_irq(&rq->lock);
> > > +			head = &rq->migration_queue;
> > > +			list_add(&req->list, head);
> > > +			set_tsk_thread_flag(req->task, TIF_NEED_MIGRATE);
> > > +			spin_unlock_irq(&rq->lock);
> > > +			wake_up_process(req->task);
> > > +		} else
> > > +			complete(&req->done);
> > 
> > I guess this is migration_thread(). The wake_up_process(req->task) looks strange,
> > why? It can't help if the task waits for the event/mutex.
> > 
> 
> Hrm, the idea was to wake up the thread that is in the migrate disabled
> section, which is what I seem to do req->task points to the process we
> try to migrate. We poke it like this until is ends its critical
> section.

But this can only waste CPU, nothing more, no? Suppose that req->thread
sleeps waiting for the mutex. You can wake it up, and it will call schedule()
again.

This can help if req->thread does something like schedule_timeout(), but
I don't think this is a common case.

Oleg.


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

* Re: [RFC] Thread Migration Preemption - v4
  2007-07-14 18:42         ` [RFC] Thread Migration Preemption - v4 Mathieu Desnoyers
  2007-07-14 19:14           ` Peter Zijlstra
  2007-07-14 19:30           ` Peter Zijlstra
@ 2007-07-14 20:23           ` Oleg Nesterov
  2007-07-14 20:33             ` Mathieu Desnoyers
  2 siblings, 1 reply; 33+ messages in thread
From: Oleg Nesterov @ 2007-07-14 20:23 UTC (permalink / raw)
  To: Mathieu Desnoyers; +Cc: linux-kernel, Ingo Molnar, Steven Rostedt

On 07/14, Mathieu Desnoyers wrote:
>
> @@ -4891,10 +4948,42 @@ static int migration_thread(void *data)
>  		list_del_init(head->next);
>  
>  		spin_unlock(&rq->lock);
> -		__migrate_task(req->task, cpu, req->dest_cpu);
> +		migrated = __migrate_task(req->task, cpu, req->dest_cpu);
>  		local_irq_enable();
> -
> -		complete(&req->done);
> +		if (!migrated) {
> +			/*
> +			 * If the process has not been migrated, let it run
> +			 * until it reaches a migration_check() so it can
> +			 * wake us up.
> +			 */
> +			spin_lock_irq(&rq->lock);
> +			head = &rq->migration_queue;
> +			list_add(&req->list, head);
> +			if (req->task->se.on_rq
> +					|| !task_migrate_count(req->task)) {
> +				/*
> +				 * The process is on the runqueue, it could
> +				 * exit its critical section at any moment,
> +				 * don't race with it and retry actively.
> +				 * Also, if the thread is not on the runqueue
> +				 * and has a zero migration count
> +				 * (__migrate_task failed because cpus allowed
> +				 * changed), just retry.
> +				 */
> +				spin_unlock_irq(&rq->lock);
> +				continue;

Again, this can deadlock. migration_thread() is SCHED_FIFO, and it shares the
same CPU with req->task. We are doing a busy-wait loop, req->task may have no
chance to finish its critical section.

> +			}
> +			set_tsk_thread_flag(req->task, TIF_NEED_MIGRATE);
> +			set_current_state(TASK_INTERRUPTIBLE);
> +			spin_unlock_irq(&rq->lock);
> +			/*
> +			 * Wait for the process currently in its critical
> +			 * section.
> +			 */
> +			wake_up_process(req->task);
> +			schedule();

As Peter pointed out, we hold up all other migration requests.

And worse, this can hang forever (until another req comes). do_check_migrate()
can wake_up() the wrong rq.

set_current_state(TASK_INTERRUPTIBLE) is bogus, we can miss a wakeup from
(say) sched_migrate_task().

Oleg.


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

* Re: [RFC] Thread Migration Preemption - v4
  2007-07-14 19:14           ` Peter Zijlstra
@ 2007-07-14 20:25             ` Mathieu Desnoyers
  0 siblings, 0 replies; 33+ messages in thread
From: Mathieu Desnoyers @ 2007-07-14 20:25 UTC (permalink / raw)
  To: Peter Zijlstra; +Cc: Oleg Nesterov, linux-kernel, Ingo Molnar, Steven Rostedt

* Peter Zijlstra (a.p.zijlstra@chello.nl) wrote:
> Would have been nice if you'd CC'ed me :-/
> 
Sorry

> On Sat, 2007-07-14 at 14:42 -0400, Mathieu Desnoyers wrote:
> 
> > @@ -4891,10 +4948,42 @@ static int migration_thread(void *data)
> >  		list_del_init(head->next);
> >  
> >  		spin_unlock(&rq->lock);
> > -		__migrate_task(req->task, cpu, req->dest_cpu);
> > +		migrated = __migrate_task(req->task, cpu, req->dest_cpu);
> >  		local_irq_enable();
> > -
> > -		complete(&req->done);
> > +		if (!migrated) {
> > +			/*
> > +			 * If the process has not been migrated, let it run
> > +			 * until it reaches a migration_check() so it can
> > +			 * wake us up.
> > +			 */
> > +			spin_lock_irq(&rq->lock);
> > +			head = &rq->migration_queue;
> > +			list_add(&req->list, head);
> > +			if (req->task->se.on_rq
> > +					|| !task_migrate_count(req->task)) {
> > +				/*
> > +				 * The process is on the runqueue, it could
> > +				 * exit its critical section at any moment,
> > +				 * don't race with it and retry actively.
> > +				 * Also, if the thread is not on the runqueue
> > +				 * and has a zero migration count
> > +				 * (__migrate_task failed because cpus allowed
> > +				 * changed), just retry.
> > +				 */
> > +				spin_unlock_irq(&rq->lock);
> > +				continue;
> > +			}
> > +			set_tsk_thread_flag(req->task, TIF_NEED_MIGRATE);
> > +			set_current_state(TASK_INTERRUPTIBLE);
> > +			spin_unlock_irq(&rq->lock);
> > +			/*
> > +			 * Wait for the process currently in its critical
> > +			 * section.
> > +			 */
> > +			wake_up_process(req->task);
> > +			schedule();
> > +		} else
> > +			complete(&req->done);
> >  	}
> >  	__set_current_state(TASK_RUNNING);
> >  	return 0;
> 
> I'm not really liking this, this way we hold up all other migration
> requests.
> 

True. You approach of delayed migration helps on this.

-- 
Mathieu Desnoyers
Computer Engineering Ph.D. Student, Ecole Polytechnique de Montreal
OpenPGP key fingerprint: 8CD5 52C3 8E3C 4140 715F  BA06 3F25 A8FE 3BAE 9A68

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

* Re: [RFC] Thread Migration Preemption - v4
  2007-07-14 19:30           ` Peter Zijlstra
@ 2007-07-14 20:26             ` Mathieu Desnoyers
  0 siblings, 0 replies; 33+ messages in thread
From: Mathieu Desnoyers @ 2007-07-14 20:26 UTC (permalink / raw)
  To: Peter Zijlstra; +Cc: Oleg Nesterov, linux-kernel, Ingo Molnar, Steven Rostedt

* Peter Zijlstra (a.p.zijlstra@chello.nl) wrote:
> On Sat, 2007-07-14 at 14:42 -0400, Mathieu Desnoyers wrote:
> 
> > Note: (or we could say FIXME)
> > Is we ever want to check migration pending in assembly code, we will have to
> > make sure we test the right thread flag bits on each architectures. Care should
> > also be taken to check that the thread flags used won't trigger false positives
> > in non selective asm thread flag checks.
> > 
> > FIXME (HOTPLUG) :
> > 
> > > >     /* Affinity changed (again). */
> > > >     if (!cpu_isset(dest_cpu, p->cpus_allowed))
> > > >             goto out;
> > > >  
> > > >     on_rq = p->se.on_rq;
> > > > +#ifdef CONFIG_PREEMPT
> > > > +   if (!on_rq && task_thread_info(p)->migrate_count)
> > > > +           goto out;
> > > > +#endif
> > > 
> > > This means that move_task_off_dead_cpu() will spin until the task will be
> > > scheduled
> > > on the dead CPU. Given that we hold tasklist_lock and irqs are disabled, this
> > > may
> > > never happen.
> > >
> > 
> > Yes. My idea to fix this issue is the following:
> > 
> > If a thread has non zero migrate_count, we should still move it to a
> > different CPU upon hotplug cpu removal, even if this thread resists
> > migration. Care should be taken to send _all_ such threads to the _same_
> > CPU so they don't race for the per-cpu ressources. Does it make sense ?
> > 
> > We would have to keep the CPU affinity of the threads running on the
> > wrong CPU until they end their migrate disabled section, so that we can
> > put them back on their original CPU if it goes back online, otherwise we
> > could end up with concurrent per-cpu variables accesses.
> > 
> > (I'll wait for reply before coding a solution for this CPU HOTPLUG
> > related problem)
> 
> What would, aside from technical issues, be the problem with making
> migration_disable() delay CPU_DOWN until migration_enable()?
> 

Because if we thing a little further, migration disabling could be a
very interesting way to provide cheap per-cpu data structure access to
user-space. But we would not want user-space processes to hold CPU_DOWN
forever...

-- 
Mathieu Desnoyers
Computer Engineering Ph.D. Student, Ecole Polytechnique de Montreal
OpenPGP key fingerprint: 8CD5 52C3 8E3C 4140 715F  BA06 3F25 A8FE 3BAE 9A68

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

* Re: [RFC] Thread Migration Preemption - v4
  2007-07-14 20:23           ` Oleg Nesterov
@ 2007-07-14 20:33             ` Mathieu Desnoyers
  2007-07-14 20:42               ` Oleg Nesterov
  0 siblings, 1 reply; 33+ messages in thread
From: Mathieu Desnoyers @ 2007-07-14 20:33 UTC (permalink / raw)
  To: Oleg Nesterov; +Cc: linux-kernel, Ingo Molnar, Steven Rostedt

* Oleg Nesterov (oleg@tv-sign.ru) wrote:
> On 07/14, Mathieu Desnoyers wrote:
> >
> > @@ -4891,10 +4948,42 @@ static int migration_thread(void *data)
> >  		list_del_init(head->next);
> >  
> >  		spin_unlock(&rq->lock);
> > -		__migrate_task(req->task, cpu, req->dest_cpu);
> > +		migrated = __migrate_task(req->task, cpu, req->dest_cpu);
> >  		local_irq_enable();
> > -
> > -		complete(&req->done);
> > +		if (!migrated) {
> > +			/*
> > +			 * If the process has not been migrated, let it run
> > +			 * until it reaches a migration_check() so it can
> > +			 * wake us up.
> > +			 */
> > +			spin_lock_irq(&rq->lock);
> > +			head = &rq->migration_queue;
> > +			list_add(&req->list, head);
> > +			if (req->task->se.on_rq
> > +					|| !task_migrate_count(req->task)) {
> > +				/*
> > +				 * The process is on the runqueue, it could
> > +				 * exit its critical section at any moment,
> > +				 * don't race with it and retry actively.
> > +				 * Also, if the thread is not on the runqueue
> > +				 * and has a zero migration count
> > +				 * (__migrate_task failed because cpus allowed
> > +				 * changed), just retry.
> > +				 */
> > +				spin_unlock_irq(&rq->lock);
> > +				continue;
> 
> Again, this can deadlock. migration_thread() is SCHED_FIFO, and it shares the
> same CPU with req->task. We are doing a busy-wait loop, req->task may have no
> chance to finish its critical section.
> 

If we share the CPU with the other thread, it means that it won't be on
the runqueue while we are holding the rq lock. This first case will then
end up in the else branch.

The other case, !task_migrate_count(req->task), is meant to check if the
process has been scheduled between the unlock/lock of the rq. In this
case, it has already decremented its migrate_count to 0.

> > +			}
> > +			set_tsk_thread_flag(req->task, TIF_NEED_MIGRATE);
> > +			set_current_state(TASK_INTERRUPTIBLE);
> > +			spin_unlock_irq(&rq->lock);
> > +			/*
> > +			 * Wait for the process currently in its critical
> > +			 * section.
> > +			 */
> > +			wake_up_process(req->task);
> > +			schedule();
> 
> As Peter pointed out, we hold up all other migration requests.
> 
> And worse, this can hang forever (until another req comes). do_check_migrate()
> can wake_up() the wrong rq.

True.

> 
> set_current_state(TASK_INTERRUPTIBLE) is bogus, we can miss a wakeup from
> (say) sched_migrate_task().
> 

Yep, this is why it's an RFC. We will have to work on this a little
more.

Regards,

Mathieu

> Oleg.
> 

-- 
Mathieu Desnoyers
Computer Engineering Ph.D. Student, Ecole Polytechnique de Montreal
OpenPGP key fingerprint: 8CD5 52C3 8E3C 4140 715F  BA06 3F25 A8FE 3BAE 9A68

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

* Re: [RFC] Thread Migration Preemption - v4
  2007-07-14 20:33             ` Mathieu Desnoyers
@ 2007-07-14 20:42               ` Oleg Nesterov
  0 siblings, 0 replies; 33+ messages in thread
From: Oleg Nesterov @ 2007-07-14 20:42 UTC (permalink / raw)
  To: Mathieu Desnoyers; +Cc: linux-kernel, Ingo Molnar, Steven Rostedt

On 07/14, Mathieu Desnoyers wrote:
>
> * Oleg Nesterov (oleg@tv-sign.ru) wrote:
> > On 07/14, Mathieu Desnoyers wrote:
> > >
> > > @@ -4891,10 +4948,42 @@ static int migration_thread(void *data)
> > >  		list_del_init(head->next);
> > >  
> > >  		spin_unlock(&rq->lock);
> > > -		__migrate_task(req->task, cpu, req->dest_cpu);
> > > +		migrated = __migrate_task(req->task, cpu, req->dest_cpu);
> > >  		local_irq_enable();
> > > -
> > > -		complete(&req->done);
> > > +		if (!migrated) {
> > > +			/*
> > > +			 * If the process has not been migrated, let it run
> > > +			 * until it reaches a migration_check() so it can
> > > +			 * wake us up.
> > > +			 */
> > > +			spin_lock_irq(&rq->lock);
> > > +			head = &rq->migration_queue;
> > > +			list_add(&req->list, head);
> > > +			if (req->task->se.on_rq
> > > +					|| !task_migrate_count(req->task)) {
> > > +				/*
> > > +				 * The process is on the runqueue, it could
> > > +				 * exit its critical section at any moment,
> > > +				 * don't race with it and retry actively.
> > > +				 * Also, if the thread is not on the runqueue
> > > +				 * and has a zero migration count
> > > +				 * (__migrate_task failed because cpus allowed
> > > +				 * changed), just retry.
> > > +				 */
> > > +				spin_unlock_irq(&rq->lock);
> > > +				continue;
> > 
> > Again, this can deadlock. migration_thread() is SCHED_FIFO, and it shares the
> > same CPU with req->task. We are doing a busy-wait loop, req->task may have no
> > chance to finish its critical section.
> > 
> 
> If we share the CPU with the other thread, it means that it won't be on
> the runqueue while we are holding the rq lock.

Why? The req->task could be runnable, but preempted by migration_thread().
In that case req->task->se.on_rq should be true.

I didn't read the new scheduler yet, but I belive on_rq == 0 only when
the task sleeps, it is like the current ->array = NULL. Please correct
me if I am wrong.

Oleg.


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

* Re: [RFC] Thread Migration Preemption
  2007-07-05 21:51 [RFC] Thread Migration Preemption Mathieu Desnoyers
                   ` (2 preceding siblings ...)
  2007-07-06 11:59 ` Andi Kleen
@ 2007-07-23 18:33 ` Ingo Molnar
  3 siblings, 0 replies; 33+ messages in thread
From: Ingo Molnar @ 2007-07-23 18:33 UTC (permalink / raw)
  To: Mathieu Desnoyers
  Cc: Steven Rostedt, Ingo Molnar, linux-kernel, Peter Zijlstra,
	Andrew Morton


* Mathieu Desnoyers <mathieu.desnoyers@polymtl.ca> wrote:

> Thread Migration Preemption
> 
> This patch adds the ability to protect critical sections from 
> migration to another CPU without disabling preemption.
> 
> This will be useful to minimize the amount of preemption disabling for 
> the -rt patch. [...]

unfortunately this abstraction has a number of fundamental 
disadvantages. (and hence the -rt patch does not make use of this 
facility)

firstly, its effects on load-balancing are quite brutal: it disables 
migration to another CPU, hence disturbing SMP load-balancing. It also 
adds an unplannable O(N) overhead into the load-balancer.

secondly, it has similar problems as preempt_disable(): it's opaque (not 
attached to a data structure) and thus it does not truly map the per-CPU 
data structure in any explicit way. It's little more than a per-task BKL 
for per-CPU data structures.

so in -rt we resisted the disable-migration approach from the early days 
on and are using two approaches to 'map' per-cpu data structures to 
PREEMPT_RT: firstly the use of PER_CPU_LOCKED data structures (which 
attach a per-cpu sleeping lock to per_cpu() data structures) - these are 
relatively easy first-approach conversions. As a second approach, if 
performance matters, the use of true atomic data structures.

	Ingo

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

end of thread, other threads:[~2007-07-23 18:33 UTC | newest]

Thread overview: 33+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2007-07-06  6:02 [RFC] Thread Migration Preemption Oleg Nesterov
2007-07-06 14:23 ` Mathieu Desnoyers
2007-07-06 14:56   ` Oleg Nesterov
2007-07-11  4:49     ` [RFC] Thread Migration Preemption - v2 Mathieu Desnoyers
2007-07-11 16:36       ` Oleg Nesterov
2007-07-14 18:27         ` Mathieu Desnoyers
2007-07-14 19:56           ` Oleg Nesterov
2007-07-14 18:40         ` [RFC] Thread Migration Preemption - v3 Mathieu Desnoyers
2007-07-14 18:42         ` [RFC] Thread Migration Preemption - v4 Mathieu Desnoyers
2007-07-14 19:14           ` Peter Zijlstra
2007-07-14 20:25             ` Mathieu Desnoyers
2007-07-14 19:30           ` Peter Zijlstra
2007-07-14 20:26             ` Mathieu Desnoyers
2007-07-14 20:23           ` Oleg Nesterov
2007-07-14 20:33             ` Mathieu Desnoyers
2007-07-14 20:42               ` Oleg Nesterov
  -- strict thread matches above, loose matches on Subject: below --
2007-07-05 21:51 [RFC] Thread Migration Preemption Mathieu Desnoyers
2007-07-05 22:46 ` Steven Rostedt
2007-07-06  6:12 ` Nick Piggin
2007-07-06 14:34   ` Mathieu Desnoyers
2007-07-06 14:34   ` Steven Rostedt
2007-07-06 15:43     ` Daniel Walker
2007-07-08  9:05     ` Nick Piggin
2007-07-10 23:39   ` Matt Mackall
2007-07-11  0:02     ` Nick Piggin
2007-07-11  0:36       ` Matt Mackall
2007-07-11  0:55         ` Mathieu Desnoyers
2007-07-11  1:15           ` Nick Piggin
2007-07-06 11:59 ` Andi Kleen
2007-07-06 14:41   ` Mathieu Desnoyers
2007-07-06 17:11     ` Andi Kleen
2007-07-11  4:57       ` Mathieu Desnoyers
2007-07-23 18:33 ` Ingo Molnar

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