Skip to content

Commit cccb45d

Browse files
author
Peter Zijlstra
committed
sched/deadline: Less agressive dl_server handling
Chris reported that commit 5f6bd38 ("sched/rt: Remove default bandwidth control") caused a significant dip in his favourite benchmark of the day. Simply disabling dl_server cured things. His workload hammers the 0->1, 1->0 transitions, and the dl_server_{start,stop}() overhead kills it -- fairly obviously a bad idea in hind sight and all that. Change things around to only disable the dl_server when there has not been a fair task around for a whole period. Since the default period is 1 second, this ensures the benchmark never trips this, overhead gone. Fixes: 557a6bf ("sched/fair: Add trivial fair server") Reported-by: Chris Mason <[email protected]> Signed-off-by: Peter Zijlstra (Intel) <[email protected]> Reviewed-by: Juri Lelli <[email protected]> Acked-by: Juri Lelli <[email protected]> Link: https://lkml.kernel.org/r/[email protected]
1 parent 570c8ef commit cccb45d

File tree

3 files changed

+23
-12
lines changed

3 files changed

+23
-12
lines changed

include/linux/sched.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -698,6 +698,7 @@ struct sched_dl_entity {
698698
unsigned int dl_defer : 1;
699699
unsigned int dl_defer_armed : 1;
700700
unsigned int dl_defer_running : 1;
701+
unsigned int dl_server_idle : 1;
701702

702703
/*
703704
* Bandwidth enforcement timer. Each -deadline task has its

kernel/sched/deadline.c

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1150,6 +1150,8 @@ static void __push_dl_task(struct rq *rq, struct rq_flags *rf)
11501150
/* a defer timer will not be reset if the runtime consumed was < dl_server_min_res */
11511151
static const u64 dl_server_min_res = 1 * NSEC_PER_MSEC;
11521152

1153+
static bool dl_server_stopped(struct sched_dl_entity *dl_se);
1154+
11531155
static enum hrtimer_restart dl_server_timer(struct hrtimer *timer, struct sched_dl_entity *dl_se)
11541156
{
11551157
struct rq *rq = rq_of_dl_se(dl_se);
@@ -1169,6 +1171,7 @@ static enum hrtimer_restart dl_server_timer(struct hrtimer *timer, struct sched_
11691171

11701172
if (!dl_se->server_has_tasks(dl_se)) {
11711173
replenish_dl_entity(dl_se);
1174+
dl_server_stopped(dl_se);
11721175
return HRTIMER_NORESTART;
11731176
}
11741177

@@ -1572,8 +1575,10 @@ void dl_server_update_idle_time(struct rq *rq, struct task_struct *p)
15721575
void dl_server_update(struct sched_dl_entity *dl_se, s64 delta_exec)
15731576
{
15741577
/* 0 runtime = fair server disabled */
1575-
if (dl_se->dl_runtime)
1578+
if (dl_se->dl_runtime) {
1579+
dl_se->dl_server_idle = 0;
15761580
update_curr_dl_se(dl_se->rq, dl_se, delta_exec);
1581+
}
15771582
}
15781583

15791584
void dl_server_start(struct sched_dl_entity *dl_se)
@@ -1596,7 +1601,7 @@ void dl_server_start(struct sched_dl_entity *dl_se)
15961601
setup_new_dl_entity(dl_se);
15971602
}
15981603

1599-
if (!dl_se->dl_runtime)
1604+
if (!dl_se->dl_runtime || dl_se->dl_server_active)
16001605
return;
16011606

16021607
dl_se->dl_server_active = 1;
@@ -1617,6 +1622,20 @@ void dl_server_stop(struct sched_dl_entity *dl_se)
16171622
dl_se->dl_server_active = 0;
16181623
}
16191624

1625+
static bool dl_server_stopped(struct sched_dl_entity *dl_se)
1626+
{
1627+
if (!dl_se->dl_server_active)
1628+
return false;
1629+
1630+
if (dl_se->dl_server_idle) {
1631+
dl_server_stop(dl_se);
1632+
return true;
1633+
}
1634+
1635+
dl_se->dl_server_idle = 1;
1636+
return false;
1637+
}
1638+
16201639
void dl_server_init(struct sched_dl_entity *dl_se, struct rq *rq,
16211640
dl_server_has_tasks_f has_tasks,
16221641
dl_server_pick_f pick_task)
@@ -2354,7 +2373,7 @@ static struct task_struct *__pick_task_dl(struct rq *rq)
23542373
if (dl_server(dl_se)) {
23552374
p = dl_se->server_pick_task(dl_se);
23562375
if (!p) {
2357-
if (dl_server_active(dl_se)) {
2376+
if (!dl_server_stopped(dl_se)) {
23582377
dl_se->dl_yielded = 1;
23592378
update_curr_dl_se(rq, dl_se, 0);
23602379
}

kernel/sched/fair.c

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5802,7 +5802,6 @@ static bool throttle_cfs_rq(struct cfs_rq *cfs_rq)
58025802
struct cfs_bandwidth *cfs_b = tg_cfs_bandwidth(cfs_rq->tg);
58035803
struct sched_entity *se;
58045804
long queued_delta, runnable_delta, idle_delta, dequeue = 1;
5805-
long rq_h_nr_queued = rq->cfs.h_nr_queued;
58065805

58075806
raw_spin_lock(&cfs_b->lock);
58085807
/* This will start the period timer if necessary */
@@ -5886,10 +5885,6 @@ static bool throttle_cfs_rq(struct cfs_rq *cfs_rq)
58865885

58875886
/* At this point se is NULL and we are at root level*/
58885887
sub_nr_running(rq, queued_delta);
5889-
5890-
/* Stop the fair server if throttling resulted in no runnable tasks */
5891-
if (rq_h_nr_queued && !rq->cfs.h_nr_queued)
5892-
dl_server_stop(&rq->fair_server);
58935888
done:
58945889
/*
58955890
* Note: distribution will already see us throttled via the
@@ -6966,7 +6961,6 @@ static void set_next_buddy(struct sched_entity *se);
69666961
static int dequeue_entities(struct rq *rq, struct sched_entity *se, int flags)
69676962
{
69686963
bool was_sched_idle = sched_idle_rq(rq);
6969-
int rq_h_nr_queued = rq->cfs.h_nr_queued;
69706964
bool task_sleep = flags & DEQUEUE_SLEEP;
69716965
bool task_delayed = flags & DEQUEUE_DELAYED;
69726966
struct task_struct *p = NULL;
@@ -7050,9 +7044,6 @@ static int dequeue_entities(struct rq *rq, struct sched_entity *se, int flags)
70507044

70517045
sub_nr_running(rq, h_nr_queued);
70527046

7053-
if (rq_h_nr_queued && !rq->cfs.h_nr_queued)
7054-
dl_server_stop(&rq->fair_server);
7055-
70567047
/* balance early to pull high priority tasks */
70577048
if (unlikely(!was_sched_idle && sched_idle_rq(rq)))
70587049
rq->next_balance = jiffies;

0 commit comments

Comments
 (0)