diff options
author | Stanislaw Gruszka <sgruszka@redhat.com> | 2010-04-27 17:12:15 -0400 |
---|---|---|
committer | Thomas Gleixner <tglx@linutronix.de> | 2010-05-10 08:24:26 -0400 |
commit | 29f87b793da421a6ab816d991dc8dbf909dfb66a (patch) | |
tree | 807e95b5f7a41f163000d24f82e85afa96eccdd2 /kernel/posix-cpu-timers.c | |
parent | dbb6be6d5e974c42bbecd183effaa0df69e1dd8b (diff) |
posix-cpu-timers: Optimize run_posix_cpu_timers()
We can optimize and simplify things taking into account signal->cputimer
is always running when we have configured any process wide cpu timer.
In check_process_timers(), we don't have to check if new updated value of
signal->cputime_expires is smaller, since we maintain new first expiration
time ({prof,virt,sched}_expires) in code flow and all other writes to
expiration cache are protected by sighand->siglock .
Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
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 | 80 |
1 files changed, 29 insertions, 51 deletions
diff --git a/kernel/posix-cpu-timers.c b/kernel/posix-cpu-timers.c index 799f360d1475..00bb252f29a2 100644 --- a/kernel/posix-cpu-timers.c +++ b/kernel/posix-cpu-timers.c | |||
@@ -1002,16 +1002,9 @@ static void stop_process_timers(struct signal_struct *sig) | |||
1002 | struct thread_group_cputimer *cputimer = &sig->cputimer; | 1002 | struct thread_group_cputimer *cputimer = &sig->cputimer; |
1003 | unsigned long flags; | 1003 | unsigned long flags; |
1004 | 1004 | ||
1005 | if (!cputimer->running) | ||
1006 | return; | ||
1007 | |||
1008 | spin_lock_irqsave(&cputimer->lock, flags); | 1005 | spin_lock_irqsave(&cputimer->lock, flags); |
1009 | cputimer->running = 0; | 1006 | cputimer->running = 0; |
1010 | spin_unlock_irqrestore(&cputimer->lock, flags); | 1007 | spin_unlock_irqrestore(&cputimer->lock, flags); |
1011 | |||
1012 | sig->cputime_expires.prof_exp = cputime_zero; | ||
1013 | sig->cputime_expires.virt_exp = cputime_zero; | ||
1014 | sig->cputime_expires.sched_exp = 0; | ||
1015 | } | 1008 | } |
1016 | 1009 | ||
1017 | static u32 onecputick; | 1010 | static u32 onecputick; |
@@ -1048,6 +1041,23 @@ static void check_cpu_itimer(struct task_struct *tsk, struct cpu_itimer *it, | |||
1048 | } | 1041 | } |
1049 | } | 1042 | } |
1050 | 1043 | ||
1044 | /** | ||
1045 | * task_cputime_zero - Check a task_cputime struct for all zero fields. | ||
1046 | * | ||
1047 | * @cputime: The struct to compare. | ||
1048 | * | ||
1049 | * Checks @cputime to see if all fields are zero. Returns true if all fields | ||
1050 | * are zero, false if any field is nonzero. | ||
1051 | */ | ||
1052 | static inline int task_cputime_zero(const struct task_cputime *cputime) | ||
1053 | { | ||
1054 | if (cputime_eq(cputime->utime, cputime_zero) && | ||
1055 | cputime_eq(cputime->stime, cputime_zero) && | ||
1056 | cputime->sum_exec_runtime == 0) | ||
1057 | return 1; | ||
1058 | return 0; | ||
1059 | } | ||
1060 | |||
1051 | /* | 1061 | /* |
1052 | * Check for any per-thread CPU timers that have fired and move them | 1062 | * Check for any per-thread CPU timers that have fired and move them |
1053 | * off the tsk->*_timers list onto the firing list. Per-thread timers | 1063 | * off the tsk->*_timers list onto the firing list. Per-thread timers |
@@ -1065,19 +1075,6 @@ static void check_process_timers(struct task_struct *tsk, | |||
1065 | unsigned long soft; | 1075 | unsigned long soft; |
1066 | 1076 | ||
1067 | /* | 1077 | /* |
1068 | * Don't sample the current process CPU clocks if there are no timers. | ||
1069 | */ | ||
1070 | if (list_empty(&timers[CPUCLOCK_PROF]) && | ||
1071 | cputime_eq(sig->it[CPUCLOCK_PROF].expires, cputime_zero) && | ||
1072 | sig->rlim[RLIMIT_CPU].rlim_cur == RLIM_INFINITY && | ||
1073 | list_empty(&timers[CPUCLOCK_VIRT]) && | ||
1074 | cputime_eq(sig->it[CPUCLOCK_VIRT].expires, cputime_zero) && | ||
1075 | list_empty(&timers[CPUCLOCK_SCHED])) { | ||
1076 | stop_process_timers(sig); | ||
1077 | return; | ||
1078 | } | ||
1079 | |||
1080 | /* | ||
1081 | * Collect the current process totals. | 1078 | * Collect the current process totals. |
1082 | */ | 1079 | */ |
1083 | thread_group_cputimer(tsk, &cputime); | 1080 | thread_group_cputimer(tsk, &cputime); |
@@ -1166,18 +1163,11 @@ static void check_process_timers(struct task_struct *tsk, | |||
1166 | } | 1163 | } |
1167 | } | 1164 | } |
1168 | 1165 | ||
1169 | if (!cputime_eq(prof_expires, cputime_zero) && | 1166 | sig->cputime_expires.prof_exp = prof_expires; |
1170 | (cputime_eq(sig->cputime_expires.prof_exp, cputime_zero) || | 1167 | sig->cputime_expires.virt_exp = virt_expires; |
1171 | cputime_gt(sig->cputime_expires.prof_exp, prof_expires))) | 1168 | sig->cputime_expires.sched_exp = sched_expires; |
1172 | sig->cputime_expires.prof_exp = prof_expires; | 1169 | if (task_cputime_zero(&sig->cputime_expires)) |
1173 | if (!cputime_eq(virt_expires, cputime_zero) && | 1170 | stop_process_timers(sig); |
1174 | (cputime_eq(sig->cputime_expires.virt_exp, cputime_zero) || | ||
1175 | cputime_gt(sig->cputime_expires.virt_exp, virt_expires))) | ||
1176 | sig->cputime_expires.virt_exp = virt_expires; | ||
1177 | if (sched_expires != 0 && | ||
1178 | (sig->cputime_expires.sched_exp == 0 || | ||
1179 | sig->cputime_expires.sched_exp > sched_expires)) | ||
1180 | sig->cputime_expires.sched_exp = sched_expires; | ||
1181 | } | 1171 | } |
1182 | 1172 | ||
1183 | /* | 1173 | /* |
@@ -1250,23 +1240,6 @@ out: | |||
1250 | } | 1240 | } |
1251 | 1241 | ||
1252 | /** | 1242 | /** |
1253 | * task_cputime_zero - Check a task_cputime struct for all zero fields. | ||
1254 | * | ||
1255 | * @cputime: The struct to compare. | ||
1256 | * | ||
1257 | * Checks @cputime to see if all fields are zero. Returns true if all fields | ||
1258 | * are zero, false if any field is nonzero. | ||
1259 | */ | ||
1260 | static inline int task_cputime_zero(const struct task_cputime *cputime) | ||
1261 | { | ||
1262 | if (cputime_eq(cputime->utime, cputime_zero) && | ||
1263 | cputime_eq(cputime->stime, cputime_zero) && | ||
1264 | cputime->sum_exec_runtime == 0) | ||
1265 | return 1; | ||
1266 | return 0; | ||
1267 | } | ||
1268 | |||
1269 | /** | ||
1270 | * task_cputime_expired - Compare two task_cputime entities. | 1243 | * task_cputime_expired - Compare two task_cputime entities. |
1271 | * | 1244 | * |
1272 | * @sample: The task_cputime structure to be checked for expiration. | 1245 | * @sample: The task_cputime structure to be checked for expiration. |
@@ -1322,7 +1295,7 @@ static inline int fastpath_timer_check(struct task_struct *tsk) | |||
1322 | } | 1295 | } |
1323 | 1296 | ||
1324 | sig = tsk->signal; | 1297 | sig = tsk->signal; |
1325 | if (!task_cputime_zero(&sig->cputime_expires)) { | 1298 | if (sig->cputimer.running) { |
1326 | struct task_cputime group_sample; | 1299 | struct task_cputime group_sample; |
1327 | 1300 | ||
1328 | thread_group_cputimer(tsk, &group_sample); | 1301 | thread_group_cputimer(tsk, &group_sample); |
@@ -1359,7 +1332,12 @@ void run_posix_cpu_timers(struct task_struct *tsk) | |||
1359 | * put them on the firing list. | 1332 | * put them on the firing list. |
1360 | */ | 1333 | */ |
1361 | check_thread_timers(tsk, &firing); | 1334 | check_thread_timers(tsk, &firing); |
1362 | check_process_timers(tsk, &firing); | 1335 | /* |
1336 | * If there are any active process wide timers (POSIX 1.b, itimers, | ||
1337 | * RLIMIT_CPU) cputimer must be running. | ||
1338 | */ | ||
1339 | if (tsk->signal->cputimer.running) | ||
1340 | check_process_timers(tsk, &firing); | ||
1363 | 1341 | ||
1364 | /* | 1342 | /* |
1365 | * We must release these locks before taking any timer's lock. | 1343 | * We must release these locks before taking any timer's lock. |