Skip to content

Commit 76d92ac

Browse files
committed
sched: Migrate sched to use new tick dependency mask model
Instead of providing asynchronous checks for the nohz subsystem to verify sched tick dependency, migrate sched to the new mask. Everytime a task is enqueued or dequeued, we evaluate the state of the tick dependency on top of the policy of the tasks in the runqueue, by order of priority: SCHED_DEADLINE: Need the tick in order to periodically check for runtime SCHED_FIFO : Don't need the tick (no round-robin) SCHED_RR : Need the tick if more than 1 task of the same priority for round robin (simplified with checking if more than one SCHED_RR task no matter what priority). SCHED_NORMAL : Need the tick if more than 1 task for round-robin. We could optimize that further with one flag per sched policy on the tick dependency mask and perform only the checks relevant to the policy concerned by an enqueue/dequeue operation. Since the checks aren't based on the current task anymore, we could get rid of the task switch hook but it's still needed for posix cpu timers. Reviewed-by: Chris Metcalf <cmetcalf@ezchip.com> Cc: Christoph Lameter <cl@linux.com> Cc: Chris Metcalf <cmetcalf@ezchip.com> Cc: Ingo Molnar <mingo@kernel.org> Cc: Luiz Capitulino <lcapitulino@redhat.com> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Rik van Riel <riel@redhat.com> Cc: Thomas Gleixner <tglx@linutronix.de> Cc: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Frederic Weisbecker <fweisbec@gmail.com>
1 parent 01d36d0 commit 76d92ac

File tree

4 files changed

+53
-37
lines changed

4 files changed

+53
-37
lines changed

include/linux/sched.h

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2364,10 +2364,7 @@ static inline void wake_up_nohz_cpu(int cpu) { }
23642364
#endif
23652365

23662366
#ifdef CONFIG_NO_HZ_FULL
2367-
extern bool sched_can_stop_tick(void);
23682367
extern u64 scheduler_tick_max_deferment(void);
2369-
#else
2370-
static inline bool sched_can_stop_tick(void) { return false; }
23712368
#endif
23722369

23732370
#ifdef CONFIG_SCHED_AUTOGROUP

kernel/sched/core.c

Lines changed: 20 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -701,31 +701,36 @@ static inline bool got_nohz_idle_kick(void)
701701
#endif /* CONFIG_NO_HZ_COMMON */
702702

703703
#ifdef CONFIG_NO_HZ_FULL
704-
bool sched_can_stop_tick(void)
704+
bool sched_can_stop_tick(struct rq *rq)
705705
{
706+
int fifo_nr_running;
707+
708+
/* Deadline tasks, even if single, need the tick */
709+
if (rq->dl.dl_nr_running)
710+
return false;
711+
706712
/*
707-
* FIFO realtime policy runs the highest priority task. Other runnable
708-
* tasks are of a lower priority. The scheduler tick does nothing.
713+
* FIFO realtime policy runs the highest priority task (after DEADLINE).
714+
* Other runnable tasks are of a lower priority. The scheduler tick
715+
* isn't needed.
709716
*/
710-
if (current->policy == SCHED_FIFO)
717+
fifo_nr_running = rq->rt.rt_nr_running - rq->rt.rr_nr_running;
718+
if (fifo_nr_running)
711719
return true;
712720

713721
/*
714722
* Round-robin realtime tasks time slice with other tasks at the same
715-
* realtime priority. Is this task the only one at this priority?
723+
* realtime priority.
716724
*/
717-
if (current->policy == SCHED_RR) {
718-
struct sched_rt_entity *rt_se = &current->rt;
719-
720-
return list_is_singular(&rt_se->run_list);
725+
if (rq->rt.rr_nr_running) {
726+
if (rq->rt.rr_nr_running == 1)
727+
return true;
728+
else
729+
return false;
721730
}
722731

723-
/*
724-
* More than one running task need preemption.
725-
* nr_running update is assumed to be visible
726-
* after IPI is sent from wakers.
727-
*/
728-
if (this_rq()->nr_running > 1)
732+
/* Normal multitasking need periodic preemption checks */
733+
if (rq->cfs.nr_running > 1)
729734
return false;
730735

731736
return true;

kernel/sched/sched.h

Lines changed: 33 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1279,6 +1279,35 @@ unsigned long to_ratio(u64 period, u64 runtime);
12791279

12801280
extern void init_entity_runnable_average(struct sched_entity *se);
12811281

1282+
#ifdef CONFIG_NO_HZ_FULL
1283+
extern bool sched_can_stop_tick(struct rq *rq);
1284+
1285+
/*
1286+
* Tick may be needed by tasks in the runqueue depending on their policy and
1287+
* requirements. If tick is needed, lets send the target an IPI to kick it out of
1288+
* nohz mode if necessary.
1289+
*/
1290+
static inline void sched_update_tick_dependency(struct rq *rq)
1291+
{
1292+
int cpu;
1293+
1294+
if (!tick_nohz_full_enabled())
1295+
return;
1296+
1297+
cpu = cpu_of(rq);
1298+
1299+
if (!tick_nohz_full_cpu(cpu))
1300+
return;
1301+
1302+
if (sched_can_stop_tick(rq))
1303+
tick_nohz_dep_clear_cpu(cpu, TICK_DEP_BIT_SCHED);
1304+
else
1305+
tick_nohz_dep_set_cpu(cpu, TICK_DEP_BIT_SCHED);
1306+
}
1307+
#else
1308+
static inline void sched_update_tick_dependency(struct rq *rq) { }
1309+
#endif
1310+
12821311
static inline void add_nr_running(struct rq *rq, unsigned count)
12831312
{
12841313
unsigned prev_nr = rq->nr_running;
@@ -1290,26 +1319,16 @@ static inline void add_nr_running(struct rq *rq, unsigned count)
12901319
if (!rq->rd->overload)
12911320
rq->rd->overload = true;
12921321
#endif
1293-
1294-
#ifdef CONFIG_NO_HZ_FULL
1295-
if (tick_nohz_full_cpu(rq->cpu)) {
1296-
/*
1297-
* Tick is needed if more than one task runs on a CPU.
1298-
* Send the target an IPI to kick it out of nohz mode.
1299-
*
1300-
* We assume that IPI implies full memory barrier and the
1301-
* new value of rq->nr_running is visible on reception
1302-
* from the target.
1303-
*/
1304-
tick_nohz_full_kick_cpu(rq->cpu);
1305-
}
1306-
#endif
13071322
}
1323+
1324+
sched_update_tick_dependency(rq);
13081325
}
13091326

13101327
static inline void sub_nr_running(struct rq *rq, unsigned count)
13111328
{
13121329
rq->nr_running -= count;
1330+
/* Check if we still need preemption */
1331+
sched_update_tick_dependency(rq);
13131332
}
13141333

13151334
static inline void rq_last_tick_reset(struct rq *rq)

kernel/time/tick-sched.c

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -204,11 +204,6 @@ static bool can_stop_full_tick(struct tick_sched *ts)
204204
return false;
205205
}
206206

207-
if (!sched_can_stop_tick()) {
208-
trace_tick_stop(0, TICK_DEP_MASK_SCHED);
209-
return false;
210-
}
211-
212207
if (!posix_cpu_timers_can_stop_tick(current)) {
213208
trace_tick_stop(0, TICK_DEP_MASK_POSIX_TIMER);
214209
return false;

0 commit comments

Comments
 (0)