diff options
| author | KOSAKI Motohiro <kosaki.motohiro@jp.fujitsu.com> | 2013-05-26 17:35:41 -0400 |
|---|---|---|
| committer | Frederic Weisbecker <fweisbec@gmail.com> | 2013-07-04 12:02:30 -0400 |
| commit | fa18f7bde3ad4568d1d343b60d963bfbd8dc3991 (patch) | |
| tree | aa51270ce1fcc53f2547571b615a53e4e1bce464 /kernel | |
| parent | a0b2062b0904ef07944c4a6e4d0f88ee44f1e9f2 (diff) | |
posix-cpu-timers: don't account cpu timer after stopped thread runtime accounting
When tsk->signal->cputimer->running is 1, signal->cputimer (i.e. per process
timer account) and tsk->sum_sched_runtime (i.e. per thread timer account)
increase at the same pace because update_curr() increases both accounting.
However, there is one exception. When thread exiting, __exit_signal() turns
over task's sum_shced_runtime to sig->sum_sched_runtime, but it doesn't stop
signal->cputimer accounting.
This inconsistency makes POSIX timer wake up too early. This patch fixes it.
Original-patch-by: Olivier Langlois <olivier@trillion01.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Ingo Molnar <mingo@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Acked-by: Peter Zijlstra <peterz@infradead.org>
Signed-off-by: Olivier Langlois <olivier@trillion01.com>
Signed-off-by: KOSAKI Motohiro <kosaki.motohiro@jp.fujitsu.com>
Signed-off-by: Frederic Weisbecker <fweisbec@gmail.com>
Diffstat (limited to 'kernel')
| -rw-r--r-- | kernel/sched/stats.h | 39 |
1 files changed, 36 insertions, 3 deletions
diff --git a/kernel/sched/stats.h b/kernel/sched/stats.h index 2ef90a51ec5e..71bac979d5ee 100644 --- a/kernel/sched/stats.h +++ b/kernel/sched/stats.h | |||
| @@ -162,6 +162,39 @@ sched_info_switch(struct task_struct *prev, struct task_struct *next) | |||
| 162 | */ | 162 | */ |
| 163 | 163 | ||
| 164 | /** | 164 | /** |
| 165 | * cputimer_running - return true if cputimer is running | ||
| 166 | * | ||
| 167 | * @tsk: Pointer to target task. | ||
| 168 | */ | ||
| 169 | static inline bool cputimer_running(struct task_struct *tsk) | ||
| 170 | |||
| 171 | { | ||
| 172 | struct thread_group_cputimer *cputimer = &tsk->signal->cputimer; | ||
| 173 | |||
| 174 | if (!cputimer->running) | ||
| 175 | return false; | ||
| 176 | |||
| 177 | /* | ||
| 178 | * After we flush the task's sum_exec_runtime to sig->sum_sched_runtime | ||
| 179 | * in __exit_signal(), we won't account to the signal struct further | ||
| 180 | * cputime consumed by that task, even though the task can still be | ||
| 181 | * ticking after __exit_signal(). | ||
| 182 | * | ||
| 183 | * In order to keep a consistent behaviour between thread group cputime | ||
| 184 | * and thread group cputimer accounting, lets also ignore the cputime | ||
| 185 | * elapsing after __exit_signal() in any thread group timer running. | ||
| 186 | * | ||
| 187 | * This makes sure that POSIX CPU clocks and timers are synchronized, so | ||
| 188 | * that a POSIX CPU timer won't expire while the corresponding POSIX CPU | ||
| 189 | * clock delta is behind the expiring timer value. | ||
| 190 | */ | ||
| 191 | if (unlikely(!tsk->sighand)) | ||
| 192 | return false; | ||
| 193 | |||
| 194 | return true; | ||
| 195 | } | ||
| 196 | |||
| 197 | /** | ||
| 165 | * account_group_user_time - Maintain utime for a thread group. | 198 | * account_group_user_time - Maintain utime for a thread group. |
| 166 | * | 199 | * |
| 167 | * @tsk: Pointer to task structure. | 200 | * @tsk: Pointer to task structure. |
| @@ -176,7 +209,7 @@ static inline void account_group_user_time(struct task_struct *tsk, | |||
| 176 | { | 209 | { |
| 177 | struct thread_group_cputimer *cputimer = &tsk->signal->cputimer; | 210 | struct thread_group_cputimer *cputimer = &tsk->signal->cputimer; |
| 178 | 211 | ||
| 179 | if (!cputimer->running) | 212 | if (!cputimer_running(tsk)) |
| 180 | return; | 213 | return; |
| 181 | 214 | ||
| 182 | raw_spin_lock(&cputimer->lock); | 215 | raw_spin_lock(&cputimer->lock); |
| @@ -199,7 +232,7 @@ static inline void account_group_system_time(struct task_struct *tsk, | |||
| 199 | { | 232 | { |
| 200 | struct thread_group_cputimer *cputimer = &tsk->signal->cputimer; | 233 | struct thread_group_cputimer *cputimer = &tsk->signal->cputimer; |
| 201 | 234 | ||
| 202 | if (!cputimer->running) | 235 | if (!cputimer_running(tsk)) |
| 203 | return; | 236 | return; |
| 204 | 237 | ||
| 205 | raw_spin_lock(&cputimer->lock); | 238 | raw_spin_lock(&cputimer->lock); |
| @@ -222,7 +255,7 @@ static inline void account_group_exec_runtime(struct task_struct *tsk, | |||
| 222 | { | 255 | { |
| 223 | struct thread_group_cputimer *cputimer = &tsk->signal->cputimer; | 256 | struct thread_group_cputimer *cputimer = &tsk->signal->cputimer; |
| 224 | 257 | ||
| 225 | if (!cputimer->running) | 258 | if (!cputimer_running(tsk)) |
| 226 | return; | 259 | return; |
| 227 | 260 | ||
| 228 | raw_spin_lock(&cputimer->lock); | 261 | raw_spin_lock(&cputimer->lock); |
