diff options
| -rw-r--r-- | kernel/posix-cpu-timers.c | 104 |
1 files changed, 35 insertions, 69 deletions
diff --git a/kernel/posix-cpu-timers.c b/kernel/posix-cpu-timers.c index d01e0a348e61..7c7166f766cc 100644 --- a/kernel/posix-cpu-timers.c +++ b/kernel/posix-cpu-timers.c | |||
| @@ -547,97 +547,63 @@ static inline int expires_gt(cputime_t expires, cputime_t new_exp) | |||
| 547 | cputime_gt(expires, new_exp); | 547 | cputime_gt(expires, new_exp); |
| 548 | } | 548 | } |
| 549 | 549 | ||
| 550 | static inline int expires_le(cputime_t expires, cputime_t new_exp) | ||
| 551 | { | ||
| 552 | return !cputime_eq(expires, cputime_zero) && | ||
| 553 | cputime_le(expires, new_exp); | ||
| 554 | } | ||
| 555 | /* | 550 | /* |
| 556 | * Insert the timer on the appropriate list before any timers that | 551 | * Insert the timer on the appropriate list before any timers that |
| 557 | * expire later. This must be called with the tasklist_lock held | 552 | * expire later. This must be called with the tasklist_lock held |
| 558 | * for reading, and interrupts disabled. | 553 | * for reading, and interrupts disabled. |
| 559 | */ | 554 | */ |
| 560 | static void arm_timer(struct k_itimer *timer, union cpu_time_count now) | 555 | static void arm_timer(struct k_itimer *timer) |
| 561 | { | 556 | { |
| 562 | struct task_struct *p = timer->it.cpu.task; | 557 | struct task_struct *p = timer->it.cpu.task; |
| 563 | struct list_head *head, *listpos; | 558 | struct list_head *head, *listpos; |
| 559 | struct task_cputime *cputime_expires; | ||
| 564 | struct cpu_timer_list *const nt = &timer->it.cpu; | 560 | struct cpu_timer_list *const nt = &timer->it.cpu; |
| 565 | struct cpu_timer_list *next; | 561 | struct cpu_timer_list *next; |
| 566 | 562 | ||
| 567 | head = (CPUCLOCK_PERTHREAD(timer->it_clock) ? | 563 | if (CPUCLOCK_PERTHREAD(timer->it_clock)) { |
| 568 | p->cpu_timers : p->signal->cpu_timers); | 564 | head = p->cpu_timers; |
| 565 | cputime_expires = &p->cputime_expires; | ||
| 566 | } else { | ||
| 567 | head = p->signal->cpu_timers; | ||
| 568 | cputime_expires = &p->signal->cputime_expires; | ||
| 569 | } | ||
| 569 | head += CPUCLOCK_WHICH(timer->it_clock); | 570 | head += CPUCLOCK_WHICH(timer->it_clock); |
| 570 | 571 | ||
| 571 | BUG_ON(!irqs_disabled()); | 572 | BUG_ON(!irqs_disabled()); |
| 572 | spin_lock(&p->sighand->siglock); | 573 | spin_lock(&p->sighand->siglock); |
| 573 | 574 | ||
| 574 | listpos = head; | 575 | listpos = head; |
| 575 | if (CPUCLOCK_WHICH(timer->it_clock) == CPUCLOCK_SCHED) { | 576 | list_for_each_entry(next, head, entry) { |
| 576 | list_for_each_entry(next, head, entry) { | 577 | if (cpu_time_before(timer->it_clock, nt->expires, next->expires)) |
| 577 | if (next->expires.sched > nt->expires.sched) | 578 | break; |
| 578 | break; | 579 | listpos = &next->entry; |
| 579 | listpos = &next->entry; | ||
| 580 | } | ||
| 581 | } else { | ||
| 582 | list_for_each_entry(next, head, entry) { | ||
| 583 | if (cputime_gt(next->expires.cpu, nt->expires.cpu)) | ||
| 584 | break; | ||
| 585 | listpos = &next->entry; | ||
| 586 | } | ||
| 587 | } | 580 | } |
| 588 | list_add(&nt->entry, listpos); | 581 | list_add(&nt->entry, listpos); |
| 589 | 582 | ||
| 590 | if (listpos == head) { | 583 | if (listpos == head) { |
| 584 | union cpu_time_count *exp = &nt->expires; | ||
| 585 | |||
| 591 | /* | 586 | /* |
| 592 | * We are the new earliest-expiring timer. | 587 | * We are the new earliest-expiring POSIX 1.b timer, hence |
| 593 | * If we are a thread timer, there can always | 588 | * need to update expiration cache. Take into account that |
| 594 | * be a process timer telling us to stop earlier. | 589 | * for process timers we share expiration cache with itimers |
| 590 | * and RLIMIT_CPU and for thread timers with RLIMIT_RTTIME. | ||
| 595 | */ | 591 | */ |
| 596 | 592 | ||
| 597 | if (CPUCLOCK_PERTHREAD(timer->it_clock)) { | 593 | switch (CPUCLOCK_WHICH(timer->it_clock)) { |
| 598 | union cpu_time_count *exp = &nt->expires; | 594 | case CPUCLOCK_PROF: |
| 599 | 595 | if (expires_gt(cputime_expires->prof_exp, exp->cpu)) | |
| 600 | switch (CPUCLOCK_WHICH(timer->it_clock)) { | 596 | cputime_expires->prof_exp = exp->cpu; |
| 601 | default: | 597 | break; |
| 602 | BUG(); | 598 | case CPUCLOCK_VIRT: |
| 603 | case CPUCLOCK_PROF: | 599 | if (expires_gt(cputime_expires->virt_exp, exp->cpu)) |
| 604 | if (expires_gt(p->cputime_expires.prof_exp, | 600 | cputime_expires->virt_exp = exp->cpu; |
| 605 | exp->cpu)) | 601 | break; |
| 606 | p->cputime_expires.prof_exp = exp->cpu; | 602 | case CPUCLOCK_SCHED: |
| 607 | break; | 603 | if (cputime_expires->sched_exp == 0 || |
| 608 | case CPUCLOCK_VIRT: | 604 | cputime_expires->sched_exp > exp->sched) |
| 609 | if (expires_gt(p->cputime_expires.virt_exp, | 605 | cputime_expires->sched_exp = exp->sched; |
| 610 | exp->cpu)) | 606 | break; |
| 611 | p->cputime_expires.virt_exp = exp->cpu; | ||
| 612 | break; | ||
| 613 | case CPUCLOCK_SCHED: | ||
| 614 | if (p->cputime_expires.sched_exp == 0 || | ||
| 615 | p->cputime_expires.sched_exp > exp->sched) | ||
| 616 | p->cputime_expires.sched_exp = | ||
| 617 | exp->sched; | ||
| 618 | break; | ||
| 619 | } | ||
| 620 | } else { | ||
| 621 | struct signal_struct *const sig = p->signal; | ||
| 622 | union cpu_time_count *exp = &timer->it.cpu.expires; | ||
| 623 | |||
| 624 | /* | ||
| 625 | * For a process timer, set the cached expiration time. | ||
| 626 | */ | ||
| 627 | switch (CPUCLOCK_WHICH(timer->it_clock)) { | ||
| 628 | default: | ||
| 629 | BUG(); | ||
| 630 | case CPUCLOCK_VIRT: | ||
| 631 | if (expires_gt(sig->cputime_expires.virt_exp, exp->cpu)) | ||
| 632 | sig->cputime_expires.virt_exp = exp->cpu; | ||
| 633 | case CPUCLOCK_PROF: | ||
| 634 | if (expires_gt(sig->cputime_expires.prof_exp, exp->cpu)) | ||
| 635 | sig->cputime_expires.prof_exp = exp->cpu; | ||
| 636 | break; | ||
| 637 | case CPUCLOCK_SCHED: | ||
| 638 | sig->cputime_expires.sched_exp = exp->sched; | ||
| 639 | break; | ||
| 640 | } | ||
| 641 | } | 607 | } |
| 642 | } | 608 | } |
| 643 | 609 | ||
| @@ -819,7 +785,7 @@ int posix_cpu_timer_set(struct k_itimer *timer, int flags, | |||
| 819 | if (new_expires.sched != 0 && | 785 | if (new_expires.sched != 0 && |
| 820 | (timer->it_sigev_notify & ~SIGEV_THREAD_ID) != SIGEV_NONE && | 786 | (timer->it_sigev_notify & ~SIGEV_THREAD_ID) != SIGEV_NONE && |
| 821 | cpu_time_before(timer->it_clock, val, new_expires)) { | 787 | cpu_time_before(timer->it_clock, val, new_expires)) { |
| 822 | arm_timer(timer, val); | 788 | arm_timer(timer); |
| 823 | } | 789 | } |
| 824 | 790 | ||
| 825 | read_unlock(&tasklist_lock); | 791 | read_unlock(&tasklist_lock); |
| @@ -1283,7 +1249,7 @@ void posix_cpu_timer_schedule(struct k_itimer *timer) | |||
| 1283 | /* | 1249 | /* |
| 1284 | * Now re-arm for the new expiry time. | 1250 | * Now re-arm for the new expiry time. |
| 1285 | */ | 1251 | */ |
| 1286 | arm_timer(timer, now); | 1252 | arm_timer(timer); |
| 1287 | 1253 | ||
| 1288 | out_unlock: | 1254 | out_unlock: |
| 1289 | read_unlock(&tasklist_lock); | 1255 | read_unlock(&tasklist_lock); |
