Commit 29f87b793da421a6ab816d991dc8dbf909dfb66a

Authored by Stanislaw Gruszka
Committed by Thomas Gleixner
1 parent dbb6be6d5e

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.