another rt group sched update
Subsystems (5)
cover another rt group sched update
this time compile tested on all 16 combinations of:
CONFIG_SMP
CONFIG_FAIR_GROUP_SCHED
CONFIG_HIGH_RES_TIMERS
CONFIG_NO_HZ
ran some but not all combinations
--
PATCH 1/11 sched: rt throttling vs no_hz
We need to teach no_hz about the rt throttling because its tick driven.
--- include/linux/sched.h | 2 ++ kernel/sched.c | 23 ++++++++++++++++++++++- kernel/sched_rt.c | 30 ++++++++++++++++-------------- kernel/time/tick-sched.c | 5 +++++ 4 files changed, 45 insertions(+), 15 deletions(-)
include/linux/sched.h +2 -0
@@ -230,6 +230,8 @@ static inline int select_nohz_load_balan }#endif +extern unsigned long rt_needs_cpu (int cpu); +/* * Only dump TASK_* tasks. (0 for all tasks) */
kernel/sched.c +22 -1
@@ -442,6 +442,7 @@ struct rq {struct cfs_rq cfs;struct rt_rq rt;u64 rt_period_expire; +int rt_throttled;#ifdef CONFIG_FAIR_GROUP_SCHED /* list of leaf cfs_rq on this cpu: */
@@ -594,6 +595,23 @@ static void update_rq_clock(struct rq *r#define task_rq (p) cpu_rq(task_cpu(p))#define cpu_curr (cpu) (cpu_rq(cpu)->curr) +unsigned long rt_needs_cpu (int cpu) +{ +struct rq *rq =cpu_rq (cpu); +u64 delta; + +if (!rq->rt_throttled) +return 0 ; + +if (rq->clock > rq->rt_period_expire) +return 1 ; + + delta = rq->rt_period_expire - rq->clock; +do_div (delta,NSEC_PER_SEC /HZ ); + +return (unsigned long )delta; +} +/* * Tunables that become constants when CONFIG_SCHED_DEBUG is off: */
@@ -7099,9 +7117,11 @@ static void init_rt_rq(struct rt_rq *rt_/* delimiter for bitsearch: */ __set_bit (MAX_RT_PRIO , array->bitmap); +#if definedCONFIG_SMP || definedCONFIG_FAIR_GROUP_SCHED + rt_rq->highest_prio =MAX_RT_PRIO ; +#endif #ifdef CONFIG_SMP rt_rq->rt_nr_migratory =0 ; - rt_rq->highest_prio =MAX_RT_PRIO ; rt_rq->overloaded =0 ;#endif
@@ -7186,6 +7206,7 @@ void __init sched_init(void)list_add (&init_task_group.list, &task_groups);#endif rq->rt_period_expire =0 ; + rq->rt_throttled =0 ;for (j =0 ; j <CPU_LOAD_IDX_MAX ; j++) rq->cpu_load[j] =0 ;
kernel/sched_rt.c +16 -14
@@ -175,7 +175,11 @@ static int sched_rt_ratio_exceeded(struc ratio = (period * rt_ratio) >>SCHED_RT_FRAC_SHIFT ;if (rt_rq->rt_time > ratio) { +struct rq *rq =rq_of_rt_rq (rt_rq); + + rq->rt_throttled =1 ; rt_rq->rt_throttled =1 ; +sched_rt_ratio_dequeue (rt_rq);return 1 ; }
@@ -183,18 +187,6 @@ static int sched_rt_ratio_exceeded(strucreturn 0 ; } -static void __update_sched_rt_period (struct rt_rq *rt_rq,u64 period) -{ -unsigned long rt_ratio =sched_rt_ratio (rt_rq); -u64 ratio = (period * rt_ratio) >>SCHED_RT_FRAC_SHIFT ; - - rt_rq->rt_time -=min (rt_rq->rt_time, ratio); -if (rt_rq->rt_throttled) { - rt_rq->rt_throttled =0 ; -sched_rt_ratio_enqueue (rt_rq); - } -} -static void update_sched_rt_period (struct rq *rq) {struct rt_rq *rt_rq;
@@ -204,8 +196,18 @@ static void update_sched_rt_period(struc period = (u64 )sysctl_sched_rt_period *NSEC_PER_MSEC ; rq->rt_period_expire += period; -for_each_leaf_rt_rq (rt_rq, rq) -__update_sched_rt_period (rt_rq, period); +for_each_leaf_rt_rq (rt_rq, rq) { +unsigned long rt_ratio =sched_rt_ratio (rt_rq); +u64 ratio = (period * rt_ratio) >>SCHED_RT_FRAC_SHIFT ; + + rt_rq->rt_time -=min (rt_rq->rt_time, ratio); +if (rt_rq->rt_throttled) { + rt_rq->rt_throttled =0 ; +sched_rt_ratio_enqueue (rt_rq); + } + } + + rq->rt_throttled =0 ; } }
kernel/time/tick-sched.c +5 -0
@@ -153,6 +153,7 @@ void tick_nohz_update_jiffies(void)void tick_nohz_stop_sched_tick (void ) {unsigned long seq, last_jiffies, next_jiffies, delta_jiffies, flags; +unsigned long rt_jiffies;struct tick_sched *ts;ktime_t last_update, expires, now, delta;struct clock_event_device *dev =__get_cpu_var (tick_cpu_device).evtdev;
@@ -216,6 +217,10 @@ void tick_nohz_stop_sched_tick(void) next_jiffies =get_next_timer_interrupt (last_jiffies); delta_jiffies = next_jiffies - last_jiffies; + rt_jiffies =rt_needs_cpu (cpu); +if (rt_jiffies && rt_jiffies < delta_jiffies) + delta_jiffies = rt_jiffies; +if (rcu_needs_cpu (cpu)) delta_jiffies =1 ;/*
--
PATCH 2/11 sched: load_balance_monitor rename
In reply to Peter Zijlstradon't start the load_balance_monitor when there is only a single cpu. rename the kthread because its currently longer than TASK_COMM_LEN
--- kernel/sched.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-)
kernel/sched.c +4 -1
@@ -7070,8 +7070,11 @@ void __init sched_init_smp(void)sched_init_granularity ();#ifdef CONFIG_FAIR_GROUP_SCHED +if (nr_cpu_ids ==1 ) +return ; + lb_monitor_task =kthread_create (load_balance_monitor,NULL , -"load_balance_monitor" ); +"group_balance" );if (!IS_ERR (lb_monitor_task)) { lb_monitor_task->flags |=PF_NOFREEZE ;wake_up_process (lb_monitor_task);
--
PATCH 3/11 hrtimer: clean up cpu->base locking tricks
In reply to Peter ZijlstraIn order to more easily allow for the scheduler to use timers, clean up the locking a bit.
--- kernel/hrtimer.c | 109 +++++++++++++++++++++++++++++++++++++++++++---- kernel/time/tick-sched.c | 8 --- 2 files changed, 102 insertions(+), 15 deletions(-)
kernel/hrtimer.c +19 -1
@@ -1063,7 +1063,9 @@ void hrtimer_interrupt(struct clock_even basenow =ktime_add (now, base->offset);while ((node = base->first)) { +enum hrtimer_restart (*fn)(struct hrtimer *);struct hrtimer *timer; +int restart; timer = rb_entry(node, struct hrtimer, node);
@@ -1091,13 +1093,29 @@ void hrtimer_interrupt(struct clock_even HRTIMER_STATE_CALLBACK, 0);timer_stats_account_hrtimer (timer); + fn = timer->function; +if (timer->cb_mode ==HRTIMER_CB_IRQSAFE_NO_SOFTIRQ ) { +/* +* Used for scheduler timers, avoid lock +* inversion with rq->lock and tasklist_lock. +* +* These timers are required to deal with +* enqueue expiry themselves and are not +* allowed to migrate. +*/ +spin_unlock (&cpu_base->lock); + restart =fn (timer); +spin_lock (&cpu_base->lock); + }else + restart =fn (timer); +/* * Note: We clear the CALLBACK bit after * enqueue_hrtimer to avoid reprogramming of * the event hardware. This happens at the end * of this function anyway. */ -if (timer->function (timer) !=HRTIMER_NORESTART ) { +if (restart !=HRTIMER_NORESTART ) {BUG_ON (timer->state !=HRTIMER_STATE_CALLBACK );enqueue_hrtimer (timer, base,0 ); }
kernel/time/tick-sched.c +0 -8
@@ -514,7 +514,6 @@ static enum hrtimer_restart tick_sched_t {struct tick_sched *ts = container_of(timer, struct tick_sched, sched_timer); -struct hrtimer_cpu_base *base = timer->base->cpu_base;struct pt_regs *regs =get_irq_regs ();ktime_t now =ktime_get ();int cpu =smp_processor_id ();
@@ -552,15 +551,8 @@ static enum hrtimer_restart tick_sched_ttouch_softlockup_watchdog (); ts->idle_jiffies++; } -/* -* update_process_times() might take tasklist_lock, hence -* drop the base lock. sched-tick hrtimers are per-CPU and -* never accessible by userspace APIs, so this is safe to do. -*/ -spin_unlock (&base->lock);update_process_times (user_mode (regs));profile_tick (CPU_PROFILING ); -spin_lock (&base->lock); }/* Do not restart, when we are in the idle loop */
--
PATCH 4/11 hrtimer: fixup the HRTIMER_CB_IRQSAFE_NO_SOFTIRQ fallback
In reply to Peter ZijlstraCurrently all highres=off timers are run from softirq context, but HRTIMER_CB_IRQSAFE_NO_SOFTIRQ timers expect to run from irq context.
Fix this up by splitting it similar to the highres=on case.
--- include/linux/hrtimer.h | 5 - kernel/hrtimer.c | 232 +++++++++++++++++++++++++----------------------- kernel/timer.c | 3 3 files changed, 125 insertions(+), 115 deletions(-)
kernel/hrtimer.c +121 -111
@@ -622,6 +622,11 @@ static inline int hrtimer_cb_pending(strstatic inline void hrtimer_remove_cb_pending (struct hrtimer *timer) { }static inline void hrtimer_init_hres (struct hrtimer_cpu_base *base) { }static inline void hrtimer_init_timer_hres (struct hrtimer *timer) { } +static inline int hrtimer_reprogram (struct hrtimer *timer, +struct hrtimer_clock_base *base) +{ +return 0 ; +}#endif /* CONFIG_HIGH_RES_TIMERS */
@@ -1030,6 +1035,85 @@ int hrtimer_get_res(const clockid_t whic }EXPORT_SYMBOL_GPL (hrtimer_get_res); +static void run_hrtimer_pending (struct hrtimer_cpu_base *cpu_base) +{ +spin_lock_irq (&cpu_base->lock); + +while (!list_empty (&cpu_base->cb_pending)) { +enum hrtimer_restart (*fn)(struct hrtimer *); +struct hrtimer *timer; +int restart; + + timer =list_entry (cpu_base->cb_pending.next, + struct hrtimer, cb_entry); + +timer_stats_account_hrtimer (timer); + + fn = timer->function; +__remove_hrtimer (timer, timer->base,HRTIMER_STATE_CALLBACK ,0 ); +spin_unlock_irq (&cpu_base->lock); + + restart =fn (timer); + +spin_lock_irq (&cpu_base->lock); + + timer->state &= ~HRTIMER_STATE_CALLBACK ; +if (restart ==HRTIMER_RESTART ) { +BUG_ON (hrtimer_active (timer)); +/* +* Enqueue the timer, allow reprogramming of the event +* device +*/ +enqueue_hrtimer (timer, timer->base,1 ); + }else if (hrtimer_active (timer)) { +/* +* If the timer was rearmed on another CPU, reprogram +* the event device. +*/ +if (timer->base->first == &timer->node) +hrtimer_reprogram (timer, timer->base); + } + } +spin_unlock_irq (&cpu_base->lock); +} + +static void __run_hrtimer (struct hrtimer *timer) +{ +struct hrtimer_clock_base *base = timer->base; +struct hrtimer_cpu_base *cpu_base = base->cpu_base; +enum hrtimer_restart (*fn)(struct hrtimer *); +int restart; + +__remove_hrtimer (timer, base,HRTIMER_STATE_CALLBACK ,0 ); +timer_stats_account_hrtimer (timer); + + fn = timer->function; +if (timer->cb_mode ==HRTIMER_CB_IRQSAFE_NO_SOFTIRQ ) { +/* +* Used for scheduler timers, avoid lock inversion with +* rq->lock and tasklist_lock. +* +* These timers are required to deal with enqueue expiry +* themselves and are not allowed to migrate. +*/ +spin_unlock (&cpu_base->lock); + restart =fn (timer); +spin_lock (&cpu_base->lock); + }else + restart =fn (timer); + +/* +* Note: We clear the CALLBACK bit after enqueue_hrtimer to avoid +* reprogramming of the event hardware. This happens at the end of this +* function anyway. +*/ +if (restart !=HRTIMER_NORESTART ) { +BUG_ON (timer->state !=HRTIMER_STATE_CALLBACK ); +enqueue_hrtimer (timer, base,0 ); + } + timer->state &= ~HRTIMER_STATE_CALLBACK ; +} +#ifdef CONFIG_HIGH_RES_TIMERS /*
@@ -1063,9 +1147,7 @@ void hrtimer_interrupt(struct clock_even basenow =ktime_add (now, base->offset);while ((node = base->first)) { -enum hrtimer_restart (*fn)(struct hrtimer *);struct hrtimer *timer; -int restart; timer = rb_entry(node, struct hrtimer, node);
@@ -1089,37 +1171,7 @@ void hrtimer_interrupt(struct clock_evencontinue ; } -__remove_hrtimer (timer, base, -HRTIMER_STATE_CALLBACK ,0 ); -timer_stats_account_hrtimer (timer); - - fn = timer->function; -if (timer->cb_mode ==HRTIMER_CB_IRQSAFE_NO_SOFTIRQ ) { -/* -* Used for scheduler timers, avoid lock -* inversion with rq->lock and tasklist_lock. -* -* These timers are required to deal with -* enqueue expiry themselves and are not -* allowed to migrate. -*/ -spin_unlock (&cpu_base->lock); - restart =fn (timer); -spin_lock (&cpu_base->lock); - }else - restart =fn (timer); - -/* -* Note: We clear the CALLBACK bit after -* enqueue_hrtimer to avoid reprogramming of -* the event hardware. This happens at the end -* of this function anyway. -*/ -if (restart !=HRTIMER_NORESTART ) { -BUG_ON (timer->state !=HRTIMER_STATE_CALLBACK ); -enqueue_hrtimer (timer, base,0 ); - } - timer->state &= ~HRTIMER_STATE_CALLBACK ; +__run_hrtimer (timer); }spin_unlock (&cpu_base->lock); base++;
@@ -1140,52 +1192,41 @@ void hrtimer_interrupt(struct clock_evenstatic void run_hrtimer_softirq (struct softirq_action *h) { -struct hrtimer_cpu_base *cpu_base = &__get_cpu_var (hrtimer_bases); - -spin_lock_irq (&cpu_base->lock); - -while (!list_empty (&cpu_base->cb_pending)) { -enum hrtimer_restart (*fn)(struct hrtimer *); -struct hrtimer *timer; -int restart; - - timer =list_entry (cpu_base->cb_pending.next, - struct hrtimer, cb_entry); +run_hrtimer_pending (&__get_cpu_var (hrtimer_bases)); +} -timer_stats_account_hrtimer (timer); +#endif /* CONFIG_HIGH_RES_TIMERS */ - fn = timer->function; -__remove_hrtimer (timer, timer->base,HRTIMER_STATE_CALLBACK ,0 ); -spin_unlock_irq (&cpu_base->lock); +/* +* Called from timer softirq every jiffy, expire hrtimers: +* +* For HRT its the fall back code to run the softirq in the timer +* softirq context in case the hrtimer initialization failed or has +* not been done yet. +*/ +void hrtimer_run_pending (void ) +{ +struct hrtimer_cpu_base *cpu_base = &__get_cpu_var (hrtimer_bases); - restart =fn (timer); +if (hrtimer_hres_active ()) +return ; -spin_lock_irq (&cpu_base->lock); +/* +* This _is_ ugly: We have to check in the softirq context, +* whether we can switch to highres and / or nohz mode. The +* clocksource switch happens in the timer interrupt with +* xtime_lock held. Notification from there only sets the +* check bit in the tick_oneshot code, otherwise we might +* deadlock vs. xtime_lock. +*/ +if (tick_check_oneshot_change (!hrtimer_is_hres_enabled ())) +hrtimer_switch_to_hres (); - timer->state &= ~HRTIMER_STATE_CALLBACK ; -if (restart ==HRTIMER_RESTART ) { -BUG_ON (hrtimer_active (timer)); -/* -* Enqueue the timer, allow reprogramming of the event -* device -*/ -enqueue_hrtimer (timer, timer->base,1 ); - }else if (hrtimer_active (timer)) { -/* -* If the timer was rearmed on another CPU, reprogram -* the event device. -*/ -if (timer->base->first == &timer->node) -hrtimer_reprogram (timer, timer->base); - } - } -spin_unlock_irq (&cpu_base->lock); +run_hrtimer_pending (cpu_base); } -#endif /* CONFIG_HIGH_RES_TIMERS */ -/* -* Expire the per base hrtimer-queue: +* Called from hardirq context every jiffy */ static inline void run_hrtimer_queue (struct hrtimer_cpu_base *cpu_base,int index)
@@ -1199,46 +1240,27 @@ static inline void run_hrtimer_queue(strif (base->get_softirq_time) base->softirq_time = base->get_softirq_time (); -spin_lock_irq (&cpu_base->lock); +spin_lock (&cpu_base->lock);while ((node = base->first)) {struct hrtimer *timer; -enum hrtimer_restart (*fn)(struct hrtimer *); -int restart; timer = rb_entry(node, struct hrtimer, node);if (base->softirq_time.tv64 <= timer->expires.tv64)break ; -#ifdef CONFIG_HIGH_RES_TIMERS -WARN_ON_ONCE (timer->cb_mode ==HRTIMER_CB_IRQSAFE_NO_SOFTIRQ ); -#endif -timer_stats_account_hrtimer (timer); - - fn = timer->function; -__remove_hrtimer (timer, base,HRTIMER_STATE_CALLBACK ,0 ); -spin_unlock_irq (&cpu_base->lock); - - restart =fn (timer); - -spin_lock_irq (&cpu_base->lock); - - timer->state &= ~HRTIMER_STATE_CALLBACK ; -if (restart !=HRTIMER_NORESTART ) { -BUG_ON (hrtimer_active (timer)); -enqueue_hrtimer (timer, base,0 ); +if (timer->cb_mode ==HRTIMER_CB_SOFTIRQ ) { +__remove_hrtimer (timer, base,HRTIMER_STATE_PENDING ,0 ); +list_add_tail (&timer->cb_entry, + &base->cpu_base->cb_pending); +continue ; } + +__run_hrtimer (timer); } -spin_unlock_irq (&cpu_base->lock); +spin_unlock (&cpu_base->lock); } -/* -* Called from timer softirq every jiffy, expire hrtimers: -* -* For HRT its the fall back code to run the softirq in the timer -* softirq context in case the hrtimer initialization failed or has -* not been done yet. -*/ void hrtimer_run_queues (void ) {struct hrtimer_cpu_base *cpu_base = &__get_cpu_var (hrtimer_bases);
@@ -1247,18 +1269,6 @@ void hrtimer_run_queues(void)if (hrtimer_hres_active ())return ; -/* -* This _is_ ugly: We have to check in the softirq context, -* whether we can switch to highres and / or nohz mode. The -* clocksource switch happens in the timer interrupt with -* xtime_lock held. Notification from there only sets the -* check bit in the tick_oneshot code, otherwise we might -* deadlock vs. xtime_lock. -*/ -if (tick_check_oneshot_change (!hrtimer_is_hres_enabled ())) -if (hrtimer_switch_to_hres ()) -return ; -hrtimer_get_softirq_time (cpu_base);for (i =0 ; i <HRTIMER_MAX_CLOCK_BASES ; i++)
kernel/timer.c +2 -1
@@ -896,7 +896,7 @@ static void run_timer_softirq(struct sof {tvec_base_t *base =__get_cpu_var (tvec_bases); -hrtimer_run_queues (); +hrtimer_run_pending ();if (time_after_eq (jiffies, base->timer_jiffies))__run_timers (base);
@@ -907,6 +907,7 @@ static void run_timer_softirq(struct sof*/ void run_local_timers (void ) { +hrtimer_run_queues ();raise_softirq (TIMER_SOFTIRQ );softlockup_tick (); }
include/linux/hrtimer.h +2 -3
@@ -115,10 +115,8 @@ struct hrtimer {enum hrtimer_restart (*function)(struct hrtimer *);struct hrtimer_clock_base *base;unsigned long state; -#ifdef CONFIG_HIGH_RES_TIMERS enum hrtimer_cb_mode cb_mode;struct list_head cb_entry; -#endif #ifdef CONFIG_TIMER_STATS void *start_site;char start_comm[16 ];
@@ -194,10 +192,10 @@ struct hrtimer_cpu_base {spinlock_t lock;struct lock_class_key lock_key;struct hrtimer_clock_base clock_base[HRTIMER_MAX_CLOCK_BASES ]; +struct list_head cb_pending;#ifdef CONFIG_HIGH_RES_TIMERS ktime_t expires_next;int hres_active; -struct list_head cb_pending;unsigned long nr_events;#endif };
@@ -319,6 +317,7 @@ extern void hrtimer_init_sleeper(struct/* Soft interrupt function to run the hrtimer queues: */ extern void hrtimer_run_queues (void ); +extern void hrtimer_run_pending (void );/* Bootup initialization: */ extern void __init hrtimers_init (void );
--
Re: [PATCH 04/11] hrtimer: fixup the HRTIMER_CB_IRQSAFE_NO_SOFTIRQ fallback
Quoted 1 line · Peter Zijlstra
plain text document attachment (hrtimer-fallback.patch)
I know I should have boot tested more combinations :-( Please fold this into the patch.
--- kernel/hrtimer.c | 38 ++++++++++++++++++-------------------- 1 file changed, 18 insertions(+), 20 deletions(-)
kernel/hrtimer.c +18 -20
@@ -325,6 +325,22 @@ unsigned long ktime_divns(const ktime_t }#endif /* BITS_PER_LONG >= 64 */ +/* +* Check, whether the timer is on the callback pending list +*/ +static inline int hrtimer_cb_pending (const struct hrtimer *timer) +{ +return timer->state &HRTIMER_STATE_PENDING ; +} + +/* +* Remove a timer from the callback pending list +*/ +static inline void hrtimer_remove_cb_pending (struct hrtimer *timer) +{ +list_del_init (&timer->cb_entry); +} +/* High resolution timer related functions */ #ifdef CONFIG_HIGH_RES_TIMERS
@@ -494,29 +510,12 @@ void hres_timers_resume(void) }/* -* Check, whether the timer is on the callback pending list -*/ -static inline int hrtimer_cb_pending (const struct hrtimer *timer) -{ -return timer->state &HRTIMER_STATE_PENDING ; -} - -/* -* Remove a timer from the callback pending list -*/ -static inline void hrtimer_remove_cb_pending (struct hrtimer *timer) -{ -list_del_init (&timer->cb_entry); -} - -/* * Initialize the high resolution related parts of cpu_base */ static inline void hrtimer_init_hres (struct hrtimer_cpu_base *base) { base->expires_next.tv64 =KTIME_MAX ; base->hres_active =0 ; -INIT_LIST_HEAD (&base->cb_pending); }/*
@@ -524,7 +523,6 @@ static inline void hrtimer_init_hres(str*/ static inline void hrtimer_init_timer_hres (struct hrtimer *timer) { -INIT_LIST_HEAD (&timer->cb_entry); }/*
@@ -618,8 +616,6 @@ static inline int hrtimer_enqueue_reprog {return 0 ; } -static inline int hrtimer_cb_pending (struct hrtimer *timer) {return 0 ; } -static inline void hrtimer_remove_cb_pending (struct hrtimer *timer) { }static inline void hrtimer_init_hres (struct hrtimer_cpu_base *base) { }static inline void hrtimer_init_timer_hres (struct hrtimer *timer) { } static inline int hrtimer_reprogram(struct hrtimer *timer,
@@ -1006,6 +1002,7 @@ void hrtimer_init(struct hrtimer *timer, clock_id =CLOCK_MONOTONIC ; timer->base = &cpu_base->clock_base[clock_id]; +INIT_LIST_HEAD (&timer->cb_entry);hrtimer_init_timer_hres (timer);#ifdef CONFIG_TIMER_STATS
@@ -1419,6 +1416,7 @@ static void __devinit init_hrtimers_cpu(for (i =0 ; i <HRTIMER_MAX_CLOCK_BASES ; i++) cpu_base->clock_base[i].cpu_base = cpu_base; +INIT_LIST_HEAD (&cpu_base->cb_pending);hrtimer_init_hres (cpu_base); }
Re: [PATCH 04/11] hrtimer: fixup the HRTIMER_CB_IRQSAFE_NO_SOFTIRQ fallback
Quoted 5 lines · Peter Zijlstra
Quoted 1 line · Peter Zijlstra
plain text document attachment (hrtimer-fallback.patch)
I know I should have boot tested more combinations :-( Please fold this into the patch.
done.
Ingo
PATCH 5/11 hrtimer: unlock hrtimer_wakeup
In reply to Peter Zijlstrahrtimer_wakeup creates a
base->lock
rq->lock
lock dependancy. Avoid this by switching to HRTIMER_CB_IRQSAFE_NO_SOFTIRQ which doesn't hold base->lock.
This fully untangles hrtimer locks from the scheduler locks, and allows hrtimer usage in the scheduler proper.
--- kernel/hrtimer.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
kernel/hrtimer.c +3 -1
@@ -1296,7 +1296,7 @@ void hrtimer_init_sleeper(struct hrtimer sl->timer.function = hrtimer_wakeup; sl->task = task;#ifdef CONFIG_HIGH_RES_TIMERS - sl->timer.cb_mode =HRTIMER_CB_IRQSAFE_NO_RESTART ; + sl->timer.cb_mode =HRTIMER_CB_IRQSAFE_NO_SOFTIRQ ;#endif }
@@ -1307,6 +1307,8 @@ static int __sched do_nanosleep(struct h do { set_current_state(TASK_INTERRUPTIBLE); hrtimer_start(&t->timer, t->timer.expires, mode); + if (!hrtimer_active(&t->timer)) + t->task = NULL; if (likely(t->task)) schedule();
--
PATCH 6/11 sched: rt-group: reduce rescheduling
In reply to Peter ZijlstraOnly reschedule if the new group has a higher prio task.
--- kernel/sched_rt.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-)
kernel/sched_rt.c +4 -1
@@ -94,8 +94,11 @@ static void sched_rt_ratio_enqueue(strucstruct sched_rt_entity *rt_se = rt_rq->rt_se;if (rt_se && !on_rt_rq (rt_se) && rt_rq->rt_nr_running) { +struct task_struct *curr =rq_of_rt_rq (rt_rq)->curr; +enqueue_rt_entity (rt_se); -resched_task (rq_of_rt_rq (rt_rq)->curr); +if (rt_rq->highest_prio < curr->prio) +resched_task (curr); } }
--
PATCH 7/11 sched: rt-group: per group period
In reply to Peter ZijlstraSteven asked for per group periods in order to get closer to RMA or EDF scheduling.
Use the fancy new hrtimers to provide a per group period
--- include/linux/sched.h | 2 kernel/sched.c | 229 ++++++++++++++++++++++++++++++++++++++++++----- kernel/sched_rt.c | 61 ++++++------ kernel/sysctl.c | 2 kernel/time/tick-sched.c | 5 - 5 files changed, 237 insertions(+), 62 deletions(-)
kernel/sched.c +205 -24
@@ -177,6 +177,7 @@ struct task_group {struct rt_rq **rt_rq;unsigned int rt_ratio; +ktime_t rt_period;/* * shares assigned to a task group governs how much of cpu bandwidth
@@ -372,6 +373,7 @@ struct rt_rq {#endif int rt_throttled;u64 rt_time; +struct hrtimer rt_period_timer;#ifdef CONFIG_FAIR_GROUP_SCHED struct rq *rq;
@@ -441,8 +443,6 @@ struct rq {struct cfs_rq cfs;struct rt_rq rt; -u64 rt_period_expire; -int rt_throttled;#ifdef CONFIG_FAIR_GROUP_SCHED /* list of leaf cfs_rq on this cpu: */
@@ -595,23 +595,6 @@ static void update_rq_clock(struct rq *r#define task_rq (p) cpu_rq(task_cpu(p))#define cpu_curr (cpu) (cpu_rq(cpu)->curr) -unsigned long rt_needs_cpu (int cpu) -{ -struct rq *rq =cpu_rq (cpu); -u64 delta; - -if (!rq->rt_throttled) -return 0 ; - -if (rq->clock > rq->rt_period_expire) -return 1 ; - - delta = rq->rt_period_expire - rq->clock; -do_div (delta,NSEC_PER_SEC /HZ ); - -return (unsigned long )delta; -} -/* * Tunables that become constants when CONFIG_SCHED_DEBUG is off: */
@@ -652,10 +635,10 @@ const_debug unsigned int sysctl_sched_fe const_debug unsigned int sysctl_sched_nr_migrate = 32;/* -* period over which we measure -rt task cpu usage in ms. +* period over which we measure -rt task cpu usage in us. * default: 1s */ -const_debug unsigned int sysctl_sched_rt_period = 1000; +const_debug unsigned int sysctl_sched_rt_period = 1000000;#define SCHED_RT_FRAC_SHIFT 16#define SCHED_RT_FRAC (1UL << SCHED_RT_FRAC_SHIFT)
@@ -1245,6 +1228,12 @@ static unsigned long cpu_avg_load_per_tastatic int task_hot (struct task_struct *p,u64 now,struct sched_domain *sd);#endif /* CONFIG_SMP */ +static inline ktime_t ns_to_ktime (u64 ns) +{ +static const ktime_t ktime_zero = { .tv64 =0 }; +return ktime_add_ns (ktime_zero, ns); +} +#include "sched_stats.h" #include "sched_idletask.c" #include "sched_fair.c"
@@ -3741,7 +3730,6 @@ void scheduler_tick(void) rq->tick_timestamp = rq->clock;update_cpu_load (rq); curr->sched_class->task_tick (rq, curr,0 ); -update_sched_rt_period (rq);spin_unlock (&rq->lock);#ifdef CONFIG_SMP
@@ -5287,6 +5275,158 @@ static inline void sched_init_granularit sysctl_sched_batch_wakeup_granularity *= factor; } +static enum hrtimer_restart sched_rt_period_timer (struct hrtimer *timer) +{ +struct rt_rq *rt_rq = + container_of(timer, struct rt_rq, rt_period_timer); +struct rq *rq =rq_of_rt_rq (rt_rq); +ktime_t now =ktime_get (); + +WARN_ON (smp_processor_id () !=cpu_of (rq)); +WARN_ON (!in_irq ()); + +spin_lock (&rq->lock); +update_sched_rt_period (rt_rq); +spin_unlock (&rq->lock); + +hrtimer_forward (timer, now,sched_rt_period (rt_rq)); +return HRTIMER_RESTART ; +} + +static void sched_rt_period_start (struct rt_rq *rt_rq) +{ +ktime_t period =sched_rt_period (rt_rq); + +WARN_ON (smp_processor_id () !=cpu_of (rq_of_rt_rq (rt_rq))); + +for (;;) { +ktime_t now =ktime_get (); +hrtimer_forward (&rt_rq->rt_period_timer, now, period); +hrtimer_start (&rt_rq->rt_period_timer, + rt_rq->rt_period_timer.expires, +HRTIMER_MODE_ABS ); +if (hrtimer_active (&rt_rq->rt_period_timer)) +break ; + } +} + +#if definedCONFIG_SMP || definedCONFIG_FAIR_GROUP_SCHED +static void sched_rt_period_stop (struct rt_rq *rt_rq) +{ +hrtimer_cancel (&rt_rq->rt_period_timer); +} +#endif + +static void sched_rt_period_start_cpu (int cpu) +{ +struct rq *rq =cpu_rq (cpu); +struct rt_rq *rt_rq; + +for_each_leaf_rt_rq (rt_rq, rq) +sched_rt_period_start (rt_rq); +} + +#ifdef CONFIG_SMP +static void sched_rt_period_stop_cpu (int cpu) +{ +struct rq *rq =cpu_rq (cpu); +struct rt_rq *rt_rq; + +for_each_leaf_rt_rq (rt_rq, rq) +sched_rt_period_stop (rt_rq); +} + +static int sched_rt_period_hotplug (struct notifier_block *nfb, +unsigned long action,void *hcpu) +{ +int cpu = (unsigned long )hcpu; + +switch (action) { +case CPU_UP_PREPARE : +case CPU_UP_PREPARE_FROZEN : +case CPU_DOWN_FAILED : +case CPU_DOWN_FAILED_FROZEN : +sched_rt_period_start_cpu (cpu); +return NOTIFY_OK ; + +case CPU_DOWN_PREPARE : +case CPU_DOWN_PREPARE_FROZEN : +case CPU_UP_CANCELED : +case CPU_UP_CANCELED_FROZEN : +sched_rt_period_stop_cpu (cpu); +return NOTIFY_OK ; + +case CPU_ONLINE : +case CPU_ONLINE_FROZEN : +case CPU_DEAD : +case CPU_DEAD_FROZEN : +return NOTIFY_OK ; + +default : +return NOTIFY_DONE ; + } + +return NOTIFY_OK ; +} + +static void __init __sched_rt_period_init (void *arg) +{ +int cpu =smp_processor_id (); +sched_rt_period_start_cpu (cpu); +} + +static void __init sched_rt_period_init (void ) +{ +on_each_cpu (__sched_rt_period_init,NULL ,0 ,1 ); +hotcpu_notifier (sched_rt_period_hotplug,0 ); +} + +#ifdef CONFIG_FAIR_GROUP_SCHED +static void __sched_rt_period_init_tg (void *arg) +{ +struct task_group *tg = arg; +int cpu =smp_processor_id (); + +sched_rt_period_start (tg->rt_rq[cpu]); +} + +static void sched_rt_period_init_tg (struct task_group *tg) +{ +on_each_cpu (__sched_rt_period_init_tg, tg,0 ,1 ); +} + +static void __sched_rt_period_destroy_tg (void *arg) +{ +struct task_group *tg = arg; +int cpu =smp_processor_id (); + +sched_rt_period_stop (tg->rt_rq[cpu]); +} + +static void sched_rt_period_destroy_tg (struct task_group *tg) +{ +on_each_cpu (__sched_rt_period_destroy_tg, tg,0 ,1 ); +} +#endif /* CONFIG_FAIR_GROUP_SCHED */ +#else /* CONFIG_SMP */ +static void __init sched_rt_period_init (void ) +{ +sched_rt_period_start_cpu (0 ); +} + +#ifdef CONFIG_FAIR_GROUP_SCHED +static void sched_rt_period_init_tg (struct task_group *tg) +{ +sched_rt_period_start (tg->rt_rq[0 ]); +} + +static void sched_rt_period_destroy_tg (struct task_group *tg) +{ +sched_rt_period_stop (tg->rt_rq[0 ]); +} +#endif /* CONFIG_FAIR_GROUP_SCHED */ +#endif /* CONFIG_SMP */ +#ifdef CONFIG_SMP /* * This is how migration works:
@@ -7068,6 +7208,7 @@ void __init sched_init_smp(void)if (set_cpus_allowed (current, non_isolated_cpus) <0 )BUG ();sched_init_granularity (); +sched_rt_period_init ();#ifdef CONFIG_FAIR_GROUP_SCHED if (nr_cpu_ids ==1 )
@@ -7088,6 +7229,7 @@ void __init sched_init_smp(void)void __init sched_init_smp (void ) {sched_init_granularity (); +sched_rt_period_init (); }#endif /* CONFIG_SMP */
@@ -7131,6 +7273,11 @@ static void init_rt_rq(struct rt_rq *rt_ rt_rq->rt_time =0 ; rt_rq->rt_throttled =0 ; +hrtimer_init (&rt_rq->rt_period_timer, +CLOCK_MONOTONIC ,HRTIMER_MODE_REL ); + rt_rq->rt_period_timer.function = sched_rt_period_timer; + rt_rq->rt_period_timer.cb_mode =HRTIMER_CB_IRQSAFE_NO_SOFTIRQ ; +#ifdef CONFIG_FAIR_GROUP_SCHED rt_rq->rq = rq;#endif
@@ -7201,6 +7348,8 @@ void __init sched_init(void) &per_cpu(init_sched_entity, i), i, 1); init_task_group.rt_ratio = sysctl_sched_rt_ratio;/* XXX */ + init_task_group.rt_period = +ns_to_ktime (sysctl_sched_rt_period *NSEC_PER_USEC );INIT_LIST_HEAD (&rq->leaf_rt_rq_list); init_tg_rt_entry(rq, &init_task_group, &per_cpu(init_rt_rq, i),
@@ -7208,8 +7357,6 @@ void __init sched_init(void)list_add (&init_task_group.list, &task_groups);#endif - rq->rt_period_expire =0 ; - rq->rt_throttled =0 ;for (j =0 ; j <CPU_LOAD_IDX_MAX ; j++) rq->cpu_load[j] =0 ;
@@ -7598,6 +7745,7 @@ struct task_group *sched_create_group(vo tg->shares =NICE_0_LOAD ; tg->rt_ratio =0 ;/* XXX */ + tg->rt_period =ns_to_ktime (sysctl_sched_rt_period *NSEC_PER_USEC );for_each_possible_cpu (i) { rq =cpu_rq (i);
@@ -7637,6 +7785,8 @@ struct task_group *sched_create_group(volist_add_rcu (&tg->list, &task_groups);unlock_task_group_list (); +sched_rt_period_init_tg (tg); +return tg; err:
@@ -7658,6 +7808,8 @@ void sched_destroy_group(struct task_grostruct rt_rq *rt_rq =NULL ;int i; +sched_rt_period_destroy_tg (tg); +lock_task_group_list ();for_each_possible_cpu (i) { cfs_rq = tg->cfs_rq[i];
@@ -7815,6 +7967,19 @@ unsigned long sched_group_rt_ratio(struc return tg->rt_ratio; } +int sched_group_set_rt_period (struct task_group *tg,unsigned long rt_period) +{ + tg->rt_period =ns_to_ktime ((u64 )rt_period *NSEC_PER_USEC ); +return 0 ; +} + +unsigned long sched_group_rt_period (struct task_group *tg) +{ +u64 ns =ktime_to_ns (tg->rt_period); +do_div (ns,NSEC_PER_USEC ); +return ns; +} +#endif /* CONFIG_FAIR_GROUP_SCHED */ #ifdef CONFIG_FAIR_CGROUP_SCHED
@@ -7903,6 +8068,17 @@ static u64 cpu_rt_ratio_read_uint(structreturn (u64 ) tg->rt_ratio; } +static int cpu_rt_period_write_uint (struct cgroup *cgrp,struct cftype *cftype, +u64 rt_period_val) +{ +return sched_group_set_rt_period (cgroup_tg (cgrp), rt_period_val); +} + +static u64 cpu_rt_period_read_uint (struct cgroup *cgrp,struct cftype *cft) +{ +return (u64 )sched_group_rt_period (cgroup_tg (cgrp)); +} +static struct cftype cpu_files[] = { { .name ="shares" ,
@@ -7914,6 +8090,11 @@ static struct cftype cpu_files[] = { .read_uint = cpu_rt_ratio_read_uint, .write_uint = cpu_rt_ratio_write_uint, }, + { + .name = "rt_period_us", + .read_uint = cpu_rt_period_read_uint, + .write_uint = cpu_rt_period_write_uint, + }, };static int cpu_cgroup_populate (struct cgroup_subsys *ss,struct cgroup *cont)
include/linux/sched.h +0 -2
@@ -230,8 +230,6 @@ static inline int select_nohz_load_balan }#endif -extern unsigned long rt_needs_cpu (int cpu); -/* * Only dump TASK_* tasks. (0 for all tasks) */
kernel/sched_rt.c +31 -30
96 lines not on this page · raw message
kernel/sysctl.c +1 -1
@@ -311,7 +311,7 @@ static struct ctl_table kern_table[] = { }, { .ctl_name = CTL_UNNUMBERED, - .procname = "sched_rt_period_ms", + .procname = "sched_rt_period_us", .data = &sysctl_sched_rt_period, .maxlen = sizeof(unsigned int), .mode = 0644,
kernel/time/tick-sched.c +0 -5
@@ -153,7 +153,6 @@ void tick_nohz_update_jiffies(void)void tick_nohz_stop_sched_tick (void ) {unsigned long seq, last_jiffies, next_jiffies, delta_jiffies, flags; -unsigned long rt_jiffies;struct tick_sched *ts;ktime_t last_update, expires, now, delta;struct clock_event_device *dev =__get_cpu_var (tick_cpu_device).evtdev;
@@ -217,10 +216,6 @@ void tick_nohz_stop_sched_tick(void) next_jiffies =get_next_timer_interrupt (last_jiffies); delta_jiffies = next_jiffies - last_jiffies; - rt_jiffies =rt_needs_cpu (cpu); -if (rt_jiffies && rt_jiffies < delta_jiffies) - delta_jiffies = rt_jiffies; -if (rcu_needs_cpu (cpu)) delta_jiffies =1 ;/*
--
PATCH 8/11 sched: rt-group: deal with PI
In reply to Peter ZijlstraSteven mentioned the fun case where a lock holding task will be throttled.
Simple fix: allow groups that have boosted tasks to run anyway. This is ofcourse not quite correct. Needs more tricks.
--- kernel/sched.c | 3 +++ kernel/sched_rt.c | 48 ++++++++++++++++++++++++++++++++++++++++-------- 2 files changed, 43 insertions(+), 8 deletions(-)
kernel/sched.c +3 -0
@@ -376,6 +376,8 @@ struct rt_rq {struct hrtimer rt_period_timer;#ifdef CONFIG_FAIR_GROUP_SCHED +unsigned long rt_nr_boosted; +struct rq *rq;struct list_head leaf_rt_rq_list;struct task_group *tg;
@@ -7279,6 +7281,7 @@ static void init_rt_rq(struct rt_rq *rt_ rt_rq->rt_period_timer.cb_mode =HRTIMER_CB_IRQSAFE_NO_SOFTIRQ ;#ifdef CONFIG_FAIR_GROUP_SCHED + rt_rq->rt_nr_boosted =0 ; rt_rq->rq = rq;#endif }
kernel/sched_rt.c +40 -8
106 lines not on this page · raw message
--
PATCH 9/11 sched: rt-group: dynamic period ticks
In reply to Peter ZijlstraDisable the period updates for inactive groups.
--- kernel/sched.c | 158 ------------------------------------------------------ kernel/sched_rt.c | 54 ++++++++++++++++++ 2 files changed, 53 insertions(+), 159 deletions(-)
kernel/sched.c +0 -158
@@ -5277,158 +5277,6 @@ static inline void sched_init_granularit sysctl_sched_batch_wakeup_granularity *= factor; } -static enum hrtimer_restart sched_rt_period_timer (struct hrtimer *timer) -{ -struct rt_rq *rt_rq = - container_of(timer, struct rt_rq, rt_period_timer); -struct rq *rq =rq_of_rt_rq (rt_rq); -ktime_t now =ktime_get (); - -WARN_ON (smp_processor_id () !=cpu_of (rq)); -WARN_ON (!in_irq ()); - -spin_lock (&rq->lock); -update_sched_rt_period (rt_rq); -spin_unlock (&rq->lock); - -hrtimer_forward (timer, now,sched_rt_period (rt_rq)); -return HRTIMER_RESTART ; -} - -static void sched_rt_period_start (struct rt_rq *rt_rq) -{ -ktime_t period =sched_rt_period (rt_rq); - -WARN_ON (smp_processor_id () !=cpu_of (rq_of_rt_rq (rt_rq))); - -for (;;) { -ktime_t now =ktime_get (); -hrtimer_forward (&rt_rq->rt_period_timer, now, period); -hrtimer_start (&rt_rq->rt_period_timer, - rt_rq->rt_period_timer.expires, -HRTIMER_MODE_ABS ); -if (hrtimer_active (&rt_rq->rt_period_timer)) -break ; - } -} - -#if definedCONFIG_SMP || definedCONFIG_FAIR_GROUP_SCHED -static void sched_rt_period_stop (struct rt_rq *rt_rq) -{ -hrtimer_cancel (&rt_rq->rt_period_timer); -} -#endif - -static void sched_rt_period_start_cpu (int cpu) -{ -struct rq *rq =cpu_rq (cpu); -struct rt_rq *rt_rq; - -for_each_leaf_rt_rq (rt_rq, rq) -sched_rt_period_start (rt_rq); -} - -#ifdef CONFIG_SMP -static void sched_rt_period_stop_cpu (int cpu) -{ -struct rq *rq =cpu_rq (cpu); -struct rt_rq *rt_rq; - -for_each_leaf_rt_rq (rt_rq, rq) -sched_rt_period_stop (rt_rq); -} - -static int sched_rt_period_hotplug (struct notifier_block *nfb, -unsigned long action,void *hcpu) -{ -int cpu = (unsigned long )hcpu; - -switch (action) { -case CPU_UP_PREPARE : -case CPU_UP_PREPARE_FROZEN : -case CPU_DOWN_FAILED : -case CPU_DOWN_FAILED_FROZEN : -sched_rt_period_start_cpu (cpu); -return NOTIFY_OK ; - -case CPU_DOWN_PREPARE : -case CPU_DOWN_PREPARE_FROZEN : -case CPU_UP_CANCELED : -case CPU_UP_CANCELED_FROZEN : -sched_rt_period_stop_cpu (cpu); -return NOTIFY_OK ; - -case CPU_ONLINE : -case CPU_ONLINE_FROZEN : -case CPU_DEAD : -case CPU_DEAD_FROZEN : -return NOTIFY_OK ; - -default : -return NOTIFY_DONE ; - } - -return NOTIFY_OK ; -} - -static void __init __sched_rt_period_init (void *arg) -{ -int cpu =smp_processor_id (); -sched_rt_period_start_cpu (cpu); -} - -static void __init sched_rt_period_init (void ) -{ -on_each_cpu (__sched_rt_period_init,NULL ,0 ,1 ); -hotcpu_notifier (sched_rt_period_hotplug,0 ); -} - -#ifdef CONFIG_FAIR_GROUP_SCHED -static void __sched_rt_period_init_tg (void *arg) -{ -struct task_group *tg = arg; -int cpu =smp_processor_id (); - -sched_rt_period_start (tg->rt_rq[cpu]); -} - -static void sched_rt_period_init_tg (struct task_group *tg) -{ -on_each_cpu (__sched_rt_period_init_tg, tg,0 ,1 ); -} - -static void __sched_rt_period_destroy_tg (void *arg) -{ -struct task_group *tg = arg; -int cpu =smp_processor_id (); - -sched_rt_period_stop (tg->rt_rq[cpu]); -} - -static void sched_rt_period_destroy_tg (struct task_group *tg) -{ -on_each_cpu (__sched_rt_period_destroy_tg, tg,0 ,1 ); -} -#endif /* CONFIG_FAIR_GROUP_SCHED */ -#else /* CONFIG_SMP */ -static void __init sched_rt_period_init (void ) -{ -sched_rt_period_start_cpu (0 ); -} - -#ifdef CONFIG_FAIR_GROUP_SCHED -static void sched_rt_period_init_tg (struct task_group *tg) -{ -sched_rt_period_start (tg->rt_rq[0 ]); -} - -static void sched_rt_period_destroy_tg (struct task_group *tg) -{ -sched_rt_period_stop (tg->rt_rq[0 ]); -} -#endif /* CONFIG_FAIR_GROUP_SCHED */ -#endif /* CONFIG_SMP */ -#ifdef CONFIG_SMP /* * This is how migration works:
@@ -7210,7 +7058,6 @@ void __init sched_init_smp(void)if (set_cpus_allowed (current, non_isolated_cpus) <0 )BUG ();sched_init_granularity (); -sched_rt_period_init ();#ifdef CONFIG_FAIR_GROUP_SCHED if (nr_cpu_ids ==1 )
@@ -7231,7 +7078,6 @@ void __init sched_init_smp(void)void __init sched_init_smp (void ) {sched_init_granularity (); -sched_rt_period_init (); }#endif /* CONFIG_SMP */
@@ -7788,8 +7634,6 @@ struct task_group *sched_create_group(volist_add_rcu (&tg->list, &task_groups);unlock_task_group_list (); -sched_rt_period_init_tg (tg); -return tg; err:
@@ -7811,8 +7655,6 @@ void sched_destroy_group(struct task_grostruct rt_rq *rt_rq =NULL ;int i; -sched_rt_period_destroy_tg (tg); -lock_task_group_list ();for_each_possible_cpu (i) { cfs_rq = tg->cfs_rq[i];
kernel/sched_rt.c +53 -1
79 lines not on this page · raw message
--
PATCH 10/11 sched: rt-group: EDF
In reply to Peter ZijlstraUse a simple Ealiest Deadline First implementation to schedule the realtime groups.
--- include/linux/sched.h | 1 kernel/sched.c | 13 +++++ kernel/sched_rt.c | 115 +++++++++++++++++++++++++++++++++++++++++++++++--- 3 files changed, 124 insertions(+), 5 deletions(-)
include/linux/sched.h +1 -0
@@ -942,6 +942,7 @@ struct sched_rt_entity {int nr_cpus_allowed;#ifdef CONFIG_FAIR_GROUP_SCHED +struct rb_node run_node;struct sched_rt_entity *parent;/* rq on which this entity is (to be) queued: */ struct rt_rq *rt_rq;
kernel/sched.c +13 -0
@@ -360,6 +360,11 @@ struct cfs_rq {#endif }; +enum rt_rq_type { +RT_RQ_PRIO , +RT_RQ_EDF , +}; +/* Real-Time classes' related field in a runqueue: */ struct rt_rq {struct rt_prio_array active;
@@ -376,6 +381,10 @@ struct rt_rq {struct hrtimer rt_period_timer;#ifdef CONFIG_FAIR_GROUP_SCHED +enum rt_rq_type rt_rq_type; +struct rb_root deadlines; +struct rb_node *rb_leftmost; +unsigned long rt_nr_boosted;struct rq *rq;
@@ -7127,6 +7136,9 @@ static void init_rt_rq(struct rt_rq *rt_ rt_rq->rt_period_timer.cb_mode =HRTIMER_CB_IRQSAFE_NO_SOFTIRQ ;#ifdef CONFIG_FAIR_GROUP_SCHED + rt_rq->rt_rq_type =RT_RQ_PRIO ; + rt_rq->deadlines =RB_ROOT ; + rt_rq->rb_leftmost =NULL ; rt_rq->rt_nr_boosted =0 ; rt_rq->rq = rq;#endif
@@ -7196,6 +7208,7 @@ void __init sched_init(void) &per_cpu (init_cfs_rq, i), &per_cpu(init_sched_entity, i), i, 1); + rq->rt.rt_rq_type =RT_RQ_EDF ; init_task_group.rt_ratio = sysctl_sched_rt_ratio;/* XXX */ init_task_group.rt_period =ns_to_ktime (sysctl_sched_rt_period *NSEC_PER_USEC );
kernel/sched_rt.c +110 -5
173 lines not on this page · raw message
--
PATCH 11/11 sched: rt-group: interface
In reply to Peter ZijlstraChange the rt_ratio interface to rt_runtime_us, to match rt_period_us. This avoids picking a granularity for the ratio.
--- include/linux/sched.h | 8 +++ kernel/sched.c | 116 ++++++++++++++++++++++++++++++++++---------------- kernel/sched_rt.c | 42 +++++++----------- kernel/sysctl.c | 4 - 4 files changed, 106 insertions(+), 64 deletions(-)
include/linux/sched.h +7 -1
@@ -1518,7 +1518,7 @@ extern unsigned int sysctl_sched_featureextern unsigned int sysctl_sched_migration_cost;extern unsigned int sysctl_sched_nr_migrate;extern unsigned int sysctl_sched_rt_period; -extern unsigned int sysctl_sched_rt_ratio; +extern unsigned int sysctl_sched_rt_runtime;#if defined(CONFIG_FAIR_GROUP_SCHED ) && defined(CONFIG_SMP )extern unsigned int sysctl_sched_min_bal_int_shares;extern unsigned int sysctl_sched_max_bal_int_shares;
@@ -2014,6 +2014,12 @@ extern void sched_destroy_group(struct textern void sched_move_task (struct task_struct *tsk);extern int sched_group_set_shares (struct task_group *tg,unsigned long shares);extern unsigned long sched_group_shares (struct task_group *tg); +extern int sched_group_set_rt_runtime (struct task_group *tg, +unsigned long rt_runtime_us); +extern unsigned long sched_group_rt_runtime (struct task_group *tg); +extern int sched_group_set_rt_period (struct task_group *tg, +unsigned long rt_runtime_us); +extern unsigned long sched_group_rt_period (struct task_group *tg);#endif
kernel/sched.c +79 -37
193 lines not on this page · raw message
kernel/sched_rt.c +18 -24
110 lines not on this page · raw message
kernel/sysctl.c +2 -2
@@ -319,8 +319,8 @@ static struct ctl_table kern_table[] = { }, { .ctl_name = CTL_UNNUMBERED, - .procname = "sched_rt_ratio", - .data = &sysctl_sched_rt_ratio, + .procname = "sched_rt_runtime_us", + .data = &sysctl_sched_rt_runtime, .maxlen = sizeof(unsigned int), .mode = 0644, .proc_handler = &proc_dointvec,
--
The list of open points and issues for this work:
- review/testing
- handle the PI case better
The only thing I can come up with currently is to basically have two priority arrays one for boosted and one for non boosted tasks, and normally run the highest of either array, but in the case of a throttled group, only pick from the boosted array.
Not sure I like that for its space overhead, Steven?
- I occasionally see a weird lockup on iterating the task_groups list on smp machines. - I failed to see anything wrong, but hey, this stack of used brown paper bags is steadily growing.
- figure out what to do for UID based group scheduling, the current implementation leaves it impossible for !root users to execute real time tasks by setting rt_runtime_us to 0, and it has no way to change it.
Srivatsa, what happened to the per uid weight patches?, Perhaps we can extend that interface to allow changing this.
- I guess documentation needs to be written ;-)
Peter Zijlstra
maintainerQuoted 3 lines · Peter Zijlstra
- I occasionally see a weird lockup on iterating the
task_groupslist on smp machines. - I failed to see anything wrong, but hey, this stack of used brown paper bags is steadily growing.
D'oh
---
Don't add a task_group to the task_groups list for each cpu, there is only a single task_group.
---
kernel/sched.c +4 -2
@@ -7175,6 +7175,10 @@ void __init sched_init(void)init_defrootdomain ();#endif +#ifdef CONFIG_FAIR_GROUP_SCHED +list_add (&init_task_group.list, &task_groups); +#endif +for_each_possible_cpu (i) {struct rq *rq;
@@ -7201,8 +7205,6 @@ void __init sched_init(void)init_tg_rt_entry (rq, &init_task_group, &per_cpu (init_rt_rq, i), &per_cpu (init_sched_rt_entity, i), i,1 ); - -list_add (&init_task_group.list, &task_groups);#endif for (j =0 ; j <CPU_LOAD_IDX_MAX ; j++)
Quoted 7 lines · Peter Zijlstra
- figure out what to do for UID based group scheduling, the current implementation leaves it impossible for !root users to execute real time tasks by setting
rt_runtime_usto 0, and it has no way to change it.Srivatsa, what happened to the per uid weight patches?, Perhaps we can extend that interface to allow changing this.
Hi Peter,
The sysfs interface for tweaking each user's share should be in
mainline already (sysfs_create_file() in user_kobject_create()). This could be extended for your purpose, hopefully in a straightforward manner (you never know that with sysfs :(
Signature · 2 lines
Regards, vatsa
Quoted 6 lines · Srivatsa Vaddagiri
Quoted 5 lines · Peter Zijlstra
- figure out what to do for UID based group scheduling, the current implementation leaves it impossible for !root users to execute real time tasks by setting
rt_runtime_usto 0, and it has no way to change it.
Quoted 8 lines
Quoted 2 lines
Srivatsa, what happened to the per uid weight patches?, Perhaps we can extend that interface to allow changing this.
Hi Peter,
The sysfs interface for tweaking each user's share should be in
mainline already (sysfs_create_file()inuser_kobject_create()). This could be extended for your purpose, hopefully in a straightforward manner (you never know that with sysfs :(
Ah, I missed that going in. Thanks, I'll give it a go.
[PATCH 12/11] sched: rt-group: uid-group interface
In reply to Srivatsa VaddagiriSubject: sched: rt-group: add uid-group interface
Extend the /sys/kernel/uids/<uid>/ interface to allow setting the group's rt_period and rt_runtime.
--- include/linux/sched.h | 4 +- kernel/user.c | 93 +++++++++++++++++++++++++++++++++++++++++++------- 2 files changed, 84 insertions(+), 13 deletions(-)
include/linux/sched.h +3 -1
@@ -559,7 +559,9 @@ struct user_struct {struct task_group *tg;#ifdef CONFIG_SYSFS struct kset kset; -struct subsys_attribute user_attr; +struct subsys_attribute share_attr; +struct subsys_attribute rt_period_attr; +struct subsys_attribute rt_runtime_attr;struct work_struct work;#endif #endif
kernel/user.c +81 -12
130 lines not on this page · raw message
Ingo Molnar
AppliedRe: [PATCH 12/11] sched: rt-group: uid-group interface
Quoted 4 lines · Peter Zijlstra
Subject: sched: rt-group: add uid-group interface
Extend the /sys/kernel/uids/<uid>/ interface to allow setting the group's
rt_periodandrt_runtime.
thanks, applied.
Ingo
Re: [PATCH 12/11] sched: rt-group: uid-group interface
In reply to Peter ZijlstraQuoted 6 lines · Peter Zijlstra
Subject: sched: rt-group: add uid-group interface
Extend the /sys/kernel/uids/<uid>/ interface to allow setting the group's
rt_periodandrt_runtime.
Hi Peter,
Cool stuff! I will try out these patches and try to give you some feedback.
One request though, could you please add some documentation to Documentation/ABI/testing/sysfs-kernel-uids?
Thanks,
Signature · 2 lines
regards, Dhaval
Re: [PATCH 12/11] sched: rt-group: uid-group interface
Quoted 4 lines · Dhaval Giani
Quoted 3 lines · Peter Zijlstra
Subject: sched: rt-group: add uid-group interface
Quoted 8 lines
Quoted 3 lines
Extend the /sys/kernel/uids/<uid>/ interface to allow setting the group's
rt_periodandrt_runtime.Hi Peter,
Cool stuff! I will try out these patches and try to give you some feedback.
Thanks, much appreciated!
Quoted 2 lines
One request though, could you please add some documentation to
Documentation/ABI/testing/sysfs-kernel-uids?
I already have documentation on the todo list, I'll add this file to that list :-)
Re: [PATCH 12/11] sched: rt-group: uid-group interface
Quoted 15 lines · Peter Zijlstra
Quoted 4 lines · Dhaval Giani
Quoted 3 lines · Peter Zijlstra
Subject: sched: rt-group: add uid-group interface
Quoted 8 lines
Quoted 3 lines
Extend the /sys/kernel/uids/<uid>/ interface to allow setting the group's
rt_periodandrt_runtime.Hi Peter,
Cool stuff! I will try out these patches and try to give you some feedback.
Quoted 7 lines
Thanks, much appreciated!
Quoted 2 lines
One request though, could you please add some documentation to
Documentation/ABI/testing/sysfs-kernel-uids?I already have documentation on the todo list, I'll add this file to that list :-)
Care to rebase the patch against -mm, we fixed the mixed-up usage of ksets and kobjects, and this can not apply anymore:
http://git.kernel.org/?p=linux/kernel/git/gregkh/patches.git;a=blob;f=driver/struct-user_info-sysfs.patch;hb=HEAD
There is also an attribute group now which makes it much easier to add new files.
Thanks,
Kay
Re: [PATCH 12/11] sched: rt-group: uid-group interface
Quoted 24 lines · Kay Sievers
Quoted 15 lines · Peter Zijlstra
Quoted 4 lines · Dhaval Giani
Quoted 3 lines · Peter Zijlstra
Subject: sched: rt-group: add uid-group interface
Quoted 8 lines
Quoted 3 lines
Extend the /sys/kernel/uids/<uid>/ interface to allow setting the group's
rt_periodandrt_runtime.Hi Peter,
Cool stuff! I will try out these patches and try to give you some feedback.
Quoted 7 lines
Thanks, much appreciated!
Quoted 2 lines
One request though, could you please add some documentation to
Documentation/ABI/testing/sysfs-kernel-uids?I already have documentation on the todo list, I'll add this file to that list :-)
Quoted 6 lines
Care to rebase the patch against -mm, we fixed the mixed-up usage of ksets and kobjects, and this can not apply anymore:
http://git.kernel.org/?p=linux/kernel/git/gregkh/patches.git;a=blob;f=driver/struct-user_info-sysfs.patch;hb=HEADThere is also an attribute group now which makes it much easier to add new files.
Ingo, Greg,
What would be the easiest way to carry this forward? sched-devel and greg's tree would intersect at this point and leave poor akpm with the resulting mess. Should I just make an incremental patch akpm can carry and push? Or can we base one tree off the other?
Re: [PATCH 12/11] sched: rt-group: uid-group interface
Quoted 33 lines · Peter Zijlstra
Quoted 24 lines · Kay Sievers
Quoted 15 lines · Peter Zijlstra
Quoted 4 lines · Dhaval Giani
Quoted 3 lines · Peter Zijlstra
Subject: sched: rt-group: add uid-group interface
Quoted 8 lines
Quoted 3 lines
Extend the /sys/kernel/uids/<uid>/ interface to allow setting the group's
rt_periodandrt_runtime.Hi Peter,
Cool stuff! I will try out these patches and try to give you some feedback.
Quoted 7 lines
Thanks, much appreciated!
Quoted 2 lines
One request though, could you please add some documentation to
Documentation/ABI/testing/sysfs-kernel-uids?I already have documentation on the todo list, I'll add this file to that list :-)
Quoted 6 lines
Care to rebase the patch against -mm, we fixed the mixed-up usage of ksets and kobjects, and this can not apply anymore:
http://git.kernel.org/?p=linux/kernel/git/gregkh/patches.git;a=blob;f=driver/struct-user_info-sysfs.patch;hb=HEADThere is also an attribute group now which makes it much easier to add new files.
Quoted 6 lines
Ingo, Greg,
What would be the easiest way to carry this forward? sched-devel and greg's tree would intersect at this point and leave poor akpm with the resulting mess. Should I just make an incremental patch akpm can carry and push? Or can we base one tree off the other?
If it's just a single patch for this, I'd be glad to take it. But by looking at the [11/12] above, I doubt this is so...
If it's not that rough (12 patches is not a big deal), I'd be glad to take these through my tree, after you fix up Kay's requests above :)
thanks,
greg k-h
Re: [PATCH 12/11] sched: rt-group: uid-group interface
Quoted 41 lines · Greg KH
Quoted 33 lines · Peter Zijlstra
Quoted 24 lines · Kay Sievers
Quoted 15 lines · Peter Zijlstra
Quoted 4 lines · Dhaval Giani
Quoted 3 lines · Peter Zijlstra
Subject: sched: rt-group: add uid-group interface
Quoted 8 lines
Quoted 3 lines
Extend the /sys/kernel/uids/<uid>/ interface to allow setting the group's
rt_periodandrt_runtime.Hi Peter,
Cool stuff! I will try out these patches and try to give you some feedback.
Quoted 7 lines
Thanks, much appreciated!
Quoted 2 lines
One request though, could you please add some documentation to
Documentation/ABI/testing/sysfs-kernel-uids?I already have documentation on the todo list, I'll add this file to that list :-)
Quoted 6 lines
Care to rebase the patch against -mm, we fixed the mixed-up usage of ksets and kobjects, and this can not apply anymore:
http://git.kernel.org/?p=linux/kernel/git/gregkh/patches.git;a=blob;f=driver/struct-user_info-sysfs.patch;hb=HEADThere is also an attribute group now which makes it much easier to add new files.
Quoted 6 lines
Ingo, Greg,
What would be the easiest way to carry this forward? sched-devel and greg's tree would intersect at this point and leave poor akpm with the resulting mess. Should I just make an incremental patch akpm can carry and push? Or can we base one tree off the other?
Quoted 5 lines
If it's just a single patch for this, I'd be glad to take it. But by looking at the [11/12] above, I doubt this is so...
If it's not that rough (12 patches is not a big deal), I'd be glad to take these through my tree, after you fix up Kay's requests above :)
hm, i'd really like to see this tested and go through sched.git. It's only the few sysfs bits which interfere, right?
Ingo
Re: [PATCH 12/11] sched: rt-group: uid-group interface
Quoted 44 lines · Ingo Molnar
Quoted 41 lines · Greg KH
Quoted 39 lines · Peter Zijlstra
Quoted 24 lines · Kay Sievers
Quoted 15 lines · Peter Zijlstra
Quoted 4 lines · Dhaval Giani
Quoted 3 lines · Peter Zijlstra
Subject: sched: rt-group: add uid-group interface
Quoted 8 lines
Quoted 3 lines
Extend the /sys/kernel/uids/<uid>/ interface to allow setting the group's
rt_periodandrt_runtime.Hi Peter,
Cool stuff! I will try out these patches and try to give you some feedback.
Quoted 7 lines
Thanks, much appreciated!
Quoted 2 lines
One request though, could you please add some documentation to
Documentation/ABI/testing/sysfs-kernel-uids?I already have documentation on the todo list, I'll add this file to that list :-)
Quoted 6 lines
Care to rebase the patch against -mm, we fixed the mixed-up usage of ksets and kobjects, and this can not apply anymore:
http://git.kernel.org/?p=linux/kernel/git/gregkh/patches.git;a=blob;f=driver/struct-user_info-sysfs.patch;hb=HEADThere is also an attribute group now which makes it much easier to add new files.
Ingo, Greg,
What would be the easiest way to carry this forward? sched-devel and greg's tree would intersect at this point and leave poor akpm with the resulting mess. Should I just make an incremental patch akpm can carry and push? Or can we base one tree off the other?
Quoted 8 lines
Quoted 5 lines
If it's just a single patch for this, I'd be glad to take it. But by looking at the [11/12] above, I doubt this is so...
If it's not that rough (12 patches is not a big deal), I'd be glad to take these through my tree, after you fix up Kay's requests above :)
hm, i'd really like to see this tested and go through sched.git. It's only the few sysfs bits which interfere, right?
Yes, that should be it.
So why not put the majority of this through sched.git, then when my sysfs changes go in at the beginning of the .25 merge cycle, you can then add the sysfs changes through your tree or anywhere else.
Unless you are relying on the sysfs changes for this whole feature, and without them it just doesn't make any sense at all?
thanks,
greg k-h
Re: [PATCH 12/11] sched: rt-group: uid-group interface
Quoted 13 lines · Greg KH
Quoted 13 lines
Quoted 12 lines
Quoted 6 lines
Ingo, Greg,
What would be the easiest way to carry this forward? sched-devel and greg's tree would intersect at this point and leave poor akpm with the resulting mess. Should I just make an incremental patch akpm can carry and push? Or can we base one tree off the other?
If it's just a single patch for this, I'd be glad to take it. But by looking at the [11/12] above, I doubt this is so...
If it's not that rough (12 patches is not a big deal), I'd be glad to take these through my tree, after you fix up Kay's requests above :)
Quoted 9 lines
Quoted 2 lines
hm, i'd really like to see this tested and go through sched.git. It's only the few sysfs bits which interfere, right?
Yes, that should be it.
So why not put the majority of this through sched.git, then when my sysfs changes go in at the beginning of the .25 merge cycle, you can then add the sysfs changes through your tree or anywhere else.
Hi,
I was wondering where these changes are right now. I don't see the sysfs interface for rt-group-sched in mainline right now.
Thanks,
Signature · 2 lines
regards, Dhaval
Re: [PATCH 12/11] sched: rt-group: uid-group interface
Quoted 24 lines · Dhaval Giani
Quoted 13 lines · Greg KH
Quoted 13 lines
Quoted 12 lines
Quoted 6 lines
Ingo, Greg,
What would be the easiest way to carry this forward? sched-devel and greg's tree would intersect at this point and leave poor akpm with the resulting mess. Should I just make an incremental patch akpm can carry and push? Or can we base one tree off the other?
If it's just a single patch for this, I'd be glad to take it. But by looking at the [11/12] above, I doubt this is so...
If it's not that rough (12 patches is not a big deal), I'd be glad to take these through my tree, after you fix up Kay's requests above :)
Quoted 9 lines
Quoted 2 lines
hm, i'd really like to see this tested and go through sched.git. It's only the few sysfs bits which interfere, right?
Yes, that should be it.
So why not put the majority of this through sched.git, then when my sysfs changes go in at the beginning of the .25 merge cycle, you can then add the sysfs changes through your tree or anywhere else.
Quoted 4 lines
Hi,
I was wondering where these changes are right now. I don't see the sysfs interface for rt-group-sched in mainline right now.
All of the sysfs changes I had are in Linus's tree, so you don't need me anymore :)
thanks,
greg k-h
Re: [PATCH 12/11] sched: rt-group: uid-group interface
In reply to Dhaval GianiQuoted 8 lines · Dhaval Giani
Quoted 6 lines · Peter Zijlstra
Subject: sched: rt-group: add uid-group interface
Extend the /sys/kernel/uids/<uid>/ interface to allow setting the group's
rt_periodandrt_runtime.
Quoted 7 lines
Hi Peter,
Cool stuff! I will try out these patches and try to give you some feedback.
One request though, could you please add some documentation to
Documentation/ABI/testing/sysfs-kernel-uids?
compile tested only attempt at finalizing the interface
---
include/linux/sched.h +4 -4
@@ -1519,8 +1519,6 @@ extern unsigned int sysctl_sched_child_rextern unsigned int sysctl_sched_features;extern unsigned int sysctl_sched_migration_cost;extern unsigned int sysctl_sched_nr_migrate; -extern unsigned int sysctl_sched_rt_period; -extern unsigned int sysctl_sched_rt_runtime;#if defined(CONFIG_FAIR_GROUP_SCHED ) && defined(CONFIG_SMP )extern unsigned int sysctl_sched_min_bal_int_shares;extern unsigned int sysctl_sched_max_bal_int_shares;
@@ -1530,6 +1528,8 @@ int sched_nr_latency_handler(struct ctl_ struct file *file, void __user *buffer, size_t *length, loff_t *ppos);#endif +extern unsigned int sysctl_sched_rt_period; +extern int sysctl_sched_rt_runtime;extern unsigned int sysctl_sched_compat_yield;
@@ -2017,8 +2017,8 @@ extern void sched_move_task(struct task_extern int sched_group_set_shares (struct task_group *tg,unsigned long shares);extern unsigned long sched_group_shares (struct task_group *tg);extern int sched_group_set_rt_runtime (struct task_group *tg, -unsigned long rt_runtime_us); -extern unsigned long sched_group_rt_runtime (struct task_group *tg); +long rt_runtime_us); +extern long sched_group_rt_runtime (struct task_group *tg);extern int sched_group_set_rt_period (struct task_group *tg,unsigned long rt_runtime_us);extern unsigned long sched_group_rt_period (struct task_group *tg);
kernel/sched.c +69 -20
143 lines not on this page · raw message
kernel/sched_rt.c +5 -2
@@ -60,7 +60,7 @@ static inline int on_rt_rq(struct sched_static inline u64 sched_rt_runtime (struct rt_rq *rt_rq) {if (!rt_rq->tg) -return 0 ; +return RUNTIME_INF ;return rt_rq->tg->rt_runtime; }
@@ -220,6 +220,9 @@ static struct sched_rt_entity *next_rt_dstatic inline u64 sched_rt_runtime (struct rt_rq *rt_rq) { +if (sysctl_sched_rt_runtime ==-1 ) +return RUNTIME_INF ; +return (u64 )sysctl_sched_rt_runtime *NSEC_PER_USEC ; }
@@ -304,7 +307,7 @@ static int sched_rt_runtime_exceeded(str {u64 runtime =sched_rt_runtime (rt_rq); -if (!runtime) +if (runtime ==RUNTIME_INF ) goto out;if (rt_rq->rt_throttled)
kernel/sysctl.c +16 -16
@@ -309,22 +309,6 @@ static struct ctl_table kern_table[] = { .mode = 0644, .proc_handler = &proc_dointvec, }, - { - .ctl_name = CTL_UNNUMBERED, - .procname = "sched_rt_period_us", - .data = &sysctl_sched_rt_period, - .maxlen = sizeof(unsigned int), - .mode = 0644, - .proc_handler = &proc_dointvec, - }, - { - .ctl_name = CTL_UNNUMBERED, - .procname = "sched_rt_runtime_us", - .data = &sysctl_sched_rt_runtime, - .maxlen = sizeof(unsigned int), - .mode = 0644, - .proc_handler = &proc_dointvec, - },#if defined(CONFIG_FAIR_GROUP_SCHED ) && defined(CONFIG_SMP ) { .ctl_name = CTL_UNNUMBERED,
@@ -346,6 +330,22 @@ static struct ctl_table kern_table[] = {#endif { .ctl_name = CTL_UNNUMBERED, + .procname = "sched_rt_period_us", + .data = &sysctl_sched_rt_period, + .maxlen = sizeof(unsigned int), + .mode = 0644, + .proc_handler = &proc_dointvec, + }, + { + .ctl_name = CTL_UNNUMBERED, + .procname = "sched_rt_runtime_us", + .data = &sysctl_sched_rt_runtime, + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = &proc_dointvec, + }, + { + .ctl_name = CTL_UNNUMBERED, .procname = "sched_compat_yield", .data = &sysctl_sched_compat_yield, .maxlen = sizeof(unsigned int),
kernel/user.c +3 -3
@@ -175,17 +175,17 @@ static ssize_t cpu_rt_runtime_show(struc { struct user_struct *up = container_of(kset, struct user_struct, kset); -return sprintf (buffer,"%lu\n" ,sched_group_rt_runtime (up->tg)); +return sprintf (buffer,"%ld\n" ,sched_group_rt_runtime (up->tg)); }static ssize_t cpu_rt_runtime_store (struct kset *kset,const char *buffer,size_t size) { struct user_struct *up = container_of(kset, struct user_struct, kset); -unsigned long rt_runtime_us; +long rt_runtime_us;int rc; -sscanf (buffer,"%lu" , &rt_runtime_us); +sscanf (buffer,"%ld" , &rt_runtime_us); rc =sched_group_set_rt_runtime (up->tg, rt_runtime_us);return (rc ?: size);
Documentation/ABI/testing/sysfs-kernel-uids +11 -0
@@ -12,3 +12,14 @@ Description: B has shares = 2048, User B will get twice the CPU bandwidth user A will. For more details refer Documentation/sched-design-CFS.txt + +What: /sys/kernel/uids/<uid>/cpu_rt_period_us +Date: January 2008 +Contact: Peter Zijlstra <[email protected]> +Description: See Documentation/sched-rt-group.txt + +What: /sys/kernel/uids/<uid>/cpu_rt_runtime_us +Date: January 2008 +Contact: Peter Zijlstra <[email protected]> +Description: See Documentation/sched-rt-group.txt +
Documentation/sched-rt-group.txt new file +69 -0
69 lines not on this page · raw message
Ingo Molnar
AppliedQuoted 8 lines · Peter Zijlstra
this time compile tested on all 16 combinations of:
CONFIG_SMP
CONFIG_FAIR_GROUP_SCHED
CONFIG_HIGH_RES_TIMERS
CONFIG_NO_HZran some but not all combinations
thanks, applied. This is a really big step forwards in terms of making RT task CPU usage more flexible and more manageable.
Ingo