aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPeter Zijlstra <a.p.zijlstra@chello.nl>2008-06-19 03:06:57 -0400
committerIngo Molnar <mingo@elte.hu>2008-06-19 03:06:57 -0400
commitad2a3f13b7258a5daaaeb8cff9f835aac468b71d (patch)
treeac9ea87be655aba0a372b6b4a25215547da0e291
parent7ea56616ba6b3d67a4892728182e38ae162ea3e7 (diff)
sched: rt-group: heirarchy aware throttle
The bandwidth throttle code dequeues a group when it runs out of quota, and re-queues it once the period rolls over and the quota gets refreshed. Sadly it failed to take the hierarchy into consideration. Share more of the enqueue/dequeue code with regular task opterations. Also, some operations like sched_setscheduler() can dequeue/enqueue tasks that are in throttled runqueues, we should not inadvertly re-enqueue empty runqueues so check for that. Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl> Tested-by: Daniel K. <dk@uw.no> Signed-off-by: Ingo Molnar <mingo@elte.hu>
-rw-r--r--kernel/sched_rt.c59
1 files changed, 33 insertions, 26 deletions
diff --git a/kernel/sched_rt.c b/kernel/sched_rt.c
index 3432d573205d..837241568d76 100644
--- a/kernel/sched_rt.c
+++ b/kernel/sched_rt.c
@@ -449,13 +449,19 @@ void dec_rt_tasks(struct sched_rt_entity *rt_se, struct rt_rq *rt_rq)
449#endif 449#endif
450} 450}
451 451
452static void enqueue_rt_entity(struct sched_rt_entity *rt_se) 452static void __enqueue_rt_entity(struct sched_rt_entity *rt_se)
453{ 453{
454 struct rt_rq *rt_rq = rt_rq_of_se(rt_se); 454 struct rt_rq *rt_rq = rt_rq_of_se(rt_se);
455 struct rt_prio_array *array = &rt_rq->active; 455 struct rt_prio_array *array = &rt_rq->active;
456 struct rt_rq *group_rq = group_rt_rq(rt_se); 456 struct rt_rq *group_rq = group_rt_rq(rt_se);
457 457
458 if (group_rq && rt_rq_throttled(group_rq)) 458 /*
459 * Don't enqueue the group if its throttled, or when empty.
460 * The latter is a consequence of the former when a child group
461 * get throttled and the current group doesn't have any other
462 * active members.
463 */
464 if (group_rq && (rt_rq_throttled(group_rq) || !group_rq->rt_nr_running))
459 return; 465 return;
460 466
461 list_add_tail(&rt_se->run_list, array->queue + rt_se_prio(rt_se)); 467 list_add_tail(&rt_se->run_list, array->queue + rt_se_prio(rt_se));
@@ -464,7 +470,7 @@ static void enqueue_rt_entity(struct sched_rt_entity *rt_se)
464 inc_rt_tasks(rt_se, rt_rq); 470 inc_rt_tasks(rt_se, rt_rq);
465} 471}
466 472
467static void dequeue_rt_entity(struct sched_rt_entity *rt_se) 473static void __dequeue_rt_entity(struct sched_rt_entity *rt_se)
468{ 474{
469 struct rt_rq *rt_rq = rt_rq_of_se(rt_se); 475 struct rt_rq *rt_rq = rt_rq_of_se(rt_se);
470 struct rt_prio_array *array = &rt_rq->active; 476 struct rt_prio_array *array = &rt_rq->active;
@@ -480,11 +486,10 @@ static void dequeue_rt_entity(struct sched_rt_entity *rt_se)
480 * Because the prio of an upper entry depends on the lower 486 * Because the prio of an upper entry depends on the lower
481 * entries, we must remove entries top - down. 487 * entries, we must remove entries top - down.
482 */ 488 */
483static void dequeue_rt_stack(struct task_struct *p) 489static void dequeue_rt_stack(struct sched_rt_entity *rt_se)
484{ 490{
485 struct sched_rt_entity *rt_se, *back = NULL; 491 struct sched_rt_entity *back = NULL;
486 492
487 rt_se = &p->rt;
488 for_each_sched_rt_entity(rt_se) { 493 for_each_sched_rt_entity(rt_se) {
489 rt_se->back = back; 494 rt_se->back = back;
490 back = rt_se; 495 back = rt_se;
@@ -492,7 +497,26 @@ static void dequeue_rt_stack(struct task_struct *p)
492 497
493 for (rt_se = back; rt_se; rt_se = rt_se->back) { 498 for (rt_se = back; rt_se; rt_se = rt_se->back) {
494 if (on_rt_rq(rt_se)) 499 if (on_rt_rq(rt_se))
495 dequeue_rt_entity(rt_se); 500 __dequeue_rt_entity(rt_se);
501 }
502}
503
504static void enqueue_rt_entity(struct sched_rt_entity *rt_se)
505{
506 dequeue_rt_stack(rt_se);
507 for_each_sched_rt_entity(rt_se)
508 __enqueue_rt_entity(rt_se);
509}
510
511static void dequeue_rt_entity(struct sched_rt_entity *rt_se)
512{
513 dequeue_rt_stack(rt_se);
514
515 for_each_sched_rt_entity(rt_se) {
516 struct rt_rq *rt_rq = group_rt_rq(rt_se);
517
518 if (rt_rq && rt_rq->rt_nr_running)
519 __enqueue_rt_entity(rt_se);
496 } 520 }
497} 521}
498 522
@@ -506,32 +530,15 @@ static void enqueue_task_rt(struct rq *rq, struct task_struct *p, int wakeup)
506 if (wakeup) 530 if (wakeup)
507 rt_se->timeout = 0; 531 rt_se->timeout = 0;
508 532
509 dequeue_rt_stack(p); 533 enqueue_rt_entity(rt_se);
510
511 /*
512 * enqueue everybody, bottom - up.
513 */
514 for_each_sched_rt_entity(rt_se)
515 enqueue_rt_entity(rt_se);
516} 534}
517 535
518static void dequeue_task_rt(struct rq *rq, struct task_struct *p, int sleep) 536static void dequeue_task_rt(struct rq *rq, struct task_struct *p, int sleep)
519{ 537{
520 struct sched_rt_entity *rt_se = &p->rt; 538 struct sched_rt_entity *rt_se = &p->rt;
521 struct rt_rq *rt_rq;
522 539
523 update_curr_rt(rq); 540 update_curr_rt(rq);
524 541 dequeue_rt_entity(rt_se);
525 dequeue_rt_stack(p);
526
527 /*
528 * re-enqueue all non-empty rt_rq entities.
529 */
530 for_each_sched_rt_entity(rt_se) {
531 rt_rq = group_rt_rq(rt_se);
532 if (rt_rq && rt_rq->rt_nr_running)
533 enqueue_rt_entity(rt_se);
534 }
535} 542}
536 543
537/* 544/*