diff options
| author | Stanislaw Gruszka <sgruszka@redhat.com> | 2010-03-11 17:04:37 -0500 |
|---|---|---|
| committer | Thomas Gleixner <tglx@linutronix.de> | 2010-03-12 16:40:39 -0500 |
| commit | f55db609042faecd5e518ce372b87f846659b32e (patch) | |
| tree | ca544704af0825aad53d39fa517a945ba89e59ad /kernel | |
| parent | 522dba7134d6b2e5821d3457f7941ec34f668e6d (diff) | |
cpu-timers: Simplify RLIMIT_CPU handling
Let always set signal->cputime_expires expiration cache when setting
new itimer, POSIX 1.b timer, and RLIMIT_CPU. Since we are
initializing prof_exp expiration cache during fork(), this allows to
remove "RLIMIT_CPU != inf" check from fastpath_timer_check() and do
some other cleanups.
Checked against regression using test cases from:
http://marc.info/?l=linux-kernel&m=123749066504641&w=4
http://marc.info/?l=linux-kernel&m=123811277916642&w=2
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')
| -rw-r--r-- | kernel/posix-cpu-timers.c | 75 |
1 files changed, 27 insertions, 48 deletions
diff --git a/kernel/posix-cpu-timers.c b/kernel/posix-cpu-timers.c index 1a22dfd42df9..d01e0a348e61 100644 --- a/kernel/posix-cpu-timers.c +++ b/kernel/posix-cpu-timers.c | |||
| @@ -11,19 +11,18 @@ | |||
| 11 | #include <trace/events/timer.h> | 11 | #include <trace/events/timer.h> |
| 12 | 12 | ||
| 13 | /* | 13 | /* |
| 14 | * Called after updating RLIMIT_CPU to set timer expiration if necessary. | 14 | * Called after updating RLIMIT_CPU to run cpu timer and update |
| 15 | * tsk->signal->cputime_expires expiration cache if necessary. Needs | ||
| 16 | * siglock protection since other code may update expiration cache as | ||
| 17 | * well. | ||
| 15 | */ | 18 | */ |
| 16 | void update_rlimit_cpu(unsigned long rlim_new) | 19 | void update_rlimit_cpu(unsigned long rlim_new) |
| 17 | { | 20 | { |
| 18 | cputime_t cputime = secs_to_cputime(rlim_new); | 21 | cputime_t cputime = secs_to_cputime(rlim_new); |
| 19 | struct signal_struct *const sig = current->signal; | ||
| 20 | 22 | ||
| 21 | if (cputime_eq(sig->it[CPUCLOCK_PROF].expires, cputime_zero) || | 23 | spin_lock_irq(¤t->sighand->siglock); |
| 22 | cputime_gt(sig->it[CPUCLOCK_PROF].expires, cputime)) { | 24 | set_process_cpu_timer(current, CPUCLOCK_PROF, &cputime, NULL); |
| 23 | spin_lock_irq(¤t->sighand->siglock); | 25 | spin_unlock_irq(¤t->sighand->siglock); |
| 24 | set_process_cpu_timer(current, CPUCLOCK_PROF, &cputime, NULL); | ||
| 25 | spin_unlock_irq(¤t->sighand->siglock); | ||
| 26 | } | ||
| 27 | } | 26 | } |
| 28 | 27 | ||
| 29 | static int check_clock(const clockid_t which_clock) | 28 | static int check_clock(const clockid_t which_clock) |
| @@ -564,7 +563,6 @@ static void arm_timer(struct k_itimer *timer, union cpu_time_count now) | |||
| 564 | struct list_head *head, *listpos; | 563 | struct list_head *head, *listpos; |
| 565 | struct cpu_timer_list *const nt = &timer->it.cpu; | 564 | struct cpu_timer_list *const nt = &timer->it.cpu; |
| 566 | struct cpu_timer_list *next; | 565 | struct cpu_timer_list *next; |
| 567 | unsigned long i; | ||
| 568 | 566 | ||
| 569 | head = (CPUCLOCK_PERTHREAD(timer->it_clock) ? | 567 | head = (CPUCLOCK_PERTHREAD(timer->it_clock) ? |
| 570 | p->cpu_timers : p->signal->cpu_timers); | 568 | p->cpu_timers : p->signal->cpu_timers); |
| @@ -630,20 +628,11 @@ static void arm_timer(struct k_itimer *timer, union cpu_time_count now) | |||
| 630 | default: | 628 | default: |
| 631 | BUG(); | 629 | BUG(); |
| 632 | case CPUCLOCK_VIRT: | 630 | case CPUCLOCK_VIRT: |
| 633 | if (expires_le(sig->it[CPUCLOCK_VIRT].expires, | 631 | if (expires_gt(sig->cputime_expires.virt_exp, exp->cpu)) |
| 634 | exp->cpu)) | 632 | sig->cputime_expires.virt_exp = exp->cpu; |
| 635 | break; | ||
| 636 | sig->cputime_expires.virt_exp = exp->cpu; | ||
| 637 | break; | ||
| 638 | case CPUCLOCK_PROF: | 633 | case CPUCLOCK_PROF: |
| 639 | if (expires_le(sig->it[CPUCLOCK_PROF].expires, | 634 | if (expires_gt(sig->cputime_expires.prof_exp, exp->cpu)) |
| 640 | exp->cpu)) | 635 | sig->cputime_expires.prof_exp = exp->cpu; |
| 641 | break; | ||
| 642 | i = sig->rlim[RLIMIT_CPU].rlim_cur; | ||
| 643 | if (i != RLIM_INFINITY && | ||
| 644 | i <= cputime_to_secs(exp->cpu)) | ||
| 645 | break; | ||
| 646 | sig->cputime_expires.prof_exp = exp->cpu; | ||
| 647 | break; | 636 | break; |
| 648 | case CPUCLOCK_SCHED: | 637 | case CPUCLOCK_SCHED: |
| 649 | sig->cputime_expires.sched_exp = exp->sched; | 638 | sig->cputime_expires.sched_exp = exp->sched; |
| @@ -1386,7 +1375,7 @@ static inline int fastpath_timer_check(struct task_struct *tsk) | |||
| 1386 | return 1; | 1375 | return 1; |
| 1387 | } | 1376 | } |
| 1388 | 1377 | ||
| 1389 | return sig->rlim[RLIMIT_CPU].rlim_cur != RLIM_INFINITY; | 1378 | return 0; |
| 1390 | } | 1379 | } |
| 1391 | 1380 | ||
| 1392 | /* | 1381 | /* |
| @@ -1452,21 +1441,23 @@ void run_posix_cpu_timers(struct task_struct *tsk) | |||
| 1452 | } | 1441 | } |
| 1453 | 1442 | ||
| 1454 | /* | 1443 | /* |
| 1455 | * Set one of the process-wide special case CPU timers. | 1444 | * Set one of the process-wide special case CPU timers or RLIMIT_CPU. |
| 1456 | * The tsk->sighand->siglock must be held by the caller. | 1445 | * The tsk->sighand->siglock must be held by the caller. |
| 1457 | * The *newval argument is relative and we update it to be absolute, *oldval | ||
| 1458 | * is absolute and we update it to be relative. | ||
| 1459 | */ | 1446 | */ |
| 1460 | void set_process_cpu_timer(struct task_struct *tsk, unsigned int clock_idx, | 1447 | void set_process_cpu_timer(struct task_struct *tsk, unsigned int clock_idx, |
| 1461 | cputime_t *newval, cputime_t *oldval) | 1448 | cputime_t *newval, cputime_t *oldval) |
| 1462 | { | 1449 | { |
| 1463 | union cpu_time_count now; | 1450 | union cpu_time_count now; |
| 1464 | struct list_head *head; | ||
| 1465 | 1451 | ||
| 1466 | BUG_ON(clock_idx == CPUCLOCK_SCHED); | 1452 | BUG_ON(clock_idx == CPUCLOCK_SCHED); |
| 1467 | cpu_timer_sample_group(clock_idx, tsk, &now); | 1453 | cpu_timer_sample_group(clock_idx, tsk, &now); |
| 1468 | 1454 | ||
| 1469 | if (oldval) { | 1455 | if (oldval) { |
| 1456 | /* | ||
| 1457 | * We are setting itimer. The *oldval is absolute and we update | ||
| 1458 | * it to be relative, *newval argument is relative and we update | ||
| 1459 | * it to be absolute. | ||
| 1460 | */ | ||
| 1470 | if (!cputime_eq(*oldval, cputime_zero)) { | 1461 | if (!cputime_eq(*oldval, cputime_zero)) { |
| 1471 | if (cputime_le(*oldval, now.cpu)) { | 1462 | if (cputime_le(*oldval, now.cpu)) { |
| 1472 | /* Just about to fire. */ | 1463 | /* Just about to fire. */ |
| @@ -1479,33 +1470,21 @@ void set_process_cpu_timer(struct task_struct *tsk, unsigned int clock_idx, | |||
| 1479 | if (cputime_eq(*newval, cputime_zero)) | 1470 | if (cputime_eq(*newval, cputime_zero)) |
| 1480 | return; | 1471 | return; |
| 1481 | *newval = cputime_add(*newval, now.cpu); | 1472 | *newval = cputime_add(*newval, now.cpu); |
| 1482 | |||
| 1483 | /* | ||
| 1484 | * If the RLIMIT_CPU timer will expire before the | ||
| 1485 | * ITIMER_PROF timer, we have nothing else to do. | ||
| 1486 | */ | ||
| 1487 | if (tsk->signal->rlim[RLIMIT_CPU].rlim_cur | ||
| 1488 | < cputime_to_secs(*newval)) | ||
| 1489 | return; | ||
| 1490 | } | 1473 | } |
| 1491 | 1474 | ||
| 1492 | /* | 1475 | /* |
| 1493 | * Check whether there are any process timers already set to fire | 1476 | * Update expiration cache if we are the earliest timer, or eventually |
| 1494 | * before this one. If so, we don't have anything more to do. | 1477 | * RLIMIT_CPU limit is earlier than prof_exp cpu timer expire. |
| 1495 | */ | 1478 | */ |
| 1496 | head = &tsk->signal->cpu_timers[clock_idx]; | 1479 | switch (clock_idx) { |
| 1497 | if (list_empty(head) || | 1480 | case CPUCLOCK_PROF: |
| 1498 | cputime_ge(list_first_entry(head, | 1481 | if (expires_gt(tsk->signal->cputime_expires.prof_exp, *newval)) |
| 1499 | struct cpu_timer_list, entry)->expires.cpu, | ||
| 1500 | *newval)) { | ||
| 1501 | switch (clock_idx) { | ||
| 1502 | case CPUCLOCK_PROF: | ||
| 1503 | tsk->signal->cputime_expires.prof_exp = *newval; | 1482 | tsk->signal->cputime_expires.prof_exp = *newval; |
| 1504 | break; | 1483 | break; |
| 1505 | case CPUCLOCK_VIRT: | 1484 | case CPUCLOCK_VIRT: |
| 1485 | if (expires_gt(tsk->signal->cputime_expires.virt_exp, *newval)) | ||
| 1506 | tsk->signal->cputime_expires.virt_exp = *newval; | 1486 | tsk->signal->cputime_expires.virt_exp = *newval; |
| 1507 | break; | 1487 | break; |
| 1508 | } | ||
| 1509 | } | 1488 | } |
| 1510 | } | 1489 | } |
| 1511 | 1490 | ||
