Commit 29f87b793da421a6ab816d991dc8dbf909dfb66a
Committed by
Thomas Gleixner
1 parent
dbb6be6d5e
Exists in
master
and in
39 other branches
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>
Showing 1 changed file with 29 additions and 51 deletions Side-by-side Diff
kernel/posix-cpu-timers.c
... | ... | @@ -1002,16 +1002,9 @@ |
1002 | 1002 | struct thread_group_cputimer *cputimer = &sig->cputimer; |
1003 | 1003 | unsigned long flags; |
1004 | 1004 | |
1005 | - if (!cputimer->running) | |
1006 | - return; | |
1007 | - | |
1008 | 1005 | spin_lock_irqsave(&cputimer->lock, flags); |
1009 | 1006 | cputimer->running = 0; |
1010 | 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 | 1010 | static u32 onecputick; |
... | ... | @@ -1048,6 +1041,23 @@ |
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 | 1062 | * Check for any per-thread CPU timers that have fired and move them |
1053 | 1063 | * off the tsk->*_timers list onto the firing list. Per-thread timers |
... | ... | @@ -1065,19 +1075,6 @@ |
1065 | 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 | 1078 | * Collect the current process totals. |
1082 | 1079 | */ |
1083 | 1080 | thread_group_cputimer(tsk, &cputime); |
... | ... | @@ -1166,18 +1163,11 @@ |
1166 | 1163 | } |
1167 | 1164 | } |
1168 | 1165 | |
1169 | - if (!cputime_eq(prof_expires, cputime_zero) && | |
1170 | - (cputime_eq(sig->cputime_expires.prof_exp, cputime_zero) || | |
1171 | - cputime_gt(sig->cputime_expires.prof_exp, prof_expires))) | |
1172 | - sig->cputime_expires.prof_exp = prof_expires; | |
1173 | - if (!cputime_eq(virt_expires, cputime_zero) && | |
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; | |
1166 | + sig->cputime_expires.prof_exp = prof_expires; | |
1167 | + sig->cputime_expires.virt_exp = virt_expires; | |
1168 | + sig->cputime_expires.sched_exp = sched_expires; | |
1169 | + if (task_cputime_zero(&sig->cputime_expires)) | |
1170 | + stop_process_timers(sig); | |
1181 | 1171 | } |
1182 | 1172 | |
1183 | 1173 | /* |
... | ... | @@ -1250,23 +1240,6 @@ |
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 | 1243 | * task_cputime_expired - Compare two task_cputime entities. |
1271 | 1244 | * |
1272 | 1245 | * @sample: The task_cputime structure to be checked for expiration. |
... | ... | @@ -1322,7 +1295,7 @@ |
1322 | 1295 | } |
1323 | 1296 | |
1324 | 1297 | sig = tsk->signal; |
1325 | - if (!task_cputime_zero(&sig->cputime_expires)) { | |
1298 | + if (sig->cputimer.running) { | |
1326 | 1299 | struct task_cputime group_sample; |
1327 | 1300 | |
1328 | 1301 | thread_group_cputimer(tsk, &group_sample); |
... | ... | @@ -1359,7 +1332,12 @@ |
1359 | 1332 | * put them on the firing list. |
1360 | 1333 | */ |
1361 | 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 | 1343 | * We must release these locks before taking any timer's lock. |