diff options
author | Stanislaw Gruszka <sgruszka@redhat.com> | 2010-03-11 17:04:42 -0500 |
---|---|---|
committer | Thomas Gleixner <tglx@linutronix.de> | 2010-03-12 16:40:41 -0500 |
commit | c28739375bf0d6e239b4fa939ec8372aa2c707d2 (patch) | |
tree | 9d213503878c59b7adc9ca3e0517c566921f3c9a /kernel/posix-cpu-timers.c | |
parent | 1f169f84d25a74fb2dc67274d31d082ce30c60fb (diff) |
cpu-timers: Avoid iterating over all threads in fastpath_timer_check()
Spread p->sighand->siglock locking scope to make sure that
fastpath_timer_check() never iterates over all threads. Without
locking there is small possibility that signal->cputimer will stop
running while we write values to signal->cputime_expires.
Calling thread_group_cputime() from fastpath_timer_check() is not only
bad because it is slow, also it is racy with __exit_signal() which can
lead to invalid signal->{s,u}time values.
Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
Cc: Ingo Molnar <mingo@elte.hu>
Cc: Oleg Nesterov <oleg@redhat.com>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Hidetoshi Seto <seto.hidetoshi@jp.fujitsu.com>
Cc: Balbir Singh <balbir@in.ibm.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Diffstat (limited to 'kernel/posix-cpu-timers.c')
-rw-r--r-- | kernel/posix-cpu-timers.c | 14 |
1 files changed, 7 insertions, 7 deletions
diff --git a/kernel/posix-cpu-timers.c b/kernel/posix-cpu-timers.c index 7d9d0fab1651..564b3b0240dd 100644 --- a/kernel/posix-cpu-timers.c +++ b/kernel/posix-cpu-timers.c | |||
@@ -550,7 +550,7 @@ static inline int expires_gt(cputime_t expires, cputime_t new_exp) | |||
550 | /* | 550 | /* |
551 | * Insert the timer on the appropriate list before any timers that | 551 | * Insert the timer on the appropriate list before any timers that |
552 | * expire later. This must be called with the tasklist_lock held | 552 | * expire later. This must be called with the tasklist_lock held |
553 | * for reading, and interrupts disabled. | 553 | * for reading, interrupts disabled and p->sighand->siglock taken. |
554 | */ | 554 | */ |
555 | static void arm_timer(struct k_itimer *timer) | 555 | static void arm_timer(struct k_itimer *timer) |
556 | { | 556 | { |
@@ -569,9 +569,6 @@ static void arm_timer(struct k_itimer *timer) | |||
569 | } | 569 | } |
570 | head += CPUCLOCK_WHICH(timer->it_clock); | 570 | head += CPUCLOCK_WHICH(timer->it_clock); |
571 | 571 | ||
572 | BUG_ON(!irqs_disabled()); | ||
573 | spin_lock(&p->sighand->siglock); | ||
574 | |||
575 | listpos = head; | 572 | listpos = head; |
576 | list_for_each_entry(next, head, entry) { | 573 | list_for_each_entry(next, head, entry) { |
577 | if (cpu_time_before(timer->it_clock, nt->expires, next->expires)) | 574 | if (cpu_time_before(timer->it_clock, nt->expires, next->expires)) |
@@ -606,8 +603,6 @@ static void arm_timer(struct k_itimer *timer) | |||
606 | break; | 603 | break; |
607 | } | 604 | } |
608 | } | 605 | } |
609 | |||
610 | spin_unlock(&p->sighand->siglock); | ||
611 | } | 606 | } |
612 | 607 | ||
613 | /* | 608 | /* |
@@ -720,7 +715,6 @@ int posix_cpu_timer_set(struct k_itimer *timer, int flags, | |||
720 | ret = TIMER_RETRY; | 715 | ret = TIMER_RETRY; |
721 | } else | 716 | } else |
722 | list_del_init(&timer->it.cpu.entry); | 717 | list_del_init(&timer->it.cpu.entry); |
723 | spin_unlock(&p->sighand->siglock); | ||
724 | 718 | ||
725 | /* | 719 | /* |
726 | * We need to sample the current value to convert the new | 720 | * We need to sample the current value to convert the new |
@@ -774,6 +768,7 @@ int posix_cpu_timer_set(struct k_itimer *timer, int flags, | |||
774 | * disable this firing since we are already reporting | 768 | * disable this firing since we are already reporting |
775 | * it as an overrun (thanks to bump_cpu_timer above). | 769 | * it as an overrun (thanks to bump_cpu_timer above). |
776 | */ | 770 | */ |
771 | spin_unlock(&p->sighand->siglock); | ||
777 | read_unlock(&tasklist_lock); | 772 | read_unlock(&tasklist_lock); |
778 | goto out; | 773 | goto out; |
779 | } | 774 | } |
@@ -793,6 +788,7 @@ int posix_cpu_timer_set(struct k_itimer *timer, int flags, | |||
793 | arm_timer(timer); | 788 | arm_timer(timer); |
794 | } | 789 | } |
795 | 790 | ||
791 | spin_unlock(&p->sighand->siglock); | ||
796 | read_unlock(&tasklist_lock); | 792 | read_unlock(&tasklist_lock); |
797 | 793 | ||
798 | /* | 794 | /* |
@@ -1206,6 +1202,7 @@ void posix_cpu_timer_schedule(struct k_itimer *timer) | |||
1206 | goto out; | 1202 | goto out; |
1207 | } | 1203 | } |
1208 | read_lock(&tasklist_lock); /* arm_timer needs it. */ | 1204 | read_lock(&tasklist_lock); /* arm_timer needs it. */ |
1205 | spin_lock(&p->sighand->siglock); | ||
1209 | } else { | 1206 | } else { |
1210 | read_lock(&tasklist_lock); | 1207 | read_lock(&tasklist_lock); |
1211 | if (unlikely(p->signal == NULL)) { | 1208 | if (unlikely(p->signal == NULL)) { |
@@ -1226,6 +1223,7 @@ void posix_cpu_timer_schedule(struct k_itimer *timer) | |||
1226 | clear_dead_task(timer, now); | 1223 | clear_dead_task(timer, now); |
1227 | goto out_unlock; | 1224 | goto out_unlock; |
1228 | } | 1225 | } |
1226 | spin_lock(&p->sighand->siglock); | ||
1229 | cpu_timer_sample_group(timer->it_clock, p, &now); | 1227 | cpu_timer_sample_group(timer->it_clock, p, &now); |
1230 | bump_cpu_timer(timer, now); | 1228 | bump_cpu_timer(timer, now); |
1231 | /* Leave the tasklist_lock locked for the call below. */ | 1229 | /* Leave the tasklist_lock locked for the call below. */ |
@@ -1234,7 +1232,9 @@ void posix_cpu_timer_schedule(struct k_itimer *timer) | |||
1234 | /* | 1232 | /* |
1235 | * Now re-arm for the new expiry time. | 1233 | * Now re-arm for the new expiry time. |
1236 | */ | 1234 | */ |
1235 | BUG_ON(!irqs_disabled()); | ||
1237 | arm_timer(timer); | 1236 | arm_timer(timer); |
1237 | spin_unlock(&p->sighand->siglock); | ||
1238 | 1238 | ||
1239 | out_unlock: | 1239 | out_unlock: |
1240 | read_unlock(&tasklist_lock); | 1240 | read_unlock(&tasklist_lock); |