summaryrefslogtreecommitdiffstats
path: root/kernel/time/posix-cpu-timers.c
diff options
context:
space:
mode:
authorFrederic Weisbecker <fweisbec@gmail.com>2015-07-17 16:25:49 -0400
committerFrederic Weisbecker <fweisbec@gmail.com>2016-03-02 10:44:27 -0500
commitb78783000d5cb7c5994e6742e1d1ce594bfea15b (patch)
tree8f4468e342ae4e25efb9679e6d93db02f3f0ec6a /kernel/time/posix-cpu-timers.c
parent76d92ac305f23cada3a9b3c48a7ccea5f71019cb (diff)
posix-cpu-timers: Migrate to use new tick dependency mask model
Instead of providing asynchronous checks for the nohz subsystem to verify posix cpu timers tick dependency, migrate the latter to the new mask. In order to keep track of the running timers and expose the tick dependency accordingly, we must probe the timers queuing and dequeuing on threads and process lists. Unfortunately it implies both task and signal level dependencies. We should be able to further optimize this and merge all that on the task level dependency, at the cost of a bit of complexity and may be overhead. 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>
Diffstat (limited to 'kernel/time/posix-cpu-timers.c')
-rw-r--r--kernel/time/posix-cpu-timers.c52
1 files changed, 11 insertions, 41 deletions
diff --git a/kernel/time/posix-cpu-timers.c b/kernel/time/posix-cpu-timers.c
index f5e86d282d52..1cafba860b08 100644
--- a/kernel/time/posix-cpu-timers.c
+++ b/kernel/time/posix-cpu-timers.c
@@ -333,7 +333,6 @@ static int posix_cpu_clock_get(const clockid_t which_clock, struct timespec *tp)
333 return err; 333 return err;
334} 334}
335 335
336
337/* 336/*
338 * Validate the clockid_t for a new CPU-clock timer, and initialize the timer. 337 * Validate the clockid_t for a new CPU-clock timer, and initialize the timer.
339 * This is called from sys_timer_create() and do_cpu_nanosleep() with the 338 * This is called from sys_timer_create() and do_cpu_nanosleep() with the
@@ -517,6 +516,10 @@ static void arm_timer(struct k_itimer *timer)
517 cputime_expires->sched_exp = exp; 516 cputime_expires->sched_exp = exp;
518 break; 517 break;
519 } 518 }
519 if (CPUCLOCK_PERTHREAD(timer->it_clock))
520 tick_dep_set_task(p, TICK_DEP_BIT_POSIX_TIMER);
521 else
522 tick_dep_set_signal(p->signal, TICK_DEP_BIT_POSIX_TIMER);
520 } 523 }
521} 524}
522 525
@@ -582,39 +585,6 @@ static int cpu_timer_sample_group(const clockid_t which_clock,
582 return 0; 585 return 0;
583} 586}
584 587
585#ifdef CONFIG_NO_HZ_FULL
586static void nohz_kick_work_fn(struct work_struct *work)
587{
588 tick_nohz_full_kick_all();
589}
590
591static DECLARE_WORK(nohz_kick_work, nohz_kick_work_fn);
592
593/*
594 * We need the IPIs to be sent from sane process context.
595 * The posix cpu timers are always set with irqs disabled.
596 */
597static void posix_cpu_timer_kick_nohz(void)
598{
599 if (context_tracking_is_enabled())
600 schedule_work(&nohz_kick_work);
601}
602
603bool posix_cpu_timers_can_stop_tick(struct task_struct *tsk)
604{
605 if (!task_cputime_zero(&tsk->cputime_expires))
606 return false;
607
608 /* Check if cputimer is running. This is accessed without locking. */
609 if (READ_ONCE(tsk->signal->cputimer.running))
610 return false;
611
612 return true;
613}
614#else
615static inline void posix_cpu_timer_kick_nohz(void) { }
616#endif
617
618/* 588/*
619 * Guts of sys_timer_settime for CPU timers. 589 * Guts of sys_timer_settime for CPU timers.
620 * This is called with the timer locked and interrupts disabled. 590 * This is called with the timer locked and interrupts disabled.
@@ -761,8 +731,7 @@ static int posix_cpu_timer_set(struct k_itimer *timer, int timer_flags,
761 sample_to_timespec(timer->it_clock, 731 sample_to_timespec(timer->it_clock,
762 old_incr, &old->it_interval); 732 old_incr, &old->it_interval);
763 } 733 }
764 if (!ret) 734
765 posix_cpu_timer_kick_nohz();
766 return ret; 735 return ret;
767} 736}
768 737
@@ -911,6 +880,8 @@ static void check_thread_timers(struct task_struct *tsk,
911 __group_send_sig_info(SIGXCPU, SEND_SIG_PRIV, tsk); 880 __group_send_sig_info(SIGXCPU, SEND_SIG_PRIV, tsk);
912 } 881 }
913 } 882 }
883 if (task_cputime_zero(tsk_expires))
884 tick_dep_clear_task(tsk, TICK_DEP_BIT_POSIX_TIMER);
914} 885}
915 886
916static inline void stop_process_timers(struct signal_struct *sig) 887static inline void stop_process_timers(struct signal_struct *sig)
@@ -919,6 +890,7 @@ static inline void stop_process_timers(struct signal_struct *sig)
919 890
920 /* Turn off cputimer->running. This is done without locking. */ 891 /* Turn off cputimer->running. This is done without locking. */
921 WRITE_ONCE(cputimer->running, false); 892 WRITE_ONCE(cputimer->running, false);
893 tick_dep_clear_signal(sig, TICK_DEP_BIT_POSIX_TIMER);
922} 894}
923 895
924static u32 onecputick; 896static u32 onecputick;
@@ -1095,8 +1067,6 @@ void posix_cpu_timer_schedule(struct k_itimer *timer)
1095 arm_timer(timer); 1067 arm_timer(timer);
1096 unlock_task_sighand(p, &flags); 1068 unlock_task_sighand(p, &flags);
1097 1069
1098 /* Kick full dynticks CPUs in case they need to tick on the new timer */
1099 posix_cpu_timer_kick_nohz();
1100out: 1070out:
1101 timer->it_overrun_last = timer->it_overrun; 1071 timer->it_overrun_last = timer->it_overrun;
1102 timer->it_overrun = -1; 1072 timer->it_overrun = -1;
@@ -1270,7 +1240,7 @@ void set_process_cpu_timer(struct task_struct *tsk, unsigned int clock_idx,
1270 } 1240 }
1271 1241
1272 if (!*newval) 1242 if (!*newval)
1273 goto out; 1243 return;
1274 *newval += now; 1244 *newval += now;
1275 } 1245 }
1276 1246
@@ -1288,8 +1258,8 @@ void set_process_cpu_timer(struct task_struct *tsk, unsigned int clock_idx,
1288 tsk->signal->cputime_expires.virt_exp = *newval; 1258 tsk->signal->cputime_expires.virt_exp = *newval;
1289 break; 1259 break;
1290 } 1260 }
1291out: 1261
1292 posix_cpu_timer_kick_nohz(); 1262 tick_dep_set_signal(tsk->signal, TICK_DEP_BIT_POSIX_TIMER);
1293} 1263}
1294 1264
1295static int do_cpu_nanosleep(const clockid_t which_clock, int flags, 1265static int do_cpu_nanosleep(const clockid_t which_clock, int flags,