From 4e64c8dfdb92fa358349c24969c617039ab88cd3 Mon Sep 17 00:00:00 2001
From: Leon Woestenberg <leon.woestenberg@gmail.com>
Date: Sun, 6 May 2007 15:32:33 +0000
Subject: linux-efika: Add kernel 2.6.20.11 with CFS scheduler.

---
 .../linux/linux-efika-2.6.20.11/.mtn2git_empty     |    0
 .../sched-cfs-v9-v2.6.20.11.patch                  | 5590 ++++++++++++++++++++
 packages/linux/linux-efika_2.6.20.11.bb            |   86 +
 3 files changed, 5676 insertions(+)
 create mode 100644 packages/linux/linux-efika-2.6.20.11/.mtn2git_empty
 create mode 100644 packages/linux/linux-efika-2.6.20.11/sched-cfs-v9-v2.6.20.11.patch
 create mode 100644 packages/linux/linux-efika_2.6.20.11.bb

diff --git a/packages/linux/linux-efika-2.6.20.11/.mtn2git_empty b/packages/linux/linux-efika-2.6.20.11/.mtn2git_empty
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/packages/linux/linux-efika-2.6.20.11/sched-cfs-v9-v2.6.20.11.patch b/packages/linux/linux-efika-2.6.20.11/sched-cfs-v9-v2.6.20.11.patch
new file mode 100644
index 0000000000..29071a99ac
--- /dev/null
+++ b/packages/linux/linux-efika-2.6.20.11/sched-cfs-v9-v2.6.20.11.patch
@@ -0,0 +1,5590 @@
+This is the Complete Fair Scheduler (CFS) v9 patch for
+linux 2.6.20.10 patch (rediffed cleanly against .11).
+
+http://people.redhat.com/mingo/cfs-scheduler/
+
+Index: linux-cfs-2.6.20.8.q/Documentation/kernel-parameters.txt
+===================================================================
+--- linux-cfs-2.6.20.8.q.orig/Documentation/kernel-parameters.txt
++++ linux-cfs-2.6.20.8.q/Documentation/kernel-parameters.txt
+@@ -914,49 +914,6 @@ and is between 256 and 4096 characters. 
+ 
+ 	mga=		[HW,DRM]
+ 
+-	migration_cost=
+-			[KNL,SMP] debug: override scheduler migration costs
+-			Format: <level-1-usecs>,<level-2-usecs>,...
+-			This debugging option can be used to override the
+-			default scheduler migration cost matrix. The numbers
+-			are indexed by 'CPU domain distance'.
+-			E.g. migration_cost=1000,2000,3000 on an SMT NUMA
+-			box will set up an intra-core migration cost of
+-			1 msec, an inter-core migration cost of 2 msecs,
+-			and an inter-node migration cost of 3 msecs.
+-
+-			WARNING: using the wrong values here can break
+-			scheduler performance, so it's only for scheduler
+-			development purposes, not production environments.
+-
+-	migration_debug=
+-			[KNL,SMP] migration cost auto-detect verbosity
+-			Format=<0|1|2>
+-			If a system's migration matrix reported at bootup
+-			seems erroneous then this option can be used to
+-			increase verbosity of the detection process.
+-			We default to 0 (no extra messages), 1 will print
+-			some more information, and 2 will be really
+-			verbose (probably only useful if you also have a
+-			serial console attached to the system).
+-
+-	migration_factor=
+-			[KNL,SMP] multiply/divide migration costs by a factor
+-			Format=<percent>
+-			This debug option can be used to proportionally
+-			increase or decrease the auto-detected migration
+-			costs for all entries of the migration matrix.
+-			E.g. migration_factor=150 will increase migration
+-			costs by 50%. (and thus the scheduler will be less
+-			eager migrating cache-hot tasks)
+-			migration_factor=80 will decrease migration costs
+-			by 20%. (thus the scheduler will be more eager to
+-			migrate tasks)
+-
+-			WARNING: using the wrong values here can break
+-			scheduler performance, so it's only for scheduler
+-			development purposes, not production environments.
+-
+ 	mousedev.tap_time=
+ 			[MOUSE] Maximum time between finger touching and
+ 			leaving touchpad surface for touch to be considered
+Index: linux-cfs-2.6.20.8.q/Documentation/sched-design-CFS.txt
+===================================================================
+--- /dev/null
++++ linux-cfs-2.6.20.8.q/Documentation/sched-design-CFS.txt
+@@ -0,0 +1,107 @@
++[announce] [patch] Modular Scheduler Core and Completely Fair Scheduler [CFS]
++
++i'm pleased to announce the first release of the "Modular Scheduler Core
++and Completely Fair Scheduler [CFS]" patchset:
++
++   http://redhat.com/~mingo/cfs-scheduler/
++
++This project is a complete rewrite of the Linux task scheduler. My goal
++is to address various feature requests and to fix deficiencies in the
++vanilla scheduler that were suggested/found in the past few years, both
++for desktop scheduling and for server scheduling workloads.
++
++[ QuickStart: apply the patch, recompile, reboot. The new scheduler
++  will be active by default and all tasks will default to the
++  SCHED_NORMAL interactive scheduling class. ]
++
++Highlights are:
++
++ - the introduction of Scheduling Classes: an extensible hierarchy of
++   scheduler modules. These modules encapsulate scheduling policy
++   details and are handled by the scheduler core without the core
++   code assuming about them too much.
++
++ - sched_fair.c implements the 'CFS desktop scheduler': it is a
++   replacement for the vanilla scheduler's SCHED_OTHER interactivity
++   code.
++
++   i'd like to give credit to Con Kolivas for the general approach here:
++   he has proven via RSDL/SD that 'fair scheduling' is possible and that
++   it results in better desktop scheduling. Kudos Con!
++
++   The CFS patch uses a completely different approach and implementation
++   from RSDL/SD. My goal was to make CFS's interactivity quality exceed
++   that of RSDL/SD, which is a high standard to meet :-) Testing
++   feedback is welcome to decide this one way or another. [ and, in any
++   case, all of SD's logic could be added via a kernel/sched_sd.c module
++   as well, if Con is interested in such an approach. ]
++
++   CFS's design is quite radical: it does not use runqueues, it uses a
++   time-ordered rbtree to build a 'timeline' of future task execution,
++   and thus has no 'array switch' artifacts (by which both the vanilla
++   scheduler and RSDL/SD are affected).
++
++   CFS uses nanosecond granularity accounting and does not rely on any
++   jiffies or other HZ detail. Thus the CFS scheduler has no notion of
++   'timeslices' and has no heuristics whatsoever. There is only one
++   central tunable:
++
++         /proc/sys/kernel/sched_granularity_ns
++
++   which can be used to tune the scheduler from 'desktop' (low
++   latencies) to 'server' (good batching) workloads. It defaults to a
++   setting suitable for desktop workloads. SCHED_BATCH is handled by the
++   CFS scheduler module too.
++
++   due to its design, the CFS scheduler is not prone to any of the
++   'attacks' that exist today against the heuristics of the stock
++   scheduler: fiftyp.c, thud.c, chew.c, ring-test.c, massive_intr.c all
++   work fine and do not impact interactivity and produce the expected
++   behavior.
++
++   the CFS scheduler has a much stronger handling of nice levels and
++   SCHED_BATCH: both types of workloads should be isolated much more
++   agressively than under the vanilla scheduler.
++
++   ( another rdetail: due to nanosec accounting and timeline sorting,
++     sched_yield() support is very simple under CFS, and in fact under
++     CFS sched_yield() behaves much better than under any other
++     scheduler i have tested so far. )
++
++ - sched_rt.c implements SCHED_FIFO and SCHED_RR semantics, in a simpler
++   way than the vanilla scheduler does. It uses 100 runqueues (for all
++   100 RT priority levels, instead of 140 in the vanilla scheduler)
++   and it needs no expired array.
++
++ - reworked/sanitized SMP load-balancing: the runqueue-walking
++   assumptions are gone from the load-balancing code now, and
++   iterators of the scheduling modules are used. The balancing code got
++   quite a bit simpler as a result.
++
++the core scheduler got smaller by more than 700 lines:
++
++ kernel/sched.c | 1454 ++++++++++++++++------------------------------------------------
++ 1 file changed, 372 insertions(+), 1082 deletions(-)
++
++and even adding all the scheduling modules, the total size impact is
++relatively small:
++
++ 18 files changed, 1454 insertions(+), 1133 deletions(-)
++
++most of the increase is due to extensive comments. The kernel size
++impact is in fact a small negative:
++
++   text    data     bss     dec     hex filename
++  23366    4001      24   27391    6aff kernel/sched.o.vanilla
++  24159    2705      56   26920    6928 kernel/sched.o.CFS
++
++(this is mainly due to the benefit of getting rid of the expired array
++and its data structure overhead.)
++
++thanks go to Thomas Gleixner and Arjan van de Ven for review of this
++patchset.
++
++as usual, any sort of feedback, bugreports, fixes and suggestions are
++more than welcome,
++
++	Ingo
+Index: linux-cfs-2.6.20.8.q/Makefile
+===================================================================
+--- linux-cfs-2.6.20.8.q.orig/Makefile
++++ linux-cfs-2.6.20.8.q/Makefile
+@@ -1,7 +1,7 @@
+ VERSION = 2
+ PATCHLEVEL = 6
+ SUBLEVEL = 20
+-EXTRAVERSION = .11
++EXTRAVERSION = .11-cfs-v9
+ NAME = Homicidal Dwarf Hamster
+ 
+ # *DOCUMENTATION*
+Index: linux-cfs-2.6.20.8.q/arch/i386/kernel/smpboot.c
+===================================================================
+--- linux-cfs-2.6.20.8.q.orig/arch/i386/kernel/smpboot.c
++++ linux-cfs-2.6.20.8.q/arch/i386/kernel/smpboot.c
+@@ -1132,18 +1132,6 @@ exit:
+ }
+ #endif
+ 
+-static void smp_tune_scheduling(void)
+-{
+-	unsigned long cachesize;       /* kB   */
+-
+-	if (cpu_khz) {
+-		cachesize = boot_cpu_data.x86_cache_size;
+-
+-		if (cachesize > 0)
+-			max_cache_size = cachesize * 1024;
+-	}
+-}
+-
+ /*
+  * Cycle through the processors sending APIC IPIs to boot each.
+  */
+@@ -1172,7 +1160,6 @@ static void __init smp_boot_cpus(unsigne
+ 	x86_cpu_to_apicid[0] = boot_cpu_physical_apicid;
+ 
+ 	current_thread_info()->cpu = 0;
+-	smp_tune_scheduling();
+ 
+ 	set_cpu_sibling_map(0);
+ 
+Index: linux-cfs-2.6.20.8.q/arch/i386/kernel/syscall_table.S
+===================================================================
+--- linux-cfs-2.6.20.8.q.orig/arch/i386/kernel/syscall_table.S
++++ linux-cfs-2.6.20.8.q/arch/i386/kernel/syscall_table.S
+@@ -319,3 +319,4 @@ ENTRY(sys_call_table)
+ 	.long sys_move_pages
+ 	.long sys_getcpu
+ 	.long sys_epoll_pwait
++	.long sys_sched_yield_to	/* 320 */
+Index: linux-cfs-2.6.20.8.q/arch/i386/kernel/tsc.c
+===================================================================
+--- linux-cfs-2.6.20.8.q.orig/arch/i386/kernel/tsc.c
++++ linux-cfs-2.6.20.8.q/arch/i386/kernel/tsc.c
+@@ -61,6 +61,8 @@ static inline int check_tsc_unstable(voi
+ 
+ void mark_tsc_unstable(void)
+ {
++	sched_clock_unstable_event();
++
+ 	tsc_unstable = 1;
+ }
+ EXPORT_SYMBOL_GPL(mark_tsc_unstable);
+@@ -107,13 +109,7 @@ unsigned long long sched_clock(void)
+ {
+ 	unsigned long long this_offset;
+ 
+-	/*
+-	 * in the NUMA case we dont use the TSC as they are not
+-	 * synchronized across all CPUs.
+-	 */
+-#ifndef CONFIG_NUMA
+-	if (!cpu_khz || check_tsc_unstable())
+-#endif
++	if (!cpu_khz || !cpu_has_tsc)
+ 		/* no locking but a rare wrong value is not a big deal */
+ 		return (jiffies_64 - INITIAL_JIFFIES) * (1000000000 / HZ);
+ 
+Index: linux-cfs-2.6.20.8.q/arch/ia64/kernel/setup.c
+===================================================================
+--- linux-cfs-2.6.20.8.q.orig/arch/ia64/kernel/setup.c
++++ linux-cfs-2.6.20.8.q/arch/ia64/kernel/setup.c
+@@ -773,7 +773,6 @@ static void __cpuinit
+ get_max_cacheline_size (void)
+ {
+ 	unsigned long line_size, max = 1;
+-	unsigned int cache_size = 0;
+ 	u64 l, levels, unique_caches;
+         pal_cache_config_info_t cci;
+         s64 status;
+@@ -803,8 +802,6 @@ get_max_cacheline_size (void)
+ 		line_size = 1 << cci.pcci_line_size;
+ 		if (line_size > max)
+ 			max = line_size;
+-		if (cache_size < cci.pcci_cache_size)
+-			cache_size = cci.pcci_cache_size;
+ 		if (!cci.pcci_unified) {
+ 			status = ia64_pal_cache_config_info(l,
+ 						    /* cache_type (instruction)= */ 1,
+@@ -821,9 +818,6 @@ get_max_cacheline_size (void)
+ 			ia64_i_cache_stride_shift = cci.pcci_stride;
+ 	}
+   out:
+-#ifdef CONFIG_SMP
+-	max_cache_size = max(max_cache_size, cache_size);
+-#endif
+ 	if (max > ia64_max_cacheline_size)
+ 		ia64_max_cacheline_size = max;
+ }
+Index: linux-cfs-2.6.20.8.q/arch/mips/kernel/smp.c
+===================================================================
+--- linux-cfs-2.6.20.8.q.orig/arch/mips/kernel/smp.c
++++ linux-cfs-2.6.20.8.q/arch/mips/kernel/smp.c
+@@ -245,7 +245,6 @@ void __init smp_prepare_cpus(unsigned in
+ {
+ 	init_new_context(current, &init_mm);
+ 	current_thread_info()->cpu = 0;
+-	smp_tune_scheduling();
+ 	plat_prepare_cpus(max_cpus);
+ #ifndef CONFIG_HOTPLUG_CPU
+ 	cpu_present_map = cpu_possible_map;
+Index: linux-cfs-2.6.20.8.q/arch/sparc/kernel/smp.c
+===================================================================
+--- linux-cfs-2.6.20.8.q.orig/arch/sparc/kernel/smp.c
++++ linux-cfs-2.6.20.8.q/arch/sparc/kernel/smp.c
+@@ -69,16 +69,6 @@ void __cpuinit smp_store_cpu_info(int id
+ 	cpu_data(id).prom_node = cpu_node;
+ 	cpu_data(id).mid = cpu_get_hwmid(cpu_node);
+ 
+-	/* this is required to tune the scheduler correctly */
+-	/* is it possible to have CPUs with different cache sizes? */
+-	if (id == boot_cpu_id) {
+-		int cache_line,cache_nlines;
+-		cache_line = 0x20;
+-		cache_line = prom_getintdefault(cpu_node, "ecache-line-size", cache_line);
+-		cache_nlines = 0x8000;
+-		cache_nlines = prom_getintdefault(cpu_node, "ecache-nlines", cache_nlines);
+-		max_cache_size = cache_line * cache_nlines;
+-	}
+ 	if (cpu_data(id).mid < 0)
+ 		panic("No MID found for CPU%d at node 0x%08d", id, cpu_node);
+ }
+Index: linux-cfs-2.6.20.8.q/arch/sparc64/kernel/smp.c
+===================================================================
+--- linux-cfs-2.6.20.8.q.orig/arch/sparc64/kernel/smp.c
++++ linux-cfs-2.6.20.8.q/arch/sparc64/kernel/smp.c
+@@ -1293,41 +1293,6 @@ int setup_profiling_timer(unsigned int m
+ 	return 0;
+ }
+ 
+-static void __init smp_tune_scheduling(void)
+-{
+-	struct device_node *dp;
+-	int instance;
+-	unsigned int def, smallest = ~0U;
+-
+-	def = ((tlb_type == hypervisor) ?
+-	       (3 * 1024 * 1024) :
+-	       (4 * 1024 * 1024));
+-
+-	instance = 0;
+-	while (!cpu_find_by_instance(instance, &dp, NULL)) {
+-		unsigned int val;
+-
+-		val = of_getintprop_default(dp, "ecache-size", def);
+-		if (val < smallest)
+-			smallest = val;
+-
+-		instance++;
+-	}
+-
+-	/* Any value less than 256K is nonsense.  */
+-	if (smallest < (256U * 1024U))
+-		smallest = 256 * 1024;
+-
+-	max_cache_size = smallest;
+-
+-	if (smallest < 1U * 1024U * 1024U)
+-		printk(KERN_INFO "Using max_cache_size of %uKB\n",
+-		       smallest / 1024U);
+-	else
+-		printk(KERN_INFO "Using max_cache_size of %uMB\n",
+-		       smallest / 1024U / 1024U);
+-}
+-
+ /* Constrain the number of cpus to max_cpus.  */
+ void __init smp_prepare_cpus(unsigned int max_cpus)
+ {
+@@ -1363,7 +1328,6 @@ void __init smp_prepare_cpus(unsigned in
+ 	}
+ 
+ 	smp_store_cpu_info(boot_cpu_id);
+-	smp_tune_scheduling();
+ }
+ 
+ /* Set this up early so that things like the scheduler can init
+Index: linux-cfs-2.6.20.8.q/fs/proc/array.c
+===================================================================
+--- linux-cfs-2.6.20.8.q.orig/fs/proc/array.c
++++ linux-cfs-2.6.20.8.q/fs/proc/array.c
+@@ -165,7 +165,6 @@ static inline char * task_state(struct t
+ 	rcu_read_lock();
+ 	buffer += sprintf(buffer,
+ 		"State:\t%s\n"
+-		"SleepAVG:\t%lu%%\n"
+ 		"Tgid:\t%d\n"
+ 		"Pid:\t%d\n"
+ 		"PPid:\t%d\n"
+@@ -173,9 +172,8 @@ static inline char * task_state(struct t
+ 		"Uid:\t%d\t%d\t%d\t%d\n"
+ 		"Gid:\t%d\t%d\t%d\t%d\n",
+ 		get_task_state(p),
+-		(p->sleep_avg/1024)*100/(1020000000/1024),
+-	       	p->tgid, p->pid,
+-	       	pid_alive(p) ? rcu_dereference(p->real_parent)->tgid : 0,
++		p->tgid, p->pid,
++		pid_alive(p) ? rcu_dereference(p->real_parent)->tgid : 0,
+ 		pid_alive(p) && p->ptrace ? rcu_dereference(p->parent)->pid : 0,
+ 		p->uid, p->euid, p->suid, p->fsuid,
+ 		p->gid, p->egid, p->sgid, p->fsgid);
+@@ -312,6 +310,11 @@ int proc_pid_status(struct task_struct *
+ 	return buffer - orig;
+ }
+ 
++int proc_pid_sched(struct task_struct *task, char *buffer)
++{
++	return sched_print_task_state(task, buffer) - buffer;
++}
++
+ static int do_task_stat(struct task_struct *task, char * buffer, int whole)
+ {
+ 	unsigned long vsize, eip, esp, wchan = ~0UL;
+Index: linux-cfs-2.6.20.8.q/fs/proc/base.c
+===================================================================
+--- linux-cfs-2.6.20.8.q.orig/fs/proc/base.c
++++ linux-cfs-2.6.20.8.q/fs/proc/base.c
+@@ -1839,6 +1839,7 @@ static struct pid_entry tgid_base_stuff[
+ 	INF("environ",    S_IRUSR, pid_environ),
+ 	INF("auxv",       S_IRUSR, pid_auxv),
+ 	INF("status",     S_IRUGO, pid_status),
++	INF("sched",      S_IRUGO, pid_sched),
+ 	INF("cmdline",    S_IRUGO, pid_cmdline),
+ 	INF("stat",       S_IRUGO, tgid_stat),
+ 	INF("statm",      S_IRUGO, pid_statm),
+@@ -2121,6 +2122,7 @@ static struct pid_entry tid_base_stuff[]
+ 	INF("environ",   S_IRUSR, pid_environ),
+ 	INF("auxv",      S_IRUSR, pid_auxv),
+ 	INF("status",    S_IRUGO, pid_status),
++	INF("sched",     S_IRUGO, pid_sched),
+ 	INF("cmdline",   S_IRUGO, pid_cmdline),
+ 	INF("stat",      S_IRUGO, tid_stat),
+ 	INF("statm",     S_IRUGO, pid_statm),
+Index: linux-cfs-2.6.20.8.q/fs/proc/internal.h
+===================================================================
+--- linux-cfs-2.6.20.8.q.orig/fs/proc/internal.h
++++ linux-cfs-2.6.20.8.q/fs/proc/internal.h
+@@ -36,6 +36,7 @@ extern int proc_exe_link(struct inode *,
+ extern int proc_tid_stat(struct task_struct *,  char *);
+ extern int proc_tgid_stat(struct task_struct *, char *);
+ extern int proc_pid_status(struct task_struct *, char *);
++extern int proc_pid_sched(struct task_struct *, char *);
+ extern int proc_pid_statm(struct task_struct *, char *);
+ 
+ extern struct file_operations proc_maps_operations;
+Index: linux-cfs-2.6.20.8.q/include/asm-generic/bitops/sched.h
+===================================================================
+--- linux-cfs-2.6.20.8.q.orig/include/asm-generic/bitops/sched.h
++++ linux-cfs-2.6.20.8.q/include/asm-generic/bitops/sched.h
+@@ -6,28 +6,23 @@
+ 
+ /*
+  * Every architecture must define this function. It's the fastest
+- * way of searching a 140-bit bitmap where the first 100 bits are
+- * unlikely to be set. It's guaranteed that at least one of the 140
+- * bits is cleared.
++ * way of searching a 100-bit bitmap.  It's guaranteed that at least
++ * one of the 100 bits is cleared.
+  */
+ static inline int sched_find_first_bit(const unsigned long *b)
+ {
+ #if BITS_PER_LONG == 64
+-	if (unlikely(b[0]))
++	if (b[0])
+ 		return __ffs(b[0]);
+-	if (likely(b[1]))
+-		return __ffs(b[1]) + 64;
+-	return __ffs(b[2]) + 128;
++	return __ffs(b[1]) + 64;
+ #elif BITS_PER_LONG == 32
+-	if (unlikely(b[0]))
++	if (b[0])
+ 		return __ffs(b[0]);
+-	if (unlikely(b[1]))
++	if (b[1])
+ 		return __ffs(b[1]) + 32;
+-	if (unlikely(b[2]))
++	if (b[2])
+ 		return __ffs(b[2]) + 64;
+-	if (b[3])
+-		return __ffs(b[3]) + 96;
+-	return __ffs(b[4]) + 128;
++	return __ffs(b[3]) + 96;
+ #else
+ #error BITS_PER_LONG not defined
+ #endif
+Index: linux-cfs-2.6.20.8.q/include/asm-i386/topology.h
+===================================================================
+--- linux-cfs-2.6.20.8.q.orig/include/asm-i386/topology.h
++++ linux-cfs-2.6.20.8.q/include/asm-i386/topology.h
+@@ -85,7 +85,6 @@ static inline int node_to_first_cpu(int 
+ 	.idle_idx		= 1,			\
+ 	.newidle_idx		= 2,			\
+ 	.wake_idx		= 1,			\
+-	.per_cpu_gain		= 100,			\
+ 	.flags			= SD_LOAD_BALANCE	\
+ 				| SD_BALANCE_EXEC	\
+ 				| SD_BALANCE_FORK	\
+Index: linux-cfs-2.6.20.8.q/include/asm-i386/unistd.h
+===================================================================
+--- linux-cfs-2.6.20.8.q.orig/include/asm-i386/unistd.h
++++ linux-cfs-2.6.20.8.q/include/asm-i386/unistd.h
+@@ -325,10 +325,11 @@
+ #define __NR_move_pages		317
+ #define __NR_getcpu		318
+ #define __NR_epoll_pwait	319
++#define __NR_sched_yield_to	320
+ 
+ #ifdef __KERNEL__
+ 
+-#define NR_syscalls 320
++#define NR_syscalls 321
+ 
+ #define __ARCH_WANT_IPC_PARSE_VERSION
+ #define __ARCH_WANT_OLD_READDIR
+Index: linux-cfs-2.6.20.8.q/include/asm-ia64/topology.h
+===================================================================
+--- linux-cfs-2.6.20.8.q.orig/include/asm-ia64/topology.h
++++ linux-cfs-2.6.20.8.q/include/asm-ia64/topology.h
+@@ -65,7 +65,6 @@ void build_cpu_to_node_map(void);
+ 	.max_interval		= 4,			\
+ 	.busy_factor		= 64,			\
+ 	.imbalance_pct		= 125,			\
+-	.per_cpu_gain		= 100,			\
+ 	.cache_nice_tries	= 2,			\
+ 	.busy_idx		= 2,			\
+ 	.idle_idx		= 1,			\
+@@ -97,7 +96,6 @@ void build_cpu_to_node_map(void);
+ 	.newidle_idx		= 0, /* unused */	\
+ 	.wake_idx		= 1,			\
+ 	.forkexec_idx		= 1,			\
+-	.per_cpu_gain		= 100,			\
+ 	.flags			= SD_LOAD_BALANCE	\
+ 				| SD_BALANCE_EXEC	\
+ 				| SD_BALANCE_FORK	\
+Index: linux-cfs-2.6.20.8.q/include/asm-mips/mach-ip27/topology.h
+===================================================================
+--- linux-cfs-2.6.20.8.q.orig/include/asm-mips/mach-ip27/topology.h
++++ linux-cfs-2.6.20.8.q/include/asm-mips/mach-ip27/topology.h
+@@ -28,7 +28,6 @@ extern unsigned char __node_distances[MA
+ 	.busy_factor		= 32,			\
+ 	.imbalance_pct		= 125,			\
+ 	.cache_nice_tries	= 1,			\
+-	.per_cpu_gain		= 100,			\
+ 	.flags			= SD_LOAD_BALANCE	\
+ 				| SD_BALANCE_EXEC	\
+ 				| SD_WAKE_BALANCE,	\
+Index: linux-cfs-2.6.20.8.q/include/asm-powerpc/topology.h
+===================================================================
+--- linux-cfs-2.6.20.8.q.orig/include/asm-powerpc/topology.h
++++ linux-cfs-2.6.20.8.q/include/asm-powerpc/topology.h
+@@ -57,7 +57,6 @@ static inline int pcibus_to_node(struct 
+ 	.busy_factor		= 32,			\
+ 	.imbalance_pct		= 125,			\
+ 	.cache_nice_tries	= 1,			\
+-	.per_cpu_gain		= 100,			\
+ 	.busy_idx		= 3,			\
+ 	.idle_idx		= 1,			\
+ 	.newidle_idx		= 2,			\
+Index: linux-cfs-2.6.20.8.q/include/asm-x86_64/topology.h
+===================================================================
+--- linux-cfs-2.6.20.8.q.orig/include/asm-x86_64/topology.h
++++ linux-cfs-2.6.20.8.q/include/asm-x86_64/topology.h
+@@ -43,7 +43,6 @@ extern int __node_distance(int, int);
+ 	.newidle_idx		= 0, 			\
+ 	.wake_idx		= 1,			\
+ 	.forkexec_idx		= 1,			\
+-	.per_cpu_gain		= 100,			\
+ 	.flags			= SD_LOAD_BALANCE	\
+ 				| SD_BALANCE_FORK	\
+ 				| SD_BALANCE_EXEC	\
+Index: linux-cfs-2.6.20.8.q/include/asm-x86_64/unistd.h
+===================================================================
+--- linux-cfs-2.6.20.8.q.orig/include/asm-x86_64/unistd.h
++++ linux-cfs-2.6.20.8.q/include/asm-x86_64/unistd.h
+@@ -619,8 +619,10 @@ __SYSCALL(__NR_sync_file_range, sys_sync
+ __SYSCALL(__NR_vmsplice, sys_vmsplice)
+ #define __NR_move_pages		279
+ __SYSCALL(__NR_move_pages, sys_move_pages)
++#define __NR_sched_yield_to	280
++__SYSCALL(__NR_sched_yield_to, sys_sched_yield_to)
+ 
+-#define __NR_syscall_max __NR_move_pages
++#define __NR_syscall_max __NR_sched_yield_to
+ 
+ #ifndef __NO_STUBS
+ #define __ARCH_WANT_OLD_READDIR
+Index: linux-cfs-2.6.20.8.q/include/linux/hardirq.h
+===================================================================
+--- linux-cfs-2.6.20.8.q.orig/include/linux/hardirq.h
++++ linux-cfs-2.6.20.8.q/include/linux/hardirq.h
+@@ -79,6 +79,19 @@
+ #endif
+ 
+ #ifdef CONFIG_PREEMPT
++# define PREEMPT_CHECK_OFFSET 1
++#else
++# define PREEMPT_CHECK_OFFSET 0
++#endif
++
++/*
++ * Check whether we were atomic before we did preempt_disable():
++ * (used by the scheduler)
++ */
++#define in_atomic_preempt_off() \
++		((preempt_count() & ~PREEMPT_ACTIVE) != PREEMPT_CHECK_OFFSET)
++
++#ifdef CONFIG_PREEMPT
+ # define preemptible()	(preempt_count() == 0 && !irqs_disabled())
+ # define IRQ_EXIT_OFFSET (HARDIRQ_OFFSET-1)
+ #else
+Index: linux-cfs-2.6.20.8.q/include/linux/ktime.h
+===================================================================
+--- linux-cfs-2.6.20.8.q.orig/include/linux/ktime.h
++++ linux-cfs-2.6.20.8.q/include/linux/ktime.h
+@@ -274,4 +274,6 @@ extern void ktime_get_ts(struct timespec
+ /* Get the real (wall-) time in timespec format: */
+ #define ktime_get_real_ts(ts)	getnstimeofday(ts)
+ 
++extern ktime_t ktime_get(void);
++
+ #endif
+Index: linux-cfs-2.6.20.8.q/include/linux/sched.h
+===================================================================
+--- linux-cfs-2.6.20.8.q.orig/include/linux/sched.h
++++ linux-cfs-2.6.20.8.q/include/linux/sched.h
+@@ -2,7 +2,6 @@
+ #define _LINUX_SCHED_H
+ 
+ #include <linux/auxvec.h>	/* For AT_VECTOR_SIZE */
+-
+ /*
+  * cloning flags:
+  */
+@@ -37,6 +36,8 @@
+ 
+ #ifdef __KERNEL__
+ 
++#include <linux/rbtree.h>	/* For run_node */
++
+ struct sched_param {
+ 	int sched_priority;
+ };
+@@ -196,13 +197,13 @@ extern void init_idle(struct task_struct
+ extern cpumask_t nohz_cpu_mask;
+ 
+ /*
+- * Only dump TASK_* tasks. (-1 for all tasks)
++ * Only dump TASK_* tasks. (0 for all tasks)
+  */
+ extern void show_state_filter(unsigned long state_filter);
+ 
+ static inline void show_state(void)
+ {
+-	show_state_filter(-1);
++	show_state_filter(0);
+ }
+ 
+ extern void show_regs(struct pt_regs *);
+@@ -464,7 +465,7 @@ struct signal_struct {
+ 	 * from jiffies_to_ns(utime + stime) if sched_clock uses something
+ 	 * other than jiffies.)
+ 	 */
+-	unsigned long long sched_time;
++	unsigned long long sum_sched_runtime;
+ 
+ 	/*
+ 	 * We don't bother to synchronize most readers of this at all,
+@@ -524,6 +525,7 @@ struct signal_struct {
+ #define MAX_RT_PRIO		MAX_USER_RT_PRIO
+ 
+ #define MAX_PRIO		(MAX_RT_PRIO + 40)
++#define DEFAULT_PRIO		(MAX_RT_PRIO + 20)
+ 
+ #define rt_prio(prio)		unlikely((prio) < MAX_RT_PRIO)
+ #define rt_task(p)		rt_prio((p)->prio)
+@@ -635,7 +637,14 @@ enum idle_type
+ /*
+  * sched-domains (multiprocessor balancing) declarations:
+  */
+-#define SCHED_LOAD_SCALE	128UL	/* increase resolution of load */
++
++/*
++ * Increase resolution of nice-level calculations:
++ */
++#define SCHED_LOAD_SHIFT	10
++#define SCHED_LOAD_SCALE	(1UL << SCHED_LOAD_SHIFT)
++
++#define SCHED_LOAD_SCALE_FUZZ	(SCHED_LOAD_SCALE >> 5)
+ 
+ #ifdef CONFIG_SMP
+ #define SD_LOAD_BALANCE		1	/* Do load balancing on this domain. */
+@@ -684,7 +693,6 @@ struct sched_domain {
+ 	unsigned int imbalance_pct;	/* No balance until over watermark */
+ 	unsigned long long cache_hot_time; /* Task considered cache hot (ns) */
+ 	unsigned int cache_nice_tries;	/* Leave cache hot tasks for # tries */
+-	unsigned int per_cpu_gain;	/* CPU % gained by adding domain cpus */
+ 	unsigned int busy_idx;
+ 	unsigned int idle_idx;
+ 	unsigned int newidle_idx;
+@@ -733,12 +741,6 @@ struct sched_domain {
+ extern int partition_sched_domains(cpumask_t *partition1,
+ 				    cpumask_t *partition2);
+ 
+-/*
+- * Maximum cache size the migration-costs auto-tuning code will
+- * search from:
+- */
+-extern unsigned int max_cache_size;
+-
+ #endif	/* CONFIG_SMP */
+ 
+ 
+@@ -789,14 +791,28 @@ struct mempolicy;
+ struct pipe_inode_info;
+ struct uts_namespace;
+ 
+-enum sleep_type {
+-	SLEEP_NORMAL,
+-	SLEEP_NONINTERACTIVE,
+-	SLEEP_INTERACTIVE,
+-	SLEEP_INTERRUPTED,
+-};
++struct rq;
+ 
+-struct prio_array;
++struct sched_class {
++	struct sched_class *next;
++
++	void (*enqueue_task) (struct rq *rq, struct task_struct *p,
++			      int wakeup, u64 now);
++	void (*dequeue_task) (struct rq *rq, struct task_struct *p,
++			      int sleep, u64 now);
++	void (*yield_task) (struct rq *rq, struct task_struct *p,
++			    struct task_struct *p_to);
++
++	void (*check_preempt_curr) (struct rq *rq, struct task_struct *p);
++
++	struct task_struct * (*pick_next_task) (struct rq *rq, u64 now);
++	void (*put_prev_task) (struct rq *rq, struct task_struct *p, u64 now);
++
++	struct task_struct * (*load_balance_start) (struct rq *rq);
++	struct task_struct * (*load_balance_next) (struct rq *rq);
++	void (*task_tick) (struct rq *rq, struct task_struct *p);
++	void (*task_new) (struct rq *rq, struct task_struct *p);
++};
+ 
+ struct task_struct {
+ 	volatile long state;	/* -1 unrunnable, 0 runnable, >0 stopped */
+@@ -813,26 +829,45 @@ struct task_struct {
+ #endif
+ #endif
+ 	int load_weight;	/* for niceness load balancing purposes */
++	int load_shift;
++
+ 	int prio, static_prio, normal_prio;
++	int on_rq;
+ 	struct list_head run_list;
+-	struct prio_array *array;
++	struct rb_node run_node;
+ 
+ 	unsigned short ioprio;
+ #ifdef CONFIG_BLK_DEV_IO_TRACE
+ 	unsigned int btrace_seq;
+ #endif
+-	unsigned long sleep_avg;
+-	unsigned long long timestamp, last_ran;
+-	unsigned long long sched_time; /* sched_clock time spent running */
+-	enum sleep_type sleep_type;
++	/* CFS scheduling class statistics fields: */
++	u64 wait_start_fair;
++	u64 wait_start;
++	u64 exec_start;
++	u64 sleep_start;
++	u64 block_start;
++	u64 sleep_max;
++	u64 block_max;
++	u64 exec_max;
++	u64 wait_max;
++	u64 last_ran;
++
++	s64 wait_runtime;
++	u64 sum_exec_runtime;
++	s64 fair_key;
++	s64 sum_wait_runtime;
+ 
+ 	unsigned long policy;
+ 	cpumask_t cpus_allowed;
+-	unsigned int time_slice, first_time_slice;
++	unsigned int time_slice;
++	struct sched_class *sched_class;
++
++	s64 min_wait_runtime;
+ 
+ #if defined(CONFIG_SCHEDSTATS) || defined(CONFIG_TASK_DELAY_ACCT)
+ 	struct sched_info sched_info;
+ #endif
++	u64 nr_switches;
+ 
+ 	struct list_head tasks;
+ 	/*
+@@ -1195,8 +1230,9 @@ static inline int set_cpus_allowed(struc
+ #endif
+ 
+ extern unsigned long long sched_clock(void);
++extern void sched_clock_unstable_event(void);
+ extern unsigned long long
+-current_sched_time(const struct task_struct *current_task);
++current_sched_runtime(const struct task_struct *current_task);
+ 
+ /* sched_exec is called by processes performing an exec */
+ #ifdef CONFIG_SMP
+@@ -1212,6 +1248,13 @@ static inline void idle_task_exit(void) 
+ #endif
+ 
+ extern void sched_idle_next(void);
++extern char * sched_print_task_state(struct task_struct *p, char *buffer);
++
++extern unsigned int sysctl_sched_granularity;
++extern unsigned int sysctl_sched_wakeup_granularity;
++extern unsigned int sysctl_sched_sleep_history_max;
++extern unsigned int sysctl_sched_child_runs_first;
++extern unsigned int sysctl_sched_load_smoothing;
+ 
+ #ifdef CONFIG_RT_MUTEXES
+ extern int rt_mutex_getprio(struct task_struct *p);
+@@ -1290,8 +1333,7 @@ extern void FASTCALL(wake_up_new_task(st
+ #else
+  static inline void kick_process(struct task_struct *tsk) { }
+ #endif
+-extern void FASTCALL(sched_fork(struct task_struct * p, int clone_flags));
+-extern void FASTCALL(sched_exit(struct task_struct * p));
++extern void sched_fork(struct task_struct * p, int clone_flags);
+ 
+ extern int in_group_p(gid_t);
+ extern int in_egroup_p(gid_t);
+Index: linux-cfs-2.6.20.8.q/include/linux/topology.h
+===================================================================
+--- linux-cfs-2.6.20.8.q.orig/include/linux/topology.h
++++ linux-cfs-2.6.20.8.q/include/linux/topology.h
+@@ -96,7 +96,6 @@
+ 	.busy_factor		= 64,			\
+ 	.imbalance_pct		= 110,			\
+ 	.cache_nice_tries	= 0,			\
+-	.per_cpu_gain		= 25,			\
+ 	.busy_idx		= 0,			\
+ 	.idle_idx		= 0,			\
+ 	.newidle_idx		= 1,			\
+@@ -128,7 +127,6 @@
+ 	.busy_factor		= 64,			\
+ 	.imbalance_pct		= 125,			\
+ 	.cache_nice_tries	= 1,			\
+-	.per_cpu_gain		= 100,			\
+ 	.busy_idx		= 2,			\
+ 	.idle_idx		= 1,			\
+ 	.newidle_idx		= 2,			\
+@@ -159,7 +157,6 @@
+ 	.busy_factor		= 64,			\
+ 	.imbalance_pct		= 125,			\
+ 	.cache_nice_tries	= 1,			\
+-	.per_cpu_gain		= 100,			\
+ 	.busy_idx		= 2,			\
+ 	.idle_idx		= 1,			\
+ 	.newidle_idx		= 2,			\
+@@ -193,7 +190,6 @@
+ 	.newidle_idx		= 0, /* unused */	\
+ 	.wake_idx		= 0, /* unused */	\
+ 	.forkexec_idx		= 0, /* unused */	\
+-	.per_cpu_gain		= 100,			\
+ 	.flags			= SD_LOAD_BALANCE	\
+ 				| SD_SERIALIZE,	\
+ 	.last_balance		= jiffies,		\
+Index: linux-cfs-2.6.20.8.q/init/main.c
+===================================================================
+--- linux-cfs-2.6.20.8.q.orig/init/main.c
++++ linux-cfs-2.6.20.8.q/init/main.c
+@@ -422,7 +422,7 @@ static void noinline rest_init(void)
+ 
+ 	/*
+ 	 * The boot idle thread must execute schedule()
+-	 * at least one to get things moving:
++	 * at least once to get things moving:
+ 	 */
+ 	preempt_enable_no_resched();
+ 	schedule();
+Index: linux-cfs-2.6.20.8.q/kernel/exit.c
+===================================================================
+--- linux-cfs-2.6.20.8.q.orig/kernel/exit.c
++++ linux-cfs-2.6.20.8.q/kernel/exit.c
+@@ -112,7 +112,7 @@ static void __exit_signal(struct task_st
+ 		sig->maj_flt += tsk->maj_flt;
+ 		sig->nvcsw += tsk->nvcsw;
+ 		sig->nivcsw += tsk->nivcsw;
+-		sig->sched_time += tsk->sched_time;
++		sig->sum_sched_runtime += tsk->sum_exec_runtime;
+ 		sig = NULL; /* Marker for below. */
+ 	}
+ 
+@@ -170,7 +170,6 @@ repeat:
+ 		zap_leader = (leader->exit_signal == -1);
+ 	}
+ 
+-	sched_exit(p);
+ 	write_unlock_irq(&tasklist_lock);
+ 	proc_flush_task(p);
+ 	release_thread(p);
+Index: linux-cfs-2.6.20.8.q/kernel/fork.c
+===================================================================
+--- linux-cfs-2.6.20.8.q.orig/kernel/fork.c
++++ linux-cfs-2.6.20.8.q/kernel/fork.c
+@@ -874,7 +874,7 @@ static inline int copy_signal(unsigned l
+ 	sig->utime = sig->stime = sig->cutime = sig->cstime = cputime_zero;
+ 	sig->nvcsw = sig->nivcsw = sig->cnvcsw = sig->cnivcsw = 0;
+ 	sig->min_flt = sig->maj_flt = sig->cmin_flt = sig->cmaj_flt = 0;
+-	sig->sched_time = 0;
++	sig->sum_sched_runtime = 0;
+ 	INIT_LIST_HEAD(&sig->cpu_timers[0]);
+ 	INIT_LIST_HEAD(&sig->cpu_timers[1]);
+ 	INIT_LIST_HEAD(&sig->cpu_timers[2]);
+@@ -1037,7 +1037,7 @@ static struct task_struct *copy_process(
+ 
+ 	p->utime = cputime_zero;
+ 	p->stime = cputime_zero;
+- 	p->sched_time = 0;
++
+ 	p->rchar = 0;		/* I/O counter: bytes read */
+ 	p->wchar = 0;		/* I/O counter: bytes written */
+ 	p->syscr = 0;		/* I/O counter: read syscalls */
+Index: linux-cfs-2.6.20.8.q/kernel/hrtimer.c
+===================================================================
+--- linux-cfs-2.6.20.8.q.orig/kernel/hrtimer.c
++++ linux-cfs-2.6.20.8.q/kernel/hrtimer.c
+@@ -45,7 +45,7 @@
+  *
+  * returns the time in ktime_t format
+  */
+-static ktime_t ktime_get(void)
++ktime_t ktime_get(void)
+ {
+ 	struct timespec now;
+ 
+Index: linux-cfs-2.6.20.8.q/kernel/posix-cpu-timers.c
+===================================================================
+--- linux-cfs-2.6.20.8.q.orig/kernel/posix-cpu-timers.c
++++ linux-cfs-2.6.20.8.q/kernel/posix-cpu-timers.c
+@@ -161,7 +161,7 @@ static inline cputime_t virt_ticks(struc
+ }
+ static inline unsigned long long sched_ns(struct task_struct *p)
+ {
+-	return (p == current) ? current_sched_time(p) : p->sched_time;
++	return (p == current) ? current_sched_runtime(p) : p->sum_exec_runtime;
+ }
+ 
+ int posix_cpu_clock_getres(const clockid_t which_clock, struct timespec *tp)
+@@ -246,10 +246,10 @@ static int cpu_clock_sample_group_locked
+ 		} while (t != p);
+ 		break;
+ 	case CPUCLOCK_SCHED:
+-		cpu->sched = p->signal->sched_time;
++		cpu->sched = p->signal->sum_sched_runtime;
+ 		/* Add in each other live thread.  */
+ 		while ((t = next_thread(t)) != p) {
+-			cpu->sched += t->sched_time;
++			cpu->sched += t->sum_exec_runtime;
+ 		}
+ 		cpu->sched += sched_ns(p);
+ 		break;
+@@ -417,7 +417,7 @@ int posix_cpu_timer_del(struct k_itimer 
+  */
+ static void cleanup_timers(struct list_head *head,
+ 			   cputime_t utime, cputime_t stime,
+-			   unsigned long long sched_time)
++			   unsigned long long sum_exec_runtime)
+ {
+ 	struct cpu_timer_list *timer, *next;
+ 	cputime_t ptime = cputime_add(utime, stime);
+@@ -446,10 +446,10 @@ static void cleanup_timers(struct list_h
+ 	++head;
+ 	list_for_each_entry_safe(timer, next, head, entry) {
+ 		list_del_init(&timer->entry);
+-		if (timer->expires.sched < sched_time) {
++		if (timer->expires.sched < sum_exec_runtime) {
+ 			timer->expires.sched = 0;
+ 		} else {
+-			timer->expires.sched -= sched_time;
++			timer->expires.sched -= sum_exec_runtime;
+ 		}
+ 	}
+ }
+@@ -462,7 +462,7 @@ static void cleanup_timers(struct list_h
+ void posix_cpu_timers_exit(struct task_struct *tsk)
+ {
+ 	cleanup_timers(tsk->cpu_timers,
+-		       tsk->utime, tsk->stime, tsk->sched_time);
++		       tsk->utime, tsk->stime, tsk->sum_exec_runtime);
+ 
+ }
+ void posix_cpu_timers_exit_group(struct task_struct *tsk)
+@@ -470,7 +470,7 @@ void posix_cpu_timers_exit_group(struct 
+ 	cleanup_timers(tsk->signal->cpu_timers,
+ 		       cputime_add(tsk->utime, tsk->signal->utime),
+ 		       cputime_add(tsk->stime, tsk->signal->stime),
+-		       tsk->sched_time + tsk->signal->sched_time);
++		       tsk->sum_exec_runtime + tsk->signal->sum_sched_runtime);
+ }
+ 
+ 
+@@ -531,7 +531,7 @@ static void process_timer_rebalance(stru
+ 		nsleft = max_t(unsigned long long, nsleft, 1);
+ 		do {
+ 			if (likely(!(t->flags & PF_EXITING))) {
+-				ns = t->sched_time + nsleft;
++				ns = t->sum_exec_runtime + nsleft;
+ 				if (t->it_sched_expires == 0 ||
+ 				    t->it_sched_expires > ns) {
+ 					t->it_sched_expires = ns;
+@@ -999,7 +999,7 @@ static void check_thread_timers(struct t
+ 		struct cpu_timer_list *t = list_entry(timers->next,
+ 						      struct cpu_timer_list,
+ 						      entry);
+-		if (!--maxfire || tsk->sched_time < t->expires.sched) {
++		if (!--maxfire || tsk->sum_exec_runtime < t->expires.sched) {
+ 			tsk->it_sched_expires = t->expires.sched;
+ 			break;
+ 		}
+@@ -1019,7 +1019,7 @@ static void check_process_timers(struct 
+ 	int maxfire;
+ 	struct signal_struct *const sig = tsk->signal;
+ 	cputime_t utime, stime, ptime, virt_expires, prof_expires;
+-	unsigned long long sched_time, sched_expires;
++	unsigned long long sum_sched_runtime, sched_expires;
+ 	struct task_struct *t;
+ 	struct list_head *timers = sig->cpu_timers;
+ 
+@@ -1039,12 +1039,12 @@ static void check_process_timers(struct 
+ 	 */
+ 	utime = sig->utime;
+ 	stime = sig->stime;
+-	sched_time = sig->sched_time;
++	sum_sched_runtime = sig->sum_sched_runtime;
+ 	t = tsk;
+ 	do {
+ 		utime = cputime_add(utime, t->utime);
+ 		stime = cputime_add(stime, t->stime);
+-		sched_time += t->sched_time;
++		sum_sched_runtime += t->sum_exec_runtime;
+ 		t = next_thread(t);
+ 	} while (t != tsk);
+ 	ptime = cputime_add(utime, stime);
+@@ -1085,7 +1085,7 @@ static void check_process_timers(struct 
+ 		struct cpu_timer_list *t = list_entry(timers->next,
+ 						      struct cpu_timer_list,
+ 						      entry);
+-		if (!--maxfire || sched_time < t->expires.sched) {
++		if (!--maxfire || sum_sched_runtime < t->expires.sched) {
+ 			sched_expires = t->expires.sched;
+ 			break;
+ 		}
+@@ -1177,7 +1177,7 @@ static void check_process_timers(struct 
+ 		virt_left = cputime_sub(virt_expires, utime);
+ 		virt_left = cputime_div_non_zero(virt_left, nthreads);
+ 		if (sched_expires) {
+-			sched_left = sched_expires - sched_time;
++			sched_left = sched_expires - sum_sched_runtime;
+ 			do_div(sched_left, nthreads);
+ 			sched_left = max_t(unsigned long long, sched_left, 1);
+ 		} else {
+@@ -1203,7 +1203,7 @@ static void check_process_timers(struct 
+ 				t->it_virt_expires = ticks;
+ 			}
+ 
+-			sched = t->sched_time + sched_left;
++			sched = t->sum_exec_runtime + sched_left;
+ 			if (sched_expires && (t->it_sched_expires == 0 ||
+ 					      t->it_sched_expires > sched)) {
+ 				t->it_sched_expires = sched;
+@@ -1295,7 +1295,7 @@ void run_posix_cpu_timers(struct task_st
+ 
+ 	if (UNEXPIRED(prof) && UNEXPIRED(virt) &&
+ 	    (tsk->it_sched_expires == 0 ||
+-	     tsk->sched_time < tsk->it_sched_expires))
++	     tsk->sum_exec_runtime < tsk->it_sched_expires))
+ 		return;
+ 
+ #undef	UNEXPIRED
+Index: linux-cfs-2.6.20.8.q/kernel/sched.c
+===================================================================
+--- linux-cfs-2.6.20.8.q.orig/kernel/sched.c
++++ linux-cfs-2.6.20.8.q/kernel/sched.c
+@@ -89,110 +89,13 @@
+  */
+ #define MIN_TIMESLICE		max(5 * HZ / 1000, 1)
+ #define DEF_TIMESLICE		(100 * HZ / 1000)
+-#define ON_RUNQUEUE_WEIGHT	 30
+-#define CHILD_PENALTY		 95
+-#define PARENT_PENALTY		100
+-#define EXIT_WEIGHT		  3
+-#define PRIO_BONUS_RATIO	 25
+-#define MAX_BONUS		(MAX_USER_PRIO * PRIO_BONUS_RATIO / 100)
+-#define INTERACTIVE_DELTA	  2
+-#define MAX_SLEEP_AVG		(DEF_TIMESLICE * MAX_BONUS)
+-#define STARVATION_LIMIT	(MAX_SLEEP_AVG)
+-#define NS_MAX_SLEEP_AVG	(JIFFIES_TO_NS(MAX_SLEEP_AVG))
+-
+-/*
+- * If a task is 'interactive' then we reinsert it in the active
+- * array after it has expired its current timeslice. (it will not
+- * continue to run immediately, it will still roundrobin with
+- * other interactive tasks.)
+- *
+- * This part scales the interactivity limit depending on niceness.
+- *
+- * We scale it linearly, offset by the INTERACTIVE_DELTA delta.
+- * Here are a few examples of different nice levels:
+- *
+- *  TASK_INTERACTIVE(-20): [1,1,1,1,1,1,1,1,1,0,0]
+- *  TASK_INTERACTIVE(-10): [1,1,1,1,1,1,1,0,0,0,0]
+- *  TASK_INTERACTIVE(  0): [1,1,1,1,0,0,0,0,0,0,0]
+- *  TASK_INTERACTIVE( 10): [1,1,0,0,0,0,0,0,0,0,0]
+- *  TASK_INTERACTIVE( 19): [0,0,0,0,0,0,0,0,0,0,0]
+- *
+- * (the X axis represents the possible -5 ... 0 ... +5 dynamic
+- *  priority range a task can explore, a value of '1' means the
+- *  task is rated interactive.)
+- *
+- * Ie. nice +19 tasks can never get 'interactive' enough to be
+- * reinserted into the active array. And only heavily CPU-hog nice -20
+- * tasks will be expired. Default nice 0 tasks are somewhere between,
+- * it takes some effort for them to get interactive, but it's not
+- * too hard.
+- */
+-
+-#define CURRENT_BONUS(p) \
+-	(NS_TO_JIFFIES((p)->sleep_avg) * MAX_BONUS / \
+-		MAX_SLEEP_AVG)
+-
+-#define GRANULARITY	(10 * HZ / 1000 ? : 1)
+-
+-#ifdef CONFIG_SMP
+-#define TIMESLICE_GRANULARITY(p)	(GRANULARITY * \
+-		(1 << (((MAX_BONUS - CURRENT_BONUS(p)) ? : 1) - 1)) * \
+-			num_online_cpus())
+-#else
+-#define TIMESLICE_GRANULARITY(p)	(GRANULARITY * \
+-		(1 << (((MAX_BONUS - CURRENT_BONUS(p)) ? : 1) - 1)))
+-#endif
+-
+-#define SCALE(v1,v1_max,v2_max) \
+-	(v1) * (v2_max) / (v1_max)
+-
+-#define DELTA(p) \
+-	(SCALE(TASK_NICE(p) + 20, 40, MAX_BONUS) - 20 * MAX_BONUS / 40 + \
+-		INTERACTIVE_DELTA)
+-
+-#define TASK_INTERACTIVE(p) \
+-	((p)->prio <= (p)->static_prio - DELTA(p))
+-
+-#define INTERACTIVE_SLEEP(p) \
+-	(JIFFIES_TO_NS(MAX_SLEEP_AVG * \
+-		(MAX_BONUS / 2 + DELTA((p)) + 1) / MAX_BONUS - 1))
+-
+-#define TASK_PREEMPTS_CURR(p, rq) \
+-	((p)->prio < (rq)->curr->prio)
+-
+-#define SCALE_PRIO(x, prio) \
+-	max(x * (MAX_PRIO - prio) / (MAX_USER_PRIO / 2), MIN_TIMESLICE)
+-
+-static unsigned int static_prio_timeslice(int static_prio)
+-{
+-	if (static_prio < NICE_TO_PRIO(0))
+-		return SCALE_PRIO(DEF_TIMESLICE * 4, static_prio);
+-	else
+-		return SCALE_PRIO(DEF_TIMESLICE, static_prio);
+-}
+-
+-/*
+- * task_timeslice() scales user-nice values [ -20 ... 0 ... 19 ]
+- * to time slice values: [800ms ... 100ms ... 5ms]
+- *
+- * The higher a thread's priority, the bigger timeslices
+- * it gets during one round of execution. But even the lowest
+- * priority thread gets MIN_TIMESLICE worth of execution time.
+- */
+-
+-static inline unsigned int task_timeslice(struct task_struct *p)
+-{
+-	return static_prio_timeslice(p->static_prio);
+-}
+ 
+ /*
+- * These are the runqueue data structures:
++ * This is the priority-queue data structure of the RT scheduling class:
+  */
+-
+ struct prio_array {
+-	unsigned int nr_active;
+-	DECLARE_BITMAP(bitmap, MAX_PRIO+1); /* include 1 bit for delimiter */
+-	struct list_head queue[MAX_PRIO];
++	DECLARE_BITMAP(bitmap, MAX_RT_PRIO+1); /* include 1 bit for delimiter */
++	struct list_head queue[MAX_RT_PRIO];
+ };
+ 
+ /*
+@@ -209,12 +112,13 @@ struct rq {
+ 	 * nr_running and cpu_load should be in the same cacheline because
+ 	 * remote CPUs use both these fields when doing load calculation.
+ 	 */
+-	unsigned long nr_running;
++	long nr_running;
+ 	unsigned long raw_weighted_load;
+-#ifdef CONFIG_SMP
+-	unsigned long cpu_load[3];
+-#endif
+-	unsigned long long nr_switches;
++	#define CPU_LOAD_IDX_MAX 5
++	unsigned long cpu_load[CPU_LOAD_IDX_MAX];
++
++	u64 nr_switches;
++	unsigned long nr_load_updates;
+ 
+ 	/*
+ 	 * This is part of a global counter where only the total sum
+@@ -224,14 +128,29 @@ struct rq {
+ 	 */
+ 	unsigned long nr_uninterruptible;
+ 
+-	unsigned long expired_timestamp;
+-	/* Cached timestamp set by update_cpu_clock() */
+-	unsigned long long most_recent_timestamp;
+ 	struct task_struct *curr, *idle;
+ 	unsigned long next_balance;
+ 	struct mm_struct *prev_mm;
+-	struct prio_array *active, *expired, arrays[2];
+-	int best_expired_prio;
++
++	u64 clock, prev_clock_raw;
++	s64 clock_max_delta;
++	u64 fair_clock, prev_fair_clock;
++	u64 exec_clock, prev_exec_clock;
++	u64 wait_runtime;
++
++	unsigned int clock_warps;
++	unsigned int clock_unstable_events;
++
++	struct sched_class *load_balance_class;
++
++	struct prio_array active;
++	int rt_load_balance_idx;
++	struct list_head *rt_load_balance_head, *rt_load_balance_curr;
++
++	struct rb_root tasks_timeline;
++	struct rb_node *rb_leftmost;
++	struct rb_node *rb_load_balance_curr;
++
+ 	atomic_t nr_iowait;
+ 
+ #ifdef CONFIG_SMP
+@@ -268,7 +187,107 @@ struct rq {
+ 	struct lock_class_key rq_lock_key;
+ };
+ 
+-static DEFINE_PER_CPU(struct rq, runqueues);
++static DEFINE_PER_CPU(struct rq, runqueues) ____cacheline_aligned_in_smp;
++
++static inline void check_preempt_curr(struct rq *rq, struct task_struct *p)
++{
++	rq->curr->sched_class->check_preempt_curr(rq, p);
++}
++
++#define SCALE_PRIO(x, prio) \
++	max(x * (MAX_PRIO - prio) / (MAX_USER_PRIO / 2), MIN_TIMESLICE)
++
++/*
++ * static_prio_timeslice() scales user-nice values [ -20 ... 0 ... 19 ]
++ * to time slice values: [800ms ... 100ms ... 5ms]
++ */
++static unsigned int static_prio_timeslice(int static_prio)
++{
++	if (static_prio == NICE_TO_PRIO(19))
++		return 1;
++
++	if (static_prio < NICE_TO_PRIO(0))
++		return SCALE_PRIO(DEF_TIMESLICE * 4, static_prio);
++	else
++		return SCALE_PRIO(DEF_TIMESLICE, static_prio);
++}
++
++/*
++ * Print out various scheduling related per-task fields:
++ */
++char * sched_print_task_state(struct task_struct *p, char *buffer)
++{
++	struct rq *this_rq = &per_cpu(runqueues, raw_smp_processor_id());
++	unsigned long long t0, t1;
++
++#define P(F) \
++	buffer += sprintf(buffer, "%-25s:%20Ld\n", #F, (long long)p->F)
++
++	P(wait_start);
++	P(wait_start_fair);
++	P(exec_start);
++	P(sleep_start);
++	P(block_start);
++	P(sleep_max);
++	P(block_max);
++	P(exec_max);
++	P(wait_max);
++	P(min_wait_runtime);
++	P(last_ran);
++	P(wait_runtime);
++	P(sum_exec_runtime);
++#undef P
++
++	t0 = sched_clock();
++	t1 = sched_clock();
++	buffer += sprintf(buffer, "%-25s:%20Ld\n", "clock-delta",
++				(long long)t1-t0);
++	buffer += sprintf(buffer, "%-25s:%20Ld\n", "rq-wait_runtime",
++				(long long)this_rq->wait_runtime);
++	buffer += sprintf(buffer, "%-25s:%20Ld\n", "rq-exec_clock",
++				(long long)this_rq->exec_clock);
++	buffer += sprintf(buffer, "%-25s:%20Ld\n", "rq-fair_clock",
++				(long long)this_rq->fair_clock);
++	buffer += sprintf(buffer, "%-25s:%20Ld\n", "rq-clock",
++				(long long)this_rq->clock);
++	buffer += sprintf(buffer, "%-25s:%20Ld\n", "rq-prev_clock_raw",
++				(long long)this_rq->prev_clock_raw);
++	buffer += sprintf(buffer, "%-25s:%20Ld\n", "rq-clock_max_delta",
++				(long long)this_rq->clock_max_delta);
++	buffer += sprintf(buffer, "%-25s:%20u\n", "rq-clock_warps",
++				this_rq->clock_warps);
++	buffer += sprintf(buffer, "%-25s:%20u\n", "rq-clock_unstable_events",
++				this_rq->clock_unstable_events);
++	return buffer;
++}
++
++/*
++ * Per-runqueue clock, as finegrained as the platform can give us:
++ */
++static inline unsigned long long __rq_clock(struct rq *rq)
++{
++	u64 now = sched_clock();
++	u64 clock = rq->clock;
++	u64 prev_raw = rq->prev_clock_raw;
++	s64 delta = now - prev_raw;
++
++	/*
++	 * Protect against sched_clock() occasionally going backwards:
++	 */
++	if (unlikely(delta < 0)) {
++		clock++;
++		rq->clock_warps++;
++	} else {
++		if (unlikely(delta > rq->clock_max_delta))
++			rq->clock_max_delta = delta;
++		clock += delta;
++	}
++
++	rq->prev_clock_raw = now;
++	rq->clock = clock;
++
++	return clock;
++}
+ 
+ static inline int cpu_of(struct rq *rq)
+ {
+@@ -279,6 +298,16 @@ static inline int cpu_of(struct rq *rq)
+ #endif
+ }
+ 
++static inline unsigned long long rq_clock(struct rq *rq)
++{
++	int this_cpu = smp_processor_id();
++
++	if (this_cpu == cpu_of(rq))
++		return __rq_clock(rq);
++
++	return rq->clock;
++}
++
+ /*
+  * The domain tree (rq->sd) is protected by RCU's quiescent state transition.
+  * See detach_destroy_domains: synchronize_sched for details.
+@@ -423,134 +452,6 @@ static inline void task_rq_unlock(struct
+ 	spin_unlock_irqrestore(&rq->lock, *flags);
+ }
+ 
+-#ifdef CONFIG_SCHEDSTATS
+-/*
+- * bump this up when changing the output format or the meaning of an existing
+- * format, so that tools can adapt (or abort)
+- */
+-#define SCHEDSTAT_VERSION 14
+-
+-static int show_schedstat(struct seq_file *seq, void *v)
+-{
+-	int cpu;
+-
+-	seq_printf(seq, "version %d\n", SCHEDSTAT_VERSION);
+-	seq_printf(seq, "timestamp %lu\n", jiffies);
+-	for_each_online_cpu(cpu) {
+-		struct rq *rq = cpu_rq(cpu);
+-#ifdef CONFIG_SMP
+-		struct sched_domain *sd;
+-		int dcnt = 0;
+-#endif
+-
+-		/* runqueue-specific stats */
+-		seq_printf(seq,
+-		    "cpu%d %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu",
+-		    cpu, rq->yld_both_empty,
+-		    rq->yld_act_empty, rq->yld_exp_empty, rq->yld_cnt,
+-		    rq->sched_switch, rq->sched_cnt, rq->sched_goidle,
+-		    rq->ttwu_cnt, rq->ttwu_local,
+-		    rq->rq_sched_info.cpu_time,
+-		    rq->rq_sched_info.run_delay, rq->rq_sched_info.pcnt);
+-
+-		seq_printf(seq, "\n");
+-
+-#ifdef CONFIG_SMP
+-		/* domain-specific stats */
+-		preempt_disable();
+-		for_each_domain(cpu, sd) {
+-			enum idle_type itype;
+-			char mask_str[NR_CPUS];
+-
+-			cpumask_scnprintf(mask_str, NR_CPUS, sd->span);
+-			seq_printf(seq, "domain%d %s", dcnt++, mask_str);
+-			for (itype = SCHED_IDLE; itype < MAX_IDLE_TYPES;
+-					itype++) {
+-				seq_printf(seq, " %lu %lu %lu %lu %lu %lu %lu "
+-						"%lu",
+-				    sd->lb_cnt[itype],
+-				    sd->lb_balanced[itype],
+-				    sd->lb_failed[itype],
+-				    sd->lb_imbalance[itype],
+-				    sd->lb_gained[itype],
+-				    sd->lb_hot_gained[itype],
+-				    sd->lb_nobusyq[itype],
+-				    sd->lb_nobusyg[itype]);
+-			}
+-			seq_printf(seq, " %lu %lu %lu %lu %lu %lu %lu %lu %lu"
+-			    " %lu %lu %lu\n",
+-			    sd->alb_cnt, sd->alb_failed, sd->alb_pushed,
+-			    sd->sbe_cnt, sd->sbe_balanced, sd->sbe_pushed,
+-			    sd->sbf_cnt, sd->sbf_balanced, sd->sbf_pushed,
+-			    sd->ttwu_wake_remote, sd->ttwu_move_affine,
+-			    sd->ttwu_move_balance);
+-		}
+-		preempt_enable();
+-#endif
+-	}
+-	return 0;
+-}
+-
+-static int schedstat_open(struct inode *inode, struct file *file)
+-{
+-	unsigned int size = PAGE_SIZE * (1 + num_online_cpus() / 32);
+-	char *buf = kmalloc(size, GFP_KERNEL);
+-	struct seq_file *m;
+-	int res;
+-
+-	if (!buf)
+-		return -ENOMEM;
+-	res = single_open(file, show_schedstat, NULL);
+-	if (!res) {
+-		m = file->private_data;
+-		m->buf = buf;
+-		m->size = size;
+-	} else
+-		kfree(buf);
+-	return res;
+-}
+-
+-const struct file_operations proc_schedstat_operations = {
+-	.open    = schedstat_open,
+-	.read    = seq_read,
+-	.llseek  = seq_lseek,
+-	.release = single_release,
+-};
+-
+-/*
+- * Expects runqueue lock to be held for atomicity of update
+- */
+-static inline void
+-rq_sched_info_arrive(struct rq *rq, unsigned long delta_jiffies)
+-{
+-	if (rq) {
+-		rq->rq_sched_info.run_delay += delta_jiffies;
+-		rq->rq_sched_info.pcnt++;
+-	}
+-}
+-
+-/*
+- * Expects runqueue lock to be held for atomicity of update
+- */
+-static inline void
+-rq_sched_info_depart(struct rq *rq, unsigned long delta_jiffies)
+-{
+-	if (rq)
+-		rq->rq_sched_info.cpu_time += delta_jiffies;
+-}
+-# define schedstat_inc(rq, field)	do { (rq)->field++; } while (0)
+-# define schedstat_add(rq, field, amt)	do { (rq)->field += (amt); } while (0)
+-#else /* !CONFIG_SCHEDSTATS */
+-static inline void
+-rq_sched_info_arrive(struct rq *rq, unsigned long delta_jiffies)
+-{}
+-static inline void
+-rq_sched_info_depart(struct rq *rq, unsigned long delta_jiffies)
+-{}
+-# define schedstat_inc(rq, field)	do { } while (0)
+-# define schedstat_add(rq, field, amt)	do { } while (0)
+-#endif
+-
+ /*
+  * this_rq_lock - lock this runqueue and disable interrupts.
+  */
+@@ -566,178 +467,60 @@ static inline struct rq *this_rq_lock(vo
+ 	return rq;
+ }
+ 
+-#if defined(CONFIG_SCHEDSTATS) || defined(CONFIG_TASK_DELAY_ACCT)
+-/*
+- * Called when a process is dequeued from the active array and given
+- * the cpu.  We should note that with the exception of interactive
+- * tasks, the expired queue will become the active queue after the active
+- * queue is empty, without explicitly dequeuing and requeuing tasks in the
+- * expired queue.  (Interactive tasks may be requeued directly to the
+- * active queue, thus delaying tasks in the expired queue from running;
+- * see scheduler_tick()).
+- *
+- * This function is only called from sched_info_arrive(), rather than
+- * dequeue_task(). Even though a task may be queued and dequeued multiple
+- * times as it is shuffled about, we're really interested in knowing how
+- * long it was from the *first* time it was queued to the time that it
+- * finally hit a cpu.
+- */
+-static inline void sched_info_dequeued(struct task_struct *t)
+-{
+-	t->sched_info.last_queued = 0;
+-}
+-
+ /*
+- * Called when a task finally hits the cpu.  We can now calculate how
+- * long it was waiting to run.  We also note when it began so that we
+- * can keep stats on how long its timeslice is.
++ * CPU frequency is/was unstable - start new by setting prev_clock_raw:
+  */
+-static void sched_info_arrive(struct task_struct *t)
++void sched_clock_unstable_event(void)
+ {
+-	unsigned long now = jiffies, delta_jiffies = 0;
+-
+-	if (t->sched_info.last_queued)
+-		delta_jiffies = now - t->sched_info.last_queued;
+-	sched_info_dequeued(t);
+-	t->sched_info.run_delay += delta_jiffies;
+-	t->sched_info.last_arrival = now;
+-	t->sched_info.pcnt++;
++	unsigned long flags;
++	struct rq *rq;
+ 
+-	rq_sched_info_arrive(task_rq(t), delta_jiffies);
++	rq = task_rq_lock(current, &flags);
++	rq->prev_clock_raw = sched_clock();
++	rq->clock_unstable_events++;
++	task_rq_unlock(rq, &flags);
+ }
+ 
+ /*
+- * Called when a process is queued into either the active or expired
+- * array.  The time is noted and later used to determine how long we
+- * had to wait for us to reach the cpu.  Since the expired queue will
+- * become the active queue after active queue is empty, without dequeuing
+- * and requeuing any tasks, we are interested in queuing to either. It
+- * is unusual but not impossible for tasks to be dequeued and immediately
+- * requeued in the same or another array: this can happen in sched_yield(),
+- * set_user_nice(), and even load_balance() as it moves tasks from runqueue
+- * to runqueue.
++ * resched_task - mark a task 'to be rescheduled now'.
+  *
+- * This function is only called from enqueue_task(), but also only updates
+- * the timestamp if it is already not set.  It's assumed that
+- * sched_info_dequeued() will clear that stamp when appropriate.
+- */
+-static inline void sched_info_queued(struct task_struct *t)
+-{
+-	if (unlikely(sched_info_on()))
+-		if (!t->sched_info.last_queued)
+-			t->sched_info.last_queued = jiffies;
+-}
+-
+-/*
+- * Called when a process ceases being the active-running process, either
+- * voluntarily or involuntarily.  Now we can calculate how long we ran.
++ * On UP this means the setting of the need_resched flag, on SMP it
++ * might also involve a cross-CPU call to trigger the scheduler on
++ * the target CPU.
+  */
+-static inline void sched_info_depart(struct task_struct *t)
+-{
+-	unsigned long delta_jiffies = jiffies - t->sched_info.last_arrival;
++#ifdef CONFIG_SMP
+ 
+-	t->sched_info.cpu_time += delta_jiffies;
+-	rq_sched_info_depart(task_rq(t), delta_jiffies);
+-}
++#ifndef tsk_is_polling
++#define tsk_is_polling(t) test_tsk_thread_flag(t, TIF_POLLING_NRFLAG)
++#endif
+ 
+-/*
+- * Called when tasks are switched involuntarily due, typically, to expiring
+- * their time slice.  (This may also be called when switching to or from
+- * the idle task.)  We are only called when prev != next.
+- */
+-static inline void
+-__sched_info_switch(struct task_struct *prev, struct task_struct *next)
++static void resched_task(struct task_struct *p)
+ {
+-	struct rq *rq = task_rq(prev);
+-
+-	/*
+-	 * prev now departs the cpu.  It's not interesting to record
+-	 * stats about how efficient we were at scheduling the idle
+-	 * process, however.
+-	 */
+-	if (prev != rq->idle)
+-		sched_info_depart(prev);
++	int cpu;
+ 
+-	if (next != rq->idle)
+-		sched_info_arrive(next);
+-}
+-static inline void
+-sched_info_switch(struct task_struct *prev, struct task_struct *next)
+-{
+-	if (unlikely(sched_info_on()))
+-		__sched_info_switch(prev, next);
+-}
+-#else
+-#define sched_info_queued(t)		do { } while (0)
+-#define sched_info_switch(t, next)	do { } while (0)
+-#endif /* CONFIG_SCHEDSTATS || CONFIG_TASK_DELAY_ACCT */
++	assert_spin_locked(&task_rq(p)->lock);
+ 
+-/*
+- * Adding/removing a task to/from a priority array:
+- */
+-static void dequeue_task(struct task_struct *p, struct prio_array *array)
+-{
+-	array->nr_active--;
+-	list_del(&p->run_list);
+-	if (list_empty(array->queue + p->prio))
+-		__clear_bit(p->prio, array->bitmap);
+-}
++	if (unlikely(test_tsk_thread_flag(p, TIF_NEED_RESCHED)))
++		return;
+ 
+-static void enqueue_task(struct task_struct *p, struct prio_array *array)
+-{
+-	sched_info_queued(p);
+-	list_add_tail(&p->run_list, array->queue + p->prio);
+-	__set_bit(p->prio, array->bitmap);
+-	array->nr_active++;
+-	p->array = array;
+-}
++	set_tsk_thread_flag(p, TIF_NEED_RESCHED);
+ 
+-/*
+- * Put task to the end of the run list without the overhead of dequeue
+- * followed by enqueue.
+- */
+-static void requeue_task(struct task_struct *p, struct prio_array *array)
+-{
+-	list_move_tail(&p->run_list, array->queue + p->prio);
+-}
++	cpu = task_cpu(p);
++	if (cpu == smp_processor_id())
++		return;
+ 
+-static inline void
+-enqueue_task_head(struct task_struct *p, struct prio_array *array)
+-{
+-	list_add(&p->run_list, array->queue + p->prio);
+-	__set_bit(p->prio, array->bitmap);
+-	array->nr_active++;
+-	p->array = array;
++	/* NEED_RESCHED must be visible before we test polling */
++	smp_mb();
++	if (!tsk_is_polling(p))
++		smp_send_reschedule(cpu);
+ }
+-
+-/*
+- * __normal_prio - return the priority that is based on the static
+- * priority but is modified by bonuses/penalties.
+- *
+- * We scale the actual sleep average [0 .... MAX_SLEEP_AVG]
+- * into the -5 ... 0 ... +5 bonus/penalty range.
+- *
+- * We use 25% of the full 0...39 priority range so that:
+- *
+- * 1) nice +19 interactive tasks do not preempt nice 0 CPU hogs.
+- * 2) nice -20 CPU hogs do not get preempted by nice 0 tasks.
+- *
+- * Both properties are important to certain workloads.
+- */
+-
+-static inline int __normal_prio(struct task_struct *p)
++#else
++static inline void resched_task(struct task_struct *p)
+ {
+-	int bonus, prio;
+-
+-	bonus = CURRENT_BONUS(p) - MAX_BONUS / 2;
+-
+-	prio = p->static_prio - bonus;
+-	if (prio < MAX_RT_PRIO)
+-		prio = MAX_RT_PRIO;
+-	if (prio > MAX_PRIO-1)
+-		prio = MAX_PRIO-1;
+-	return prio;
++	assert_spin_locked(&task_rq(p)->lock);
++	set_tsk_need_resched(p);
+ }
++#endif
+ 
+ /*
+  * To aid in avoiding the subversion of "niceness" due to uneven distribution
+@@ -761,22 +544,33 @@ static inline int __normal_prio(struct t
+ #define RTPRIO_TO_LOAD_WEIGHT(rp) \
+ 	(PRIO_TO_LOAD_WEIGHT(MAX_RT_PRIO) + LOAD_WEIGHT(rp))
+ 
++/*
++ * Nice levels are logarithmic. These are the load shifts assigned
++ * to nice levels, where a step of every 2 nice levels means a
++ * multiplicator of 2:
++ */
++const int prio_to_load_shift[40] = {
++/* -20 */ 20, 19, 19, 18, 18, 17, 17, 16, 16, 15,
++/* -10 */ 15, 14, 14, 13, 13, 12, 12, 11, 11, 10,
++/*   0 */ 10,  9,  9,  8,  8,  7,  7,  6,  6,  5,
++/*  10 */  5,  4,  4,  3,  3,  2,  2,  1,  1,  0
++};
++
++static int get_load_shift(struct task_struct *p)
++{
++	int prio = p->static_prio;
++
++	if (rt_prio(prio) || p->policy == SCHED_BATCH)
++		return 0;
++
++	return prio_to_load_shift[prio - MAX_RT_PRIO];
++}
++
+ static void set_load_weight(struct task_struct *p)
+ {
+-	if (has_rt_policy(p)) {
+-#ifdef CONFIG_SMP
+-		if (p == task_rq(p)->migration_thread)
+-			/*
+-			 * The migration thread does the actual balancing.
+-			 * Giving its load any weight will skew balancing
+-			 * adversely.
+-			 */
+-			p->load_weight = 0;
+-		else
+-#endif
+-			p->load_weight = RTPRIO_TO_LOAD_WEIGHT(p->rt_priority);
+-	} else
+-		p->load_weight = PRIO_TO_LOAD_WEIGHT(p->static_prio);
++	p->load_shift = get_load_shift(p);
++	p->load_weight = 1 << p->load_shift;
++	p->wait_runtime = 0;
+ }
+ 
+ static inline void
+@@ -803,6 +597,40 @@ static inline void dec_nr_running(struct
+ 	dec_raw_weighted_load(rq, p);
+ }
+ 
++static void activate_task(struct rq *rq, struct task_struct *p, int wakeup);
++
++#include "sched_stats.h"
++#include "sched_rt.c"
++#include "sched_fair.c"
++#include "sched_debug.c"
++
++#define sched_class_highest (&rt_sched_class)
++
++static void enqueue_task(struct rq *rq, struct task_struct *p, int wakeup)
++{
++	u64 now = rq_clock(rq);
++
++	sched_info_queued(p);
++	p->sched_class->enqueue_task(rq, p, wakeup, now);
++	p->on_rq = 1;
++}
++
++static void dequeue_task(struct rq *rq, struct task_struct *p, int sleep)
++{
++	u64 now = rq_clock(rq);
++
++	p->sched_class->dequeue_task(rq, p, sleep, now);
++	p->on_rq = 0;
++}
++
++/*
++ * __normal_prio - return the priority that is based on the static prio
++ */
++static inline int __normal_prio(struct task_struct *p)
++{
++	return p->static_prio;
++}
++
+ /*
+  * Calculate the expected normal priority: i.e. priority
+  * without taking RT-inheritance into account. Might be
+@@ -842,210 +670,31 @@ static int effective_prio(struct task_st
+ }
+ 
+ /*
+- * __activate_task - move a task to the runqueue.
++ * activate_task - move a task to the runqueue.
+  */
+-static void __activate_task(struct task_struct *p, struct rq *rq)
++static void activate_task(struct rq *rq, struct task_struct *p, int wakeup)
+ {
+-	struct prio_array *target = rq->active;
+-
+-	if (batch_task(p))
+-		target = rq->expired;
+-	enqueue_task(p, target);
++	enqueue_task(rq, p, wakeup);
+ 	inc_nr_running(p, rq);
+ }
+ 
+ /*
+- * __activate_idle_task - move idle task to the _front_ of runqueue.
++ * activate_idle_task - move idle task to the _front_ of runqueue.
+  */
+-static inline void __activate_idle_task(struct task_struct *p, struct rq *rq)
++static inline void activate_idle_task(struct task_struct *p, struct rq *rq)
+ {
+-	enqueue_task_head(p, rq->active);
++	enqueue_task(rq, p, 0);
+ 	inc_nr_running(p, rq);
+ }
+ 
+ /*
+- * Recalculate p->normal_prio and p->prio after having slept,
+- * updating the sleep-average too:
+- */
+-static int recalc_task_prio(struct task_struct *p, unsigned long long now)
+-{
+-	/* Caller must always ensure 'now >= p->timestamp' */
+-	unsigned long sleep_time = now - p->timestamp;
+-
+-	if (batch_task(p))
+-		sleep_time = 0;
+-
+-	if (likely(sleep_time > 0)) {
+-		/*
+-		 * This ceiling is set to the lowest priority that would allow
+-		 * a task to be reinserted into the active array on timeslice
+-		 * completion.
+-		 */
+-		unsigned long ceiling = INTERACTIVE_SLEEP(p);
+-
+-		if (p->mm && sleep_time > ceiling && p->sleep_avg < ceiling) {
+-			/*
+-			 * Prevents user tasks from achieving best priority
+-			 * with one single large enough sleep.
+-			 */
+-			p->sleep_avg = ceiling;
+-			/*
+-			 * Using INTERACTIVE_SLEEP() as a ceiling places a
+-			 * nice(0) task 1ms sleep away from promotion, and
+-			 * gives it 700ms to round-robin with no chance of
+-			 * being demoted.  This is more than generous, so
+-			 * mark this sleep as non-interactive to prevent the
+-			 * on-runqueue bonus logic from intervening should
+-			 * this task not receive cpu immediately.
+-			 */
+-			p->sleep_type = SLEEP_NONINTERACTIVE;
+-		} else {
+-			/*
+-			 * Tasks waking from uninterruptible sleep are
+-			 * limited in their sleep_avg rise as they
+-			 * are likely to be waiting on I/O
+-			 */
+-			if (p->sleep_type == SLEEP_NONINTERACTIVE && p->mm) {
+-				if (p->sleep_avg >= ceiling)
+-					sleep_time = 0;
+-				else if (p->sleep_avg + sleep_time >=
+-					 ceiling) {
+-						p->sleep_avg = ceiling;
+-						sleep_time = 0;
+-				}
+-			}
+-
+-			/*
+-			 * This code gives a bonus to interactive tasks.
+-			 *
+-			 * The boost works by updating the 'average sleep time'
+-			 * value here, based on ->timestamp. The more time a
+-			 * task spends sleeping, the higher the average gets -
+-			 * and the higher the priority boost gets as well.
+-			 */
+-			p->sleep_avg += sleep_time;
+-
+-		}
+-		if (p->sleep_avg > NS_MAX_SLEEP_AVG)
+-			p->sleep_avg = NS_MAX_SLEEP_AVG;
+-	}
+-
+-	return effective_prio(p);
+-}
+-
+-/*
+- * activate_task - move a task to the runqueue and do priority recalculation
+- *
+- * Update all the scheduling statistics stuff. (sleep average
+- * calculation, priority modifiers, etc.)
+- */
+-static void activate_task(struct task_struct *p, struct rq *rq, int local)
+-{
+-	unsigned long long now;
+-
+-	if (rt_task(p))
+-		goto out;
+-
+-	now = sched_clock();
+-#ifdef CONFIG_SMP
+-	if (!local) {
+-		/* Compensate for drifting sched_clock */
+-		struct rq *this_rq = this_rq();
+-		now = (now - this_rq->most_recent_timestamp)
+-			+ rq->most_recent_timestamp;
+-	}
+-#endif
+-
+-	/*
+-	 * Sleep time is in units of nanosecs, so shift by 20 to get a
+-	 * milliseconds-range estimation of the amount of time that the task
+-	 * spent sleeping:
+-	 */
+-	if (unlikely(prof_on == SLEEP_PROFILING)) {
+-		if (p->state == TASK_UNINTERRUPTIBLE)
+-			profile_hits(SLEEP_PROFILING, (void *)get_wchan(p),
+-				     (now - p->timestamp) >> 20);
+-	}
+-
+-	p->prio = recalc_task_prio(p, now);
+-
+-	/*
+-	 * This checks to make sure it's not an uninterruptible task
+-	 * that is now waking up.
+-	 */
+-	if (p->sleep_type == SLEEP_NORMAL) {
+-		/*
+-		 * Tasks which were woken up by interrupts (ie. hw events)
+-		 * are most likely of interactive nature. So we give them
+-		 * the credit of extending their sleep time to the period
+-		 * of time they spend on the runqueue, waiting for execution
+-		 * on a CPU, first time around:
+-		 */
+-		if (in_interrupt())
+-			p->sleep_type = SLEEP_INTERRUPTED;
+-		else {
+-			/*
+-			 * Normal first-time wakeups get a credit too for
+-			 * on-runqueue time, but it will be weighted down:
+-			 */
+-			p->sleep_type = SLEEP_INTERACTIVE;
+-		}
+-	}
+-	p->timestamp = now;
+-out:
+-	__activate_task(p, rq);
+-}
+-
+-/*
+  * deactivate_task - remove a task from the runqueue.
+  */
+-static void deactivate_task(struct task_struct *p, struct rq *rq)
++static void deactivate_task(struct rq *rq, struct task_struct *p, int sleep)
+ {
++	dequeue_task(rq, p, sleep);
+ 	dec_nr_running(p, rq);
+-	dequeue_task(p, p->array);
+-	p->array = NULL;
+-}
+-
+-/*
+- * resched_task - mark a task 'to be rescheduled now'.
+- *
+- * On UP this means the setting of the need_resched flag, on SMP it
+- * might also involve a cross-CPU call to trigger the scheduler on
+- * the target CPU.
+- */
+-#ifdef CONFIG_SMP
+-
+-#ifndef tsk_is_polling
+-#define tsk_is_polling(t) test_tsk_thread_flag(t, TIF_POLLING_NRFLAG)
+-#endif
+-
+-static void resched_task(struct task_struct *p)
+-{
+-	int cpu;
+-
+-	assert_spin_locked(&task_rq(p)->lock);
+-
+-	if (unlikely(test_tsk_thread_flag(p, TIF_NEED_RESCHED)))
+-		return;
+-
+-	set_tsk_thread_flag(p, TIF_NEED_RESCHED);
+-
+-	cpu = task_cpu(p);
+-	if (cpu == smp_processor_id())
+-		return;
+-
+-	/* NEED_RESCHED must be visible before we test polling */
+-	smp_mb();
+-	if (!tsk_is_polling(p))
+-		smp_send_reschedule(cpu);
+-}
+-#else
+-static inline void resched_task(struct task_struct *p)
+-{
+-	assert_spin_locked(&task_rq(p)->lock);
+-	set_tsk_need_resched(p);
+ }
+-#endif
+ 
+ /**
+  * task_curr - is this task currently executing on a CPU?
+@@ -1085,7 +734,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->array && !task_running(rq, p)) {
++	if (!p->on_rq && !task_running(rq, p)) {
+ 		set_task_cpu(p, dest_cpu);
+ 		return 0;
+ 	}
+@@ -1116,7 +765,7 @@ void wait_task_inactive(struct task_stru
+ repeat:
+ 	rq = task_rq_lock(p, &flags);
+ 	/* Must be off runqueue entirely, not preempted. */
+-	if (unlikely(p->array || task_running(rq, p))) {
++	if (unlikely(p->on_rq || task_running(rq, p))) {
+ 		/* If it's preempted, we yield.  It could be a while. */
+ 		preempted = !task_running(rq, p);
+ 		task_rq_unlock(rq, &flags);
+@@ -1292,9 +941,9 @@ static int sched_balance_self(int cpu, i
+ 	struct sched_domain *tmp, *sd = NULL;
+ 
+ 	for_each_domain(cpu, tmp) {
+- 		/*
+- 	 	 * If power savings logic is enabled for a domain, stop there.
+- 	 	 */
++		/*
++		 * If power savings logic is enabled for a domain, stop there.
++		 */
+ 		if (tmp->flags & SD_POWERSAVINGS_BALANCE)
+ 			break;
+ 		if (tmp->flags & flag)
+@@ -1412,7 +1061,7 @@ static int try_to_wake_up(struct task_st
+ 	if (!(old_state & state))
+ 		goto out;
+ 
+-	if (p->array)
++	if (p->on_rq)
+ 		goto out_running;
+ 
+ 	cpu = task_cpu(p);
+@@ -1505,7 +1154,7 @@ out_set_cpu:
+ 		old_state = p->state;
+ 		if (!(old_state & state))
+ 			goto out;
+-		if (p->array)
++		if (p->on_rq)
+ 			goto out_running;
+ 
+ 		this_cpu = smp_processor_id();
+@@ -1514,25 +1163,10 @@ out_set_cpu:
+ 
+ out_activate:
+ #endif /* CONFIG_SMP */
+-	if (old_state == TASK_UNINTERRUPTIBLE) {
++	if (old_state == TASK_UNINTERRUPTIBLE)
+ 		rq->nr_uninterruptible--;
+-		/*
+-		 * Tasks on involuntary sleep don't earn
+-		 * sleep_avg beyond just interactive state.
+-		 */
+-		p->sleep_type = SLEEP_NONINTERACTIVE;
+-	} else
+ 
+-	/*
+-	 * Tasks that have marked their sleep as noninteractive get
+-	 * woken up with their sleep average not weighted in an
+-	 * interactive way.
+-	 */
+-		if (old_state & TASK_NONINTERACTIVE)
+-			p->sleep_type = SLEEP_NONINTERACTIVE;
+-
+-
+-	activate_task(p, rq, cpu == this_cpu);
++	activate_task(rq, p, 1);
+ 	/*
+ 	 * Sync wakeups (i.e. those types of wakeups where the waker
+ 	 * has indicated that it will leave the CPU in short order)
+@@ -1541,10 +1175,8 @@ out_activate:
+ 	 * the waker guarantees that the freshly woken up task is going
+ 	 * to be considered on this CPU.)
+ 	 */
+-	if (!sync || cpu != this_cpu) {
+-		if (TASK_PREEMPTS_CURR(p, rq))
+-			resched_task(rq->curr);
+-	}
++	if (!sync || cpu != this_cpu)
++		check_preempt_curr(rq, p);
+ 	success = 1;
+ 
+ out_running:
+@@ -1567,19 +1199,35 @@ int fastcall wake_up_state(struct task_s
+ 	return try_to_wake_up(p, state, 0);
+ }
+ 
+-static void task_running_tick(struct rq *rq, struct task_struct *p);
++/*
++ * The task was running during this tick - call the class tick
++ * (to update the time slice counter and other statistics, etc.):
++ */
++static void task_running_tick(struct rq *rq, struct task_struct *p)
++{
++	spin_lock(&rq->lock);
++	p->sched_class->task_tick(rq, p);
++	spin_unlock(&rq->lock);
++}
++
+ /*
+  * Perform scheduler related setup for a newly forked process p.
+  * p is forked by current.
++ *
++ * __sched_fork() is basic setup used by init_idle() too:
+  */
+-void fastcall sched_fork(struct task_struct *p, int clone_flags)
++static void __sched_fork(struct task_struct *p)
+ {
+-	int cpu = get_cpu();
++	p->wait_start_fair = p->wait_start = p->exec_start = p->last_ran = 0;
++	p->sum_exec_runtime = p->wait_runtime = 0;
++	p->sum_wait_runtime = 0;
++	p->sleep_start = p->block_start = 0;
++	p->sleep_max = p->block_max = p->exec_max = p->wait_max = 0;
+ 
+-#ifdef CONFIG_SMP
+-	cpu = sched_balance_self(cpu, SD_BALANCE_FORK);
+-#endif
+-	set_task_cpu(p, cpu);
++	INIT_LIST_HEAD(&p->run_list);
++	p->on_rq = 0;
++	p->nr_switches = 0;
++	p->min_wait_runtime = 0;
+ 
+ 	/*
+ 	 * We mark the process as running here, but have not actually
+@@ -1588,16 +1236,29 @@ void fastcall sched_fork(struct task_str
+ 	 * event cannot wake it up and insert it on the runqueue either.
+ 	 */
+ 	p->state = TASK_RUNNING;
++}
++
++/*
++ * fork()/clone()-time setup:
++ */
++void sched_fork(struct task_struct *p, int clone_flags)
++{
++	int cpu = get_cpu();
++
++	__sched_fork(p);
++
++#ifdef CONFIG_SMP
++	cpu = sched_balance_self(cpu, SD_BALANCE_FORK);
++#endif
++	set_task_cpu(p, cpu);
+ 
+ 	/*
+ 	 * Make sure we do not leak PI boosting priority to the child:
+ 	 */
+ 	p->prio = current->normal_prio;
+ 
+-	INIT_LIST_HEAD(&p->run_list);
+-	p->array = NULL;
+ #if defined(CONFIG_SCHEDSTATS) || defined(CONFIG_TASK_DELAY_ACCT)
+-	if (unlikely(sched_info_on()))
++	if (likely(sched_info_on()))
+ 		memset(&p->sched_info, 0, sizeof(p->sched_info));
+ #endif
+ #if defined(CONFIG_SMP) && defined(__ARCH_WANT_UNLOCKED_CTXSW)
+@@ -1607,34 +1268,16 @@ void fastcall sched_fork(struct task_str
+ 	/* Want to start with kernel preemption disabled. */
+ 	task_thread_info(p)->preempt_count = 1;
+ #endif
+-	/*
+-	 * Share the timeslice between parent and child, thus the
+-	 * total amount of pending timeslices in the system doesn't change,
+-	 * resulting in more scheduling fairness.
+-	 */
+-	local_irq_disable();
+-	p->time_slice = (current->time_slice + 1) >> 1;
+-	/*
+-	 * The remainder of the first timeslice might be recovered by
+-	 * the parent if the child exits early enough.
+-	 */
+-	p->first_time_slice = 1;
+-	current->time_slice >>= 1;
+-	p->timestamp = sched_clock();
+-	if (unlikely(!current->time_slice)) {
+-		/*
+-		 * This case is rare, it happens when the parent has only
+-		 * a single jiffy left from its timeslice. Taking the
+-		 * runqueue lock is not a problem.
+-		 */
+-		current->time_slice = 1;
+-		task_running_tick(cpu_rq(cpu), current);
+-	}
+-	local_irq_enable();
+ 	put_cpu();
+ }
+ 
+ /*
++ * After fork, child runs first. (default) If set to 0 then
++ * parent will (try to) run first.
++ */
++unsigned int __read_mostly sysctl_sched_child_runs_first = 1;
++
++/*
+  * wake_up_new_task - wake up a newly created task for the first time.
+  *
+  * This function will do some initial scheduler statistics housekeeping
+@@ -1643,107 +1286,27 @@ void fastcall sched_fork(struct task_str
+  */
+ void fastcall wake_up_new_task(struct task_struct *p, unsigned long clone_flags)
+ {
+-	struct rq *rq, *this_rq;
+ 	unsigned long flags;
+-	int this_cpu, cpu;
++	struct rq *rq;
++	int this_cpu;
+ 
+ 	rq = task_rq_lock(p, &flags);
+ 	BUG_ON(p->state != TASK_RUNNING);
+-	this_cpu = smp_processor_id();
+-	cpu = task_cpu(p);
+-
+-	/*
+-	 * We decrease the sleep average of forking parents
+-	 * and children as well, to keep max-interactive tasks
+-	 * from forking tasks that are max-interactive. The parent
+-	 * (current) is done further down, under its lock.
+-	 */
+-	p->sleep_avg = JIFFIES_TO_NS(CURRENT_BONUS(p) *
+-		CHILD_PENALTY / 100 * MAX_SLEEP_AVG / MAX_BONUS);
++	this_cpu = smp_processor_id(); /* parent's CPU */
+ 
+ 	p->prio = effective_prio(p);
+ 
+-	if (likely(cpu == this_cpu)) {
+-		if (!(clone_flags & CLONE_VM)) {
+-			/*
+-			 * The VM isn't cloned, so we're in a good position to
+-			 * do child-runs-first in anticipation of an exec. This
+-			 * usually avoids a lot of COW overhead.
+-			 */
+-			if (unlikely(!current->array))
+-				__activate_task(p, rq);
+-			else {
+-				p->prio = current->prio;
+-				p->normal_prio = current->normal_prio;
+-				list_add_tail(&p->run_list, &current->run_list);
+-				p->array = current->array;
+-				p->array->nr_active++;
+-				inc_nr_running(p, rq);
+-			}
+-			set_need_resched();
+-		} else
+-			/* Run child last */
+-			__activate_task(p, rq);
+-		/*
+-		 * We skip the following code due to cpu == this_cpu
+-	 	 *
+-		 *   task_rq_unlock(rq, &flags);
+-		 *   this_rq = task_rq_lock(current, &flags);
+-		 */
+-		this_rq = rq;
++	if (!sysctl_sched_child_runs_first || (clone_flags & CLONE_VM) ||
++			task_cpu(p) != this_cpu || !current->on_rq) {
++		activate_task(rq, p, 0);
+ 	} else {
+-		this_rq = cpu_rq(this_cpu);
+-
+-		/*
+-		 * Not the local CPU - must adjust timestamp. This should
+-		 * get optimised away in the !CONFIG_SMP case.
+-		 */
+-		p->timestamp = (p->timestamp - this_rq->most_recent_timestamp)
+-					+ rq->most_recent_timestamp;
+-		__activate_task(p, rq);
+-		if (TASK_PREEMPTS_CURR(p, rq))
+-			resched_task(rq->curr);
+-
+ 		/*
+-		 * Parent and child are on different CPUs, now get the
+-		 * parent runqueue to update the parent's ->sleep_avg:
++		 * Let the scheduling class do new task startup
++		 * management (if any):
+ 		 */
+-		task_rq_unlock(rq, &flags);
+-		this_rq = task_rq_lock(current, &flags);
++		p->sched_class->task_new(rq, p);
+ 	}
+-	current->sleep_avg = JIFFIES_TO_NS(CURRENT_BONUS(current) *
+-		PARENT_PENALTY / 100 * MAX_SLEEP_AVG / MAX_BONUS);
+-	task_rq_unlock(this_rq, &flags);
+-}
+-
+-/*
+- * Potentially available exiting-child timeslices are
+- * retrieved here - this way the parent does not get
+- * penalized for creating too many threads.
+- *
+- * (this cannot be used to 'generate' timeslices
+- * artificially, because any timeslice recovered here
+- * was given away by the parent in the first place.)
+- */
+-void fastcall sched_exit(struct task_struct *p)
+-{
+-	unsigned long flags;
+-	struct rq *rq;
+-
+-	/*
+-	 * If the child was a (relative-) CPU hog then decrease
+-	 * the sleep_avg of the parent as well.
+-	 */
+-	rq = task_rq_lock(p->parent, &flags);
+-	if (p->first_time_slice && task_cpu(p) == task_cpu(p->parent)) {
+-		p->parent->time_slice += p->time_slice;
+-		if (unlikely(p->parent->time_slice > task_timeslice(p)))
+-			p->parent->time_slice = task_timeslice(p);
+-	}
+-	if (p->sleep_avg < p->parent->sleep_avg)
+-		p->parent->sleep_avg = p->parent->sleep_avg /
+-		(EXIT_WEIGHT + 1) * EXIT_WEIGHT + p->sleep_avg /
+-		(EXIT_WEIGHT + 1);
++	check_preempt_curr(rq, p);
+ 	task_rq_unlock(rq, &flags);
+ }
+ 
+@@ -1941,17 +1504,56 @@ unsigned long nr_active(void)
+ 	return running + uninterruptible;
+ }
+ 
+-#ifdef CONFIG_SMP
+-
+-/*
+- * Is this task likely cache-hot:
+- */
+-static inline int
+-task_hot(struct task_struct *p, unsigned long long now, struct sched_domain *sd)
++static void update_load_fair(struct rq *this_rq)
+ {
+-	return (long long)(now - p->last_ran) < (long long)sd->cache_hot_time;
++	unsigned long this_load, fair_delta, exec_delta, idle_delta;
++	unsigned int i, scale;
++	s64 fair_delta64, exec_delta64;
++	unsigned long tmp;
++	u64 tmp64;
++
++	this_rq->nr_load_updates++;
++
++	fair_delta64 = this_rq->fair_clock - this_rq->prev_fair_clock + 1;
++	this_rq->prev_fair_clock = this_rq->fair_clock;
++	WARN_ON_ONCE(fair_delta64 <= 0);
++
++	exec_delta64 = this_rq->exec_clock - this_rq->prev_exec_clock + 1;
++	this_rq->prev_exec_clock = this_rq->exec_clock;
++	WARN_ON_ONCE(exec_delta64 <= 0);
++
++	if (fair_delta64 > (s64)LONG_MAX)
++		fair_delta64 = (s64)LONG_MAX;
++	fair_delta = (unsigned long)fair_delta64;
++
++	if (exec_delta64 > (s64)LONG_MAX)
++		exec_delta64 = (s64)LONG_MAX;
++	exec_delta = (unsigned long)exec_delta64;
++	if (exec_delta > TICK_NSEC)
++		exec_delta = TICK_NSEC;
++
++	idle_delta = TICK_NSEC - exec_delta;
++
++	tmp = (SCHED_LOAD_SCALE * exec_delta) / fair_delta;
++	tmp64 = (u64)tmp * (u64)exec_delta;
++	do_div(tmp64, TICK_NSEC);
++	this_load = (unsigned long)tmp64;
++
++	/* Update our load: */
++	for (i = 0, scale = 1; i < CPU_LOAD_IDX_MAX; i++, scale += scale) {
++		unsigned long old_load, new_load;
++
++		/* scale is effectively 1 << i now, and >> i divides by scale */
++
++		old_load = this_rq->cpu_load[i];
++		new_load = this_load;
++
++		this_rq->cpu_load[i] = (old_load*(scale-1) + new_load) >> i;
++	}
+ }
+ 
++#ifdef CONFIG_SMP
++
+ /*
+  * double_rq_lock - safely lock two runqueues
+  *
+@@ -2068,23 +1670,17 @@ void sched_exec(void)
+  * pull_task - move a task from a remote runqueue to the local runqueue.
+  * Both runqueues must be locked.
+  */
+-static void pull_task(struct rq *src_rq, struct prio_array *src_array,
+-		      struct task_struct *p, struct rq *this_rq,
+-		      struct prio_array *this_array, int this_cpu)
++static void pull_task(struct rq *src_rq, struct task_struct *p,
++		      struct rq *this_rq, int this_cpu)
+ {
+-	dequeue_task(p, src_array);
+-	dec_nr_running(p, src_rq);
++	deactivate_task(src_rq, p, 0);
+ 	set_task_cpu(p, this_cpu);
+-	inc_nr_running(p, this_rq);
+-	enqueue_task(p, this_array);
+-	p->timestamp = (p->timestamp - src_rq->most_recent_timestamp)
+-				+ this_rq->most_recent_timestamp;
++	activate_task(this_rq, p, 0);
+ 	/*
+ 	 * Note that idle threads have a prio of MAX_PRIO, for this test
+ 	 * to be always true for them.
+ 	 */
+-	if (TASK_PREEMPTS_CURR(p, this_rq))
+-		resched_task(this_rq->curr);
++	check_preempt_curr(this_rq, p);
+ }
+ 
+ /*
+@@ -2109,25 +1705,59 @@ int can_migrate_task(struct task_struct 
+ 		return 0;
+ 
+ 	/*
+-	 * Aggressive migration if:
+-	 * 1) task is cache cold, or
+-	 * 2) too many balance attempts have failed.
++	 * Aggressive migration if too many balance attempts have failed:
+ 	 */
+-
+-	if (sd->nr_balance_failed > sd->cache_nice_tries) {
+-#ifdef CONFIG_SCHEDSTATS
+-		if (task_hot(p, rq->most_recent_timestamp, sd))
+-			schedstat_inc(sd, lb_hot_gained[idle]);
+-#endif
++	if (sd->nr_balance_failed > sd->cache_nice_tries)
+ 		return 1;
+-	}
+ 
+-	if (task_hot(p, rq->most_recent_timestamp, sd))
+-		return 0;
+ 	return 1;
+ }
+ 
+-#define rq_best_prio(rq) min((rq)->curr->prio, (rq)->best_expired_prio)
++/*
++ * Load-balancing iterator: iterate through the hieararchy of scheduling
++ * classes, starting with the highest-prio one:
++ */
++
++struct task_struct * load_balance_start(struct rq *rq)
++{
++	struct sched_class *class = sched_class_highest;
++	struct task_struct *p;
++
++	do {
++		p = class->load_balance_start(rq);
++		if (p) {
++			rq->load_balance_class = class;
++			return p;
++		}
++		class = class->next;
++	} while (class);
++
++	return NULL;
++}
++
++struct task_struct * load_balance_next(struct rq *rq)
++{
++	struct sched_class *class = rq->load_balance_class;
++	struct task_struct *p;
++
++	p = class->load_balance_next(rq);
++	if (p)
++		return p;
++	/*
++	 * Pick up the next class (if any) and attempt to start
++	 * the iterator there:
++	 */
++	while ((class = class->next)) {
++		p = class->load_balance_start(rq);
++		if (p) {
++			rq->load_balance_class = class;
++			return p;
++		}
++	}
++	return NULL;
++}
++
++#define rq_best_prio(rq) (rq)->curr->prio
+ 
+ /*
+  * move_tasks tries to move up to max_nr_move tasks and max_load_move weighted
+@@ -2141,11 +1771,9 @@ static int move_tasks(struct rq *this_rq
+ 		      struct sched_domain *sd, enum idle_type idle,
+ 		      int *all_pinned)
+ {
+-	int idx, pulled = 0, pinned = 0, this_best_prio, best_prio,
++	int pulled = 0, pinned = 0, this_best_prio, best_prio,
+ 	    best_prio_seen, skip_for_load;
+-	struct prio_array *array, *dst_array;
+-	struct list_head *head, *curr;
+-	struct task_struct *tmp;
++	struct task_struct *p;
+ 	long rem_load_move;
+ 
+ 	if (max_nr_move == 0 || max_load_move == 0)
+@@ -2165,76 +1793,41 @@ static int move_tasks(struct rq *this_rq
+ 	best_prio_seen = best_prio == busiest->curr->prio;
+ 
+ 	/*
+-	 * We first consider expired tasks. Those will likely not be
+-	 * executed in the near future, and they are most likely to
+-	 * be cache-cold, thus switching CPUs has the least effect
+-	 * on them.
+-	 */
+-	if (busiest->expired->nr_active) {
+-		array = busiest->expired;
+-		dst_array = this_rq->expired;
+-	} else {
+-		array = busiest->active;
+-		dst_array = this_rq->active;
+-	}
+-
+-new_array:
+-	/* Start searching at priority 0: */
+-	idx = 0;
+-skip_bitmap:
+-	if (!idx)
+-		idx = sched_find_first_bit(array->bitmap);
+-	else
+-		idx = find_next_bit(array->bitmap, MAX_PRIO, idx);
+-	if (idx >= MAX_PRIO) {
+-		if (array == busiest->expired && busiest->active->nr_active) {
+-			array = busiest->active;
+-			dst_array = this_rq->active;
+-			goto new_array;
+-		}
++	 * Start the load-balancing iterator:
++	 */
++	p = load_balance_start(busiest);
++next:
++	if (!p)
+ 		goto out;
+-	}
+-
+-	head = array->queue + idx;
+-	curr = head->prev;
+-skip_queue:
+-	tmp = list_entry(curr, struct task_struct, run_list);
+-
+-	curr = curr->prev;
+-
+ 	/*
+ 	 * To help distribute high priority tasks accross CPUs we don't
+ 	 * skip a task if it will be the highest priority task (i.e. smallest
+ 	 * prio value) on its new queue regardless of its load weight
+ 	 */
+-	skip_for_load = tmp->load_weight > rem_load_move;
+-	if (skip_for_load && idx < this_best_prio)
+-		skip_for_load = !best_prio_seen && idx == best_prio;
++	skip_for_load = p->load_weight > rem_load_move;
++	if (skip_for_load && p->prio < this_best_prio)
++		skip_for_load = !best_prio_seen && p->prio == best_prio;
+ 	if (skip_for_load ||
+-	    !can_migrate_task(tmp, busiest, this_cpu, sd, idle, &pinned)) {
++	    !can_migrate_task(p, busiest, this_cpu, sd, idle, &pinned)) {
+ 
+-		best_prio_seen |= idx == best_prio;
+-		if (curr != head)
+-			goto skip_queue;
+-		idx++;
+-		goto skip_bitmap;
++		best_prio_seen |= p->prio == best_prio;
++		p = load_balance_next(busiest);
++		goto next;
+ 	}
+ 
+-	pull_task(busiest, array, tmp, this_rq, dst_array, this_cpu);
++	pull_task(busiest, p, this_rq, this_cpu);
+ 	pulled++;
+-	rem_load_move -= tmp->load_weight;
++	rem_load_move -= p->load_weight;
+ 
+ 	/*
+ 	 * We only want to steal up to the prescribed number of tasks
+ 	 * and the prescribed amount of weighted load.
+ 	 */
+ 	if (pulled < max_nr_move && rem_load_move > 0) {
+-		if (idx < this_best_prio)
+-			this_best_prio = idx;
+-		if (curr != head)
+-			goto skip_queue;
+-		idx++;
+-		goto skip_bitmap;
++		if (p->prio < this_best_prio)
++			this_best_prio = p->prio;
++		p = load_balance_next(busiest);
++		goto next;
+ 	}
+ out:
+ 	/*
+@@ -2360,8 +1953,8 @@ find_busiest_group(struct sched_domain *
+ 		 * Busy processors will not participate in power savings
+ 		 * balance.
+ 		 */
+- 		if (idle == NOT_IDLE || !(sd->flags & SD_POWERSAVINGS_BALANCE))
+- 			goto group_next;
++		if (idle == NOT_IDLE || !(sd->flags & SD_POWERSAVINGS_BALANCE))
++			goto group_next;
+ 
+ 		/*
+ 		 * If the local group is idle or completely loaded
+@@ -2371,42 +1964,42 @@ find_busiest_group(struct sched_domain *
+ 				    !this_nr_running))
+ 			power_savings_balance = 0;
+ 
+- 		/*
++		/*
+ 		 * If a group is already running at full capacity or idle,
+ 		 * don't include that group in power savings calculations
+- 		 */
+- 		if (!power_savings_balance || sum_nr_running >= group_capacity
++		 */
++		if (!power_savings_balance || sum_nr_running >= group_capacity
+ 		    || !sum_nr_running)
+- 			goto group_next;
++			goto group_next;
+ 
+- 		/*
++		/*
+ 		 * Calculate the group which has the least non-idle load.
+- 		 * This is the group from where we need to pick up the load
+- 		 * for saving power
+- 		 */
+- 		if ((sum_nr_running < min_nr_running) ||
+- 		    (sum_nr_running == min_nr_running &&
++		 * This is the group from where we need to pick up the load
++		 * for saving power
++		 */
++		if ((sum_nr_running < min_nr_running) ||
++		    (sum_nr_running == min_nr_running &&
+ 		     first_cpu(group->cpumask) <
+ 		     first_cpu(group_min->cpumask))) {
+- 			group_min = group;
+- 			min_nr_running = sum_nr_running;
++			group_min = group;
++			min_nr_running = sum_nr_running;
+ 			min_load_per_task = sum_weighted_load /
+ 						sum_nr_running;
+- 		}
++		}
+ 
+- 		/*
++		/*
+ 		 * Calculate the group which is almost near its
+- 		 * capacity but still has some space to pick up some load
+- 		 * from other group and save more power
+- 		 */
+- 		if (sum_nr_running <= group_capacity - 1) {
+- 			if (sum_nr_running > leader_nr_running ||
+- 			    (sum_nr_running == leader_nr_running &&
+- 			     first_cpu(group->cpumask) >
+- 			      first_cpu(group_leader->cpumask))) {
+- 				group_leader = group;
+- 				leader_nr_running = sum_nr_running;
+- 			}
++		 * capacity but still has some space to pick up some load
++		 * from other group and save more power
++		 */
++		if (sum_nr_running <= group_capacity - 1) {
++			if (sum_nr_running > leader_nr_running ||
++			    (sum_nr_running == leader_nr_running &&
++			     first_cpu(group->cpumask) >
++			      first_cpu(group_leader->cpumask))) {
++				group_leader = group;
++				leader_nr_running = sum_nr_running;
++			}
+ 		}
+ group_next:
+ #endif
+@@ -2461,7 +2054,7 @@ group_next:
+ 	 * a think about bumping its value to force at least one task to be
+ 	 * moved
+ 	 */
+-	if (*imbalance < busiest_load_per_task) {
++	if (*imbalance + SCHED_LOAD_SCALE_FUZZ < busiest_load_per_task) {
+ 		unsigned long tmp, pwr_now, pwr_move;
+ 		unsigned int imbn;
+ 
+@@ -2475,7 +2068,8 @@ small_imbalance:
+ 		} else
+ 			this_load_per_task = SCHED_LOAD_SCALE;
+ 
+-		if (max_load - this_load >= busiest_load_per_task * imbn) {
++		if (max_load - this_load + SCHED_LOAD_SCALE_FUZZ >=
++					busiest_load_per_task * imbn) {
+ 			*imbalance = busiest_load_per_task;
+ 			return busiest;
+ 		}
+@@ -2884,30 +2478,6 @@ static void active_load_balance(struct r
+ 	spin_unlock(&target_rq->lock);
+ }
+ 
+-static void update_load(struct rq *this_rq)
+-{
+-	unsigned long this_load;
+-	int i, scale;
+-
+-	this_load = this_rq->raw_weighted_load;
+-
+-	/* Update our load: */
+-	for (i = 0, scale = 1; i < 3; i++, scale <<= 1) {
+-		unsigned long old_load, new_load;
+-
+-		old_load = this_rq->cpu_load[i];
+-		new_load = this_load;
+-		/*
+-		 * Round up the averaging division if load is increasing. This
+-		 * prevents us from getting stuck on 9 if the load is 10, for
+-		 * example.
+-		 */
+-		if (new_load > old_load)
+-			new_load += scale-1;
+-		this_rq->cpu_load[i] = (old_load*(scale-1) + new_load) / scale;
+-	}
+-}
+-
+ /*
+  * run_rebalance_domains is triggered when needed from the scheduler tick.
+  *
+@@ -2987,76 +2557,27 @@ static inline void idle_balance(int cpu,
+ }
+ #endif
+ 
+-static inline void wake_priority_sleeper(struct rq *rq)
+-{
+-#ifdef CONFIG_SCHED_SMT
+-	if (!rq->nr_running)
+-		return;
+-
+-	spin_lock(&rq->lock);
+-	/*
+-	 * If an SMT sibling task has been put to sleep for priority
+-	 * reasons reschedule the idle task to see if it can now run.
+-	 */
+-	if (rq->nr_running)
+-		resched_task(rq->idle);
+-	spin_unlock(&rq->lock);
+-#endif
+-}
+-
+ DEFINE_PER_CPU(struct kernel_stat, kstat);
+ 
+ EXPORT_PER_CPU_SYMBOL(kstat);
+ 
+ /*
+- * This is called on clock ticks and on context switches.
+- * Bank in p->sched_time the ns elapsed since the last tick or switch.
+- */
+-static inline void
+-update_cpu_clock(struct task_struct *p, struct rq *rq, unsigned long long now)
+-{
+-	p->sched_time += now - p->last_ran;
+-	p->last_ran = rq->most_recent_timestamp = now;
+-}
+-
+-/*
+- * Return current->sched_time plus any more ns on the sched_clock
++ * Return current->sum_exec_runtime plus any more ns on the sched_clock
+  * that have not yet been banked.
+  */
+-unsigned long long current_sched_time(const struct task_struct *p)
++unsigned long long current_sched_runtime(const struct task_struct *p)
+ {
+ 	unsigned long long ns;
+ 	unsigned long flags;
+ 
+ 	local_irq_save(flags);
+-	ns = p->sched_time + sched_clock() - p->last_ran;
++	ns = p->sum_exec_runtime + sched_clock() - p->last_ran;
+ 	local_irq_restore(flags);
+ 
+ 	return ns;
+ }
+ 
+ /*
+- * We place interactive tasks back into the active array, if possible.
+- *
+- * To guarantee that this does not starve expired tasks we ignore the
+- * interactivity of a task if the first expired task had to wait more
+- * than a 'reasonable' amount of time. This deadline timeout is
+- * load-dependent, as the frequency of array switched decreases with
+- * increasing number of running tasks. We also ignore the interactivity
+- * if a better static_prio task has expired:
+- */
+-static inline int expired_starving(struct rq *rq)
+-{
+-	if (rq->curr->static_prio > rq->best_expired_prio)
+-		return 1;
+-	if (!STARVATION_LIMIT || !rq->expired_timestamp)
+-		return 0;
+-	if (jiffies - rq->expired_timestamp > STARVATION_LIMIT * rq->nr_running)
+-		return 1;
+-	return 0;
+-}
+-
+-/*
+  * Account user cpu time to a process.
+  * @p: the process that the cpu time gets accounted to
+  * @hardirq_offset: the offset to subtract from hardirq_count()
+@@ -3129,81 +2650,6 @@ void account_steal_time(struct task_stru
+ 		cpustat->steal = cputime64_add(cpustat->steal, tmp);
+ }
+ 
+-static void task_running_tick(struct rq *rq, struct task_struct *p)
+-{
+-	if (p->array != rq->active) {
+-		/* Task has expired but was not scheduled yet */
+-		set_tsk_need_resched(p);
+-		return;
+-	}
+-	spin_lock(&rq->lock);
+-	/*
+-	 * The task was running during this tick - update the
+-	 * time slice counter. Note: we do not update a thread's
+-	 * priority until it either goes to sleep or uses up its
+-	 * timeslice. This makes it possible for interactive tasks
+-	 * to use up their timeslices at their highest priority levels.
+-	 */
+-	if (rt_task(p)) {
+-		/*
+-		 * RR tasks need a special form of timeslice management.
+-		 * FIFO tasks have no timeslices.
+-		 */
+-		if ((p->policy == SCHED_RR) && !--p->time_slice) {
+-			p->time_slice = task_timeslice(p);
+-			p->first_time_slice = 0;
+-			set_tsk_need_resched(p);
+-
+-			/* put it at the end of the queue: */
+-			requeue_task(p, rq->active);
+-		}
+-		goto out_unlock;
+-	}
+-	if (!--p->time_slice) {
+-		dequeue_task(p, rq->active);
+-		set_tsk_need_resched(p);
+-		p->prio = effective_prio(p);
+-		p->time_slice = task_timeslice(p);
+-		p->first_time_slice = 0;
+-
+-		if (!rq->expired_timestamp)
+-			rq->expired_timestamp = jiffies;
+-		if (!TASK_INTERACTIVE(p) || expired_starving(rq)) {
+-			enqueue_task(p, rq->expired);
+-			if (p->static_prio < rq->best_expired_prio)
+-				rq->best_expired_prio = p->static_prio;
+-		} else
+-			enqueue_task(p, rq->active);
+-	} else {
+-		/*
+-		 * Prevent a too long timeslice allowing a task to monopolize
+-		 * the CPU. We do this by splitting up the timeslice into
+-		 * smaller pieces.
+-		 *
+-		 * Note: this does not mean the task's timeslices expire or
+-		 * get lost in any way, they just might be preempted by
+-		 * another task of equal priority. (one with higher
+-		 * priority would have preempted this task already.) We
+-		 * requeue this task to the end of the list on this priority
+-		 * level, which is in essence a round-robin of tasks with
+-		 * equal priority.
+-		 *
+-		 * This only applies to tasks in the interactive
+-		 * delta range with at least TIMESLICE_GRANULARITY to requeue.
+-		 */
+-		if (TASK_INTERACTIVE(p) && !((task_timeslice(p) -
+-			p->time_slice) % TIMESLICE_GRANULARITY(p)) &&
+-			(p->time_slice >= TIMESLICE_GRANULARITY(p)) &&
+-			(p->array == rq->active)) {
+-
+-			requeue_task(p, rq->active);
+-			set_tsk_need_resched(p);
+-		}
+-	}
+-out_unlock:
+-	spin_unlock(&rq->lock);
+-}
+-
+ /*
+  * This function gets called by the timer code, with HZ frequency.
+  * We call it with interrupts disabled.
+@@ -3213,155 +2659,19 @@ out_unlock:
+  */
+ void scheduler_tick(void)
+ {
+-	unsigned long long now = sched_clock();
+ 	struct task_struct *p = current;
+ 	int cpu = smp_processor_id();
+ 	struct rq *rq = cpu_rq(cpu);
+ 
+-	update_cpu_clock(p, rq, now);
+-
+-	if (p == rq->idle)
+-		/* Task on the idle queue */
+-		wake_priority_sleeper(rq);
+-	else
++	if (p != rq->idle)
+ 		task_running_tick(rq, p);
++	update_load_fair(rq);
+ #ifdef CONFIG_SMP
+-	update_load(rq);
+ 	if (time_after_eq(jiffies, rq->next_balance))
+ 		raise_softirq(SCHED_SOFTIRQ);
+ #endif
+ }
+ 
+-#ifdef CONFIG_SCHED_SMT
+-static inline void wakeup_busy_runqueue(struct rq *rq)
+-{
+-	/* If an SMT runqueue is sleeping due to priority reasons wake it up */
+-	if (rq->curr == rq->idle && rq->nr_running)
+-		resched_task(rq->idle);
+-}
+-
+-/*
+- * Called with interrupt disabled and this_rq's runqueue locked.
+- */
+-static void wake_sleeping_dependent(int this_cpu)
+-{
+-	struct sched_domain *tmp, *sd = NULL;
+-	int i;
+-
+-	for_each_domain(this_cpu, tmp) {
+-		if (tmp->flags & SD_SHARE_CPUPOWER) {
+-			sd = tmp;
+-			break;
+-		}
+-	}
+-
+-	if (!sd)
+-		return;
+-
+-	for_each_cpu_mask(i, sd->span) {
+-		struct rq *smt_rq = cpu_rq(i);
+-
+-		if (i == this_cpu)
+-			continue;
+-		if (unlikely(!spin_trylock(&smt_rq->lock)))
+-			continue;
+-
+-		wakeup_busy_runqueue(smt_rq);
+-		spin_unlock(&smt_rq->lock);
+-	}
+-}
+-
+-/*
+- * number of 'lost' timeslices this task wont be able to fully
+- * utilize, if another task runs on a sibling. This models the
+- * slowdown effect of other tasks running on siblings:
+- */
+-static inline unsigned long
+-smt_slice(struct task_struct *p, struct sched_domain *sd)
+-{
+-	return p->time_slice * (100 - sd->per_cpu_gain) / 100;
+-}
+-
+-/*
+- * To minimise lock contention and not have to drop this_rq's runlock we only
+- * trylock the sibling runqueues and bypass those runqueues if we fail to
+- * acquire their lock. As we only trylock the normal locking order does not
+- * need to be obeyed.
+- */
+-static int
+-dependent_sleeper(int this_cpu, struct rq *this_rq, struct task_struct *p)
+-{
+-	struct sched_domain *tmp, *sd = NULL;
+-	int ret = 0, i;
+-
+-	/* kernel/rt threads do not participate in dependent sleeping */
+-	if (!p->mm || rt_task(p))
+-		return 0;
+-
+-	for_each_domain(this_cpu, tmp) {
+-		if (tmp->flags & SD_SHARE_CPUPOWER) {
+-			sd = tmp;
+-			break;
+-		}
+-	}
+-
+-	if (!sd)
+-		return 0;
+-
+-	for_each_cpu_mask(i, sd->span) {
+-		struct task_struct *smt_curr;
+-		struct rq *smt_rq;
+-
+-		if (i == this_cpu)
+-			continue;
+-
+-		smt_rq = cpu_rq(i);
+-		if (unlikely(!spin_trylock(&smt_rq->lock)))
+-			continue;
+-
+-		smt_curr = smt_rq->curr;
+-
+-		if (!smt_curr->mm)
+-			goto unlock;
+-
+-		/*
+-		 * If a user task with lower static priority than the
+-		 * running task on the SMT sibling is trying to schedule,
+-		 * delay it till there is proportionately less timeslice
+-		 * left of the sibling task to prevent a lower priority
+-		 * task from using an unfair proportion of the
+-		 * physical cpu's resources. -ck
+-		 */
+-		if (rt_task(smt_curr)) {
+-			/*
+-			 * With real time tasks we run non-rt tasks only
+-			 * per_cpu_gain% of the time.
+-			 */
+-			if ((jiffies % DEF_TIMESLICE) >
+-				(sd->per_cpu_gain * DEF_TIMESLICE / 100))
+-					ret = 1;
+-		} else {
+-			if (smt_curr->static_prio < p->static_prio &&
+-				!TASK_PREEMPTS_CURR(p, smt_rq) &&
+-				smt_slice(smt_curr, sd) > task_timeslice(p))
+-					ret = 1;
+-		}
+-unlock:
+-		spin_unlock(&smt_rq->lock);
+-	}
+-	return ret;
+-}
+-#else
+-static inline void wake_sleeping_dependent(int this_cpu)
+-{
+-}
+-static inline int
+-dependent_sleeper(int this_cpu, struct rq *this_rq, struct task_struct *p)
+-{
+-	return 0;
+-}
+-#endif
+-
+ #if defined(CONFIG_PREEMPT) && defined(CONFIG_DEBUG_PREEMPT)
+ 
+ void fastcall add_preempt_count(int val)
+@@ -3400,49 +2710,27 @@ EXPORT_SYMBOL(sub_preempt_count);
+ 
+ #endif
+ 
+-static inline int interactive_sleep(enum sleep_type sleep_type)
+-{
+-	return (sleep_type == SLEEP_INTERACTIVE ||
+-		sleep_type == SLEEP_INTERRUPTED);
+-}
+-
+ /*
+- * schedule() is the main scheduler function.
++ * Various schedule()-time debugging checks and statistics:
+  */
+-asmlinkage void __sched schedule(void)
++static inline void schedule_debug(struct rq *rq, struct task_struct *prev)
+ {
+-	struct task_struct *prev, *next;
+-	struct prio_array *array;
+-	struct list_head *queue;
+-	unsigned long long now;
+-	unsigned long run_time;
+-	int cpu, idx, new_prio;
+-	long *switch_count;
+-	struct rq *rq;
+-
+ 	/*
+ 	 * Test if we are atomic.  Since do_exit() needs to call into
+ 	 * schedule() atomically, we ignore that path for now.
+ 	 * Otherwise, whine if we are scheduling when we should not be.
+ 	 */
+-	if (unlikely(in_atomic() && !current->exit_state)) {
++	if (unlikely(in_atomic_preempt_off() && !prev->exit_state)) {
+ 		printk(KERN_ERR "BUG: scheduling while atomic: "
+ 			"%s/0x%08x/%d\n",
+-			current->comm, preempt_count(), current->pid);
+-		debug_show_held_locks(current);
++			prev->comm, preempt_count(), prev->pid);
++		debug_show_held_locks(prev);
+ 		if (irqs_disabled())
+-			print_irqtrace_events(current);
++			print_irqtrace_events(prev);
+ 		dump_stack();
+ 	}
+ 	profile_hit(SCHED_PROFILING, __builtin_return_address(0));
+ 
+-need_resched:
+-	preempt_disable();
+-	prev = current;
+-	release_kernel_lock(prev);
+-need_resched_nonpreemptible:
+-	rq = this_rq();
+-
+ 	/*
+ 	 * The idle thread is not allowed to schedule!
+ 	 * Remove this check after it has been exercised a bit.
+@@ -3453,19 +2741,45 @@ need_resched_nonpreemptible:
+ 	}
+ 
+ 	schedstat_inc(rq, sched_cnt);
+-	now = sched_clock();
+-	if (likely((long long)(now - prev->timestamp) < NS_MAX_SLEEP_AVG)) {
+-		run_time = now - prev->timestamp;
+-		if (unlikely((long long)(now - prev->timestamp) < 0))
+-			run_time = 0;
+-	} else
+-		run_time = NS_MAX_SLEEP_AVG;
++}
+ 
+-	/*
+-	 * Tasks charged proportionately less run_time at high sleep_avg to
+-	 * delay them losing their interactive status
+-	 */
+-	run_time /= (CURRENT_BONUS(prev) ? : 1);
++static inline struct task_struct *
++pick_next_task(struct rq *rq, struct task_struct *prev)
++{
++	struct sched_class *class = sched_class_highest;
++	u64 now = __rq_clock(rq);
++	struct task_struct *p;
++
++	prev->sched_class->put_prev_task(rq, prev, now);
++
++	do {
++		p = class->pick_next_task(rq, now);
++		if (p)
++			return p;
++		class = class->next;
++	} while (class);
++
++	return NULL;
++}
++
++/*
++ * schedule() is the main scheduler function.
++ */
++asmlinkage void __sched schedule(void)
++{
++	struct task_struct *prev, *next;
++	long *switch_count;
++	struct rq *rq;
++	int cpu;
++
++need_resched:
++	preempt_disable();
++	prev = current;
++	release_kernel_lock(prev);
++need_resched_nonpreemptible:
++	rq = this_rq();
++
++	schedule_debug(rq, prev);
+ 
+ 	spin_lock_irq(&rq->lock);
+ 
+@@ -3478,7 +2792,7 @@ need_resched_nonpreemptible:
+ 		else {
+ 			if (prev->state == TASK_UNINTERRUPTIBLE)
+ 				rq->nr_uninterruptible++;
+-			deactivate_task(prev, rq);
++			deactivate_task(rq, prev, 1);
+ 		}
+ 	}
+ 
+@@ -3486,68 +2800,25 @@ need_resched_nonpreemptible:
+ 	if (unlikely(!rq->nr_running)) {
+ 		idle_balance(cpu, rq);
+ 		if (!rq->nr_running) {
++			prev->sched_class->put_prev_task(rq, prev,
++							 __rq_clock(rq));
+ 			next = rq->idle;
+-			rq->expired_timestamp = 0;
+-			wake_sleeping_dependent(cpu);
++			schedstat_inc(rq, sched_goidle);
+ 			goto switch_tasks;
+ 		}
+ 	}
+ 
+-	array = rq->active;
+-	if (unlikely(!array->nr_active)) {
+-		/*
+-		 * Switch the active and expired arrays.
+-		 */
+-		schedstat_inc(rq, sched_switch);
+-		rq->active = rq->expired;
+-		rq->expired = array;
+-		array = rq->active;
+-		rq->expired_timestamp = 0;
+-		rq->best_expired_prio = MAX_PRIO;
+-	}
+-
+-	idx = sched_find_first_bit(array->bitmap);
+-	queue = array->queue + idx;
+-	next = list_entry(queue->next, struct task_struct, run_list);
+-
+-	if (!rt_task(next) && interactive_sleep(next->sleep_type)) {
+-		unsigned long long delta = now - next->timestamp;
+-		if (unlikely((long long)(now - next->timestamp) < 0))
+-			delta = 0;
+-
+-		if (next->sleep_type == SLEEP_INTERACTIVE)
+-			delta = delta * (ON_RUNQUEUE_WEIGHT * 128 / 100) / 128;
+-
+-		array = next->array;
+-		new_prio = recalc_task_prio(next, next->timestamp + delta);
+-
+-		if (unlikely(next->prio != new_prio)) {
+-			dequeue_task(next, array);
+-			next->prio = new_prio;
+-			enqueue_task(next, array);
+-		}
+-	}
+-	next->sleep_type = SLEEP_NORMAL;
+-	if (rq->nr_running == 1 && dependent_sleeper(cpu, rq, next))
+-		next = rq->idle;
++	next = pick_next_task(rq, prev);
++	next->nr_switches++;
++
+ switch_tasks:
+-	if (next == rq->idle)
+-		schedstat_inc(rq, sched_goidle);
+ 	prefetch(next);
+ 	prefetch_stack(next);
+ 	clear_tsk_need_resched(prev);
+ 	rcu_qsctr_inc(task_cpu(prev));
+ 
+-	update_cpu_clock(prev, rq, now);
+-
+-	prev->sleep_avg -= run_time;
+-	if ((long)prev->sleep_avg <= 0)
+-		prev->sleep_avg = 0;
+-	prev->timestamp = prev->last_ran = now;
+-
+ 	sched_info_switch(prev, next);
+ 	if (likely(prev != next)) {
+-		next->timestamp = next->last_ran = now;
+ 		rq->nr_switches++;
+ 		rq->curr = next;
+ 		++*switch_count;
+@@ -3978,29 +3249,28 @@ EXPORT_SYMBOL(sleep_on_timeout);
+  */
+ void rt_mutex_setprio(struct task_struct *p, int prio)
+ {
+-	struct prio_array *array;
+ 	unsigned long flags;
++	int oldprio, on_rq;
+ 	struct rq *rq;
+-	int oldprio;
+ 
+ 	BUG_ON(prio < 0 || prio > MAX_PRIO);
+ 
+ 	rq = task_rq_lock(p, &flags);
+ 
+ 	oldprio = p->prio;
+-	array = p->array;
+-	if (array)
+-		dequeue_task(p, array);
++	on_rq = p->on_rq;
++	if (on_rq)
++		dequeue_task(rq, p, 0);
++
++	if (rt_prio(prio))
++		p->sched_class = &rt_sched_class;
++	else
++		p->sched_class = &fair_sched_class;
++
+ 	p->prio = prio;
+ 
+-	if (array) {
+-		/*
+-		 * If changing to an RT priority then queue it
+-		 * in the active array!
+-		 */
+-		if (rt_task(p))
+-			array = rq->active;
+-		enqueue_task(p, array);
++	if (on_rq) {
++		enqueue_task(rq, p, 0);
+ 		/*
+ 		 * Reschedule if we are currently running on this runqueue and
+ 		 * our priority decreased, or if we are not currently running on
+@@ -4009,8 +3279,9 @@ void rt_mutex_setprio(struct task_struct
+ 		if (task_running(rq, p)) {
+ 			if (p->prio > oldprio)
+ 				resched_task(rq->curr);
+-		} else if (TASK_PREEMPTS_CURR(p, rq))
+-			resched_task(rq->curr);
++		} else {
++			check_preempt_curr(rq, p);
++		}
+ 	}
+ 	task_rq_unlock(rq, &flags);
+ }
+@@ -4019,8 +3290,7 @@ void rt_mutex_setprio(struct task_struct
+ 
+ void set_user_nice(struct task_struct *p, long nice)
+ {
+-	struct prio_array *array;
+-	int old_prio, delta;
++	int old_prio, delta, on_rq;
+ 	unsigned long flags;
+ 	struct rq *rq;
+ 
+@@ -4041,9 +3311,9 @@ void set_user_nice(struct task_struct *p
+ 		p->static_prio = NICE_TO_PRIO(nice);
+ 		goto out_unlock;
+ 	}
+-	array = p->array;
+-	if (array) {
+-		dequeue_task(p, array);
++	on_rq = p->on_rq;
++	if (on_rq) {
++		dequeue_task(rq, p, 0);
+ 		dec_raw_weighted_load(rq, p);
+ 	}
+ 
+@@ -4053,8 +3323,8 @@ void set_user_nice(struct task_struct *p
+ 	p->prio = effective_prio(p);
+ 	delta = p->prio - old_prio;
+ 
+-	if (array) {
+-		enqueue_task(p, array);
++	if (on_rq) {
++		enqueue_task(rq, p, 0);
+ 		inc_raw_weighted_load(rq, p);
+ 		/*
+ 		 * If the task increased its priority or is running and
+@@ -4175,20 +3445,27 @@ static inline struct task_struct *find_p
+ }
+ 
+ /* Actually do priority change: must hold rq lock. */
+-static void __setscheduler(struct task_struct *p, int policy, int prio)
++static void
++__setscheduler(struct rq *rq, struct task_struct *p, int policy, int prio)
+ {
+-	BUG_ON(p->array);
++	BUG_ON(p->on_rq);
+ 
+ 	p->policy = policy;
++	switch (p->policy) {
++	case SCHED_NORMAL:
++	case SCHED_BATCH:
++		p->sched_class = &fair_sched_class;
++		break;
++	case SCHED_FIFO:
++	case SCHED_RR:
++		p->sched_class = &rt_sched_class;
++		break;
++	}
++
+ 	p->rt_priority = prio;
+ 	p->normal_prio = normal_prio(p);
+ 	/* we are holding p->pi_lock already */
+ 	p->prio = rt_mutex_getprio(p);
+-	/*
+-	 * SCHED_BATCH tasks are treated as perpetual CPU hogs:
+-	 */
+-	if (policy == SCHED_BATCH)
+-		p->sleep_avg = 0;
+ 	set_load_weight(p);
+ }
+ 
+@@ -4204,8 +3481,7 @@ static void __setscheduler(struct task_s
+ int sched_setscheduler(struct task_struct *p, int policy,
+ 		       struct sched_param *param)
+ {
+-	int retval, oldprio, oldpolicy = -1;
+-	struct prio_array *array;
++	int retval, oldprio, oldpolicy = -1, on_rq;
+ 	unsigned long flags;
+ 	struct rq *rq;
+ 
+@@ -4279,13 +3555,13 @@ recheck:
+ 		spin_unlock_irqrestore(&p->pi_lock, flags);
+ 		goto recheck;
+ 	}
+-	array = p->array;
+-	if (array)
+-		deactivate_task(p, rq);
++	on_rq = p->on_rq;
++	if (on_rq)
++		deactivate_task(rq, p, 0);
+ 	oldprio = p->prio;
+-	__setscheduler(p, policy, param->sched_priority);
+-	if (array) {
+-		__activate_task(p, rq);
++	__setscheduler(rq, p, policy, param->sched_priority);
++	if (on_rq) {
++		activate_task(rq, p, 0);
+ 		/*
+ 		 * Reschedule if we are currently running on this runqueue and
+ 		 * our priority decreased, or if we are not currently running on
+@@ -4294,8 +3570,9 @@ recheck:
+ 		if (task_running(rq, p)) {
+ 			if (p->prio > oldprio)
+ 				resched_task(rq->curr);
+-		} else if (TASK_PREEMPTS_CURR(p, rq))
+-			resched_task(rq->curr);
++		} else {
++			check_preempt_curr(rq, p);
++		}
+ 	}
+ 	__task_rq_unlock(rq);
+ 	spin_unlock_irqrestore(&p->pi_lock, flags);
+@@ -4558,50 +3835,66 @@ asmlinkage long sys_sched_getaffinity(pi
+ 	if (ret < 0)
+ 		return ret;
+ 
+-	if (copy_to_user(user_mask_ptr, &mask, sizeof(cpumask_t)))
+-		return -EFAULT;
++	if (copy_to_user(user_mask_ptr, &mask, sizeof(cpumask_t)))
++		return -EFAULT;
++
++	return sizeof(cpumask_t);
++}
++
++/**
++ * sys_sched_yield - yield the current processor to other threads.
++ *
++ * This function yields the current CPU to other tasks. If there are no
++ * other threads running on this CPU then this function will return.
++ */
++asmlinkage long sys_sched_yield(void)
++{
++	struct rq *rq = this_rq_lock();
++
++	schedstat_inc(rq, yld_cnt);
++	if (rq->nr_running == 1)
++		schedstat_inc(rq, yld_act_empty);
++	else
++		current->sched_class->yield_task(rq, current, NULL);
++
++	/*
++	 * Since we are going to call schedule() anyway, there's
++	 * no need to preempt or enable interrupts:
++	 */
++	__release(rq->lock);
++	spin_release(&rq->lock.dep_map, 1, _THIS_IP_);
++	_raw_spin_unlock(&rq->lock);
++	preempt_enable_no_resched();
++
++	schedule();
+ 
+-	return sizeof(cpumask_t);
++	return 0;
+ }
+ 
+ /**
+- * sys_sched_yield - yield the current processor to other threads.
++ * sys_sched_yield_to - yield the current processor to another thread
+  *
+- * this function yields the current CPU by moving the calling thread
++ * This function yields the current CPU by moving the calling thread
+  * to the expired array. If there are no other threads running on this
+  * CPU then this function will return.
+  */
+-asmlinkage long sys_sched_yield(void)
++asmlinkage long sys_sched_yield_to(pid_t pid)
+ {
+-	struct rq *rq = this_rq_lock();
+-	struct prio_array *array = current->array, *target = rq->expired;
++	struct task_struct *p_to;
++	struct rq *rq;
+ 
+-	schedstat_inc(rq, yld_cnt);
+-	/*
+-	 * We implement yielding by moving the task into the expired
+-	 * queue.
+-	 *
+-	 * (special rule: RT tasks will just roundrobin in the active
+-	 *  array.)
+-	 */
+-	if (rt_task(current))
+-		target = rq->active;
++	rcu_read_lock();
++	p_to = find_task_by_pid(pid);
++	if (!p_to)
++		goto out_unlock;
+ 
+-	if (array->nr_active == 1) {
++	rq = this_rq_lock();
++
++	schedstat_inc(rq, yld_cnt);
++	if (rq->nr_running == 1)
+ 		schedstat_inc(rq, yld_act_empty);
+-		if (!rq->expired->nr_active)
+-			schedstat_inc(rq, yld_both_empty);
+-	} else if (!rq->expired->nr_active)
+-		schedstat_inc(rq, yld_exp_empty);
+-
+-	if (array != target) {
+-		dequeue_task(current, array);
+-		enqueue_task(current, target);
+-	} else
+-		/*
+-		 * requeue_task is cheaper so perform that if possible.
+-		 */
+-		requeue_task(current, array);
++	else
++		current->sched_class->yield_task(rq, current, p_to);
+ 
+ 	/*
+ 	 * Since we are going to call schedule() anyway, there's
+@@ -4610,13 +3903,19 @@ asmlinkage long sys_sched_yield(void)
+ 	__release(rq->lock);
+ 	spin_release(&rq->lock.dep_map, 1, _THIS_IP_);
+ 	_raw_spin_unlock(&rq->lock);
++	rcu_read_unlock();
+ 	preempt_enable_no_resched();
+ 
+ 	schedule();
+ 
+ 	return 0;
++
++out_unlock:
++	rcu_read_unlock();
++	return -ESRCH;
+ }
+ 
++
+ static void __cond_resched(void)
+ {
+ #ifdef CONFIG_DEBUG_SPINLOCK_SLEEP
+@@ -4812,7 +4111,7 @@ long sys_sched_rr_get_interval(pid_t pid
+ 		goto out_unlock;
+ 
+ 	jiffies_to_timespec(p->policy == SCHED_FIFO ?
+-				0 : task_timeslice(p), &t);
++				0 : static_prio_timeslice(p->static_prio), &t);
+ 	read_unlock(&tasklist_lock);
+ 	retval = copy_to_user(interval, &t, sizeof(t)) ? -EFAULT : 0;
+ out_nounlock:
+@@ -4915,7 +4214,7 @@ void show_state_filter(unsigned long sta
+ 		 * console might take alot of time:
+ 		 */
+ 		touch_nmi_watchdog();
+-		if (p->state & state_filter)
++		if (!state_filter || (p->state & state_filter))
+ 			show_task(p);
+ 	} while_each_thread(g, p);
+ 
+@@ -4925,6 +4224,7 @@ void show_state_filter(unsigned long sta
+ 	 */
+ 	if (state_filter == -1)
+ 		debug_show_all_locks();
++	sysrq_sched_debug_show();
+ }
+ 
+ /**
+@@ -4940,11 +4240,10 @@ void __cpuinit init_idle(struct task_str
+ 	struct rq *rq = cpu_rq(cpu);
+ 	unsigned long flags;
+ 
+-	idle->timestamp = sched_clock();
+-	idle->sleep_avg = 0;
+-	idle->array = NULL;
++	__sched_fork(idle);
++	idle->exec_start = sched_clock();
++
+ 	idle->prio = idle->normal_prio = MAX_PRIO;
+-	idle->state = TASK_RUNNING;
+ 	idle->cpus_allowed = cpumask_of_cpu(cpu);
+ 	set_task_cpu(idle, cpu);
+ 
+@@ -5062,19 +4361,10 @@ static int __migrate_task(struct task_st
+ 		goto out;
+ 
+ 	set_task_cpu(p, dest_cpu);
+-	if (p->array) {
+-		/*
+-		 * Sync timestamp with rq_dest's before activating.
+-		 * The same thing could be achieved by doing this step
+-		 * afterwards, and pretending it was a local activate.
+-		 * This way is cleaner and logically correct.
+-		 */
+-		p->timestamp = p->timestamp - rq_src->most_recent_timestamp
+-				+ rq_dest->most_recent_timestamp;
+-		deactivate_task(p, rq_src);
+-		__activate_task(p, rq_dest);
+-		if (TASK_PREEMPTS_CURR(p, rq_dest))
+-			resched_task(rq_dest->curr);
++	if (p->on_rq) {
++		deactivate_task(rq_src, p, 0);
++		activate_task(rq_dest, p, 0);
++		check_preempt_curr(rq_dest, p);
+ 	}
+ 	ret = 1;
+ out:
+@@ -5246,10 +4536,10 @@ void sched_idle_next(void)
+ 	 */
+ 	spin_lock_irqsave(&rq->lock, flags);
+ 
+-	__setscheduler(p, SCHED_FIFO, MAX_RT_PRIO-1);
++	__setscheduler(rq, p, SCHED_FIFO, MAX_RT_PRIO-1);
+ 
+ 	/* Add idle task to the _front_ of its priority queue: */
+-	__activate_idle_task(p, rq);
++	activate_idle_task(p, rq);
+ 
+ 	spin_unlock_irqrestore(&rq->lock, flags);
+ }
+@@ -5299,16 +4589,15 @@ static void migrate_dead(unsigned int de
+ static void migrate_dead_tasks(unsigned int dead_cpu)
+ {
+ 	struct rq *rq = cpu_rq(dead_cpu);
+-	unsigned int arr, i;
++	struct task_struct *next;
+ 
+-	for (arr = 0; arr < 2; arr++) {
+-		for (i = 0; i < MAX_PRIO; i++) {
+-			struct list_head *list = &rq->arrays[arr].queue[i];
+-
+-			while (!list_empty(list))
+-				migrate_dead(dead_cpu, list_entry(list->next,
+-					     struct task_struct, run_list));
+-		}
++	for (;;) {
++		if (!rq->nr_running)
++			break;
++		next = pick_next_task(rq, rq->curr);
++		if (!next)
++			break;
++		migrate_dead(dead_cpu, next);
+ 	}
+ }
+ #endif /* CONFIG_HOTPLUG_CPU */
+@@ -5334,7 +4623,7 @@ migration_call(struct notifier_block *nf
+ 		kthread_bind(p, cpu);
+ 		/* Must be high prio: stop_machine expects to yield to it. */
+ 		rq = task_rq_lock(p, &flags);
+-		__setscheduler(p, SCHED_FIFO, MAX_RT_PRIO-1);
++		__setscheduler(rq, p, SCHED_FIFO, MAX_RT_PRIO-1);
+ 		task_rq_unlock(rq, &flags);
+ 		cpu_rq(cpu)->migration_thread = p;
+ 		break;
+@@ -5362,9 +4651,9 @@ migration_call(struct notifier_block *nf
+ 		rq->migration_thread = NULL;
+ 		/* Idle task back to normal (off runqueue, low prio) */
+ 		rq = task_rq_lock(rq->idle, &flags);
+-		deactivate_task(rq->idle, rq);
++		deactivate_task(rq, rq->idle, 0);
+ 		rq->idle->static_prio = MAX_PRIO;
+-		__setscheduler(rq->idle, SCHED_NORMAL, 0);
++		__setscheduler(rq, rq->idle, SCHED_NORMAL, 0);
+ 		migrate_dead_tasks(cpu);
+ 		task_rq_unlock(rq, &flags);
+ 		migrate_nr_uninterruptible(rq);
+@@ -5665,483 +4954,6 @@ init_sched_build_groups(cpumask_t span, 
+ 
+ #define SD_NODES_PER_DOMAIN 16
+ 
+-/*
+- * Self-tuning task migration cost measurement between source and target CPUs.
+- *
+- * This is done by measuring the cost of manipulating buffers of varying
+- * sizes. For a given buffer-size here are the steps that are taken:
+- *
+- * 1) the source CPU reads+dirties a shared buffer
+- * 2) the target CPU reads+dirties the same shared buffer
+- *
+- * We measure how long they take, in the following 4 scenarios:
+- *
+- *  - source: CPU1, target: CPU2 | cost1
+- *  - source: CPU2, target: CPU1 | cost2
+- *  - source: CPU1, target: CPU1 | cost3
+- *  - source: CPU2, target: CPU2 | cost4
+- *
+- * We then calculate the cost3+cost4-cost1-cost2 difference - this is
+- * the cost of migration.
+- *
+- * We then start off from a small buffer-size and iterate up to larger
+- * buffer sizes, in 5% steps - measuring each buffer-size separately, and
+- * doing a maximum search for the cost. (The maximum cost for a migration
+- * normally occurs when the working set size is around the effective cache
+- * size.)
+- */
+-#define SEARCH_SCOPE		2
+-#define MIN_CACHE_SIZE		(64*1024U)
+-#define DEFAULT_CACHE_SIZE	(5*1024*1024U)
+-#define ITERATIONS		1
+-#define SIZE_THRESH		130
+-#define COST_THRESH		130
+-
+-/*
+- * The migration cost is a function of 'domain distance'. Domain
+- * distance is the number of steps a CPU has to iterate down its
+- * domain tree to share a domain with the other CPU. The farther
+- * two CPUs are from each other, the larger the distance gets.
+- *
+- * Note that we use the distance only to cache measurement results,
+- * the distance value is not used numerically otherwise. When two
+- * CPUs have the same distance it is assumed that the migration
+- * cost is the same. (this is a simplification but quite practical)
+- */
+-#define MAX_DOMAIN_DISTANCE 32
+-
+-static unsigned long long migration_cost[MAX_DOMAIN_DISTANCE] =
+-		{ [ 0 ... MAX_DOMAIN_DISTANCE-1 ] =
+-/*
+- * Architectures may override the migration cost and thus avoid
+- * boot-time calibration. Unit is nanoseconds. Mostly useful for
+- * virtualized hardware:
+- */
+-#ifdef CONFIG_DEFAULT_MIGRATION_COST
+-			CONFIG_DEFAULT_MIGRATION_COST
+-#else
+-			-1LL
+-#endif
+-};
+-
+-/*
+- * Allow override of migration cost - in units of microseconds.
+- * E.g. migration_cost=1000,2000,3000 will set up a level-1 cost
+- * of 1 msec, level-2 cost of 2 msecs and level3 cost of 3 msecs:
+- */
+-static int __init migration_cost_setup(char *str)
+-{
+-	int ints[MAX_DOMAIN_DISTANCE+1], i;
+-
+-	str = get_options(str, ARRAY_SIZE(ints), ints);
+-
+-	printk("#ints: %d\n", ints[0]);
+-	for (i = 1; i <= ints[0]; i++) {
+-		migration_cost[i-1] = (unsigned long long)ints[i]*1000;
+-		printk("migration_cost[%d]: %Ld\n", i-1, migration_cost[i-1]);
+-	}
+-	return 1;
+-}
+-
+-__setup ("migration_cost=", migration_cost_setup);
+-
+-/*
+- * Global multiplier (divisor) for migration-cutoff values,
+- * in percentiles. E.g. use a value of 150 to get 1.5 times
+- * longer cache-hot cutoff times.
+- *
+- * (We scale it from 100 to 128 to long long handling easier.)
+- */
+-
+-#define MIGRATION_FACTOR_SCALE 128
+-
+-static unsigned int migration_factor = MIGRATION_FACTOR_SCALE;
+-
+-static int __init setup_migration_factor(char *str)
+-{
+-	get_option(&str, &migration_factor);
+-	migration_factor = migration_factor * MIGRATION_FACTOR_SCALE / 100;
+-	return 1;
+-}
+-
+-__setup("migration_factor=", setup_migration_factor);
+-
+-/*
+- * Estimated distance of two CPUs, measured via the number of domains
+- * we have to pass for the two CPUs to be in the same span:
+- */
+-static unsigned long domain_distance(int cpu1, int cpu2)
+-{
+-	unsigned long distance = 0;
+-	struct sched_domain *sd;
+-
+-	for_each_domain(cpu1, sd) {
+-		WARN_ON(!cpu_isset(cpu1, sd->span));
+-		if (cpu_isset(cpu2, sd->span))
+-			return distance;
+-		distance++;
+-	}
+-	if (distance >= MAX_DOMAIN_DISTANCE) {
+-		WARN_ON(1);
+-		distance = MAX_DOMAIN_DISTANCE-1;
+-	}
+-
+-	return distance;
+-}
+-
+-static unsigned int migration_debug;
+-
+-static int __init setup_migration_debug(char *str)
+-{
+-	get_option(&str, &migration_debug);
+-	return 1;
+-}
+-
+-__setup("migration_debug=", setup_migration_debug);
+-
+-/*
+- * Maximum cache-size that the scheduler should try to measure.
+- * Architectures with larger caches should tune this up during
+- * bootup. Gets used in the domain-setup code (i.e. during SMP
+- * bootup).
+- */
+-unsigned int max_cache_size;
+-
+-static int __init setup_max_cache_size(char *str)
+-{
+-	get_option(&str, &max_cache_size);
+-	return 1;
+-}
+-
+-__setup("max_cache_size=", setup_max_cache_size);
+-
+-/*
+- * Dirty a big buffer in a hard-to-predict (for the L2 cache) way. This
+- * is the operation that is timed, so we try to generate unpredictable
+- * cachemisses that still end up filling the L2 cache:
+- */
+-static void touch_cache(void *__cache, unsigned long __size)
+-{
+-	unsigned long size = __size / sizeof(long);
+-	unsigned long chunk1 = size / 3;
+-	unsigned long chunk2 = 2 * size / 3;
+-	unsigned long *cache = __cache;
+-	int i;
+-
+-	for (i = 0; i < size/6; i += 8) {
+-		switch (i % 6) {
+-			case 0: cache[i]++;
+-			case 1: cache[size-1-i]++;
+-			case 2: cache[chunk1-i]++;
+-			case 3: cache[chunk1+i]++;
+-			case 4: cache[chunk2-i]++;
+-			case 5: cache[chunk2+i]++;
+-		}
+-	}
+-}
+-
+-/*
+- * Measure the cache-cost of one task migration. Returns in units of nsec.
+- */
+-static unsigned long long
+-measure_one(void *cache, unsigned long size, int source, int target)
+-{
+-	cpumask_t mask, saved_mask;
+-	unsigned long long t0, t1, t2, t3, cost;
+-
+-	saved_mask = current->cpus_allowed;
+-
+-	/*
+-	 * Flush source caches to RAM and invalidate them:
+-	 */
+-	sched_cacheflush();
+-
+-	/*
+-	 * Migrate to the source CPU:
+-	 */
+-	mask = cpumask_of_cpu(source);
+-	set_cpus_allowed(current, mask);
+-	WARN_ON(smp_processor_id() != source);
+-
+-	/*
+-	 * Dirty the working set:
+-	 */
+-	t0 = sched_clock();
+-	touch_cache(cache, size);
+-	t1 = sched_clock();
+-
+-	/*
+-	 * Migrate to the target CPU, dirty the L2 cache and access
+-	 * the shared buffer. (which represents the working set
+-	 * of a migrated task.)
+-	 */
+-	mask = cpumask_of_cpu(target);
+-	set_cpus_allowed(current, mask);
+-	WARN_ON(smp_processor_id() != target);
+-
+-	t2 = sched_clock();
+-	touch_cache(cache, size);
+-	t3 = sched_clock();
+-
+-	cost = t1-t0 + t3-t2;
+-
+-	if (migration_debug >= 2)
+-		printk("[%d->%d]: %8Ld %8Ld %8Ld => %10Ld.\n",
+-			source, target, t1-t0, t1-t0, t3-t2, cost);
+-	/*
+-	 * Flush target caches to RAM and invalidate them:
+-	 */
+-	sched_cacheflush();
+-
+-	set_cpus_allowed(current, saved_mask);
+-
+-	return cost;
+-}
+-
+-/*
+- * Measure a series of task migrations and return the average
+- * result. Since this code runs early during bootup the system
+- * is 'undisturbed' and the average latency makes sense.
+- *
+- * The algorithm in essence auto-detects the relevant cache-size,
+- * so it will properly detect different cachesizes for different
+- * cache-hierarchies, depending on how the CPUs are connected.
+- *
+- * Architectures can prime the upper limit of the search range via
+- * max_cache_size, otherwise the search range defaults to 20MB...64K.
+- */
+-static unsigned long long
+-measure_cost(int cpu1, int cpu2, void *cache, unsigned int size)
+-{
+-	unsigned long long cost1, cost2;
+-	int i;
+-
+-	/*
+-	 * Measure the migration cost of 'size' bytes, over an
+-	 * average of 10 runs:
+-	 *
+-	 * (We perturb the cache size by a small (0..4k)
+-	 *  value to compensate size/alignment related artifacts.
+-	 *  We also subtract the cost of the operation done on
+-	 *  the same CPU.)
+-	 */
+-	cost1 = 0;
+-
+-	/*
+-	 * dry run, to make sure we start off cache-cold on cpu1,
+-	 * and to get any vmalloc pagefaults in advance:
+-	 */
+-	measure_one(cache, size, cpu1, cpu2);
+-	for (i = 0; i < ITERATIONS; i++)
+-		cost1 += measure_one(cache, size - i * 1024, cpu1, cpu2);
+-
+-	measure_one(cache, size, cpu2, cpu1);
+-	for (i = 0; i < ITERATIONS; i++)
+-		cost1 += measure_one(cache, size - i * 1024, cpu2, cpu1);
+-
+-	/*
+-	 * (We measure the non-migrating [cached] cost on both
+-	 *  cpu1 and cpu2, to handle CPUs with different speeds)
+-	 */
+-	cost2 = 0;
+-
+-	measure_one(cache, size, cpu1, cpu1);
+-	for (i = 0; i < ITERATIONS; i++)
+-		cost2 += measure_one(cache, size - i * 1024, cpu1, cpu1);
+-
+-	measure_one(cache, size, cpu2, cpu2);
+-	for (i = 0; i < ITERATIONS; i++)
+-		cost2 += measure_one(cache, size - i * 1024, cpu2, cpu2);
+-
+-	/*
+-	 * Get the per-iteration migration cost:
+-	 */
+-	do_div(cost1, 2 * ITERATIONS);
+-	do_div(cost2, 2 * ITERATIONS);
+-
+-	return cost1 - cost2;
+-}
+-
+-static unsigned long long measure_migration_cost(int cpu1, int cpu2)
+-{
+-	unsigned long long max_cost = 0, fluct = 0, avg_fluct = 0;
+-	unsigned int max_size, size, size_found = 0;
+-	long long cost = 0, prev_cost;
+-	void *cache;
+-
+-	/*
+-	 * Search from max_cache_size*5 down to 64K - the real relevant
+-	 * cachesize has to lie somewhere inbetween.
+-	 */
+-	if (max_cache_size) {
+-		max_size = max(max_cache_size * SEARCH_SCOPE, MIN_CACHE_SIZE);
+-		size = max(max_cache_size / SEARCH_SCOPE, MIN_CACHE_SIZE);
+-	} else {
+-		/*
+-		 * Since we have no estimation about the relevant
+-		 * search range
+-		 */
+-		max_size = DEFAULT_CACHE_SIZE * SEARCH_SCOPE;
+-		size = MIN_CACHE_SIZE;
+-	}
+-
+-	if (!cpu_online(cpu1) || !cpu_online(cpu2)) {
+-		printk("cpu %d and %d not both online!\n", cpu1, cpu2);
+-		return 0;
+-	}
+-
+-	/*
+-	 * Allocate the working set:
+-	 */
+-	cache = vmalloc(max_size);
+-	if (!cache) {
+-		printk("could not vmalloc %d bytes for cache!\n", 2 * max_size);
+-		return 1000000; /* return 1 msec on very small boxen */
+-	}
+-
+-	while (size <= max_size) {
+-		prev_cost = cost;
+-		cost = measure_cost(cpu1, cpu2, cache, size);
+-
+-		/*
+-		 * Update the max:
+-		 */
+-		if (cost > 0) {
+-			if (max_cost < cost) {
+-				max_cost = cost;
+-				size_found = size;
+-			}
+-		}
+-		/*
+-		 * Calculate average fluctuation, we use this to prevent
+-		 * noise from triggering an early break out of the loop:
+-		 */
+-		fluct = abs(cost - prev_cost);
+-		avg_fluct = (avg_fluct + fluct)/2;
+-
+-		if (migration_debug)
+-			printk("-> [%d][%d][%7d] %3ld.%ld [%3ld.%ld] (%ld): "
+-				"(%8Ld %8Ld)\n",
+-				cpu1, cpu2, size,
+-				(long)cost / 1000000,
+-				((long)cost / 100000) % 10,
+-				(long)max_cost / 1000000,
+-				((long)max_cost / 100000) % 10,
+-				domain_distance(cpu1, cpu2),
+-				cost, avg_fluct);
+-
+-		/*
+-		 * If we iterated at least 20% past the previous maximum,
+-		 * and the cost has dropped by more than 20% already,
+-		 * (taking fluctuations into account) then we assume to
+-		 * have found the maximum and break out of the loop early:
+-		 */
+-		if (size_found && (size*100 > size_found*SIZE_THRESH))
+-			if (cost+avg_fluct <= 0 ||
+-				max_cost*100 > (cost+avg_fluct)*COST_THRESH) {
+-
+-				if (migration_debug)
+-					printk("-> found max.\n");
+-				break;
+-			}
+-		/*
+-		 * Increase the cachesize in 10% steps:
+-		 */
+-		size = size * 10 / 9;
+-	}
+-
+-	if (migration_debug)
+-		printk("[%d][%d] working set size found: %d, cost: %Ld\n",
+-			cpu1, cpu2, size_found, max_cost);
+-
+-	vfree(cache);
+-
+-	/*
+-	 * A task is considered 'cache cold' if at least 2 times
+-	 * the worst-case cost of migration has passed.
+-	 *
+-	 * (this limit is only listened to if the load-balancing
+-	 * situation is 'nice' - if there is a large imbalance we
+-	 * ignore it for the sake of CPU utilization and
+-	 * processing fairness.)
+-	 */
+-	return 2 * max_cost * migration_factor / MIGRATION_FACTOR_SCALE;
+-}
+-
+-static void calibrate_migration_costs(const cpumask_t *cpu_map)
+-{
+-	int cpu1 = -1, cpu2 = -1, cpu, orig_cpu = raw_smp_processor_id();
+-	unsigned long j0, j1, distance, max_distance = 0;
+-	struct sched_domain *sd;
+-
+-	j0 = jiffies;
+-
+-	/*
+-	 * First pass - calculate the cacheflush times:
+-	 */
+-	for_each_cpu_mask(cpu1, *cpu_map) {
+-		for_each_cpu_mask(cpu2, *cpu_map) {
+-			if (cpu1 == cpu2)
+-				continue;
+-			distance = domain_distance(cpu1, cpu2);
+-			max_distance = max(max_distance, distance);
+-			/*
+-			 * No result cached yet?
+-			 */
+-			if (migration_cost[distance] == -1LL)
+-				migration_cost[distance] =
+-					measure_migration_cost(cpu1, cpu2);
+-		}
+-	}
+-	/*
+-	 * Second pass - update the sched domain hierarchy with
+-	 * the new cache-hot-time estimations:
+-	 */
+-	for_each_cpu_mask(cpu, *cpu_map) {
+-		distance = 0;
+-		for_each_domain(cpu, sd) {
+-			sd->cache_hot_time = migration_cost[distance];
+-			distance++;
+-		}
+-	}
+-	/*
+-	 * Print the matrix:
+-	 */
+-	if (migration_debug)
+-		printk("migration: max_cache_size: %d, cpu: %d MHz:\n",
+-			max_cache_size,
+-#ifdef CONFIG_X86
+-			cpu_khz/1000
+-#else
+-			-1
+-#endif
+-		);
+-	if (system_state == SYSTEM_BOOTING && num_online_cpus() > 1) {
+-		printk("migration_cost=");
+-		for (distance = 0; distance <= max_distance; distance++) {
+-			if (distance)
+-				printk(",");
+-			printk("%ld", (long)migration_cost[distance] / 1000);
+-		}
+-		printk("\n");
+-	}
+-	j1 = jiffies;
+-	if (migration_debug)
+-		printk("migration: %ld seconds\n", (j1-j0) / HZ);
+-
+-	/*
+-	 * Move back to the original CPU. NUMA-Q gets confused
+-	 * if we migrate to another quad during bootup.
+-	 */
+-	if (raw_smp_processor_id() != orig_cpu) {
+-		cpumask_t mask = cpumask_of_cpu(orig_cpu),
+-			saved_mask = current->cpus_allowed;
+-
+-		set_cpus_allowed(current, mask);
+-		set_cpus_allowed(current, saved_mask);
+-	}
+-}
+-
+ #ifdef CONFIG_NUMA
+ 
+ /**
+@@ -6671,10 +5483,6 @@ static int build_sched_domains(const cpu
+ #endif
+ 		cpu_attach_domain(sd, i);
+ 	}
+-	/*
+-	 * Tune cache-hot values:
+-	 */
+-	calibrate_migration_costs(cpu_map);
+ 
+ 	return 0;
+ 
+@@ -6875,6 +5683,16 @@ void __init sched_init_smp(void)
+ 	/* Move init over to a non-isolated CPU */
+ 	if (set_cpus_allowed(current, non_isolated_cpus) < 0)
+ 		BUG();
++	/*
++	 * Increase the granularity value when there are more CPUs,
++	 * because with more CPUs the 'effective latency' as visible
++	 * to users decreases. But the relationship is not linear,
++	 * so pick a second-best guess by going with the log2 of the
++	 * number of CPUs.
++	 *
++	 * This idea comes from the SD scheduler of Con Kolivas:
++	 */
++	sysctl_sched_granularity *= 1 + ilog2(num_online_cpus());
+ }
+ #else
+ void __init sched_init_smp(void)
+@@ -6894,7 +5712,14 @@ int in_sched_functions(unsigned long add
+ 
+ void __init sched_init(void)
+ {
+-	int i, j, k;
++	int i, j;
++
++	current->sched_class = &fair_sched_class;
++	/*
++	 * Link up the scheduling class hierarchy:
++	 */
++	rt_sched_class.next = &fair_sched_class;
++	fair_sched_class.next = NULL;
+ 
+ 	for_each_possible_cpu(i) {
+ 		struct prio_array *array;
+@@ -6904,14 +5729,13 @@ void __init sched_init(void)
+ 		spin_lock_init(&rq->lock);
+ 		lockdep_set_class(&rq->lock, &rq->rq_lock_key);
+ 		rq->nr_running = 0;
+-		rq->active = rq->arrays;
+-		rq->expired = rq->arrays + 1;
+-		rq->best_expired_prio = MAX_PRIO;
++		rq->tasks_timeline = RB_ROOT;
++		rq->clock = rq->fair_clock = 1;
+ 
++		for (j = 0; j < CPU_LOAD_IDX_MAX; j++)
++			rq->cpu_load[j] = 0;
+ #ifdef CONFIG_SMP
+ 		rq->sd = NULL;
+-		for (j = 1; j < 3; j++)
+-			rq->cpu_load[j] = 0;
+ 		rq->active_balance = 0;
+ 		rq->push_cpu = 0;
+ 		rq->cpu = i;
+@@ -6920,15 +5744,13 @@ void __init sched_init(void)
+ #endif
+ 		atomic_set(&rq->nr_iowait, 0);
+ 
+-		for (j = 0; j < 2; j++) {
+-			array = rq->arrays + j;
+-			for (k = 0; k < MAX_PRIO; k++) {
+-				INIT_LIST_HEAD(array->queue + k);
+-				__clear_bit(k, array->bitmap);
+-			}
+-			// delimiter for bitsearch
+-			__set_bit(MAX_PRIO, array->bitmap);
++		array = &rq->active;
++		for (j = 0; j < MAX_RT_PRIO; j++) {
++			INIT_LIST_HEAD(array->queue + j);
++			__clear_bit(j, array->bitmap);
+ 		}
++		/* delimiter for bitsearch: */
++		__set_bit(MAX_RT_PRIO, array->bitmap);
+ 	}
+ 
+ 	set_load_weight(&init_task);
+@@ -6984,28 +5806,54 @@ EXPORT_SYMBOL(__might_sleep);
+ #ifdef CONFIG_MAGIC_SYSRQ
+ void normalize_rt_tasks(void)
+ {
+-	struct prio_array *array;
+ 	struct task_struct *p;
+ 	unsigned long flags;
+ 	struct rq *rq;
++	int on_rq;
+ 
+ 	read_lock_irq(&tasklist_lock);
+ 	for_each_process(p) {
+-		if (!rt_task(p))
++		p->fair_key = 0;
++		p->wait_runtime = 0;
++		p->wait_start_fair = 0;
++		p->wait_start = 0;
++		p->exec_start = 0;
++		p->sleep_start = 0;
++		p->block_start = 0;
++		task_rq(p)->fair_clock = 0;
++		task_rq(p)->clock = 0;
++
++		if (!rt_task(p)) {
++			/*
++			 * Renice negative nice level userspace
++			 * tasks back to 0:
++			 */
++			if (TASK_NICE(p) < 0 && p->mm)
++				set_user_nice(p, 0);
+ 			continue;
++		}
+ 
+ 		spin_lock_irqsave(&p->pi_lock, flags);
+ 		rq = __task_rq_lock(p);
++#ifdef CONFIG_SMP
++		/*
++		 * Do not touch the migration thread:
++		 */
++		if (p == rq->migration_thread)
++			goto out_unlock;
++#endif
+ 
+-		array = p->array;
+-		if (array)
+-			deactivate_task(p, task_rq(p));
+-		__setscheduler(p, SCHED_NORMAL, 0);
+-		if (array) {
+-			__activate_task(p, task_rq(p));
++		on_rq = p->on_rq;
++		if (on_rq)
++			deactivate_task(task_rq(p), p, 0);
++		__setscheduler(rq, p, SCHED_NORMAL, 0);
++		if (on_rq) {
++			activate_task(task_rq(p), p, 0);
+ 			resched_task(rq->curr);
+ 		}
+-
++#ifdef CONFIG_SMP
++ out_unlock:
++#endif
+ 		__task_rq_unlock(rq);
+ 		spin_unlock_irqrestore(&p->pi_lock, flags);
+ 	}
+Index: linux-cfs-2.6.20.8.q/kernel/sched_debug.c
+===================================================================
+--- /dev/null
++++ linux-cfs-2.6.20.8.q/kernel/sched_debug.c
+@@ -0,0 +1,161 @@
++/*
++ * kernel/time/sched_debug.c
++ *
++ * Print the CFS rbtree
++ *
++ * Copyright(C) 2007, Red Hat, Inc., Ingo Molnar
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++#include <linux/proc_fs.h>
++#include <linux/module.h>
++#include <linux/spinlock.h>
++#include <linux/sched.h>
++#include <linux/seq_file.h>
++#include <linux/kallsyms.h>
++#include <linux/ktime.h>
++
++#include <asm/uaccess.h>
++
++typedef void (*print_fn_t)(struct seq_file *m, unsigned int *classes);
++
++/*
++ * This allows printing both to /proc/sched_debug and
++ * to the console
++ */
++#define SEQ_printf(m, x...)			\
++ do {						\
++	if (m)					\
++		seq_printf(m, x);		\
++	else					\
++		printk(x);			\
++ } while (0)
++
++static void
++print_task(struct seq_file *m, struct rq *rq, struct task_struct *p, u64 now)
++{
++	if (rq->curr == p)
++		SEQ_printf(m, "R");
++	else
++		SEQ_printf(m, " ");
++
++	SEQ_printf(m, "%14s %5d %15Ld %13Ld %13Ld %9Ld %5d "
++		      "%15Ld %15Ld %15Ld\n",
++		p->comm, p->pid,
++		(long long)p->fair_key, (long long)p->fair_key - rq->fair_clock,
++		(long long)p->wait_runtime,
++		(long long)p->nr_switches,
++		p->prio,
++		(long long)p->wait_start_fair - rq->fair_clock,
++		(long long)p->sum_exec_runtime,
++		(long long)p->sum_wait_runtime);
++}
++
++static void print_rq(struct seq_file *m, struct rq *rq, u64 now)
++{
++	struct task_struct *p;
++	struct rb_node *curr;
++
++	SEQ_printf(m,
++	"\nrunnable tasks:\n"
++	"           task   PID        tree-key         delta       waiting"
++	"  switches  prio     wstart-fair"
++	"        sum-exec        sum-wait\n"
++	"-----------------------------------------------------------------"
++	"--------------------------------"
++	"--------------------------------\n");
++
++	curr = first_fair(rq);
++	while (curr) {
++		p = rb_entry(curr, struct task_struct, run_node);
++		print_task(m, rq, p, now);
++
++		curr = rb_next(curr);
++	}
++}
++
++static void print_cpu(struct seq_file *m, int cpu, u64 now)
++{
++	struct rq *rq = &per_cpu(runqueues, cpu);
++
++	SEQ_printf(m, "\ncpu: %d\n", cpu);
++#define P(x) \
++	SEQ_printf(m, "  .%-22s: %Lu\n", #x, (unsigned long long)(rq->x))
++
++	P(nr_running);
++	P(raw_weighted_load);
++	P(nr_switches);
++	P(nr_load_updates);
++	P(nr_uninterruptible);
++	P(next_balance);
++	P(curr->pid);
++	P(clock);
++	P(prev_clock_raw);
++	P(clock_warps);
++	P(clock_unstable_events);
++	P(clock_max_delta);
++	rq->clock_max_delta = 0;
++	P(fair_clock);
++	P(prev_fair_clock);
++	P(exec_clock);
++	P(prev_exec_clock);
++	P(wait_runtime);
++	P(cpu_load[0]);
++	P(cpu_load[1]);
++	P(cpu_load[2]);
++	P(cpu_load[3]);
++	P(cpu_load[4]);
++#undef P
++
++	print_rq(m, rq, now);
++}
++
++static int sched_debug_show(struct seq_file *m, void *v)
++{
++	u64 now = ktime_to_ns(ktime_get());
++	int cpu;
++
++	SEQ_printf(m, "Sched Debug Version: v0.02\n");
++	SEQ_printf(m, "now at %Lu nsecs\n", (unsigned long long)now);
++
++	for_each_online_cpu(cpu)
++		print_cpu(m, cpu, now);
++
++	SEQ_printf(m, "\n");
++
++	return 0;
++}
++
++void sysrq_sched_debug_show(void)
++{
++	sched_debug_show(NULL, NULL);
++}
++
++static int sched_debug_open(struct inode *inode, struct file *filp)
++{
++	return single_open(filp, sched_debug_show, NULL);
++}
++
++static struct file_operations sched_debug_fops = {
++	.open		= sched_debug_open,
++	.read		= seq_read,
++	.llseek		= seq_lseek,
++	.release	= seq_release,
++};
++
++static int __init init_sched_debug_procfs(void)
++{
++	struct proc_dir_entry *pe;
++
++	pe = create_proc_entry("sched_debug", 0644, NULL);
++	if (!pe)
++		return -ENOMEM;
++
++	pe->proc_fops = &sched_debug_fops;
++
++	return 0;
++}
++__initcall(init_sched_debug_procfs);
+Index: linux-cfs-2.6.20.8.q/kernel/sched_fair.c
+===================================================================
+--- /dev/null
++++ linux-cfs-2.6.20.8.q/kernel/sched_fair.c
+@@ -0,0 +1,618 @@
++/*
++ * Completely Fair Scheduling (CFS) Class (SCHED_NORMAL/SCHED_BATCH)
++ */
++
++/*
++ * Preemption granularity:
++ * (default: 2 msec, units: nanoseconds)
++ *
++ * NOTE: this granularity value is not the same as the concept of
++ * 'timeslice length' - timeslices in CFS will typically be somewhat
++ * larger than this value. (to see the precise effective timeslice
++ * length of your workload, run vmstat and monitor the context-switches
++ * field)
++ *
++ * On SMP systems the value of this is multiplied by the log2 of the
++ * number of CPUs. (i.e. factor 2x on 2-way systems, 3x on 4-way
++ * systems, 4x on 8-way systems, 5x on 16-way systems, etc.)
++ */
++unsigned int sysctl_sched_granularity __read_mostly = 2000000;
++
++unsigned int sysctl_sched_sleep_history_max __read_mostly = 2000000000;
++
++unsigned int sysctl_sched_load_smoothing = 2;
++
++/*
++ * Wake-up granularity.
++ * (default: 1 msec, units: nanoseconds)
++ *
++ * This option delays the preemption effects of decoupled workloads
++ * and reduces their over-scheduling. Synchronous workloads will still
++ * have immediate wakeup/sleep latencies.
++ */
++unsigned int sysctl_sched_wakeup_granularity __read_mostly = 0;
++
++
++extern struct sched_class fair_sched_class;
++
++/**************************************************************/
++/* Scheduling class tree data structure manipulation methods:
++ */
++
++/*
++ * Enqueue a task into the rb-tree:
++ */
++static inline void __enqueue_task_fair(struct rq *rq, struct task_struct *p)
++{
++	struct rb_node **link = &rq->tasks_timeline.rb_node;
++	struct rb_node *parent = NULL;
++	struct task_struct *entry;
++	s64 key = p->fair_key;
++	int leftmost = 1;
++
++	/*
++	 * Find the right place in the rbtree:
++	 */
++	while (*link) {
++		parent = *link;
++		entry = rb_entry(parent, struct task_struct, run_node);
++		/*
++		 * We dont care about collisions. Nodes with
++		 * the same key stay together.
++		 */
++		if (key < entry->fair_key) {
++			link = &parent->rb_left;
++		} else {
++			link = &parent->rb_right;
++			leftmost = 0;
++		}
++	}
++
++	/*
++	 * Maintain a cache of leftmost tree entries (it is frequently
++	 * used):
++	 */
++	if (leftmost)
++		rq->rb_leftmost = &p->run_node;
++
++	rb_link_node(&p->run_node, parent, link);
++	rb_insert_color(&p->run_node, &rq->tasks_timeline);
++}
++
++static inline void __dequeue_task_fair(struct rq *rq, struct task_struct *p)
++{
++	if (rq->rb_leftmost == &p->run_node)
++		rq->rb_leftmost = NULL;
++	rb_erase(&p->run_node, &rq->tasks_timeline);
++}
++
++static inline struct rb_node * first_fair(struct rq *rq)
++{
++	if (rq->rb_leftmost)
++		return rq->rb_leftmost;
++	/* Cache the value returned by rb_first() */
++	rq->rb_leftmost = rb_first(&rq->tasks_timeline);
++	return rq->rb_leftmost;
++}
++
++static struct task_struct * __pick_next_task_fair(struct rq *rq)
++{
++	return rb_entry(first_fair(rq), struct task_struct, run_node);
++}
++
++/**************************************************************/
++/* Scheduling class statistics methods:
++ */
++
++static inline u64
++rescale_load(struct task_struct *p, u64 value)
++{
++	int load_shift = p->load_shift;
++
++	if (load_shift == SCHED_LOAD_SHIFT)
++		return value;
++
++	return (value << load_shift) >> SCHED_LOAD_SHIFT;
++}
++
++static u64
++niced_granularity(struct rq *rq, struct task_struct *curr,
++		  unsigned long granularity)
++{
++	return rescale_load(curr, granularity);
++}
++
++/*
++ * Update the current task's runtime statistics. Skip current tasks that
++ * are not in our scheduling class.
++ */
++static inline void update_curr(struct rq *rq, u64 now)
++{
++	u64 delta_exec, delta_fair, delta_mine;
++	struct task_struct *curr = rq->curr;
++	unsigned long load;
++
++	if (curr->sched_class != &fair_sched_class || curr == rq->idle
++			|| !curr->on_rq)
++		return;
++	/*
++	 * Get the amount of time the current task was running
++	 * since the last time we changed raw_weighted_load:
++	 */
++	delta_exec = now - curr->exec_start;
++	if (unlikely(delta_exec > curr->exec_max))
++		curr->exec_max = delta_exec;
++
++	if (sysctl_sched_load_smoothing) {
++		delta_fair = delta_exec << SCHED_LOAD_SHIFT;
++		do_div(delta_fair, rq->raw_weighted_load);
++
++		load = rq->cpu_load[CPU_LOAD_IDX_MAX-1] + 1;
++		if (sysctl_sched_load_smoothing & 2)
++			load = max(load, rq->raw_weighted_load);
++
++		delta_mine = delta_exec << curr->load_shift;
++		do_div(delta_mine, load);
++	} else {
++		delta_fair = delta_exec << SCHED_LOAD_SHIFT;
++		do_div(delta_fair, rq->raw_weighted_load);
++
++		delta_mine = delta_exec << curr->load_shift;
++		do_div(delta_mine, rq->raw_weighted_load);
++	}
++
++	curr->sum_exec_runtime += delta_exec;
++	curr->exec_start = now;
++
++	rq->fair_clock += delta_fair;
++	rq->exec_clock += delta_exec;
++
++	/*
++	 * We executed delta_exec amount of time on the CPU,
++	 * but we were only entitled to delta_mine amount of
++	 * time during that period (if nr_running == 1 then
++	 * the two values are equal):
++	 */
++
++	/*
++	 * Task already marked for preemption, do not burden
++	 * it with the cost of not having left the CPU yet.
++	 */
++	if (unlikely(test_tsk_thread_flag(curr, TIF_NEED_RESCHED)))
++		goto out_nowait;
++
++	curr->wait_runtime -= delta_exec - delta_mine;
++	if (unlikely(curr->wait_runtime < curr->min_wait_runtime))
++		curr->min_wait_runtime = curr->wait_runtime;
++
++	rq->wait_runtime -= delta_exec - delta_mine;
++out_nowait:
++	;
++}
++
++static inline void
++update_stats_wait_start(struct rq *rq, struct task_struct *p, u64 now)
++{
++	p->wait_start_fair = rq->fair_clock;
++	p->wait_start = now;
++}
++
++/*
++ * Task is being enqueued - update stats:
++ */
++static inline void
++update_stats_enqueue(struct rq *rq, struct task_struct *p, u64 now)
++{
++	s64 key;
++
++	/*
++	 * Update the fair clock.
++	 */
++	update_curr(rq, now);
++
++	/*
++	 * Are we enqueueing a waiting task? (for current tasks
++	 * a dequeue/enqueue event is a NOP)
++	 */
++	if (p != rq->curr)
++		update_stats_wait_start(rq, p, now);
++	/*
++	 * Update the key:
++	 */
++	key = rq->fair_clock;
++
++	/*
++	 * Optimize the common nice 0 case:
++	 */
++	if (likely(p->load_shift == SCHED_LOAD_SHIFT)) {
++		key -= p->wait_runtime;
++	} else {
++		unsigned int delta_bits;
++
++		if (p->load_shift < SCHED_LOAD_SHIFT) {
++			/* plus-reniced tasks get helped: */
++			delta_bits = SCHED_LOAD_SHIFT - p->load_shift;
++			key -= p->wait_runtime << delta_bits;
++		} else {
++			/* negative-reniced tasks get hurt: */
++			delta_bits = p->load_shift - SCHED_LOAD_SHIFT;
++			key -= p->wait_runtime >> delta_bits;
++		}
++	}
++
++	p->fair_key = key;
++}
++
++/*
++ * Note: must be called with a freshly updated rq->fair_clock.
++ */
++static inline void
++update_stats_wait_end(struct rq *rq, struct task_struct *p, u64 now)
++{
++	u64 delta, fair_delta, delta_wait;
++
++	delta_wait = now - p->wait_start;
++	if (unlikely(delta_wait > p->wait_max))
++		p->wait_max = delta_wait;
++
++	delta = rq->fair_clock - p->wait_start_fair;
++	fair_delta = rescale_load(p, delta);
++
++	p->sum_wait_runtime += fair_delta;
++	rq->wait_runtime += fair_delta;
++	p->wait_runtime += fair_delta;
++
++	p->wait_start_fair = 0;
++	p->wait_start = 0;
++}
++
++static inline void
++update_stats_dequeue(struct rq *rq, struct task_struct *p, u64 now)
++{
++	update_curr(rq, now);
++	/*
++	 * Mark the end of the wait period if dequeueing a
++	 * waiting task:
++	 */
++	if (p != rq->curr)
++		update_stats_wait_end(rq, p, now);
++}
++
++/*
++ * We are picking a new current task - update its stats:
++ */
++static inline void
++update_stats_curr_start(struct rq *rq, struct task_struct *p, u64 now)
++{
++	/*
++	 * We are starting a new run period:
++	 */
++	p->exec_start = now;
++}
++
++/*
++ * We are descheduling a task - update its stats:
++ */
++static inline void
++update_stats_curr_end(struct rq *rq, struct task_struct *p, u64 now)
++{
++	update_curr(rq, now);
++
++	p->exec_start = 0;
++}
++
++/**************************************************************/
++/* Scheduling class queueing methods:
++ */
++
++/*
++ * The enqueue_task method is called before nr_running is
++ * increased. Here we update the fair scheduling stats and
++ * then put the task into the rbtree:
++ */
++static void
++enqueue_task_fair(struct rq *rq, struct task_struct *p, int wakeup, u64 now)
++{
++	unsigned long max_delta = sysctl_sched_sleep_history_max, factor;
++	u64 delta = 0;
++
++	if (wakeup) {
++		if (p->sleep_start) {
++			delta = now - p->sleep_start;
++			if ((s64)delta < 0)
++				delta = 0;
++
++			if (unlikely(delta > p->sleep_max))
++				p->sleep_max = delta;
++
++			p->sleep_start = 0;
++		}
++		if (p->block_start) {
++			delta = now - p->block_start;
++			if ((s64)delta < 0)
++				delta = 0;
++
++			if (unlikely(delta > p->block_max))
++				p->block_max = delta;
++
++			p->block_start = 0;
++		}
++
++		/*
++		 * We are after a wait period, decay the
++		 * wait_runtime value:
++		 */
++		if (max_delta != -1 && max_delta != -2) {
++			if (delta < max_delta) {
++				factor = 1024 * (max_delta -
++					(unsigned long)delta) / max_delta;
++				p->wait_runtime *= (int)factor;
++				p->wait_runtime /= 1024;
++			} else {
++				p->wait_runtime = 0;
++			}
++		}
++	}
++	update_stats_enqueue(rq, p, now);
++	if (wakeup && max_delta == -2)
++		p->wait_runtime = 0;
++	__enqueue_task_fair(rq, p);
++}
++
++/*
++ * The dequeue_task method is called before nr_running is
++ * decreased. We remove the task from the rbtree and
++ * update the fair scheduling stats:
++ */
++static void
++dequeue_task_fair(struct rq *rq, struct task_struct *p, int sleep, u64 now)
++{
++	update_stats_dequeue(rq, p, now);
++	if (sleep) {
++		if (p->state & TASK_INTERRUPTIBLE)
++			p->sleep_start = now;
++		if (p->state & TASK_UNINTERRUPTIBLE)
++			p->block_start = now;
++	}
++	__dequeue_task_fair(rq, p);
++}
++
++/*
++ * sched_yield() support is very simple via the rbtree: we just
++ * dequeue the task and move it after the next task, which
++ * causes tasks to roundrobin.
++ */
++static void
++yield_task_fair(struct rq *rq, struct task_struct *p, struct task_struct *p_to)
++{
++	struct rb_node *curr, *next, *first;
++	struct task_struct *p_next;
++	s64 yield_key;
++	u64 now;
++
++	/*
++	 * yield-to support: if we are on the same runqueue then
++	 * give half of our wait_runtime (if it's positive) to the other task:
++	 */
++	if (p_to && p->wait_runtime > 0) {
++		p_to->wait_runtime += p->wait_runtime >> 1;
++		p->wait_runtime >>= 1;
++	}
++	curr = &p->run_node;
++	first = first_fair(rq);
++	/*
++	 * Move this task to the second place in the tree:
++	 */
++	if (unlikely(curr != first)) {
++		next = first;
++	} else {
++		next = rb_next(curr);
++		/*
++		 * We were the last one already - nothing to do, return
++		 * and reschedule:
++		 */
++		if (unlikely(!next))
++			return;
++	}
++
++	p_next = rb_entry(next, struct task_struct, run_node);
++	/*
++	 * Minimally necessary key value to be the second in the tree:
++	 */
++	yield_key = p_next->fair_key + 1;
++
++	now = __rq_clock(rq);
++	dequeue_task_fair(rq, p, 0, now);
++	p->on_rq = 0;
++
++	/*
++	 * Only update the key if we need to move more backwards
++	 * than the minimally necessary position to be the second:
++	 */
++	if (p->fair_key < yield_key)
++		p->fair_key = yield_key;
++
++	__enqueue_task_fair(rq, p);
++	p->on_rq = 1;
++}
++
++/*
++ * Preempt the current task with a newly woken task if needed:
++ */
++static inline void
++__check_preempt_curr_fair(struct rq *rq, struct task_struct *p,
++			  struct task_struct *curr, unsigned long granularity)
++{
++	s64 __delta = curr->fair_key - p->fair_key;
++
++	/*
++	 * Take scheduling granularity into account - do not
++	 * preempt the current task unless the best task has
++	 * a larger than sched_granularity fairness advantage:
++	 */
++	if (__delta > niced_granularity(rq, curr, granularity))
++		resched_task(curr);
++}
++
++/*
++ * Preempt the current task with a newly woken task if needed:
++ */
++static void check_preempt_curr_fair(struct rq *rq, struct task_struct *p)
++{
++	struct task_struct *curr = rq->curr;
++
++	if ((curr == rq->idle) || rt_prio(p->prio)) {
++		resched_task(curr);
++	} else {
++		__check_preempt_curr_fair(rq, p, curr,
++					  sysctl_sched_granularity);
++	}
++}
++
++static struct task_struct * pick_next_task_fair(struct rq *rq, u64 now)
++{
++	struct task_struct *p = __pick_next_task_fair(rq);
++
++	/*
++	 * Any task has to be enqueued before it get to execute on
++	 * a CPU. So account for the time it spent waiting on the
++	 * runqueue. (note, here we rely on pick_next_task() having
++	 * done a put_prev_task_fair() shortly before this, which
++	 * updated rq->fair_clock - used by update_stats_wait_end())
++	 */
++	update_stats_wait_end(rq, p, now);
++	update_stats_curr_start(rq, p, now);
++
++	return p;
++}
++
++/*
++ * Account for a descheduled task:
++ */
++static void put_prev_task_fair(struct rq *rq, struct task_struct *prev, u64 now)
++{
++	if (prev == rq->idle)
++		return;
++
++	update_stats_curr_end(rq, prev, now);
++	/*
++	 * If the task is still waiting for the CPU (it just got
++	 * preempted), start the wait period:
++	 */
++	if (prev->on_rq)
++		update_stats_wait_start(rq, prev, now);
++}
++
++/**************************************************************/
++/* Fair scheduling class load-balancing methods:
++ */
++
++/*
++ * Load-balancing iterator. Note: while the runqueue stays locked
++ * during the whole iteration, the current task might be
++ * dequeued so the iterator has to be dequeue-safe. Here we
++ * achieve that by always pre-iterating before returning
++ * the current task:
++ */
++static struct task_struct * load_balance_start_fair(struct rq *rq)
++{
++	struct rb_node *first = first_fair(rq);
++	struct task_struct *p;
++
++	if (!first)
++		return NULL;
++
++	p = rb_entry(first, struct task_struct, run_node);
++
++	rq->rb_load_balance_curr = rb_next(first);
++
++	return p;
++}
++
++static struct task_struct * load_balance_next_fair(struct rq *rq)
++{
++	struct rb_node *curr = rq->rb_load_balance_curr;
++	struct task_struct *p;
++
++	if (!curr)
++		return NULL;
++
++	p = rb_entry(curr, struct task_struct, run_node);
++	rq->rb_load_balance_curr = rb_next(curr);
++
++	return p;
++}
++
++/*
++ * scheduler tick hitting a task of our scheduling class:
++ */
++static void task_tick_fair(struct rq *rq, struct task_struct *curr)
++{
++	struct task_struct *next;
++	u64 now = __rq_clock(rq);
++
++	/*
++	 * Dequeue and enqueue the task to update its
++	 * position within the tree:
++	 */
++	dequeue_task_fair(rq, curr, 0, now);
++	curr->on_rq = 0;
++	enqueue_task_fair(rq, curr, 0, now);
++	curr->on_rq = 1;
++
++	/*
++	 * Reschedule if another task tops the current one.
++	 */
++	next = __pick_next_task_fair(rq);
++	if (next == curr)
++		return;
++
++	if ((curr == rq->idle) || (rt_prio(next->prio) &&
++					(next->prio < curr->prio)))
++		resched_task(curr);
++	else
++		__check_preempt_curr_fair(rq, next, curr,
++					  sysctl_sched_granularity);
++}
++
++/*
++ * Share the fairness runtime between parent and child, thus the
++ * total amount of pressure for CPU stays equal - new tasks
++ * get a chance to run but frequent forkers are not allowed to
++ * monopolize the CPU. Note: the parent runqueue is locked,
++ * the child is not running yet.
++ */
++static void task_new_fair(struct rq *rq, struct task_struct *p)
++{
++	sched_info_queued(p);
++	update_stats_enqueue(rq, p, rq_clock(rq));
++	/*
++	 * Child runs first: we let it run before the parent
++	 * until it reschedules once. We set up the key so that
++	 * it will preempt the parent:
++	 */
++	p->fair_key = current->fair_key - niced_granularity(rq, rq->curr,
++						sysctl_sched_granularity) - 1;
++	__enqueue_task_fair(rq, p);
++	p->on_rq = 1;
++	inc_nr_running(p, rq);
++}
++
++/*
++ * All the scheduling class methods:
++ */
++struct sched_class fair_sched_class __read_mostly = {
++	.enqueue_task		= enqueue_task_fair,
++	.dequeue_task		= dequeue_task_fair,
++	.yield_task		= yield_task_fair,
++
++	.check_preempt_curr	= check_preempt_curr_fair,
++
++	.pick_next_task		= pick_next_task_fair,
++	.put_prev_task		= put_prev_task_fair,
++
++	.load_balance_start	= load_balance_start_fair,
++	.load_balance_next	= load_balance_next_fair,
++	.task_tick		= task_tick_fair,
++	.task_new		= task_new_fair,
++};
+Index: linux-cfs-2.6.20.8.q/kernel/sched_rt.c
+===================================================================
+--- /dev/null
++++ linux-cfs-2.6.20.8.q/kernel/sched_rt.c
+@@ -0,0 +1,184 @@
++/*
++ * Real-Time Scheduling Class (mapped to the SCHED_FIFO and SCHED_RR
++ * policies)
++ */
++
++static void
++enqueue_task_rt(struct rq *rq, struct task_struct *p, int wakeup, u64 now)
++{
++	struct prio_array *array = &rq->active;
++
++	list_add_tail(&p->run_list, array->queue + p->prio);
++	__set_bit(p->prio, array->bitmap);
++}
++
++/*
++ * Adding/removing a task to/from a priority array:
++ */
++static void
++dequeue_task_rt(struct rq *rq, struct task_struct *p, int sleep, u64 now)
++{
++	struct prio_array *array = &rq->active;
++
++	list_del(&p->run_list);
++	if (list_empty(array->queue + p->prio))
++		__clear_bit(p->prio, array->bitmap);
++}
++
++/*
++ * Put task to the end of the run list without the overhead of dequeue
++ * followed by enqueue.
++ */
++static void requeue_task_rt(struct rq *rq, struct task_struct *p)
++{
++	struct prio_array *array = &rq->active;
++
++	list_move_tail(&p->run_list, array->queue + p->prio);
++}
++
++static void
++yield_task_rt(struct rq *rq, struct task_struct *p, struct task_struct *p_to)
++{
++	requeue_task_rt(rq, p);
++}
++
++/*
++ * Preempt the current task with a newly woken task if needed:
++ */
++static void check_preempt_curr_rt(struct rq *rq, struct task_struct *p)
++{
++	if (p->prio < rq->curr->prio)
++		resched_task(rq->curr);
++}
++
++static struct task_struct * pick_next_task_rt(struct rq *rq, u64 now)
++{
++	struct prio_array *array = &rq->active;
++	struct list_head *queue;
++	int idx;
++
++	idx = sched_find_first_bit(array->bitmap);
++	if (idx >= MAX_RT_PRIO)
++		return NULL;
++
++	queue = array->queue + idx;
++	return list_entry(queue->next, struct task_struct, run_list);
++}
++
++/*
++ * No accounting done when RT tasks are descheduled:
++ */
++static void put_prev_task_rt(struct rq *rq, struct task_struct *p, u64 now)
++{
++}
++
++/*
++ * Load-balancing iterator. Note: while the runqueue stays locked
++ * during the whole iteration, the current task might be
++ * dequeued so the iterator has to be dequeue-safe. Here we
++ * achieve that by always pre-iterating before returning
++ * the current task:
++ */
++static struct task_struct * load_balance_start_rt(struct rq *rq)
++{
++	struct prio_array *array = &rq->active;
++	struct list_head *head, *curr;
++	struct task_struct *p;
++	int idx;
++
++	idx = sched_find_first_bit(array->bitmap);
++	if (idx >= MAX_RT_PRIO)
++		return NULL;
++
++	head = array->queue + idx;
++	curr = head->prev;
++
++	p = list_entry(curr, struct task_struct, run_list);
++
++	curr = curr->prev;
++
++	rq->rt_load_balance_idx = idx;
++	rq->rt_load_balance_head = head;
++	rq->rt_load_balance_curr = curr;
++
++	return p;
++}
++
++static struct task_struct * load_balance_next_rt(struct rq *rq)
++{
++	struct prio_array *array = &rq->active;
++	struct list_head *head, *curr;
++	struct task_struct *p;
++	int idx;
++
++	idx = rq->rt_load_balance_idx;
++	head = rq->rt_load_balance_head;
++	curr = rq->rt_load_balance_curr;
++
++	/*
++	 * If we arrived back to the head again then
++	 * iterate to the next queue (if any):
++	 */
++	if (unlikely(head == curr)) {
++		int next_idx = find_next_bit(array->bitmap, MAX_RT_PRIO, idx+1);
++
++		if (next_idx >= MAX_RT_PRIO)
++			return NULL;
++
++		idx = next_idx;
++		head = array->queue + idx;
++		curr = head->prev;
++
++		rq->rt_load_balance_idx = idx;
++		rq->rt_load_balance_head = head;
++	}
++
++	p = list_entry(curr, struct task_struct, run_list);
++
++	curr = curr->prev;
++
++	rq->rt_load_balance_curr = curr;
++
++	return p;
++}
++
++static void task_tick_rt(struct rq *rq, struct task_struct *p)
++{
++	/*
++	 * RR tasks need a special form of timeslice management.
++	 * FIFO tasks have no timeslices.
++	 */
++	if ((p->policy == SCHED_RR) && !--p->time_slice) {
++		p->time_slice = static_prio_timeslice(p->static_prio);
++		set_tsk_need_resched(p);
++
++		/* put it at the end of the queue: */
++		requeue_task_rt(rq, p);
++	}
++}
++
++/*
++ * No parent/child timeslice management necessary for RT tasks,
++ * just activate them:
++ */
++static void task_new_rt(struct rq *rq, struct task_struct *p)
++{
++	activate_task(rq, p, 1);
++}
++
++static struct sched_class rt_sched_class __read_mostly = {
++	.enqueue_task		= enqueue_task_rt,
++	.dequeue_task		= dequeue_task_rt,
++	.yield_task		= yield_task_rt,
++
++	.check_preempt_curr	= check_preempt_curr_rt,
++
++	.pick_next_task		= pick_next_task_rt,
++	.put_prev_task		= put_prev_task_rt,
++
++	.load_balance_start	= load_balance_start_rt,
++	.load_balance_next	= load_balance_next_rt,
++
++	.task_tick		= task_tick_rt,
++	.task_new		= task_new_rt,
++};
+Index: linux-cfs-2.6.20.8.q/kernel/sched_stats.h
+===================================================================
+--- /dev/null
++++ linux-cfs-2.6.20.8.q/kernel/sched_stats.h
+@@ -0,0 +1,235 @@
++
++#ifdef CONFIG_SCHEDSTATS
++/*
++ * bump this up when changing the output format or the meaning of an existing
++ * format, so that tools can adapt (or abort)
++ */
++#define SCHEDSTAT_VERSION 14
++
++static int show_schedstat(struct seq_file *seq, void *v)
++{
++	int cpu;
++
++	seq_printf(seq, "version %d\n", SCHEDSTAT_VERSION);
++	seq_printf(seq, "timestamp %lu\n", jiffies);
++	for_each_online_cpu(cpu) {
++		struct rq *rq = cpu_rq(cpu);
++#ifdef CONFIG_SMP
++		struct sched_domain *sd;
++		int dcnt = 0;
++#endif
++
++		/* runqueue-specific stats */
++		seq_printf(seq,
++		    "cpu%d %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu",
++		    cpu, rq->yld_both_empty,
++		    rq->yld_act_empty, rq->yld_exp_empty, rq->yld_cnt,
++		    rq->sched_switch, rq->sched_cnt, rq->sched_goidle,
++		    rq->ttwu_cnt, rq->ttwu_local,
++		    rq->rq_sched_info.cpu_time,
++		    rq->rq_sched_info.run_delay, rq->rq_sched_info.pcnt);
++
++		seq_printf(seq, "\n");
++
++#ifdef CONFIG_SMP
++		/* domain-specific stats */
++		preempt_disable();
++		for_each_domain(cpu, sd) {
++			enum idle_type itype;
++			char mask_str[NR_CPUS];
++
++			cpumask_scnprintf(mask_str, NR_CPUS, sd->span);
++			seq_printf(seq, "domain%d %s", dcnt++, mask_str);
++			for (itype = SCHED_IDLE; itype < MAX_IDLE_TYPES;
++					itype++) {
++				seq_printf(seq, " %lu %lu %lu %lu %lu %lu %lu "
++						"%lu",
++				    sd->lb_cnt[itype],
++				    sd->lb_balanced[itype],
++				    sd->lb_failed[itype],
++				    sd->lb_imbalance[itype],
++				    sd->lb_gained[itype],
++				    sd->lb_hot_gained[itype],
++				    sd->lb_nobusyq[itype],
++				    sd->lb_nobusyg[itype]);
++			}
++			seq_printf(seq, " %lu %lu %lu %lu %lu %lu %lu %lu %lu"
++			    " %lu %lu %lu\n",
++			    sd->alb_cnt, sd->alb_failed, sd->alb_pushed,
++			    sd->sbe_cnt, sd->sbe_balanced, sd->sbe_pushed,
++			    sd->sbf_cnt, sd->sbf_balanced, sd->sbf_pushed,
++			    sd->ttwu_wake_remote, sd->ttwu_move_affine,
++			    sd->ttwu_move_balance);
++		}
++		preempt_enable();
++#endif
++	}
++	return 0;
++}
++
++static int schedstat_open(struct inode *inode, struct file *file)
++{
++	unsigned int size = PAGE_SIZE * (1 + num_online_cpus() / 32);
++	char *buf = kmalloc(size, GFP_KERNEL);
++	struct seq_file *m;
++	int res;
++
++	if (!buf)
++		return -ENOMEM;
++	res = single_open(file, show_schedstat, NULL);
++	if (!res) {
++		m = file->private_data;
++		m->buf = buf;
++		m->size = size;
++	} else
++		kfree(buf);
++	return res;
++}
++
++const struct file_operations proc_schedstat_operations = {
++	.open    = schedstat_open,
++	.read    = seq_read,
++	.llseek  = seq_lseek,
++	.release = single_release,
++};
++
++/*
++ * Expects runqueue lock to be held for atomicity of update
++ */
++static inline void
++rq_sched_info_arrive(struct rq *rq, unsigned long delta_jiffies)
++{
++	if (rq) {
++		rq->rq_sched_info.run_delay += delta_jiffies;
++		rq->rq_sched_info.pcnt++;
++	}
++}
++
++/*
++ * Expects runqueue lock to be held for atomicity of update
++ */
++static inline void
++rq_sched_info_depart(struct rq *rq, unsigned long delta_jiffies)
++{
++	if (rq)
++		rq->rq_sched_info.cpu_time += delta_jiffies;
++}
++# define schedstat_inc(rq, field)	do { (rq)->field++; } while (0)
++# define schedstat_add(rq, field, amt)	do { (rq)->field += (amt); } while (0)
++#else /* !CONFIG_SCHEDSTATS */
++static inline void
++rq_sched_info_arrive(struct rq *rq, unsigned long delta_jiffies)
++{}
++static inline void
++rq_sched_info_depart(struct rq *rq, unsigned long delta_jiffies)
++{}
++# define schedstat_inc(rq, field)	do { } while (0)
++# define schedstat_add(rq, field, amt)	do { } while (0)
++#endif
++
++#if defined(CONFIG_SCHEDSTATS) || defined(CONFIG_TASK_DELAY_ACCT)
++/*
++ * Called when a process is dequeued from the active array and given
++ * the cpu.  We should note that with the exception of interactive
++ * tasks, the expired queue will become the active queue after the active
++ * queue is empty, without explicitly dequeuing and requeuing tasks in the
++ * expired queue.  (Interactive tasks may be requeued directly to the
++ * active queue, thus delaying tasks in the expired queue from running;
++ * see scheduler_tick()).
++ *
++ * This function is only called from sched_info_arrive(), rather than
++ * dequeue_task(). Even though a task may be queued and dequeued multiple
++ * times as it is shuffled about, we're really interested in knowing how
++ * long it was from the *first* time it was queued to the time that it
++ * finally hit a cpu.
++ */
++static inline void sched_info_dequeued(struct task_struct *t)
++{
++	t->sched_info.last_queued = 0;
++}
++
++/*
++ * Called when a task finally hits the cpu.  We can now calculate how
++ * long it was waiting to run.  We also note when it began so that we
++ * can keep stats on how long its timeslice is.
++ */
++static void sched_info_arrive(struct task_struct *t)
++{
++	unsigned long now = jiffies, delta_jiffies = 0;
++
++	if (t->sched_info.last_queued)
++		delta_jiffies = now - t->sched_info.last_queued;
++	sched_info_dequeued(t);
++	t->sched_info.run_delay += delta_jiffies;
++	t->sched_info.last_arrival = now;
++	t->sched_info.pcnt++;
++
++	rq_sched_info_arrive(task_rq(t), delta_jiffies);
++}
++
++/*
++ * Called when a process is queued into either the active or expired
++ * array.  The time is noted and later used to determine how long we
++ * had to wait for us to reach the cpu.  Since the expired queue will
++ * become the active queue after active queue is empty, without dequeuing
++ * and requeuing any tasks, we are interested in queuing to either. It
++ * is unusual but not impossible for tasks to be dequeued and immediately
++ * requeued in the same or another array: this can happen in sched_yield(),
++ * set_user_nice(), and even load_balance() as it moves tasks from runqueue
++ * to runqueue.
++ *
++ * This function is only called from enqueue_task(), but also only updates
++ * the timestamp if it is already not set.  It's assumed that
++ * sched_info_dequeued() will clear that stamp when appropriate.
++ */
++static inline void sched_info_queued(struct task_struct *t)
++{
++	if (unlikely(sched_info_on()))
++		if (!t->sched_info.last_queued)
++			t->sched_info.last_queued = jiffies;
++}
++
++/*
++ * Called when a process ceases being the active-running process, either
++ * voluntarily or involuntarily.  Now we can calculate how long we ran.
++ */
++static inline void sched_info_depart(struct task_struct *t)
++{
++	unsigned long delta_jiffies = jiffies - t->sched_info.last_arrival;
++
++	t->sched_info.cpu_time += delta_jiffies;
++	rq_sched_info_depart(task_rq(t), delta_jiffies);
++}
++
++/*
++ * Called when tasks are switched involuntarily due, typically, to expiring
++ * their time slice.  (This may also be called when switching to or from
++ * the idle task.)  We are only called when prev != next.
++ */
++static inline void
++__sched_info_switch(struct task_struct *prev, struct task_struct *next)
++{
++	struct rq *rq = task_rq(prev);
++
++	/*
++	 * prev now departs the cpu.  It's not interesting to record
++	 * stats about how efficient we were at scheduling the idle
++	 * process, however.
++	 */
++	if (prev != rq->idle)
++		sched_info_depart(prev);
++
++	if (next != rq->idle)
++		sched_info_arrive(next);
++}
++static inline void
++sched_info_switch(struct task_struct *prev, struct task_struct *next)
++{
++	if (unlikely(sched_info_on()))
++		__sched_info_switch(prev, next);
++}
++#else
++#define sched_info_queued(t)		do { } while (0)
++#define sched_info_switch(t, next)	do { } while (0)
++#endif /* CONFIG_SCHEDSTATS || CONFIG_TASK_DELAY_ACCT */
++
+Index: linux-cfs-2.6.20.8.q/kernel/sysctl.c
+===================================================================
+--- linux-cfs-2.6.20.8.q.orig/kernel/sysctl.c
++++ linux-cfs-2.6.20.8.q/kernel/sysctl.c
+@@ -320,6 +320,46 @@ static ctl_table kern_table[] = {
+ 		.strategy	= &sysctl_uts_string,
+ 	},
+ 	{
++		.ctl_name	= CTL_UNNUMBERED,
++		.procname	= "sched_granularity_ns",
++		.data		= &sysctl_sched_granularity,
++		.maxlen		= sizeof(unsigned int),
++		.mode		= 0644,
++		.proc_handler	= &proc_dointvec,
++	},
++	{
++		.ctl_name	= CTL_UNNUMBERED,
++		.procname	= "sched_wakeup_granularity_ns",
++		.data		= &sysctl_sched_wakeup_granularity,
++		.maxlen		= sizeof(unsigned int),
++		.mode		= 0644,
++		.proc_handler	= &proc_dointvec,
++	},
++	{
++		.ctl_name	= CTL_UNNUMBERED,
++		.procname	= "sched_sleep_history_max_ns",
++		.data		= &sysctl_sched_sleep_history_max,
++		.maxlen		= sizeof(unsigned int),
++		.mode		= 0644,
++		.proc_handler	= &proc_dointvec,
++	},
++	{
++		.ctl_name	= CTL_UNNUMBERED,
++		.procname	= "sched_child_runs_first",
++		.data		= &sysctl_sched_child_runs_first,
++		.maxlen		= sizeof(unsigned int),
++		.mode		= 0644,
++		.proc_handler	= &proc_dointvec,
++	},
++	{
++		.ctl_name	= CTL_UNNUMBERED,
++		.procname	= "sched_load_smoothing",
++		.data		= &sysctl_sched_load_smoothing,
++		.maxlen		= sizeof(unsigned int),
++		.mode		= 0644,
++		.proc_handler	= &proc_dointvec,
++	},
++	{
+ 		.ctl_name	= KERN_PANIC,
+ 		.procname	= "panic",
+ 		.data		= &panic_timeout,
diff --git a/packages/linux/linux-efika_2.6.20.11.bb b/packages/linux/linux-efika_2.6.20.11.bb
new file mode 100644
index 0000000000..d54b642a1b
--- /dev/null
+++ b/packages/linux/linux-efika_2.6.20.11.bb
@@ -0,0 +1,86 @@
+DESCRIPTION = "Linux Kernel for the EFIKA dev platform"
+SECTION = "kernel"
+LICENSE = "GPL"
+PR = "r0"
+
+COMPATIBLE_MACHINE = "efika"
+
+FILESPATH = "${FILE_DIRNAME}/linux-efika-${PV}:${FILE_DIRNAME}/linux-efika-2.6.20"
+
+SRC_URI = "${KERNELORG_MIRROR}/pub/linux/kernel/v2.6/linux-2.6.20.tar.bz2 \
+           file://0001-powerpc-serial-Dispose-irq-mapping-when-done-in-mpc52xx_serial.c.txt;p=1;patch=1 \
+           file://0003-powerpc-Add-device-tree-fixups-for-the-EFIKA.txt;p=1;patch=1 \
+           file://0004-powerpc-Use-common-52xx-of_platform-probe-code-for-EFIKA.txt;p=1;patch=1 \
+           file://0005-powerpc-Restore-proper-link-order-in-platform.txt;p=1;patch=1 \
+           file://0006-Rework-the-OHCI-quirk-mecanism-as-suggested-by-David.txt;p=1;patch=1 \
+           file://0007-Implement-support-for-split-endian-OHCI.txt;p=1;patch=1 \
+           file://0008-ohci-Rework-bus-glue-integration-to-allow-several-at-once.txt;p=1;patch=1 \
+           file://0009-ohci-Add-support-for-OHCI-controller-on-the-of_platform-bus.txt;p=1;patch=1 \
+           file://0010-libata-Add-support-for-the-MPC52xx-ATA-controller.txt;p=1;patch=1 \
+           file://0011-ohci-Whitespace-and-typo-fix-in-ohci-ppc-of.c.txt;p=1;patch=1 \
+           file://0012-ata-Fix-pata_mpc52xx.c-compatible-list.txt;p=1;patch=1 \
+           file://0013-powerpc-serial-Fix-mpc52xx_uart.c-compatible-list.txt;p=1;patch=1 \
+           file://0014-powerpc-Small-cleanup-of-EFIKA-platform.txt;p=1;patch=1 \
+           file://0015-powerpc-Add-a-unified-uevent-handler-for-bus-based-on-of_device.txt;p=1;patch=1 \
+           file://0016-macintosh-Use-the-new-of_device-common-uevent-handler.txt;p=1;patch=1 \
+           file://0017-powerpc-Add-uevent-handler-for-of_platform_bus.txt;p=1;patch=1 \
+           file://0018-powerpc-Add-uevent-handler-for-ibmebus.txt;p=1;patch=1 \
+           file://0019-MPC5200-Bestcomm-platform-driver.txt;p=1;patch=1 \
+           file://0020-Fec-MPC5200-eth-driver.txt;p=1;patch=1 \
+           file://0021-POWERPC-Copy-bestcomm-support-files-into-arch-powerpc.txt;p=1;patch=1 \
+           file://0022-MPC52xx-PCI-now-working-on-lite5200.-ugly-but-working.txt;p=1;patch=1 \
+           file://0023-POWERPC-Make-FEC-work-on-the-lite5200.txt;p=1;patch=1 \
+           file://0024-Add-missing-function-prototype.txt;p=1;patch=1 \
+           file://0025-POWERPC-Misc-EFIKA-fixups-for-rtas-chrp.txt;p=1;patch=1 \
+           file://0026-POWERPC-Cleanup-mpc52xx-PCI-support.txt;p=1;patch=1 \
+           file://0027-POWERPC-Change-name-of-mpc52xx-pci-support-file-in-Makefile.txt;p=1;patch=1 \
+           file://0028-POWERPC-Change-link-order-so-mpc52xx-fec-always-shows-up-as-eth0.txt;p=1;patch=1 \
+           file://0029-POWERPC-Fixup-pr_print-format-for-mpc52xx-pci-support.txt;p=1;patch=1 \
+           file://0030-POWERPC-Add-mpc52xx-lite5200-PCI-support.txt;p=1;patch=1 \
+           file://0031-sound-Add-support-for-the-MPC52xx-PSC-AC97-Link.txt;p=1;patch=1 \
+           file://0032-POWERPC-EFIKA-Adds-missing-interrupts-from-bestcomm-node.txt;p=1;patch=1 \
+           file://0033-EFIKA-fullduplex-prpl_aln.txt;p=1;patch=1 \
+           file://v4l.diff;p=1;patch=1 \
+           http://www.kernel.org/pub/linux/kernel/v2.6/patch-2.6.20.11.bz2;p=1;patch=1 \
+           file://sched-cfs-v9-v2.6.20.11.patch;p=1;patch=1 \
+           file://defconfig \
+		   "
+
+
+S = "${WORKDIR}/linux-2.6.20"
+
+inherit kernel
+
+export ARCH="powerpc"
+
+KERNEL_IMAGETYPE = "zImage"
+
+do_configure() {
+		install -m 644 ${WORKDIR}/defconfig ${S}/.config
+		make ARCH=${ARCH} oldconfig
+}
+
+do_stage_append () {
+#need ppc platforms includes + friends in order for external kernel modules to compile as headers as still split
+
+       install -d ${STAGING_KERNEL_DIR}/arch/
+       cp -a arch/ppc ${STAGING_KERNEL_DIR}/arch/
+       cp -a arch/powerpc ${STAGING_KERNEL_DIR}/arch/
+
+       install -d ${STAGING_KERNEL_DIR}/include/asm
+       cp -a include/asm-powerpc ${STAGING_KERNEL_DIR}/include/
+       cp -a include/asm-ppc ${STAGING_KERNEL_DIR}/include/
+}
+
+
+
+do_deploy() {
+        install -d ${DEPLOY_DIR_IMAGE}
+        install -m 0644 arch/${ARCH}/boot/${KERNEL_IMAGETYPE} ${DEPLOY_DIR_IMAGE}/${KERNEL_IMAGETYPE}-${PV}-${MACHINE}-${DATETIME}
+}
+
+do_deploy[dirs] = "${S}"
+
+addtask deploy before do_build after do_compile
+
+
-- 
cgit v1.2.3