mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 10:40:15 +02:00 
			
		
		
		
	sched: Make separate sched*.c translation units
Since once needs to do something at conferences and fixing compile warnings doesn't actually require much if any attention I decided to break up the sched.c #include "*.c" fest. This further modularizes the scheduler code. Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl> Link: http://lkml.kernel.org/n/tip-x0fcd3mnp8f9c99grcpewmhi@git.kernel.org Signed-off-by: Ingo Molnar <mingo@elte.hu>
This commit is contained in:
		
							parent
							
								
									60686317da
								
							
						
					
					
						commit
						029632fbb7
					
				
					 14 changed files with 2034 additions and 1954 deletions
				
			
		| 
						 | 
					@ -10,6 +10,8 @@
 | 
				
			||||||
#define _INCLUDE_GUARD_LATENCYTOP_H_
 | 
					#define _INCLUDE_GUARD_LATENCYTOP_H_
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <linux/compiler.h>
 | 
					#include <linux/compiler.h>
 | 
				
			||||||
 | 
					struct task_struct;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef CONFIG_LATENCYTOP
 | 
					#ifdef CONFIG_LATENCYTOP
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define LT_SAVECOUNT		32
 | 
					#define LT_SAVECOUNT		32
 | 
				
			||||||
| 
						 | 
					@ -23,7 +25,6 @@ struct latency_record {
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct task_struct;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
extern int latencytop_enabled;
 | 
					extern int latencytop_enabled;
 | 
				
			||||||
void __account_scheduler_latency(struct task_struct *task, int usecs, int inter);
 | 
					void __account_scheduler_latency(struct task_struct *task, int usecs, int inter);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -925,6 +925,15 @@ static inline struct cpumask *sched_group_cpus(struct sched_group *sg)
 | 
				
			||||||
	return to_cpumask(sg->cpumask);
 | 
						return to_cpumask(sg->cpumask);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * group_first_cpu - Returns the first cpu in the cpumask of a sched_group.
 | 
				
			||||||
 | 
					 * @group: The group whose first cpu is to be returned.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static inline unsigned int group_first_cpu(struct sched_group *group)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return cpumask_first(sched_group_cpus(group));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct sched_domain_attr {
 | 
					struct sched_domain_attr {
 | 
				
			||||||
	int relax_domain_level;
 | 
						int relax_domain_level;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2,7 +2,7 @@
 | 
				
			||||||
# Makefile for the linux kernel.
 | 
					# Makefile for the linux kernel.
 | 
				
			||||||
#
 | 
					#
 | 
				
			||||||
 | 
					
 | 
				
			||||||
obj-y     = sched.o fork.o exec_domain.o panic.o printk.o \
 | 
					obj-y     = fork.o exec_domain.o panic.o printk.o \
 | 
				
			||||||
	    cpu.o exit.o itimer.o time.o softirq.o resource.o \
 | 
						    cpu.o exit.o itimer.o time.o softirq.o resource.o \
 | 
				
			||||||
	    sysctl.o sysctl_binary.o capability.o ptrace.o timer.o user.o \
 | 
						    sysctl.o sysctl_binary.o capability.o ptrace.o timer.o user.o \
 | 
				
			||||||
	    signal.o sys.o kmod.o workqueue.o pid.o \
 | 
						    signal.o sys.o kmod.o workqueue.o pid.o \
 | 
				
			||||||
| 
						 | 
					@ -10,8 +10,12 @@ obj-y     = sched.o fork.o exec_domain.o panic.o printk.o \
 | 
				
			||||||
	    kthread.o wait.o kfifo.o sys_ni.o posix-cpu-timers.o mutex.o \
 | 
						    kthread.o wait.o kfifo.o sys_ni.o posix-cpu-timers.o mutex.o \
 | 
				
			||||||
	    hrtimer.o rwsem.o nsproxy.o srcu.o semaphore.o \
 | 
						    hrtimer.o rwsem.o nsproxy.o srcu.o semaphore.o \
 | 
				
			||||||
	    notifier.o ksysfs.o sched_clock.o cred.o \
 | 
						    notifier.o ksysfs.o sched_clock.o cred.o \
 | 
				
			||||||
	    async.o range.o
 | 
						    async.o range.o groups.o
 | 
				
			||||||
obj-y += groups.o
 | 
					
 | 
				
			||||||
 | 
					obj-y += sched.o sched_idletask.o sched_fair.o sched_rt.o sched_stoptask.o
 | 
				
			||||||
 | 
					obj-$(CONFIG_SCHED_AUTOGROUP) += sched_autogroup.o
 | 
				
			||||||
 | 
					obj-$(CONFIG_SCHEDSTATS) += sched_stats.o
 | 
				
			||||||
 | 
					obj-$(CONFIG_SCHED_DEBUG) += sched_debug.o
 | 
				
			||||||
 | 
					
 | 
				
			||||||
ifdef CONFIG_FUNCTION_TRACER
 | 
					ifdef CONFIG_FUNCTION_TRACER
 | 
				
			||||||
# Do not trace debug files and internal ftrace files
 | 
					# Do not trace debug files and internal ftrace files
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										1828
									
								
								kernel/sched.c
									
									
									
									
									
								
							
							
						
						
									
										1828
									
								
								kernel/sched.c
									
									
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							
							
								
								
									
										1064
									
								
								kernel/sched.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1064
									
								
								kernel/sched.h
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							| 
						 | 
					@ -1,15 +1,19 @@
 | 
				
			||||||
#ifdef CONFIG_SCHED_AUTOGROUP
 | 
					#ifdef CONFIG_SCHED_AUTOGROUP
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "sched.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <linux/proc_fs.h>
 | 
					#include <linux/proc_fs.h>
 | 
				
			||||||
#include <linux/seq_file.h>
 | 
					#include <linux/seq_file.h>
 | 
				
			||||||
#include <linux/kallsyms.h>
 | 
					#include <linux/kallsyms.h>
 | 
				
			||||||
#include <linux/utsname.h>
 | 
					#include <linux/utsname.h>
 | 
				
			||||||
 | 
					#include <linux/security.h>
 | 
				
			||||||
 | 
					#include <linux/export.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
unsigned int __read_mostly sysctl_sched_autogroup_enabled = 1;
 | 
					unsigned int __read_mostly sysctl_sched_autogroup_enabled = 1;
 | 
				
			||||||
static struct autogroup autogroup_default;
 | 
					static struct autogroup autogroup_default;
 | 
				
			||||||
static atomic_t autogroup_seq_nr;
 | 
					static atomic_t autogroup_seq_nr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void __init autogroup_init(struct task_struct *init_task)
 | 
					void __init autogroup_init(struct task_struct *init_task)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	autogroup_default.tg = &root_task_group;
 | 
						autogroup_default.tg = &root_task_group;
 | 
				
			||||||
	kref_init(&autogroup_default.kref);
 | 
						kref_init(&autogroup_default.kref);
 | 
				
			||||||
| 
						 | 
					@ -17,7 +21,7 @@ static void __init autogroup_init(struct task_struct *init_task)
 | 
				
			||||||
	init_task->signal->autogroup = &autogroup_default;
 | 
						init_task->signal->autogroup = &autogroup_default;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static inline void autogroup_free(struct task_group *tg)
 | 
					void autogroup_free(struct task_group *tg)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	kfree(tg->autogroup);
 | 
						kfree(tg->autogroup);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -59,10 +63,6 @@ static inline struct autogroup *autogroup_task_get(struct task_struct *p)
 | 
				
			||||||
	return ag;
 | 
						return ag;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef CONFIG_RT_GROUP_SCHED
 | 
					 | 
				
			||||||
static void free_rt_sched_group(struct task_group *tg);
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static inline struct autogroup *autogroup_create(void)
 | 
					static inline struct autogroup *autogroup_create(void)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct autogroup *ag = kzalloc(sizeof(*ag), GFP_KERNEL);
 | 
						struct autogroup *ag = kzalloc(sizeof(*ag), GFP_KERNEL);
 | 
				
			||||||
| 
						 | 
					@ -108,8 +108,7 @@ static inline struct autogroup *autogroup_create(void)
 | 
				
			||||||
	return autogroup_kref_get(&autogroup_default);
 | 
						return autogroup_kref_get(&autogroup_default);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static inline bool
 | 
					bool task_wants_autogroup(struct task_struct *p, struct task_group *tg)
 | 
				
			||||||
task_wants_autogroup(struct task_struct *p, struct task_group *tg)
 | 
					 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	if (tg != &root_task_group)
 | 
						if (tg != &root_task_group)
 | 
				
			||||||
		return false;
 | 
							return false;
 | 
				
			||||||
| 
						 | 
					@ -127,22 +126,6 @@ task_wants_autogroup(struct task_struct *p, struct task_group *tg)
 | 
				
			||||||
	return true;
 | 
						return true;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static inline bool task_group_is_autogroup(struct task_group *tg)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	return !!tg->autogroup;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static inline struct task_group *
 | 
					 | 
				
			||||||
autogroup_task_group(struct task_struct *p, struct task_group *tg)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	int enabled = ACCESS_ONCE(sysctl_sched_autogroup_enabled);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (enabled && task_wants_autogroup(p, tg))
 | 
					 | 
				
			||||||
		return p->signal->autogroup->tg;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return tg;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static void
 | 
					static void
 | 
				
			||||||
autogroup_move_group(struct task_struct *p, struct autogroup *ag)
 | 
					autogroup_move_group(struct task_struct *p, struct autogroup *ag)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
| 
						 | 
					@ -263,7 +246,7 @@ void proc_sched_autogroup_show_task(struct task_struct *p, struct seq_file *m)
 | 
				
			||||||
#endif /* CONFIG_PROC_FS */
 | 
					#endif /* CONFIG_PROC_FS */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef CONFIG_SCHED_DEBUG
 | 
					#ifdef CONFIG_SCHED_DEBUG
 | 
				
			||||||
static inline int autogroup_path(struct task_group *tg, char *buf, int buflen)
 | 
					int autogroup_path(struct task_group *tg, char *buf, int buflen)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	if (!task_group_is_autogroup(tg))
 | 
						if (!task_group_is_autogroup(tg))
 | 
				
			||||||
		return 0;
 | 
							return 0;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,5 +1,8 @@
 | 
				
			||||||
#ifdef CONFIG_SCHED_AUTOGROUP
 | 
					#ifdef CONFIG_SCHED_AUTOGROUP
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <linux/kref.h>
 | 
				
			||||||
 | 
					#include <linux/rwsem.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct autogroup {
 | 
					struct autogroup {
 | 
				
			||||||
	/*
 | 
						/*
 | 
				
			||||||
	 * reference doesn't mean how many thread attach to this
 | 
						 * reference doesn't mean how many thread attach to this
 | 
				
			||||||
| 
						 | 
					@ -13,9 +16,28 @@ struct autogroup {
 | 
				
			||||||
	int			nice;
 | 
						int			nice;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static inline bool task_group_is_autogroup(struct task_group *tg);
 | 
					extern void autogroup_init(struct task_struct *init_task);
 | 
				
			||||||
 | 
					extern void autogroup_free(struct task_group *tg);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static inline bool task_group_is_autogroup(struct task_group *tg)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return !!tg->autogroup;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					extern bool task_wants_autogroup(struct task_struct *p, struct task_group *tg);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static inline struct task_group *
 | 
					static inline struct task_group *
 | 
				
			||||||
autogroup_task_group(struct task_struct *p, struct task_group *tg);
 | 
					autogroup_task_group(struct task_struct *p, struct task_group *tg)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int enabled = ACCESS_ONCE(sysctl_sched_autogroup_enabled);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (enabled && task_wants_autogroup(p, tg))
 | 
				
			||||||
 | 
							return p->signal->autogroup->tg;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return tg;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					extern int autogroup_path(struct task_group *tg, char *buf, int buflen);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#else /* !CONFIG_SCHED_AUTOGROUP */
 | 
					#else /* !CONFIG_SCHED_AUTOGROUP */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -16,6 +16,8 @@
 | 
				
			||||||
#include <linux/kallsyms.h>
 | 
					#include <linux/kallsyms.h>
 | 
				
			||||||
#include <linux/utsname.h>
 | 
					#include <linux/utsname.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "sched.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static DEFINE_SPINLOCK(sched_debug_lock);
 | 
					static DEFINE_SPINLOCK(sched_debug_lock);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
| 
						 | 
					@ -373,7 +375,7 @@ static int sched_debug_show(struct seq_file *m, void *v)
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void sysrq_sched_debug_show(void)
 | 
					void sysrq_sched_debug_show(void)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	sched_debug_show(NULL, NULL);
 | 
						sched_debug_show(NULL, NULL);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -23,6 +23,13 @@
 | 
				
			||||||
#include <linux/latencytop.h>
 | 
					#include <linux/latencytop.h>
 | 
				
			||||||
#include <linux/sched.h>
 | 
					#include <linux/sched.h>
 | 
				
			||||||
#include <linux/cpumask.h>
 | 
					#include <linux/cpumask.h>
 | 
				
			||||||
 | 
					#include <linux/slab.h>
 | 
				
			||||||
 | 
					#include <linux/profile.h>
 | 
				
			||||||
 | 
					#include <linux/interrupt.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <trace/events/sched.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "sched.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * Targeted preemption latency for CPU-bound tasks:
 | 
					 * Targeted preemption latency for CPU-bound tasks:
 | 
				
			||||||
| 
						 | 
					@ -103,7 +110,110 @@ unsigned int __read_mostly sysctl_sched_shares_window = 10000000UL;
 | 
				
			||||||
unsigned int sysctl_sched_cfs_bandwidth_slice = 5000UL;
 | 
					unsigned int sysctl_sched_cfs_bandwidth_slice = 5000UL;
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static const struct sched_class fair_sched_class;
 | 
					/*
 | 
				
			||||||
 | 
					 * 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:
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static int get_update_sysctl_factor(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						unsigned int cpus = min_t(int, num_online_cpus(), 8);
 | 
				
			||||||
 | 
						unsigned int factor;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						switch (sysctl_sched_tunable_scaling) {
 | 
				
			||||||
 | 
						case SCHED_TUNABLESCALING_NONE:
 | 
				
			||||||
 | 
							factor = 1;
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case SCHED_TUNABLESCALING_LINEAR:
 | 
				
			||||||
 | 
							factor = cpus;
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case SCHED_TUNABLESCALING_LOG:
 | 
				
			||||||
 | 
						default:
 | 
				
			||||||
 | 
							factor = 1 + ilog2(cpus);
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return factor;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void update_sysctl(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						unsigned int factor = get_update_sysctl_factor();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define SET_SYSCTL(name) \
 | 
				
			||||||
 | 
						(sysctl_##name = (factor) * normalized_sysctl_##name)
 | 
				
			||||||
 | 
						SET_SYSCTL(sched_min_granularity);
 | 
				
			||||||
 | 
						SET_SYSCTL(sched_latency);
 | 
				
			||||||
 | 
						SET_SYSCTL(sched_wakeup_granularity);
 | 
				
			||||||
 | 
					#undef SET_SYSCTL
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void sched_init_granularity(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						update_sysctl();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if BITS_PER_LONG == 32
 | 
				
			||||||
 | 
					# define WMULT_CONST	(~0UL)
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
					# define WMULT_CONST	(1UL << 32)
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define WMULT_SHIFT	32
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Shift right and round:
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					#define SRR(x, y) (((x) + (1UL << ((y) - 1))) >> (y))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * delta *= weight / lw
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static unsigned long
 | 
				
			||||||
 | 
					calc_delta_mine(unsigned long delta_exec, unsigned long weight,
 | 
				
			||||||
 | 
							struct load_weight *lw)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						u64 tmp;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/*
 | 
				
			||||||
 | 
						 * weight can be less than 2^SCHED_LOAD_RESOLUTION for task group sched
 | 
				
			||||||
 | 
						 * entities since MIN_SHARES = 2. Treat weight as 1 if less than
 | 
				
			||||||
 | 
						 * 2^SCHED_LOAD_RESOLUTION.
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						if (likely(weight > (1UL << SCHED_LOAD_RESOLUTION)))
 | 
				
			||||||
 | 
							tmp = (u64)delta_exec * scale_load_down(weight);
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
 | 
							tmp = (u64)delta_exec;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!lw->inv_weight) {
 | 
				
			||||||
 | 
							unsigned long w = scale_load_down(lw->weight);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (BITS_PER_LONG > 32 && unlikely(w >= WMULT_CONST))
 | 
				
			||||||
 | 
								lw->inv_weight = 1;
 | 
				
			||||||
 | 
							else if (unlikely(!w))
 | 
				
			||||||
 | 
								lw->inv_weight = WMULT_CONST;
 | 
				
			||||||
 | 
							else
 | 
				
			||||||
 | 
								lw->inv_weight = WMULT_CONST / w;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/*
 | 
				
			||||||
 | 
						 * Check whether we'd overflow the 64-bit multiplication:
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						if (unlikely(tmp > WMULT_CONST))
 | 
				
			||||||
 | 
							tmp = SRR(SRR(tmp, WMULT_SHIFT/2) * lw->inv_weight,
 | 
				
			||||||
 | 
								WMULT_SHIFT/2);
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
 | 
							tmp = SRR(tmp * lw->inv_weight, WMULT_SHIFT);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return (unsigned long)min(tmp, (u64)(unsigned long)LONG_MAX);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const struct sched_class fair_sched_class;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**************************************************************
 | 
					/**************************************************************
 | 
				
			||||||
 * CFS operations on generic schedulable entities:
 | 
					 * CFS operations on generic schedulable entities:
 | 
				
			||||||
| 
						 | 
					@ -413,7 +523,7 @@ static void __dequeue_entity(struct cfs_rq *cfs_rq, struct sched_entity *se)
 | 
				
			||||||
	rb_erase(&se->run_node, &cfs_rq->tasks_timeline);
 | 
						rb_erase(&se->run_node, &cfs_rq->tasks_timeline);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static struct sched_entity *__pick_first_entity(struct cfs_rq *cfs_rq)
 | 
					struct sched_entity *__pick_first_entity(struct cfs_rq *cfs_rq)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct rb_node *left = cfs_rq->rb_leftmost;
 | 
						struct rb_node *left = cfs_rq->rb_leftmost;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -434,7 +544,7 @@ static struct sched_entity *__pick_next_entity(struct sched_entity *se)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef CONFIG_SCHED_DEBUG
 | 
					#ifdef CONFIG_SCHED_DEBUG
 | 
				
			||||||
static struct sched_entity *__pick_last_entity(struct cfs_rq *cfs_rq)
 | 
					struct sched_entity *__pick_last_entity(struct cfs_rq *cfs_rq)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct rb_node *last = rb_last(&cfs_rq->tasks_timeline);
 | 
						struct rb_node *last = rb_last(&cfs_rq->tasks_timeline);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -684,7 +794,7 @@ account_entity_enqueue(struct cfs_rq *cfs_rq, struct sched_entity *se)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	update_load_add(&cfs_rq->load, se->load.weight);
 | 
						update_load_add(&cfs_rq->load, se->load.weight);
 | 
				
			||||||
	if (!parent_entity(se))
 | 
						if (!parent_entity(se))
 | 
				
			||||||
		inc_cpu_load(rq_of(cfs_rq), se->load.weight);
 | 
							update_load_add(&rq_of(cfs_rq)->load, se->load.weight);
 | 
				
			||||||
	if (entity_is_task(se)) {
 | 
						if (entity_is_task(se)) {
 | 
				
			||||||
		add_cfs_task_weight(cfs_rq, se->load.weight);
 | 
							add_cfs_task_weight(cfs_rq, se->load.weight);
 | 
				
			||||||
		list_add(&se->group_node, &cfs_rq->tasks);
 | 
							list_add(&se->group_node, &cfs_rq->tasks);
 | 
				
			||||||
| 
						 | 
					@ -697,7 +807,7 @@ account_entity_dequeue(struct cfs_rq *cfs_rq, struct sched_entity *se)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	update_load_sub(&cfs_rq->load, se->load.weight);
 | 
						update_load_sub(&cfs_rq->load, se->load.weight);
 | 
				
			||||||
	if (!parent_entity(se))
 | 
						if (!parent_entity(se))
 | 
				
			||||||
		dec_cpu_load(rq_of(cfs_rq), se->load.weight);
 | 
							update_load_sub(&rq_of(cfs_rq)->load, se->load.weight);
 | 
				
			||||||
	if (entity_is_task(se)) {
 | 
						if (entity_is_task(se)) {
 | 
				
			||||||
		add_cfs_task_weight(cfs_rq, -se->load.weight);
 | 
							add_cfs_task_weight(cfs_rq, -se->load.weight);
 | 
				
			||||||
		list_del_init(&se->group_node);
 | 
							list_del_init(&se->group_node);
 | 
				
			||||||
| 
						 | 
					@ -1287,6 +1397,32 @@ entity_tick(struct cfs_rq *cfs_rq, struct sched_entity *curr, int queued)
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef CONFIG_CFS_BANDWIDTH
 | 
					#ifdef CONFIG_CFS_BANDWIDTH
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef HAVE_JUMP_LABEL
 | 
				
			||||||
 | 
					static struct jump_label_key __cfs_bandwidth_used;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static inline bool cfs_bandwidth_used(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return static_branch(&__cfs_bandwidth_used);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void account_cfs_bandwidth_used(int enabled, int was_enabled)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						/* only need to count groups transitioning between enabled/!enabled */
 | 
				
			||||||
 | 
						if (enabled && !was_enabled)
 | 
				
			||||||
 | 
							jump_label_inc(&__cfs_bandwidth_used);
 | 
				
			||||||
 | 
						else if (!enabled && was_enabled)
 | 
				
			||||||
 | 
							jump_label_dec(&__cfs_bandwidth_used);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#else /* HAVE_JUMP_LABEL */
 | 
				
			||||||
 | 
					static bool cfs_bandwidth_used(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return true;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void account_cfs_bandwidth_used(int enabled, int was_enabled) {}
 | 
				
			||||||
 | 
					#endif /* HAVE_JUMP_LABEL */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * default period for cfs group bandwidth.
 | 
					 * default period for cfs group bandwidth.
 | 
				
			||||||
 * default: 0.1s, units: nanoseconds
 | 
					 * default: 0.1s, units: nanoseconds
 | 
				
			||||||
| 
						 | 
					@ -1308,7 +1444,7 @@ static inline u64 sched_cfs_bandwidth_slice(void)
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * requires cfs_b->lock
 | 
					 * requires cfs_b->lock
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
static void __refill_cfs_bandwidth_runtime(struct cfs_bandwidth *cfs_b)
 | 
					void __refill_cfs_bandwidth_runtime(struct cfs_bandwidth *cfs_b)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	u64 now;
 | 
						u64 now;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1320,6 +1456,11 @@ static void __refill_cfs_bandwidth_runtime(struct cfs_bandwidth *cfs_b)
 | 
				
			||||||
	cfs_b->runtime_expires = now + ktime_to_ns(cfs_b->period);
 | 
						cfs_b->runtime_expires = now + ktime_to_ns(cfs_b->period);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static inline struct cfs_bandwidth *tg_cfs_bandwidth(struct task_group *tg)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return &tg->cfs_bandwidth;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* returns 0 on failure to allocate runtime */
 | 
					/* returns 0 on failure to allocate runtime */
 | 
				
			||||||
static int assign_cfs_rq_runtime(struct cfs_rq *cfs_rq)
 | 
					static int assign_cfs_rq_runtime(struct cfs_rq *cfs_rq)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
| 
						 | 
					@ -1530,7 +1671,7 @@ static void throttle_cfs_rq(struct cfs_rq *cfs_rq)
 | 
				
			||||||
	raw_spin_unlock(&cfs_b->lock);
 | 
						raw_spin_unlock(&cfs_b->lock);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void unthrottle_cfs_rq(struct cfs_rq *cfs_rq)
 | 
					void unthrottle_cfs_rq(struct cfs_rq *cfs_rq)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct rq *rq = rq_of(cfs_rq);
 | 
						struct rq *rq = rq_of(cfs_rq);
 | 
				
			||||||
	struct cfs_bandwidth *cfs_b = tg_cfs_bandwidth(cfs_rq->tg);
 | 
						struct cfs_bandwidth *cfs_b = tg_cfs_bandwidth(cfs_rq->tg);
 | 
				
			||||||
| 
						 | 
					@ -1839,7 +1980,112 @@ static void check_cfs_rq_runtime(struct cfs_rq *cfs_rq)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	throttle_cfs_rq(cfs_rq);
 | 
						throttle_cfs_rq(cfs_rq);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
#else
 | 
					
 | 
				
			||||||
 | 
					static inline u64 default_cfs_period(void);
 | 
				
			||||||
 | 
					static int do_sched_cfs_period_timer(struct cfs_bandwidth *cfs_b, int overrun);
 | 
				
			||||||
 | 
					static void do_sched_cfs_slack_timer(struct cfs_bandwidth *cfs_b);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static enum hrtimer_restart sched_cfs_slack_timer(struct hrtimer *timer)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct cfs_bandwidth *cfs_b =
 | 
				
			||||||
 | 
							container_of(timer, struct cfs_bandwidth, slack_timer);
 | 
				
			||||||
 | 
						do_sched_cfs_slack_timer(cfs_b);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return HRTIMER_NORESTART;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static enum hrtimer_restart sched_cfs_period_timer(struct hrtimer *timer)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct cfs_bandwidth *cfs_b =
 | 
				
			||||||
 | 
							container_of(timer, struct cfs_bandwidth, period_timer);
 | 
				
			||||||
 | 
						ktime_t now;
 | 
				
			||||||
 | 
						int overrun;
 | 
				
			||||||
 | 
						int idle = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for (;;) {
 | 
				
			||||||
 | 
							now = hrtimer_cb_get_time(timer);
 | 
				
			||||||
 | 
							overrun = hrtimer_forward(timer, now, cfs_b->period);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (!overrun)
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							idle = do_sched_cfs_period_timer(cfs_b, overrun);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return idle ? HRTIMER_NORESTART : HRTIMER_RESTART;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void init_cfs_bandwidth(struct cfs_bandwidth *cfs_b)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						raw_spin_lock_init(&cfs_b->lock);
 | 
				
			||||||
 | 
						cfs_b->runtime = 0;
 | 
				
			||||||
 | 
						cfs_b->quota = RUNTIME_INF;
 | 
				
			||||||
 | 
						cfs_b->period = ns_to_ktime(default_cfs_period());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						INIT_LIST_HEAD(&cfs_b->throttled_cfs_rq);
 | 
				
			||||||
 | 
						hrtimer_init(&cfs_b->period_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
 | 
				
			||||||
 | 
						cfs_b->period_timer.function = sched_cfs_period_timer;
 | 
				
			||||||
 | 
						hrtimer_init(&cfs_b->slack_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
 | 
				
			||||||
 | 
						cfs_b->slack_timer.function = sched_cfs_slack_timer;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void init_cfs_rq_runtime(struct cfs_rq *cfs_rq)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						cfs_rq->runtime_enabled = 0;
 | 
				
			||||||
 | 
						INIT_LIST_HEAD(&cfs_rq->throttled_list);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* requires cfs_b->lock, may release to reprogram timer */
 | 
				
			||||||
 | 
					void __start_cfs_bandwidth(struct cfs_bandwidth *cfs_b)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						/*
 | 
				
			||||||
 | 
						 * The timer may be active because we're trying to set a new bandwidth
 | 
				
			||||||
 | 
						 * period or because we're racing with the tear-down path
 | 
				
			||||||
 | 
						 * (timer_active==0 becomes visible before the hrtimer call-back
 | 
				
			||||||
 | 
						 * terminates).  In either case we ensure that it's re-programmed
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						while (unlikely(hrtimer_active(&cfs_b->period_timer))) {
 | 
				
			||||||
 | 
							raw_spin_unlock(&cfs_b->lock);
 | 
				
			||||||
 | 
							/* ensure cfs_b->lock is available while we wait */
 | 
				
			||||||
 | 
							hrtimer_cancel(&cfs_b->period_timer);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							raw_spin_lock(&cfs_b->lock);
 | 
				
			||||||
 | 
							/* if someone else restarted the timer then we're done */
 | 
				
			||||||
 | 
							if (cfs_b->timer_active)
 | 
				
			||||||
 | 
								return;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						cfs_b->timer_active = 1;
 | 
				
			||||||
 | 
						start_bandwidth_timer(&cfs_b->period_timer, cfs_b->period);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void destroy_cfs_bandwidth(struct cfs_bandwidth *cfs_b)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						hrtimer_cancel(&cfs_b->period_timer);
 | 
				
			||||||
 | 
						hrtimer_cancel(&cfs_b->slack_timer);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void unthrottle_offline_cfs_rqs(struct rq *rq)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct cfs_rq *cfs_rq;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for_each_leaf_cfs_rq(rq, cfs_rq) {
 | 
				
			||||||
 | 
							struct cfs_bandwidth *cfs_b = tg_cfs_bandwidth(cfs_rq->tg);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (!cfs_rq->runtime_enabled)
 | 
				
			||||||
 | 
								continue;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							/*
 | 
				
			||||||
 | 
							 * clock_task is not advancing so we just need to make sure
 | 
				
			||||||
 | 
							 * there's some valid quota amount
 | 
				
			||||||
 | 
							 */
 | 
				
			||||||
 | 
							cfs_rq->runtime_remaining = cfs_b->quota;
 | 
				
			||||||
 | 
							if (cfs_rq_throttled(cfs_rq))
 | 
				
			||||||
 | 
								unthrottle_cfs_rq(cfs_rq);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#else /* CONFIG_CFS_BANDWIDTH */
 | 
				
			||||||
static void account_cfs_rq_runtime(struct cfs_rq *cfs_rq,
 | 
					static void account_cfs_rq_runtime(struct cfs_rq *cfs_rq,
 | 
				
			||||||
				     unsigned long delta_exec) {}
 | 
									     unsigned long delta_exec) {}
 | 
				
			||||||
static void check_cfs_rq_runtime(struct cfs_rq *cfs_rq) {}
 | 
					static void check_cfs_rq_runtime(struct cfs_rq *cfs_rq) {}
 | 
				
			||||||
| 
						 | 
					@ -1861,8 +2107,22 @@ static inline int throttled_lb_pair(struct task_group *tg,
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void init_cfs_bandwidth(struct cfs_bandwidth *cfs_b) {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef CONFIG_FAIR_GROUP_SCHED
 | 
				
			||||||
 | 
					static void init_cfs_rq_runtime(struct cfs_rq *cfs_rq) {}
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static inline struct cfs_bandwidth *tg_cfs_bandwidth(struct task_group *tg)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return NULL;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					static inline void destroy_cfs_bandwidth(struct cfs_bandwidth *cfs_b) {}
 | 
				
			||||||
 | 
					void unthrottle_offline_cfs_rqs(struct rq *rq) {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif /* CONFIG_CFS_BANDWIDTH */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**************************************************
 | 
					/**************************************************
 | 
				
			||||||
 * CFS operations on tasks:
 | 
					 * CFS operations on tasks:
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
| 
						 | 
					@ -2029,6 +2289,61 @@ static void dequeue_task_fair(struct rq *rq, struct task_struct *p, int flags)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef CONFIG_SMP
 | 
					#ifdef CONFIG_SMP
 | 
				
			||||||
 | 
					/* Used instead of source_load when we know the type == 0 */
 | 
				
			||||||
 | 
					static unsigned long weighted_cpuload(const int cpu)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return cpu_rq(cpu)->load.weight;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Return a low guess at the load of a migration-source cpu weighted
 | 
				
			||||||
 | 
					 * according to the scheduling class and "nice" value.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * We want to under-estimate the load of migration sources, to
 | 
				
			||||||
 | 
					 * balance conservatively.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static unsigned long source_load(int cpu, int type)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct rq *rq = cpu_rq(cpu);
 | 
				
			||||||
 | 
						unsigned long total = weighted_cpuload(cpu);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (type == 0 || !sched_feat(LB_BIAS))
 | 
				
			||||||
 | 
							return total;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return min(rq->cpu_load[type-1], total);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Return a high guess at the load of a migration-target cpu weighted
 | 
				
			||||||
 | 
					 * according to the scheduling class and "nice" value.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static unsigned long target_load(int cpu, int type)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct rq *rq = cpu_rq(cpu);
 | 
				
			||||||
 | 
						unsigned long total = weighted_cpuload(cpu);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (type == 0 || !sched_feat(LB_BIAS))
 | 
				
			||||||
 | 
							return total;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return max(rq->cpu_load[type-1], total);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static unsigned long power_of(int cpu)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return cpu_rq(cpu)->cpu_power;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static unsigned long cpu_avg_load_per_task(int cpu)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct rq *rq = cpu_rq(cpu);
 | 
				
			||||||
 | 
						unsigned long nr_running = ACCESS_ONCE(rq->nr_running);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (nr_running)
 | 
				
			||||||
 | 
							return rq->load.weight / nr_running;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void task_waking_fair(struct task_struct *p)
 | 
					static void task_waking_fair(struct task_struct *p)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
| 
						 | 
					@ -2782,6 +3097,38 @@ static void pull_task(struct rq *src_rq, struct task_struct *p,
 | 
				
			||||||
	check_preempt_curr(this_rq, p, 0);
 | 
						check_preempt_curr(this_rq, p, 0);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Is this task likely cache-hot:
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static int
 | 
				
			||||||
 | 
					task_hot(struct task_struct *p, u64 now, struct sched_domain *sd)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						s64 delta;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (p->sched_class != &fair_sched_class)
 | 
				
			||||||
 | 
							return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (unlikely(p->policy == SCHED_IDLE))
 | 
				
			||||||
 | 
							return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/*
 | 
				
			||||||
 | 
						 * Buddy candidates are cache hot:
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						if (sched_feat(CACHE_HOT_BUDDY) && this_rq()->nr_running &&
 | 
				
			||||||
 | 
								(&p->se == cfs_rq_of(&p->se)->next ||
 | 
				
			||||||
 | 
								 &p->se == cfs_rq_of(&p->se)->last))
 | 
				
			||||||
 | 
							return 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (sysctl_sched_migration_cost == -1)
 | 
				
			||||||
 | 
							return 1;
 | 
				
			||||||
 | 
						if (sysctl_sched_migration_cost == 0)
 | 
				
			||||||
 | 
							return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						delta = now - p->se.exec_start;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return delta < (s64)sysctl_sched_migration_cost;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * can_migrate_task - may task p from runqueue rq be migrated to this_cpu?
 | 
					 * can_migrate_task - may task p from runqueue rq be migrated to this_cpu?
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
| 
						 | 
					@ -3161,15 +3508,6 @@ struct sg_lb_stats {
 | 
				
			||||||
	int group_has_capacity; /* Is there extra capacity in the group? */
 | 
						int group_has_capacity; /* Is there extra capacity in the group? */
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * group_first_cpu - Returns the first cpu in the cpumask of a sched_group.
 | 
					 | 
				
			||||||
 * @group: The group whose first cpu is to be returned.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
static inline unsigned int group_first_cpu(struct sched_group *group)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	return cpumask_first(sched_group_cpus(group));
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * get_sd_load_idx - Obtain the load index for a given sched domain.
 | 
					 * get_sd_load_idx - Obtain the load index for a given sched domain.
 | 
				
			||||||
 * @sd: The sched_domain whose load_idx is to be obtained.
 | 
					 * @sd: The sched_domain whose load_idx is to be obtained.
 | 
				
			||||||
| 
						 | 
					@ -3419,7 +3757,7 @@ static void update_cpu_power(struct sched_domain *sd, int cpu)
 | 
				
			||||||
	sdg->sgp->power = power;
 | 
						sdg->sgp->power = power;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void update_group_power(struct sched_domain *sd, int cpu)
 | 
					void update_group_power(struct sched_domain *sd, int cpu)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct sched_domain *child = sd->child;
 | 
						struct sched_domain *child = sd->child;
 | 
				
			||||||
	struct sched_group *group, *sdg = sd->groups;
 | 
						struct sched_group *group, *sdg = sd->groups;
 | 
				
			||||||
| 
						 | 
					@ -3685,11 +4023,6 @@ static inline void update_sd_lb_stats(struct sched_domain *sd, int this_cpu,
 | 
				
			||||||
	} while (sg != sd->groups);
 | 
						} while (sg != sd->groups);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int __weak arch_sd_sibling_asym_packing(void)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
       return 0*SD_ASYM_PACKING;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * check_asym_packing - Check to see if the group is packed into the
 | 
					 * check_asym_packing - Check to see if the group is packed into the
 | 
				
			||||||
 *			sched doman.
 | 
					 *			sched doman.
 | 
				
			||||||
| 
						 | 
					@ -4053,7 +4386,7 @@ find_busiest_queue(struct sched_domain *sd, struct sched_group *group,
 | 
				
			||||||
#define MAX_PINNED_INTERVAL	512
 | 
					#define MAX_PINNED_INTERVAL	512
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Working cpumask for load_balance and load_balance_newidle. */
 | 
					/* Working cpumask for load_balance and load_balance_newidle. */
 | 
				
			||||||
static DEFINE_PER_CPU(cpumask_var_t, load_balance_tmpmask);
 | 
					DEFINE_PER_CPU(cpumask_var_t, load_balance_tmpmask);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int need_active_balance(struct sched_domain *sd, int idle,
 | 
					static int need_active_balance(struct sched_domain *sd, int idle,
 | 
				
			||||||
			       int busiest_cpu, int this_cpu)
 | 
								       int busiest_cpu, int this_cpu)
 | 
				
			||||||
| 
						 | 
					@ -4256,7 +4589,7 @@ static int load_balance(int this_cpu, struct rq *this_rq,
 | 
				
			||||||
 * idle_balance is called by schedule() if this_cpu is about to become
 | 
					 * idle_balance is called by schedule() if this_cpu is about to become
 | 
				
			||||||
 * idle. Attempts to pull tasks from other CPUs.
 | 
					 * idle. Attempts to pull tasks from other CPUs.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
static void idle_balance(int this_cpu, struct rq *this_rq)
 | 
					void idle_balance(int this_cpu, struct rq *this_rq)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct sched_domain *sd;
 | 
						struct sched_domain *sd;
 | 
				
			||||||
	int pulled_task = 0;
 | 
						int pulled_task = 0;
 | 
				
			||||||
| 
						 | 
					@ -4631,7 +4964,7 @@ static unsigned long __read_mostly max_load_balance_interval = HZ/10;
 | 
				
			||||||
 * Scale the max load_balance interval with the number of CPUs in the system.
 | 
					 * Scale the max load_balance interval with the number of CPUs in the system.
 | 
				
			||||||
 * This trades load-balance latency on larger machines for less cross talk.
 | 
					 * This trades load-balance latency on larger machines for less cross talk.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
static void update_max_interval(void)
 | 
					void update_max_interval(void)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	max_load_balance_interval = HZ*num_online_cpus()/10;
 | 
						max_load_balance_interval = HZ*num_online_cpus()/10;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -4833,7 +5166,7 @@ static inline int on_null_domain(int cpu)
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * Trigger the SCHED_SOFTIRQ if it is time to do periodic load balancing.
 | 
					 * Trigger the SCHED_SOFTIRQ if it is time to do periodic load balancing.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
static inline void trigger_load_balance(struct rq *rq, int cpu)
 | 
					void trigger_load_balance(struct rq *rq, int cpu)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	/* Don't need to rebalance while attached to NULL domain */
 | 
						/* Don't need to rebalance while attached to NULL domain */
 | 
				
			||||||
	if (time_after_eq(jiffies, rq->next_balance) &&
 | 
						if (time_after_eq(jiffies, rq->next_balance) &&
 | 
				
			||||||
| 
						 | 
					@ -4855,15 +5188,6 @@ static void rq_offline_fair(struct rq *rq)
 | 
				
			||||||
	update_sysctl();
 | 
						update_sysctl();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#else	/* CONFIG_SMP */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/*
 | 
					 | 
				
			||||||
 * on UP we do not need to balance between CPUs:
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
static inline void idle_balance(int cpu, struct rq *rq)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#endif /* CONFIG_SMP */
 | 
					#endif /* CONFIG_SMP */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
| 
						 | 
					@ -5006,6 +5330,16 @@ static void set_curr_task_fair(struct rq *rq)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void init_cfs_rq(struct cfs_rq *cfs_rq)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						cfs_rq->tasks_timeline = RB_ROOT;
 | 
				
			||||||
 | 
						INIT_LIST_HEAD(&cfs_rq->tasks);
 | 
				
			||||||
 | 
						cfs_rq->min_vruntime = (u64)(-(1LL << 20));
 | 
				
			||||||
 | 
					#ifndef CONFIG_64BIT
 | 
				
			||||||
 | 
						cfs_rq->min_vruntime_copy = cfs_rq->min_vruntime;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef CONFIG_FAIR_GROUP_SCHED
 | 
					#ifdef CONFIG_FAIR_GROUP_SCHED
 | 
				
			||||||
static void task_move_group_fair(struct task_struct *p, int on_rq)
 | 
					static void task_move_group_fair(struct task_struct *p, int on_rq)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
| 
						 | 
					@ -5028,7 +5362,161 @@ static void task_move_group_fair(struct task_struct *p, int on_rq)
 | 
				
			||||||
	if (!on_rq)
 | 
						if (!on_rq)
 | 
				
			||||||
		p->se.vruntime += cfs_rq_of(&p->se)->min_vruntime;
 | 
							p->se.vruntime += cfs_rq_of(&p->se)->min_vruntime;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void free_fair_sched_group(struct task_group *tg)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						destroy_cfs_bandwidth(tg_cfs_bandwidth(tg));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for_each_possible_cpu(i) {
 | 
				
			||||||
 | 
							if (tg->cfs_rq)
 | 
				
			||||||
 | 
								kfree(tg->cfs_rq[i]);
 | 
				
			||||||
 | 
							if (tg->se)
 | 
				
			||||||
 | 
								kfree(tg->se[i]);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						kfree(tg->cfs_rq);
 | 
				
			||||||
 | 
						kfree(tg->se);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int alloc_fair_sched_group(struct task_group *tg, struct task_group *parent)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct cfs_rq *cfs_rq;
 | 
				
			||||||
 | 
						struct sched_entity *se;
 | 
				
			||||||
 | 
						int i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						tg->cfs_rq = kzalloc(sizeof(cfs_rq) * nr_cpu_ids, GFP_KERNEL);
 | 
				
			||||||
 | 
						if (!tg->cfs_rq)
 | 
				
			||||||
 | 
							goto err;
 | 
				
			||||||
 | 
						tg->se = kzalloc(sizeof(se) * nr_cpu_ids, GFP_KERNEL);
 | 
				
			||||||
 | 
						if (!tg->se)
 | 
				
			||||||
 | 
							goto err;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						tg->shares = NICE_0_LOAD;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						init_cfs_bandwidth(tg_cfs_bandwidth(tg));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for_each_possible_cpu(i) {
 | 
				
			||||||
 | 
							cfs_rq = kzalloc_node(sizeof(struct cfs_rq),
 | 
				
			||||||
 | 
									      GFP_KERNEL, cpu_to_node(i));
 | 
				
			||||||
 | 
							if (!cfs_rq)
 | 
				
			||||||
 | 
								goto err;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							se = kzalloc_node(sizeof(struct sched_entity),
 | 
				
			||||||
 | 
									  GFP_KERNEL, cpu_to_node(i));
 | 
				
			||||||
 | 
							if (!se)
 | 
				
			||||||
 | 
								goto err_free_rq;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							init_cfs_rq(cfs_rq);
 | 
				
			||||||
 | 
							init_tg_cfs_entry(tg, cfs_rq, se, i, parent->se[i]);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					err_free_rq:
 | 
				
			||||||
 | 
						kfree(cfs_rq);
 | 
				
			||||||
 | 
					err:
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void unregister_fair_sched_group(struct task_group *tg, int cpu)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct rq *rq = cpu_rq(cpu);
 | 
				
			||||||
 | 
						unsigned long flags;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/*
 | 
				
			||||||
 | 
						* Only empty task groups can be destroyed; so we can speculatively
 | 
				
			||||||
 | 
						* check on_list without danger of it being re-added.
 | 
				
			||||||
 | 
						*/
 | 
				
			||||||
 | 
						if (!tg->cfs_rq[cpu]->on_list)
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						raw_spin_lock_irqsave(&rq->lock, flags);
 | 
				
			||||||
 | 
						list_del_leaf_cfs_rq(tg->cfs_rq[cpu]);
 | 
				
			||||||
 | 
						raw_spin_unlock_irqrestore(&rq->lock, flags);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void init_tg_cfs_entry(struct task_group *tg, struct cfs_rq *cfs_rq,
 | 
				
			||||||
 | 
								struct sched_entity *se, int cpu,
 | 
				
			||||||
 | 
								struct sched_entity *parent)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct rq *rq = cpu_rq(cpu);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						cfs_rq->tg = tg;
 | 
				
			||||||
 | 
						cfs_rq->rq = rq;
 | 
				
			||||||
 | 
					#ifdef CONFIG_SMP
 | 
				
			||||||
 | 
						/* allow initial update_cfs_load() to truncate */
 | 
				
			||||||
 | 
						cfs_rq->load_stamp = 1;
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
						init_cfs_rq_runtime(cfs_rq);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						tg->cfs_rq[cpu] = cfs_rq;
 | 
				
			||||||
 | 
						tg->se[cpu] = se;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* se could be NULL for root_task_group */
 | 
				
			||||||
 | 
						if (!se)
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!parent)
 | 
				
			||||||
 | 
							se->cfs_rq = &rq->cfs;
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
 | 
							se->cfs_rq = parent->my_q;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						se->my_q = cfs_rq;
 | 
				
			||||||
 | 
						update_load_set(&se->load, 0);
 | 
				
			||||||
 | 
						se->parent = parent;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static DEFINE_MUTEX(shares_mutex);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int sched_group_set_shares(struct task_group *tg, unsigned long shares)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int i;
 | 
				
			||||||
 | 
						unsigned long flags;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/*
 | 
				
			||||||
 | 
						 * We can't change the weight of the root cgroup.
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						if (!tg->se[0])
 | 
				
			||||||
 | 
							return -EINVAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						shares = clamp(shares, scale_load(MIN_SHARES), scale_load(MAX_SHARES));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						mutex_lock(&shares_mutex);
 | 
				
			||||||
 | 
						if (tg->shares == shares)
 | 
				
			||||||
 | 
							goto done;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						tg->shares = shares;
 | 
				
			||||||
 | 
						for_each_possible_cpu(i) {
 | 
				
			||||||
 | 
							struct rq *rq = cpu_rq(i);
 | 
				
			||||||
 | 
							struct sched_entity *se;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							se = tg->se[i];
 | 
				
			||||||
 | 
							/* Propagate contribution to hierarchy */
 | 
				
			||||||
 | 
							raw_spin_lock_irqsave(&rq->lock, flags);
 | 
				
			||||||
 | 
							for_each_sched_entity(se)
 | 
				
			||||||
 | 
								update_cfs_shares(group_cfs_rq(se));
 | 
				
			||||||
 | 
							raw_spin_unlock_irqrestore(&rq->lock, flags);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					done:
 | 
				
			||||||
 | 
						mutex_unlock(&shares_mutex);
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#else /* CONFIG_FAIR_GROUP_SCHED */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void free_fair_sched_group(struct task_group *tg) { }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int alloc_fair_sched_group(struct task_group *tg, struct task_group *parent)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return 1;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void unregister_fair_sched_group(struct task_group *tg, int cpu) { }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif /* CONFIG_FAIR_GROUP_SCHED */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static unsigned int get_rr_interval_fair(struct rq *rq, struct task_struct *task)
 | 
					static unsigned int get_rr_interval_fair(struct rq *rq, struct task_struct *task)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
| 
						 | 
					@ -5048,7 +5536,7 @@ static unsigned int get_rr_interval_fair(struct rq *rq, struct task_struct *task
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * All the scheduling class methods:
 | 
					 * All the scheduling class methods:
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
static const struct sched_class fair_sched_class = {
 | 
					const struct sched_class fair_sched_class = {
 | 
				
			||||||
	.next			= &idle_sched_class,
 | 
						.next			= &idle_sched_class,
 | 
				
			||||||
	.enqueue_task		= enqueue_task_fair,
 | 
						.enqueue_task		= enqueue_task_fair,
 | 
				
			||||||
	.dequeue_task		= dequeue_task_fair,
 | 
						.dequeue_task		= dequeue_task_fair,
 | 
				
			||||||
| 
						 | 
					@ -5085,7 +5573,7 @@ static const struct sched_class fair_sched_class = {
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef CONFIG_SCHED_DEBUG
 | 
					#ifdef CONFIG_SCHED_DEBUG
 | 
				
			||||||
static void print_cfs_stats(struct seq_file *m, int cpu)
 | 
					void print_cfs_stats(struct seq_file *m, int cpu)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct cfs_rq *cfs_rq;
 | 
						struct cfs_rq *cfs_rq;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -5095,3 +5583,19 @@ static void print_cfs_stats(struct seq_file *m, int cpu)
 | 
				
			||||||
	rcu_read_unlock();
 | 
						rcu_read_unlock();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					__init void init_sched_fair_class(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					#ifdef CONFIG_SMP
 | 
				
			||||||
 | 
						open_softirq(SCHED_SOFTIRQ, run_rebalance_domains);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef CONFIG_NO_HZ
 | 
				
			||||||
 | 
						zalloc_cpumask_var(&nohz.idle_cpus_mask, GFP_NOWAIT);
 | 
				
			||||||
 | 
						alloc_cpumask_var(&nohz.grp_idle_mask, GFP_NOWAIT);
 | 
				
			||||||
 | 
						atomic_set(&nohz.load_balancer, nr_cpu_ids);
 | 
				
			||||||
 | 
						atomic_set(&nohz.first_pick_cpu, nr_cpu_ids);
 | 
				
			||||||
 | 
						atomic_set(&nohz.second_pick_cpu, nr_cpu_ids);
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					#endif /* SMP */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,3 +1,5 @@
 | 
				
			||||||
 | 
					#include "sched.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * idle-task scheduling class.
 | 
					 * idle-task scheduling class.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
| 
						 | 
					@ -71,7 +73,7 @@ static unsigned int get_rr_interval_idle(struct rq *rq, struct task_struct *task
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * Simple, special scheduling class for the per-CPU idle tasks:
 | 
					 * Simple, special scheduling class for the per-CPU idle tasks:
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
static const struct sched_class idle_sched_class = {
 | 
					const struct sched_class idle_sched_class = {
 | 
				
			||||||
	/* .next is NULL */
 | 
						/* .next is NULL */
 | 
				
			||||||
	/* no enqueue/yield_task for idle tasks */
 | 
						/* no enqueue/yield_task for idle tasks */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -3,7 +3,92 @@
 | 
				
			||||||
 * policies)
 | 
					 * policies)
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "sched.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <linux/slab.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int do_sched_rt_period_timer(struct rt_bandwidth *rt_b, int overrun);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct rt_bandwidth def_rt_bandwidth;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static enum hrtimer_restart sched_rt_period_timer(struct hrtimer *timer)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct rt_bandwidth *rt_b =
 | 
				
			||||||
 | 
							container_of(timer, struct rt_bandwidth, rt_period_timer);
 | 
				
			||||||
 | 
						ktime_t now;
 | 
				
			||||||
 | 
						int overrun;
 | 
				
			||||||
 | 
						int idle = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for (;;) {
 | 
				
			||||||
 | 
							now = hrtimer_cb_get_time(timer);
 | 
				
			||||||
 | 
							overrun = hrtimer_forward(timer, now, rt_b->rt_period);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (!overrun)
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							idle = do_sched_rt_period_timer(rt_b, overrun);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return idle ? HRTIMER_NORESTART : HRTIMER_RESTART;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void init_rt_bandwidth(struct rt_bandwidth *rt_b, u64 period, u64 runtime)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						rt_b->rt_period = ns_to_ktime(period);
 | 
				
			||||||
 | 
						rt_b->rt_runtime = runtime;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						raw_spin_lock_init(&rt_b->rt_runtime_lock);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						hrtimer_init(&rt_b->rt_period_timer,
 | 
				
			||||||
 | 
								CLOCK_MONOTONIC, HRTIMER_MODE_REL);
 | 
				
			||||||
 | 
						rt_b->rt_period_timer.function = sched_rt_period_timer;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void start_rt_bandwidth(struct rt_bandwidth *rt_b)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						if (!rt_bandwidth_enabled() || rt_b->rt_runtime == RUNTIME_INF)
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (hrtimer_active(&rt_b->rt_period_timer))
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						raw_spin_lock(&rt_b->rt_runtime_lock);
 | 
				
			||||||
 | 
						start_bandwidth_timer(&rt_b->rt_period_timer, rt_b->rt_period);
 | 
				
			||||||
 | 
						raw_spin_unlock(&rt_b->rt_runtime_lock);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void init_rt_rq(struct rt_rq *rt_rq, struct rq *rq)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct rt_prio_array *array;
 | 
				
			||||||
 | 
						int i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						array = &rt_rq->active;
 | 
				
			||||||
 | 
						for (i = 0; i < MAX_RT_PRIO; i++) {
 | 
				
			||||||
 | 
							INIT_LIST_HEAD(array->queue + i);
 | 
				
			||||||
 | 
							__clear_bit(i, array->bitmap);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						/* delimiter for bitsearch: */
 | 
				
			||||||
 | 
						__set_bit(MAX_RT_PRIO, array->bitmap);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if defined CONFIG_SMP
 | 
				
			||||||
 | 
						rt_rq->highest_prio.curr = MAX_RT_PRIO;
 | 
				
			||||||
 | 
						rt_rq->highest_prio.next = MAX_RT_PRIO;
 | 
				
			||||||
 | 
						rt_rq->rt_nr_migratory = 0;
 | 
				
			||||||
 | 
						rt_rq->overloaded = 0;
 | 
				
			||||||
 | 
						plist_head_init(&rt_rq->pushable_tasks);
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						rt_rq->rt_time = 0;
 | 
				
			||||||
 | 
						rt_rq->rt_throttled = 0;
 | 
				
			||||||
 | 
						rt_rq->rt_runtime = 0;
 | 
				
			||||||
 | 
						raw_spin_lock_init(&rt_rq->rt_runtime_lock);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef CONFIG_RT_GROUP_SCHED
 | 
					#ifdef CONFIG_RT_GROUP_SCHED
 | 
				
			||||||
 | 
					static void destroy_rt_bandwidth(struct rt_bandwidth *rt_b)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						hrtimer_cancel(&rt_b->rt_period_timer);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define rt_entity_is_task(rt_se) (!(rt_se)->my_q)
 | 
					#define rt_entity_is_task(rt_se) (!(rt_se)->my_q)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -25,6 +110,91 @@ static inline struct rt_rq *rt_rq_of_se(struct sched_rt_entity *rt_se)
 | 
				
			||||||
	return rt_se->rt_rq;
 | 
						return rt_se->rt_rq;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void free_rt_sched_group(struct task_group *tg)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (tg->rt_se)
 | 
				
			||||||
 | 
							destroy_rt_bandwidth(&tg->rt_bandwidth);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for_each_possible_cpu(i) {
 | 
				
			||||||
 | 
							if (tg->rt_rq)
 | 
				
			||||||
 | 
								kfree(tg->rt_rq[i]);
 | 
				
			||||||
 | 
							if (tg->rt_se)
 | 
				
			||||||
 | 
								kfree(tg->rt_se[i]);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						kfree(tg->rt_rq);
 | 
				
			||||||
 | 
						kfree(tg->rt_se);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void init_tg_rt_entry(struct task_group *tg, struct rt_rq *rt_rq,
 | 
				
			||||||
 | 
							struct sched_rt_entity *rt_se, int cpu,
 | 
				
			||||||
 | 
							struct sched_rt_entity *parent)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct rq *rq = cpu_rq(cpu);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						rt_rq->highest_prio.curr = MAX_RT_PRIO;
 | 
				
			||||||
 | 
						rt_rq->rt_nr_boosted = 0;
 | 
				
			||||||
 | 
						rt_rq->rq = rq;
 | 
				
			||||||
 | 
						rt_rq->tg = tg;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						tg->rt_rq[cpu] = rt_rq;
 | 
				
			||||||
 | 
						tg->rt_se[cpu] = rt_se;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!rt_se)
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!parent)
 | 
				
			||||||
 | 
							rt_se->rt_rq = &rq->rt;
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
 | 
							rt_se->rt_rq = parent->my_q;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						rt_se->my_q = rt_rq;
 | 
				
			||||||
 | 
						rt_se->parent = parent;
 | 
				
			||||||
 | 
						INIT_LIST_HEAD(&rt_se->run_list);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int alloc_rt_sched_group(struct task_group *tg, struct task_group *parent)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct rt_rq *rt_rq;
 | 
				
			||||||
 | 
						struct sched_rt_entity *rt_se;
 | 
				
			||||||
 | 
						int i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						tg->rt_rq = kzalloc(sizeof(rt_rq) * nr_cpu_ids, GFP_KERNEL);
 | 
				
			||||||
 | 
						if (!tg->rt_rq)
 | 
				
			||||||
 | 
							goto err;
 | 
				
			||||||
 | 
						tg->rt_se = kzalloc(sizeof(rt_se) * nr_cpu_ids, GFP_KERNEL);
 | 
				
			||||||
 | 
						if (!tg->rt_se)
 | 
				
			||||||
 | 
							goto err;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						init_rt_bandwidth(&tg->rt_bandwidth,
 | 
				
			||||||
 | 
								ktime_to_ns(def_rt_bandwidth.rt_period), 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for_each_possible_cpu(i) {
 | 
				
			||||||
 | 
							rt_rq = kzalloc_node(sizeof(struct rt_rq),
 | 
				
			||||||
 | 
									     GFP_KERNEL, cpu_to_node(i));
 | 
				
			||||||
 | 
							if (!rt_rq)
 | 
				
			||||||
 | 
								goto err;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							rt_se = kzalloc_node(sizeof(struct sched_rt_entity),
 | 
				
			||||||
 | 
									     GFP_KERNEL, cpu_to_node(i));
 | 
				
			||||||
 | 
							if (!rt_se)
 | 
				
			||||||
 | 
								goto err_free_rq;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							init_rt_rq(rt_rq, cpu_rq(i));
 | 
				
			||||||
 | 
							rt_rq->rt_runtime = tg->rt_bandwidth.rt_runtime;
 | 
				
			||||||
 | 
							init_tg_rt_entry(tg, rt_rq, rt_se, i, parent->rt_se[i]);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					err_free_rq:
 | 
				
			||||||
 | 
						kfree(rt_rq);
 | 
				
			||||||
 | 
					err:
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#else /* CONFIG_RT_GROUP_SCHED */
 | 
					#else /* CONFIG_RT_GROUP_SCHED */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define rt_entity_is_task(rt_se) (1)
 | 
					#define rt_entity_is_task(rt_se) (1)
 | 
				
			||||||
| 
						 | 
					@ -47,6 +217,12 @@ static inline struct rt_rq *rt_rq_of_se(struct sched_rt_entity *rt_se)
 | 
				
			||||||
	return &rq->rt;
 | 
						return &rq->rt;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void free_rt_sched_group(struct task_group *tg) { }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int alloc_rt_sched_group(struct task_group *tg, struct task_group *parent)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return 1;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
#endif /* CONFIG_RT_GROUP_SCHED */
 | 
					#endif /* CONFIG_RT_GROUP_SCHED */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef CONFIG_SMP
 | 
					#ifdef CONFIG_SMP
 | 
				
			||||||
| 
						 | 
					@ -556,6 +732,28 @@ static void enable_runtime(struct rq *rq)
 | 
				
			||||||
	raw_spin_unlock_irqrestore(&rq->lock, flags);
 | 
						raw_spin_unlock_irqrestore(&rq->lock, flags);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int update_runtime(struct notifier_block *nfb, unsigned long action, void *hcpu)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int cpu = (int)(long)hcpu;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						switch (action) {
 | 
				
			||||||
 | 
						case CPU_DOWN_PREPARE:
 | 
				
			||||||
 | 
						case CPU_DOWN_PREPARE_FROZEN:
 | 
				
			||||||
 | 
							disable_runtime(cpu_rq(cpu));
 | 
				
			||||||
 | 
							return NOTIFY_OK;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						case CPU_DOWN_FAILED:
 | 
				
			||||||
 | 
						case CPU_DOWN_FAILED_FROZEN:
 | 
				
			||||||
 | 
						case CPU_ONLINE:
 | 
				
			||||||
 | 
						case CPU_ONLINE_FROZEN:
 | 
				
			||||||
 | 
							enable_runtime(cpu_rq(cpu));
 | 
				
			||||||
 | 
							return NOTIFY_OK;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						default:
 | 
				
			||||||
 | 
							return NOTIFY_DONE;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int balance_runtime(struct rt_rq *rt_rq)
 | 
					static int balance_runtime(struct rt_rq *rt_rq)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	int more = 0;
 | 
						int more = 0;
 | 
				
			||||||
| 
						 | 
					@ -1178,8 +1376,6 @@ static void put_prev_task_rt(struct rq *rq, struct task_struct *p)
 | 
				
			||||||
/* Only try algorithms three times */
 | 
					/* Only try algorithms three times */
 | 
				
			||||||
#define RT_MAX_TRIES 3
 | 
					#define RT_MAX_TRIES 3
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void deactivate_task(struct rq *rq, struct task_struct *p, int sleep);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static int pick_rt_task(struct rq *rq, struct task_struct *p, int cpu)
 | 
					static int pick_rt_task(struct rq *rq, struct task_struct *p, int cpu)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	if (!task_running(rq, p) &&
 | 
						if (!task_running(rq, p) &&
 | 
				
			||||||
| 
						 | 
					@ -1653,14 +1849,15 @@ static void switched_from_rt(struct rq *rq, struct task_struct *p)
 | 
				
			||||||
		pull_rt_task(rq);
 | 
							pull_rt_task(rq);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static inline void init_sched_rt_class(void)
 | 
					void init_sched_rt_class(void)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	unsigned int i;
 | 
						unsigned int i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for_each_possible_cpu(i)
 | 
						for_each_possible_cpu(i) {
 | 
				
			||||||
		zalloc_cpumask_var_node(&per_cpu(local_cpu_mask, i),
 | 
							zalloc_cpumask_var_node(&per_cpu(local_cpu_mask, i),
 | 
				
			||||||
					GFP_KERNEL, cpu_to_node(i));
 | 
										GFP_KERNEL, cpu_to_node(i));
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
#endif /* CONFIG_SMP */
 | 
					#endif /* CONFIG_SMP */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
| 
						 | 
					@ -1800,7 +1997,7 @@ static unsigned int get_rr_interval_rt(struct rq *rq, struct task_struct *task)
 | 
				
			||||||
		return 0;
 | 
							return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static const struct sched_class rt_sched_class = {
 | 
					const struct sched_class rt_sched_class = {
 | 
				
			||||||
	.next			= &fair_sched_class,
 | 
						.next			= &fair_sched_class,
 | 
				
			||||||
	.enqueue_task		= enqueue_task_rt,
 | 
						.enqueue_task		= enqueue_task_rt,
 | 
				
			||||||
	.dequeue_task		= dequeue_task_rt,
 | 
						.dequeue_task		= dequeue_task_rt,
 | 
				
			||||||
| 
						 | 
					@ -1835,7 +2032,7 @@ static const struct sched_class rt_sched_class = {
 | 
				
			||||||
#ifdef CONFIG_SCHED_DEBUG
 | 
					#ifdef CONFIG_SCHED_DEBUG
 | 
				
			||||||
extern void print_rt_rq(struct seq_file *m, int cpu, struct rt_rq *rt_rq);
 | 
					extern void print_rt_rq(struct seq_file *m, int cpu, struct rt_rq *rt_rq);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void print_rt_stats(struct seq_file *m, int cpu)
 | 
					void print_rt_stats(struct seq_file *m, int cpu)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	rt_rq_iter_t iter;
 | 
						rt_rq_iter_t iter;
 | 
				
			||||||
	struct rt_rq *rt_rq;
 | 
						struct rt_rq *rt_rq;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										111
									
								
								kernel/sched_stats.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										111
									
								
								kernel/sched_stats.c
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,111 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <linux/slab.h>
 | 
				
			||||||
 | 
					#include <linux/fs.h>
 | 
				
			||||||
 | 
					#include <linux/seq_file.h>
 | 
				
			||||||
 | 
					#include <linux/proc_fs.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "sched.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * 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 15
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int show_schedstat(struct seq_file *seq, void *v)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int cpu;
 | 
				
			||||||
 | 
						int mask_len = DIV_ROUND_UP(NR_CPUS, 32) * 9;
 | 
				
			||||||
 | 
						char *mask_str = kmalloc(mask_len, GFP_KERNEL);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (mask_str == NULL)
 | 
				
			||||||
 | 
							return -ENOMEM;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						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 dcount = 0;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							/* runqueue-specific stats */
 | 
				
			||||||
 | 
							seq_printf(seq,
 | 
				
			||||||
 | 
							    "cpu%d %u %u %u %u %u %u %llu %llu %lu",
 | 
				
			||||||
 | 
							    cpu, rq->yld_count,
 | 
				
			||||||
 | 
							    rq->sched_switch, rq->sched_count, rq->sched_goidle,
 | 
				
			||||||
 | 
							    rq->ttwu_count, rq->ttwu_local,
 | 
				
			||||||
 | 
							    rq->rq_cpu_time,
 | 
				
			||||||
 | 
							    rq->rq_sched_info.run_delay, rq->rq_sched_info.pcount);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							seq_printf(seq, "\n");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef CONFIG_SMP
 | 
				
			||||||
 | 
							/* domain-specific stats */
 | 
				
			||||||
 | 
							rcu_read_lock();
 | 
				
			||||||
 | 
							for_each_domain(cpu, sd) {
 | 
				
			||||||
 | 
								enum cpu_idle_type itype;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								cpumask_scnprintf(mask_str, mask_len,
 | 
				
			||||||
 | 
										  sched_domain_span(sd));
 | 
				
			||||||
 | 
								seq_printf(seq, "domain%d %s", dcount++, mask_str);
 | 
				
			||||||
 | 
								for (itype = CPU_IDLE; itype < CPU_MAX_IDLE_TYPES;
 | 
				
			||||||
 | 
										itype++) {
 | 
				
			||||||
 | 
									seq_printf(seq, " %u %u %u %u %u %u %u %u",
 | 
				
			||||||
 | 
									    sd->lb_count[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,
 | 
				
			||||||
 | 
									   " %u %u %u %u %u %u %u %u %u %u %u %u\n",
 | 
				
			||||||
 | 
								    sd->alb_count, sd->alb_failed, sd->alb_pushed,
 | 
				
			||||||
 | 
								    sd->sbe_count, sd->sbe_balanced, sd->sbe_pushed,
 | 
				
			||||||
 | 
								    sd->sbf_count, sd->sbf_balanced, sd->sbf_pushed,
 | 
				
			||||||
 | 
								    sd->ttwu_wake_remote, sd->ttwu_move_affine,
 | 
				
			||||||
 | 
								    sd->ttwu_move_balance);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							rcu_read_unlock();
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						kfree(mask_str);
 | 
				
			||||||
 | 
						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;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static const struct file_operations proc_schedstat_operations = {
 | 
				
			||||||
 | 
						.open    = schedstat_open,
 | 
				
			||||||
 | 
						.read    = seq_read,
 | 
				
			||||||
 | 
						.llseek  = seq_lseek,
 | 
				
			||||||
 | 
						.release = single_release,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int __init proc_schedstat_init(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						proc_create("schedstat", 0, NULL, &proc_schedstat_operations);
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					module_init(proc_schedstat_init);
 | 
				
			||||||
| 
						 | 
					@ -1,108 +1,5 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef CONFIG_SCHEDSTATS
 | 
					#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 15
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static int show_schedstat(struct seq_file *seq, void *v)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	int cpu;
 | 
					 | 
				
			||||||
	int mask_len = DIV_ROUND_UP(NR_CPUS, 32) * 9;
 | 
					 | 
				
			||||||
	char *mask_str = kmalloc(mask_len, GFP_KERNEL);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (mask_str == NULL)
 | 
					 | 
				
			||||||
		return -ENOMEM;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	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 dcount = 0;
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		/* runqueue-specific stats */
 | 
					 | 
				
			||||||
		seq_printf(seq,
 | 
					 | 
				
			||||||
		    "cpu%d %u %u %u %u %u %u %llu %llu %lu",
 | 
					 | 
				
			||||||
		    cpu, rq->yld_count,
 | 
					 | 
				
			||||||
		    rq->sched_switch, rq->sched_count, rq->sched_goidle,
 | 
					 | 
				
			||||||
		    rq->ttwu_count, rq->ttwu_local,
 | 
					 | 
				
			||||||
		    rq->rq_cpu_time,
 | 
					 | 
				
			||||||
		    rq->rq_sched_info.run_delay, rq->rq_sched_info.pcount);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		seq_printf(seq, "\n");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#ifdef CONFIG_SMP
 | 
					 | 
				
			||||||
		/* domain-specific stats */
 | 
					 | 
				
			||||||
		rcu_read_lock();
 | 
					 | 
				
			||||||
		for_each_domain(cpu, sd) {
 | 
					 | 
				
			||||||
			enum cpu_idle_type itype;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			cpumask_scnprintf(mask_str, mask_len,
 | 
					 | 
				
			||||||
					  sched_domain_span(sd));
 | 
					 | 
				
			||||||
			seq_printf(seq, "domain%d %s", dcount++, mask_str);
 | 
					 | 
				
			||||||
			for (itype = CPU_IDLE; itype < CPU_MAX_IDLE_TYPES;
 | 
					 | 
				
			||||||
					itype++) {
 | 
					 | 
				
			||||||
				seq_printf(seq, " %u %u %u %u %u %u %u %u",
 | 
					 | 
				
			||||||
				    sd->lb_count[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,
 | 
					 | 
				
			||||||
				   " %u %u %u %u %u %u %u %u %u %u %u %u\n",
 | 
					 | 
				
			||||||
			    sd->alb_count, sd->alb_failed, sd->alb_pushed,
 | 
					 | 
				
			||||||
			    sd->sbe_count, sd->sbe_balanced, sd->sbe_pushed,
 | 
					 | 
				
			||||||
			    sd->sbf_count, sd->sbf_balanced, sd->sbf_pushed,
 | 
					 | 
				
			||||||
			    sd->ttwu_wake_remote, sd->ttwu_move_affine,
 | 
					 | 
				
			||||||
			    sd->ttwu_move_balance);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		rcu_read_unlock();
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	kfree(mask_str);
 | 
					 | 
				
			||||||
	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;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static const struct file_operations proc_schedstat_operations = {
 | 
					 | 
				
			||||||
	.open    = schedstat_open,
 | 
					 | 
				
			||||||
	.read    = seq_read,
 | 
					 | 
				
			||||||
	.llseek  = seq_lseek,
 | 
					 | 
				
			||||||
	.release = single_release,
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static int __init proc_schedstat_init(void)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	proc_create("schedstat", 0, NULL, &proc_schedstat_operations);
 | 
					 | 
				
			||||||
	return 0;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
module_init(proc_schedstat_init);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * Expects runqueue lock to be held for atomicity of update
 | 
					 * Expects runqueue lock to be held for atomicity of update
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,3 +1,5 @@
 | 
				
			||||||
 | 
					#include "sched.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * stop-task scheduling class.
 | 
					 * stop-task scheduling class.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
| 
						 | 
					@ -80,7 +82,7 @@ get_rr_interval_stop(struct rq *rq, struct task_struct *task)
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * Simple, special scheduling class for the per-CPU stop tasks:
 | 
					 * Simple, special scheduling class for the per-CPU stop tasks:
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
static const struct sched_class stop_sched_class = {
 | 
					const struct sched_class stop_sched_class = {
 | 
				
			||||||
	.next			= &rt_sched_class,
 | 
						.next			= &rt_sched_class,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	.enqueue_task		= enqueue_task_stop,
 | 
						.enqueue_task		= enqueue_task_stop,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue