aboutsummaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
authorFrederic Weisbecker <fweisbec@gmail.com>2013-10-10 10:55:57 -0400
committerFrederic Weisbecker <fweisbec@gmail.com>2013-12-09 10:50:57 -0500
commit724a371396e8162cc883a40cd8e525dfc7e5f3ff (patch)
tree5f20611f33667e192b88a061c4215ea1f6600098 /kernel
parenta934a56e1284f1863c9c800ff9c63183c25aec93 (diff)
posix-timers: Remove dead thread posix cpu timers caching
When a task is exiting or has exited, its posix cpu timers don't tick anymore and won't elapse further. It's too late for them to expire. So any further call to timer_gettime() on these timers will return the same remaining expiry time. The current code optimize this by caching the remaining delta and storing it where we use to save the absolute expiration time. This way, the future calls to timer_gettime() won't need to compute the difference between the absolute expiration time and the current time anymore. Now this optimization doesn't seem to bring much value. Computing the timer remaining delta is not very costly. Fetching the timer value OTOH can be costly in two ways: * CPUCLOCK_SCHED read requires to lock the target's rq. But some optimizations are on the way to make task_sched_runtime() not holding the rq lock of a non-running target. * CPUCLOCK_VIRT/CPUCLOCK_PROF read simply consist in fetching current->utime/current->stime except when the system uses full dynticks cputime accounting. The latter requires a per task lock in order to correctly compute user and system time. But once the target is dead, this lock shouldn't be contended anyway. All in one this caching doesn't seem to be justified. Given that it complicates the code significantly for few wins, let's remove it on single thread timers. Signed-off-by: Frederic Weisbecker <fweisbec@gmail.com> Cc: Thomas Gleixner <tglx@linutronix.de> Cc: Ingo Molnar <mingo@kernel.org> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Oleg Nesterov <oleg@redhat.com> Cc: Kosaki Motohiro <kosaki.motohiro@jp.fujitsu.com> Cc: Andrew Morton <akpm@linux-foundation.org>
Diffstat (limited to 'kernel')
-rw-r--r--kernel/posix-cpu-timers.c34
1 files changed, 16 insertions, 18 deletions
diff --git a/kernel/posix-cpu-timers.c b/kernel/posix-cpu-timers.c
index 79747b7d9420..3b7df8653913 100644
--- a/kernel/posix-cpu-timers.c
+++ b/kernel/posix-cpu-timers.c
@@ -788,7 +788,6 @@ static void posix_cpu_timer_get(struct k_itimer *timer, struct itimerspec *itp)
788{ 788{
789 unsigned long long now; 789 unsigned long long now;
790 struct task_struct *p = timer->it.cpu.task; 790 struct task_struct *p = timer->it.cpu.task;
791 int clear_dead;
792 791
793 /* 792 /*
794 * Easy part: convert the reload time. 793 * Easy part: convert the reload time.
@@ -802,6 +801,7 @@ static void posix_cpu_timer_get(struct k_itimer *timer, struct itimerspec *itp)
802 } 801 }
803 802
804 if (unlikely(p == NULL)) { 803 if (unlikely(p == NULL)) {
804 WARN_ON_ONCE(CPUCLOCK_PERTHREAD(timer->it_clock));
805 /* 805 /*
806 * This task already died and the timer will never fire. 806 * This task already died and the timer will never fire.
807 * In this case, expires is actually the dead value. 807 * In this case, expires is actually the dead value.
@@ -817,7 +817,6 @@ static void posix_cpu_timer_get(struct k_itimer *timer, struct itimerspec *itp)
817 */ 817 */
818 if (CPUCLOCK_PERTHREAD(timer->it_clock)) { 818 if (CPUCLOCK_PERTHREAD(timer->it_clock)) {
819 cpu_clock_sample(timer->it_clock, p, &now); 819 cpu_clock_sample(timer->it_clock, p, &now);
820 clear_dead = p->exit_state;
821 } else { 820 } else {
822 read_lock(&tasklist_lock); 821 read_lock(&tasklist_lock);
823 if (unlikely(p->sighand == NULL)) { 822 if (unlikely(p->sighand == NULL)) {
@@ -833,22 +832,20 @@ static void posix_cpu_timer_get(struct k_itimer *timer, struct itimerspec *itp)
833 goto dead; 832 goto dead;
834 } else { 833 } else {
835 cpu_timer_sample_group(timer->it_clock, p, &now); 834 cpu_timer_sample_group(timer->it_clock, p, &now);
836 clear_dead = (unlikely(p->exit_state) && 835 if (unlikely(p->exit_state) && thread_group_empty(p)) {
837 thread_group_empty(p)); 836 read_unlock(&tasklist_lock);
837 /*
838 * We've noticed that the thread is dead, but
839 * not yet reaped. Take this opportunity to
840 * drop our task ref.
841 */
842 clear_dead_task(timer, now);
843 goto dead;
844 }
838 } 845 }
839 read_unlock(&tasklist_lock); 846 read_unlock(&tasklist_lock);
840 } 847 }
841 848
842 if (unlikely(clear_dead)) {
843 /*
844 * We've noticed that the thread is dead, but
845 * not yet reaped. Take this opportunity to
846 * drop our task ref.
847 */
848 clear_dead_task(timer, now);
849 goto dead;
850 }
851
852 if (now < timer->it.cpu.expires) { 849 if (now < timer->it.cpu.expires) {
853 sample_to_timespec(timer->it_clock, 850 sample_to_timespec(timer->it_clock,
854 timer->it.cpu.expires - now, 851 timer->it.cpu.expires - now,
@@ -1063,11 +1060,13 @@ void posix_cpu_timer_schedule(struct k_itimer *timer)
1063 struct task_struct *p = timer->it.cpu.task; 1060 struct task_struct *p = timer->it.cpu.task;
1064 unsigned long long now; 1061 unsigned long long now;
1065 1062
1066 if (unlikely(p == NULL)) 1063 if (unlikely(p == NULL)) {
1064 WARN_ON_ONCE(CPUCLOCK_PERTHREAD(timer->it_clock));
1067 /* 1065 /*
1068 * The task was cleaned up already, no future firings. 1066 * The task was cleaned up already, no future firings.
1069 */ 1067 */
1070 goto out; 1068 goto out;
1069 }
1071 1070
1072 /* 1071 /*
1073 * Fetch the current sample and update the timer's expiry time. 1072 * Fetch the current sample and update the timer's expiry time.
@@ -1075,10 +1074,9 @@ void posix_cpu_timer_schedule(struct k_itimer *timer)
1075 if (CPUCLOCK_PERTHREAD(timer->it_clock)) { 1074 if (CPUCLOCK_PERTHREAD(timer->it_clock)) {
1076 cpu_clock_sample(timer->it_clock, p, &now); 1075 cpu_clock_sample(timer->it_clock, p, &now);
1077 bump_cpu_timer(timer, now); 1076 bump_cpu_timer(timer, now);
1078 if (unlikely(p->exit_state)) { 1077 if (unlikely(p->exit_state))
1079 clear_dead_task(timer, now);
1080 goto out; 1078 goto out;
1081 } 1079
1082 read_lock(&tasklist_lock); /* arm_timer needs it. */ 1080 read_lock(&tasklist_lock); /* arm_timer needs it. */
1083 spin_lock(&p->sighand->siglock); 1081 spin_lock(&p->sighand->siglock);
1084 } else { 1082 } else {