diff options
Diffstat (limited to 'kernel/posix-cpu-timers.c')
-rw-r--r-- | kernel/posix-cpu-timers.c | 395 |
1 files changed, 140 insertions, 255 deletions
diff --git a/kernel/posix-cpu-timers.c b/kernel/posix-cpu-timers.c index 42670e9b44e0..c7f31aa272f7 100644 --- a/kernel/posix-cpu-timers.c +++ b/kernel/posix-cpu-timers.c | |||
@@ -51,59 +51,28 @@ static int check_clock(const clockid_t which_clock) | |||
51 | return error; | 51 | return error; |
52 | } | 52 | } |
53 | 53 | ||
54 | static inline union cpu_time_count | 54 | static inline unsigned long long |
55 | timespec_to_sample(const clockid_t which_clock, const struct timespec *tp) | 55 | timespec_to_sample(const clockid_t which_clock, const struct timespec *tp) |
56 | { | 56 | { |
57 | union cpu_time_count ret; | 57 | unsigned long long ret; |
58 | ret.sched = 0; /* high half always zero when .cpu used */ | 58 | |
59 | ret = 0; /* high half always zero when .cpu used */ | ||
59 | if (CPUCLOCK_WHICH(which_clock) == CPUCLOCK_SCHED) { | 60 | if (CPUCLOCK_WHICH(which_clock) == CPUCLOCK_SCHED) { |
60 | ret.sched = (unsigned long long)tp->tv_sec * NSEC_PER_SEC + tp->tv_nsec; | 61 | ret = (unsigned long long)tp->tv_sec * NSEC_PER_SEC + tp->tv_nsec; |
61 | } else { | 62 | } else { |
62 | ret.cpu = timespec_to_cputime(tp); | 63 | ret = cputime_to_expires(timespec_to_cputime(tp)); |
63 | } | 64 | } |
64 | return ret; | 65 | return ret; |
65 | } | 66 | } |
66 | 67 | ||
67 | static void sample_to_timespec(const clockid_t which_clock, | 68 | static void sample_to_timespec(const clockid_t which_clock, |
68 | union cpu_time_count cpu, | 69 | unsigned long long expires, |
69 | struct timespec *tp) | 70 | struct timespec *tp) |
70 | { | 71 | { |
71 | if (CPUCLOCK_WHICH(which_clock) == CPUCLOCK_SCHED) | 72 | if (CPUCLOCK_WHICH(which_clock) == CPUCLOCK_SCHED) |
72 | *tp = ns_to_timespec(cpu.sched); | 73 | *tp = ns_to_timespec(expires); |
73 | else | 74 | else |
74 | cputime_to_timespec(cpu.cpu, tp); | 75 | cputime_to_timespec((__force cputime_t)expires, tp); |
75 | } | ||
76 | |||
77 | static inline int cpu_time_before(const clockid_t which_clock, | ||
78 | union cpu_time_count now, | ||
79 | union cpu_time_count then) | ||
80 | { | ||
81 | if (CPUCLOCK_WHICH(which_clock) == CPUCLOCK_SCHED) { | ||
82 | return now.sched < then.sched; | ||
83 | } else { | ||
84 | return now.cpu < then.cpu; | ||
85 | } | ||
86 | } | ||
87 | static inline void cpu_time_add(const clockid_t which_clock, | ||
88 | union cpu_time_count *acc, | ||
89 | union cpu_time_count val) | ||
90 | { | ||
91 | if (CPUCLOCK_WHICH(which_clock) == CPUCLOCK_SCHED) { | ||
92 | acc->sched += val.sched; | ||
93 | } else { | ||
94 | acc->cpu += val.cpu; | ||
95 | } | ||
96 | } | ||
97 | static inline union cpu_time_count cpu_time_sub(const clockid_t which_clock, | ||
98 | union cpu_time_count a, | ||
99 | union cpu_time_count b) | ||
100 | { | ||
101 | if (CPUCLOCK_WHICH(which_clock) == CPUCLOCK_SCHED) { | ||
102 | a.sched -= b.sched; | ||
103 | } else { | ||
104 | a.cpu -= b.cpu; | ||
105 | } | ||
106 | return a; | ||
107 | } | 76 | } |
108 | 77 | ||
109 | /* | 78 | /* |
@@ -111,47 +80,31 @@ static inline union cpu_time_count cpu_time_sub(const clockid_t which_clock, | |||
111 | * given the current clock sample. | 80 | * given the current clock sample. |
112 | */ | 81 | */ |
113 | static void bump_cpu_timer(struct k_itimer *timer, | 82 | static void bump_cpu_timer(struct k_itimer *timer, |
114 | union cpu_time_count now) | 83 | unsigned long long now) |
115 | { | 84 | { |
116 | int i; | 85 | int i; |
86 | unsigned long long delta, incr; | ||
117 | 87 | ||
118 | if (timer->it.cpu.incr.sched == 0) | 88 | if (timer->it.cpu.incr == 0) |
119 | return; | 89 | return; |
120 | 90 | ||
121 | if (CPUCLOCK_WHICH(timer->it_clock) == CPUCLOCK_SCHED) { | 91 | if (now < timer->it.cpu.expires) |
122 | unsigned long long delta, incr; | 92 | return; |
123 | 93 | ||
124 | if (now.sched < timer->it.cpu.expires.sched) | 94 | incr = timer->it.cpu.incr; |
125 | return; | 95 | delta = now + incr - timer->it.cpu.expires; |
126 | incr = timer->it.cpu.incr.sched; | ||
127 | delta = now.sched + incr - timer->it.cpu.expires.sched; | ||
128 | /* Don't use (incr*2 < delta), incr*2 might overflow. */ | ||
129 | for (i = 0; incr < delta - incr; i++) | ||
130 | incr = incr << 1; | ||
131 | for (; i >= 0; incr >>= 1, i--) { | ||
132 | if (delta < incr) | ||
133 | continue; | ||
134 | timer->it.cpu.expires.sched += incr; | ||
135 | timer->it_overrun += 1 << i; | ||
136 | delta -= incr; | ||
137 | } | ||
138 | } else { | ||
139 | cputime_t delta, incr; | ||
140 | 96 | ||
141 | if (now.cpu < timer->it.cpu.expires.cpu) | 97 | /* Don't use (incr*2 < delta), incr*2 might overflow. */ |
142 | return; | 98 | for (i = 0; incr < delta - incr; i++) |
143 | incr = timer->it.cpu.incr.cpu; | 99 | incr = incr << 1; |
144 | delta = now.cpu + incr - timer->it.cpu.expires.cpu; | 100 | |
145 | /* Don't use (incr*2 < delta), incr*2 might overflow. */ | 101 | for (; i >= 0; incr >>= 1, i--) { |
146 | for (i = 0; incr < delta - incr; i++) | 102 | if (delta < incr) |
147 | incr += incr; | 103 | continue; |
148 | for (; i >= 0; incr = incr >> 1, i--) { | 104 | |
149 | if (delta < incr) | 105 | timer->it.cpu.expires += incr; |
150 | continue; | 106 | timer->it_overrun += 1 << i; |
151 | timer->it.cpu.expires.cpu += incr; | 107 | delta -= incr; |
152 | timer->it_overrun += 1 << i; | ||
153 | delta -= incr; | ||
154 | } | ||
155 | } | 108 | } |
156 | } | 109 | } |
157 | 110 | ||
@@ -170,21 +123,21 @@ static inline int task_cputime_zero(const struct task_cputime *cputime) | |||
170 | return 0; | 123 | return 0; |
171 | } | 124 | } |
172 | 125 | ||
173 | static inline cputime_t prof_ticks(struct task_struct *p) | 126 | static inline unsigned long long prof_ticks(struct task_struct *p) |
174 | { | 127 | { |
175 | cputime_t utime, stime; | 128 | cputime_t utime, stime; |
176 | 129 | ||
177 | task_cputime(p, &utime, &stime); | 130 | task_cputime(p, &utime, &stime); |
178 | 131 | ||
179 | return utime + stime; | 132 | return cputime_to_expires(utime + stime); |
180 | } | 133 | } |
181 | static inline cputime_t virt_ticks(struct task_struct *p) | 134 | static inline unsigned long long virt_ticks(struct task_struct *p) |
182 | { | 135 | { |
183 | cputime_t utime; | 136 | cputime_t utime; |
184 | 137 | ||
185 | task_cputime(p, &utime, NULL); | 138 | task_cputime(p, &utime, NULL); |
186 | 139 | ||
187 | return utime; | 140 | return cputime_to_expires(utime); |
188 | } | 141 | } |
189 | 142 | ||
190 | static int | 143 | static int |
@@ -225,19 +178,19 @@ posix_cpu_clock_set(const clockid_t which_clock, const struct timespec *tp) | |||
225 | * Sample a per-thread clock for the given task. | 178 | * Sample a per-thread clock for the given task. |
226 | */ | 179 | */ |
227 | static int cpu_clock_sample(const clockid_t which_clock, struct task_struct *p, | 180 | static int cpu_clock_sample(const clockid_t which_clock, struct task_struct *p, |
228 | union cpu_time_count *cpu) | 181 | unsigned long long *sample) |
229 | { | 182 | { |
230 | switch (CPUCLOCK_WHICH(which_clock)) { | 183 | switch (CPUCLOCK_WHICH(which_clock)) { |
231 | default: | 184 | default: |
232 | return -EINVAL; | 185 | return -EINVAL; |
233 | case CPUCLOCK_PROF: | 186 | case CPUCLOCK_PROF: |
234 | cpu->cpu = prof_ticks(p); | 187 | *sample = prof_ticks(p); |
235 | break; | 188 | break; |
236 | case CPUCLOCK_VIRT: | 189 | case CPUCLOCK_VIRT: |
237 | cpu->cpu = virt_ticks(p); | 190 | *sample = virt_ticks(p); |
238 | break; | 191 | break; |
239 | case CPUCLOCK_SCHED: | 192 | case CPUCLOCK_SCHED: |
240 | cpu->sched = task_sched_runtime(p); | 193 | *sample = task_sched_runtime(p); |
241 | break; | 194 | break; |
242 | } | 195 | } |
243 | return 0; | 196 | return 0; |
@@ -284,7 +237,7 @@ void thread_group_cputimer(struct task_struct *tsk, struct task_cputime *times) | |||
284 | */ | 237 | */ |
285 | static int cpu_clock_sample_group(const clockid_t which_clock, | 238 | static int cpu_clock_sample_group(const clockid_t which_clock, |
286 | struct task_struct *p, | 239 | struct task_struct *p, |
287 | union cpu_time_count *cpu) | 240 | unsigned long long *sample) |
288 | { | 241 | { |
289 | struct task_cputime cputime; | 242 | struct task_cputime cputime; |
290 | 243 | ||
@@ -293,15 +246,15 @@ static int cpu_clock_sample_group(const clockid_t which_clock, | |||
293 | return -EINVAL; | 246 | return -EINVAL; |
294 | case CPUCLOCK_PROF: | 247 | case CPUCLOCK_PROF: |
295 | thread_group_cputime(p, &cputime); | 248 | thread_group_cputime(p, &cputime); |
296 | cpu->cpu = cputime.utime + cputime.stime; | 249 | *sample = cputime_to_expires(cputime.utime + cputime.stime); |
297 | break; | 250 | break; |
298 | case CPUCLOCK_VIRT: | 251 | case CPUCLOCK_VIRT: |
299 | thread_group_cputime(p, &cputime); | 252 | thread_group_cputime(p, &cputime); |
300 | cpu->cpu = cputime.utime; | 253 | *sample = cputime_to_expires(cputime.utime); |
301 | break; | 254 | break; |
302 | case CPUCLOCK_SCHED: | 255 | case CPUCLOCK_SCHED: |
303 | thread_group_cputime(p, &cputime); | 256 | thread_group_cputime(p, &cputime); |
304 | cpu->sched = cputime.sum_exec_runtime; | 257 | *sample = cputime.sum_exec_runtime; |
305 | break; | 258 | break; |
306 | } | 259 | } |
307 | return 0; | 260 | return 0; |
@@ -312,7 +265,7 @@ static int posix_cpu_clock_get(const clockid_t which_clock, struct timespec *tp) | |||
312 | { | 265 | { |
313 | const pid_t pid = CPUCLOCK_PID(which_clock); | 266 | const pid_t pid = CPUCLOCK_PID(which_clock); |
314 | int error = -EINVAL; | 267 | int error = -EINVAL; |
315 | union cpu_time_count rtn; | 268 | unsigned long long rtn; |
316 | 269 | ||
317 | if (pid == 0) { | 270 | if (pid == 0) { |
318 | /* | 271 | /* |
@@ -446,6 +399,15 @@ static int posix_cpu_timer_del(struct k_itimer *timer) | |||
446 | return ret; | 399 | return ret; |
447 | } | 400 | } |
448 | 401 | ||
402 | static void cleanup_timers_list(struct list_head *head, | ||
403 | unsigned long long curr) | ||
404 | { | ||
405 | struct cpu_timer_list *timer, *next; | ||
406 | |||
407 | list_for_each_entry_safe(timer, next, head, entry) | ||
408 | list_del_init(&timer->entry); | ||
409 | } | ||
410 | |||
449 | /* | 411 | /* |
450 | * Clean out CPU timers still ticking when a thread exited. The task | 412 | * Clean out CPU timers still ticking when a thread exited. The task |
451 | * pointer is cleared, and the expiry time is replaced with the residual | 413 | * pointer is cleared, and the expiry time is replaced with the residual |
@@ -456,37 +418,12 @@ static void cleanup_timers(struct list_head *head, | |||
456 | cputime_t utime, cputime_t stime, | 418 | cputime_t utime, cputime_t stime, |
457 | unsigned long long sum_exec_runtime) | 419 | unsigned long long sum_exec_runtime) |
458 | { | 420 | { |
459 | struct cpu_timer_list *timer, *next; | ||
460 | cputime_t ptime = utime + stime; | ||
461 | |||
462 | list_for_each_entry_safe(timer, next, head, entry) { | ||
463 | list_del_init(&timer->entry); | ||
464 | if (timer->expires.cpu < ptime) { | ||
465 | timer->expires.cpu = 0; | ||
466 | } else { | ||
467 | timer->expires.cpu -= ptime; | ||
468 | } | ||
469 | } | ||
470 | 421 | ||
471 | ++head; | 422 | cputime_t ptime = utime + stime; |
472 | list_for_each_entry_safe(timer, next, head, entry) { | ||
473 | list_del_init(&timer->entry); | ||
474 | if (timer->expires.cpu < utime) { | ||
475 | timer->expires.cpu = 0; | ||
476 | } else { | ||
477 | timer->expires.cpu -= utime; | ||
478 | } | ||
479 | } | ||
480 | 423 | ||
481 | ++head; | 424 | cleanup_timers_list(head, cputime_to_expires(ptime)); |
482 | list_for_each_entry_safe(timer, next, head, entry) { | 425 | cleanup_timers_list(++head, cputime_to_expires(utime)); |
483 | list_del_init(&timer->entry); | 426 | cleanup_timers_list(++head, sum_exec_runtime); |
484 | if (timer->expires.sched < sum_exec_runtime) { | ||
485 | timer->expires.sched = 0; | ||
486 | } else { | ||
487 | timer->expires.sched -= sum_exec_runtime; | ||
488 | } | ||
489 | } | ||
490 | } | 427 | } |
491 | 428 | ||
492 | /* | 429 | /* |
@@ -516,17 +453,21 @@ void posix_cpu_timers_exit_group(struct task_struct *tsk) | |||
516 | tsk->se.sum_exec_runtime + sig->sum_sched_runtime); | 453 | tsk->se.sum_exec_runtime + sig->sum_sched_runtime); |
517 | } | 454 | } |
518 | 455 | ||
519 | static void clear_dead_task(struct k_itimer *timer, union cpu_time_count now) | 456 | static void clear_dead_task(struct k_itimer *itimer, unsigned long long now) |
520 | { | 457 | { |
458 | struct cpu_timer_list *timer = &itimer->it.cpu; | ||
459 | |||
521 | /* | 460 | /* |
522 | * That's all for this thread or process. | 461 | * That's all for this thread or process. |
523 | * We leave our residual in expires to be reported. | 462 | * We leave our residual in expires to be reported. |
524 | */ | 463 | */ |
525 | put_task_struct(timer->it.cpu.task); | 464 | put_task_struct(timer->task); |
526 | timer->it.cpu.task = NULL; | 465 | timer->task = NULL; |
527 | timer->it.cpu.expires = cpu_time_sub(timer->it_clock, | 466 | if (timer->expires < now) { |
528 | timer->it.cpu.expires, | 467 | timer->expires = 0; |
529 | now); | 468 | } else { |
469 | timer->expires -= now; | ||
470 | } | ||
530 | } | 471 | } |
531 | 472 | ||
532 | static inline int expires_gt(cputime_t expires, cputime_t new_exp) | 473 | static inline int expires_gt(cputime_t expires, cputime_t new_exp) |
@@ -558,14 +499,14 @@ static void arm_timer(struct k_itimer *timer) | |||
558 | 499 | ||
559 | listpos = head; | 500 | listpos = head; |
560 | list_for_each_entry(next, head, entry) { | 501 | list_for_each_entry(next, head, entry) { |
561 | if (cpu_time_before(timer->it_clock, nt->expires, next->expires)) | 502 | if (nt->expires < next->expires) |
562 | break; | 503 | break; |
563 | listpos = &next->entry; | 504 | listpos = &next->entry; |
564 | } | 505 | } |
565 | list_add(&nt->entry, listpos); | 506 | list_add(&nt->entry, listpos); |
566 | 507 | ||
567 | if (listpos == head) { | 508 | if (listpos == head) { |
568 | union cpu_time_count *exp = &nt->expires; | 509 | unsigned long long exp = nt->expires; |
569 | 510 | ||
570 | /* | 511 | /* |
571 | * We are the new earliest-expiring POSIX 1.b timer, hence | 512 | * We are the new earliest-expiring POSIX 1.b timer, hence |
@@ -576,17 +517,17 @@ static void arm_timer(struct k_itimer *timer) | |||
576 | 517 | ||
577 | switch (CPUCLOCK_WHICH(timer->it_clock)) { | 518 | switch (CPUCLOCK_WHICH(timer->it_clock)) { |
578 | case CPUCLOCK_PROF: | 519 | case CPUCLOCK_PROF: |
579 | if (expires_gt(cputime_expires->prof_exp, exp->cpu)) | 520 | if (expires_gt(cputime_expires->prof_exp, expires_to_cputime(exp))) |
580 | cputime_expires->prof_exp = exp->cpu; | 521 | cputime_expires->prof_exp = expires_to_cputime(exp); |
581 | break; | 522 | break; |
582 | case CPUCLOCK_VIRT: | 523 | case CPUCLOCK_VIRT: |
583 | if (expires_gt(cputime_expires->virt_exp, exp->cpu)) | 524 | if (expires_gt(cputime_expires->virt_exp, expires_to_cputime(exp))) |
584 | cputime_expires->virt_exp = exp->cpu; | 525 | cputime_expires->virt_exp = expires_to_cputime(exp); |
585 | break; | 526 | break; |
586 | case CPUCLOCK_SCHED: | 527 | case CPUCLOCK_SCHED: |
587 | if (cputime_expires->sched_exp == 0 || | 528 | if (cputime_expires->sched_exp == 0 || |
588 | cputime_expires->sched_exp > exp->sched) | 529 | cputime_expires->sched_exp > exp) |
589 | cputime_expires->sched_exp = exp->sched; | 530 | cputime_expires->sched_exp = exp; |
590 | break; | 531 | break; |
591 | } | 532 | } |
592 | } | 533 | } |
@@ -601,20 +542,20 @@ static void cpu_timer_fire(struct k_itimer *timer) | |||
601 | /* | 542 | /* |
602 | * User don't want any signal. | 543 | * User don't want any signal. |
603 | */ | 544 | */ |
604 | timer->it.cpu.expires.sched = 0; | 545 | timer->it.cpu.expires = 0; |
605 | } else if (unlikely(timer->sigq == NULL)) { | 546 | } else if (unlikely(timer->sigq == NULL)) { |
606 | /* | 547 | /* |
607 | * This a special case for clock_nanosleep, | 548 | * This a special case for clock_nanosleep, |
608 | * not a normal timer from sys_timer_create. | 549 | * not a normal timer from sys_timer_create. |
609 | */ | 550 | */ |
610 | wake_up_process(timer->it_process); | 551 | wake_up_process(timer->it_process); |
611 | timer->it.cpu.expires.sched = 0; | 552 | timer->it.cpu.expires = 0; |
612 | } else if (timer->it.cpu.incr.sched == 0) { | 553 | } else if (timer->it.cpu.incr == 0) { |
613 | /* | 554 | /* |
614 | * One-shot timer. Clear it as soon as it's fired. | 555 | * One-shot timer. Clear it as soon as it's fired. |
615 | */ | 556 | */ |
616 | posix_timer_event(timer, 0); | 557 | posix_timer_event(timer, 0); |
617 | timer->it.cpu.expires.sched = 0; | 558 | timer->it.cpu.expires = 0; |
618 | } else if (posix_timer_event(timer, ++timer->it_requeue_pending)) { | 559 | } else if (posix_timer_event(timer, ++timer->it_requeue_pending)) { |
619 | /* | 560 | /* |
620 | * The signal did not get queued because the signal | 561 | * The signal did not get queued because the signal |
@@ -632,7 +573,7 @@ static void cpu_timer_fire(struct k_itimer *timer) | |||
632 | */ | 573 | */ |
633 | static int cpu_timer_sample_group(const clockid_t which_clock, | 574 | static int cpu_timer_sample_group(const clockid_t which_clock, |
634 | struct task_struct *p, | 575 | struct task_struct *p, |
635 | union cpu_time_count *cpu) | 576 | unsigned long long *sample) |
636 | { | 577 | { |
637 | struct task_cputime cputime; | 578 | struct task_cputime cputime; |
638 | 579 | ||
@@ -641,13 +582,13 @@ static int cpu_timer_sample_group(const clockid_t which_clock, | |||
641 | default: | 582 | default: |
642 | return -EINVAL; | 583 | return -EINVAL; |
643 | case CPUCLOCK_PROF: | 584 | case CPUCLOCK_PROF: |
644 | cpu->cpu = cputime.utime + cputime.stime; | 585 | *sample = cputime_to_expires(cputime.utime + cputime.stime); |
645 | break; | 586 | break; |
646 | case CPUCLOCK_VIRT: | 587 | case CPUCLOCK_VIRT: |
647 | cpu->cpu = cputime.utime; | 588 | *sample = cputime_to_expires(cputime.utime); |
648 | break; | 589 | break; |
649 | case CPUCLOCK_SCHED: | 590 | case CPUCLOCK_SCHED: |
650 | cpu->sched = cputime.sum_exec_runtime + task_delta_exec(p); | 591 | *sample = cputime.sum_exec_runtime + task_delta_exec(p); |
651 | break; | 592 | break; |
652 | } | 593 | } |
653 | return 0; | 594 | return 0; |
@@ -694,7 +635,7 @@ static int posix_cpu_timer_set(struct k_itimer *timer, int flags, | |||
694 | struct itimerspec *new, struct itimerspec *old) | 635 | struct itimerspec *new, struct itimerspec *old) |
695 | { | 636 | { |
696 | struct task_struct *p = timer->it.cpu.task; | 637 | struct task_struct *p = timer->it.cpu.task; |
697 | union cpu_time_count old_expires, new_expires, old_incr, val; | 638 | unsigned long long old_expires, new_expires, old_incr, val; |
698 | int ret; | 639 | int ret; |
699 | 640 | ||
700 | if (unlikely(p == NULL)) { | 641 | if (unlikely(p == NULL)) { |
@@ -749,7 +690,7 @@ static int posix_cpu_timer_set(struct k_itimer *timer, int flags, | |||
749 | } | 690 | } |
750 | 691 | ||
751 | if (old) { | 692 | if (old) { |
752 | if (old_expires.sched == 0) { | 693 | if (old_expires == 0) { |
753 | old->it_value.tv_sec = 0; | 694 | old->it_value.tv_sec = 0; |
754 | old->it_value.tv_nsec = 0; | 695 | old->it_value.tv_nsec = 0; |
755 | } else { | 696 | } else { |
@@ -764,11 +705,8 @@ static int posix_cpu_timer_set(struct k_itimer *timer, int flags, | |||
764 | * new setting. | 705 | * new setting. |
765 | */ | 706 | */ |
766 | bump_cpu_timer(timer, val); | 707 | bump_cpu_timer(timer, val); |
767 | if (cpu_time_before(timer->it_clock, val, | 708 | if (val < timer->it.cpu.expires) { |
768 | timer->it.cpu.expires)) { | 709 | old_expires = timer->it.cpu.expires - val; |
769 | old_expires = cpu_time_sub( | ||
770 | timer->it_clock, | ||
771 | timer->it.cpu.expires, val); | ||
772 | sample_to_timespec(timer->it_clock, | 710 | sample_to_timespec(timer->it_clock, |
773 | old_expires, | 711 | old_expires, |
774 | &old->it_value); | 712 | &old->it_value); |
@@ -791,8 +729,8 @@ static int posix_cpu_timer_set(struct k_itimer *timer, int flags, | |||
791 | goto out; | 729 | goto out; |
792 | } | 730 | } |
793 | 731 | ||
794 | if (new_expires.sched != 0 && !(flags & TIMER_ABSTIME)) { | 732 | if (new_expires != 0 && !(flags & TIMER_ABSTIME)) { |
795 | cpu_time_add(timer->it_clock, &new_expires, val); | 733 | new_expires += val; |
796 | } | 734 | } |
797 | 735 | ||
798 | /* | 736 | /* |
@@ -801,8 +739,7 @@ static int posix_cpu_timer_set(struct k_itimer *timer, int flags, | |||
801 | * arm the timer (we'll just fake it for timer_gettime). | 739 | * arm the timer (we'll just fake it for timer_gettime). |
802 | */ | 740 | */ |
803 | timer->it.cpu.expires = new_expires; | 741 | timer->it.cpu.expires = new_expires; |
804 | if (new_expires.sched != 0 && | 742 | if (new_expires != 0 && val < new_expires) { |
805 | cpu_time_before(timer->it_clock, val, new_expires)) { | ||
806 | arm_timer(timer); | 743 | arm_timer(timer); |
807 | } | 744 | } |
808 | 745 | ||
@@ -826,8 +763,7 @@ static int posix_cpu_timer_set(struct k_itimer *timer, int flags, | |||
826 | timer->it_overrun_last = 0; | 763 | timer->it_overrun_last = 0; |
827 | timer->it_overrun = -1; | 764 | timer->it_overrun = -1; |
828 | 765 | ||
829 | if (new_expires.sched != 0 && | 766 | if (new_expires != 0 && !(val < new_expires)) { |
830 | !cpu_time_before(timer->it_clock, val, new_expires)) { | ||
831 | /* | 767 | /* |
832 | * The designated time already passed, so we notify | 768 | * The designated time already passed, so we notify |
833 | * immediately, even if the thread never runs to | 769 | * immediately, even if the thread never runs to |
@@ -849,7 +785,7 @@ static int posix_cpu_timer_set(struct k_itimer *timer, int flags, | |||
849 | 785 | ||
850 | static void posix_cpu_timer_get(struct k_itimer *timer, struct itimerspec *itp) | 786 | static void posix_cpu_timer_get(struct k_itimer *timer, struct itimerspec *itp) |
851 | { | 787 | { |
852 | union cpu_time_count now; | 788 | unsigned long long now; |
853 | struct task_struct *p = timer->it.cpu.task; | 789 | struct task_struct *p = timer->it.cpu.task; |
854 | int clear_dead; | 790 | int clear_dead; |
855 | 791 | ||
@@ -859,7 +795,7 @@ static void posix_cpu_timer_get(struct k_itimer *timer, struct itimerspec *itp) | |||
859 | sample_to_timespec(timer->it_clock, | 795 | sample_to_timespec(timer->it_clock, |
860 | timer->it.cpu.incr, &itp->it_interval); | 796 | timer->it.cpu.incr, &itp->it_interval); |
861 | 797 | ||
862 | if (timer->it.cpu.expires.sched == 0) { /* Timer not armed at all. */ | 798 | if (timer->it.cpu.expires == 0) { /* Timer not armed at all. */ |
863 | itp->it_value.tv_sec = itp->it_value.tv_nsec = 0; | 799 | itp->it_value.tv_sec = itp->it_value.tv_nsec = 0; |
864 | return; | 800 | return; |
865 | } | 801 | } |
@@ -891,7 +827,7 @@ static void posix_cpu_timer_get(struct k_itimer *timer, struct itimerspec *itp) | |||
891 | */ | 827 | */ |
892 | put_task_struct(p); | 828 | put_task_struct(p); |
893 | timer->it.cpu.task = NULL; | 829 | timer->it.cpu.task = NULL; |
894 | timer->it.cpu.expires.sched = 0; | 830 | timer->it.cpu.expires = 0; |
895 | read_unlock(&tasklist_lock); | 831 | read_unlock(&tasklist_lock); |
896 | goto dead; | 832 | goto dead; |
897 | } else { | 833 | } else { |
@@ -912,10 +848,9 @@ static void posix_cpu_timer_get(struct k_itimer *timer, struct itimerspec *itp) | |||
912 | goto dead; | 848 | goto dead; |
913 | } | 849 | } |
914 | 850 | ||
915 | if (cpu_time_before(timer->it_clock, now, timer->it.cpu.expires)) { | 851 | if (now < timer->it.cpu.expires) { |
916 | sample_to_timespec(timer->it_clock, | 852 | sample_to_timespec(timer->it_clock, |
917 | cpu_time_sub(timer->it_clock, | 853 | timer->it.cpu.expires - now, |
918 | timer->it.cpu.expires, now), | ||
919 | &itp->it_value); | 854 | &itp->it_value); |
920 | } else { | 855 | } else { |
921 | /* | 856 | /* |
@@ -927,6 +862,28 @@ static void posix_cpu_timer_get(struct k_itimer *timer, struct itimerspec *itp) | |||
927 | } | 862 | } |
928 | } | 863 | } |
929 | 864 | ||
865 | static unsigned long long | ||
866 | check_timers_list(struct list_head *timers, | ||
867 | struct list_head *firing, | ||
868 | unsigned long long curr) | ||
869 | { | ||
870 | int maxfire = 20; | ||
871 | |||
872 | while (!list_empty(timers)) { | ||
873 | struct cpu_timer_list *t; | ||
874 | |||
875 | t = list_first_entry(timers, struct cpu_timer_list, entry); | ||
876 | |||
877 | if (!--maxfire || curr < t->expires) | ||
878 | return t->expires; | ||
879 | |||
880 | t->firing = 1; | ||
881 | list_move_tail(&t->entry, firing); | ||
882 | } | ||
883 | |||
884 | return 0; | ||
885 | } | ||
886 | |||
930 | /* | 887 | /* |
931 | * Check for any per-thread CPU timers that have fired and move them off | 888 | * Check for any per-thread CPU timers that have fired and move them off |
932 | * the tsk->cpu_timers[N] list onto the firing list. Here we update the | 889 | * the tsk->cpu_timers[N] list onto the firing list. Here we update the |
@@ -935,54 +892,20 @@ static void posix_cpu_timer_get(struct k_itimer *timer, struct itimerspec *itp) | |||
935 | static void check_thread_timers(struct task_struct *tsk, | 892 | static void check_thread_timers(struct task_struct *tsk, |
936 | struct list_head *firing) | 893 | struct list_head *firing) |
937 | { | 894 | { |
938 | int maxfire; | ||
939 | struct list_head *timers = tsk->cpu_timers; | 895 | struct list_head *timers = tsk->cpu_timers; |
940 | struct signal_struct *const sig = tsk->signal; | 896 | struct signal_struct *const sig = tsk->signal; |
897 | struct task_cputime *tsk_expires = &tsk->cputime_expires; | ||
898 | unsigned long long expires; | ||
941 | unsigned long soft; | 899 | unsigned long soft; |
942 | 900 | ||
943 | maxfire = 20; | 901 | expires = check_timers_list(timers, firing, prof_ticks(tsk)); |
944 | tsk->cputime_expires.prof_exp = 0; | 902 | tsk_expires->prof_exp = expires_to_cputime(expires); |
945 | while (!list_empty(timers)) { | ||
946 | struct cpu_timer_list *t = list_first_entry(timers, | ||
947 | struct cpu_timer_list, | ||
948 | entry); | ||
949 | if (!--maxfire || prof_ticks(tsk) < t->expires.cpu) { | ||
950 | tsk->cputime_expires.prof_exp = t->expires.cpu; | ||
951 | break; | ||
952 | } | ||
953 | t->firing = 1; | ||
954 | list_move_tail(&t->entry, firing); | ||
955 | } | ||
956 | 903 | ||
957 | ++timers; | 904 | expires = check_timers_list(++timers, firing, virt_ticks(tsk)); |
958 | maxfire = 20; | 905 | tsk_expires->virt_exp = expires_to_cputime(expires); |
959 | tsk->cputime_expires.virt_exp = 0; | ||
960 | while (!list_empty(timers)) { | ||
961 | struct cpu_timer_list *t = list_first_entry(timers, | ||
962 | struct cpu_timer_list, | ||
963 | entry); | ||
964 | if (!--maxfire || virt_ticks(tsk) < t->expires.cpu) { | ||
965 | tsk->cputime_expires.virt_exp = t->expires.cpu; | ||
966 | break; | ||
967 | } | ||
968 | t->firing = 1; | ||
969 | list_move_tail(&t->entry, firing); | ||
970 | } | ||
971 | 906 | ||
972 | ++timers; | 907 | tsk_expires->sched_exp = check_timers_list(++timers, firing, |
973 | maxfire = 20; | 908 | tsk->se.sum_exec_runtime); |
974 | tsk->cputime_expires.sched_exp = 0; | ||
975 | while (!list_empty(timers)) { | ||
976 | struct cpu_timer_list *t = list_first_entry(timers, | ||
977 | struct cpu_timer_list, | ||
978 | entry); | ||
979 | if (!--maxfire || tsk->se.sum_exec_runtime < t->expires.sched) { | ||
980 | tsk->cputime_expires.sched_exp = t->expires.sched; | ||
981 | break; | ||
982 | } | ||
983 | t->firing = 1; | ||
984 | list_move_tail(&t->entry, firing); | ||
985 | } | ||
986 | 909 | ||
987 | /* | 910 | /* |
988 | * Check for the special case thread timers. | 911 | * Check for the special case thread timers. |
@@ -1030,7 +953,8 @@ static void stop_process_timers(struct signal_struct *sig) | |||
1030 | static u32 onecputick; | 953 | static u32 onecputick; |
1031 | 954 | ||
1032 | static void check_cpu_itimer(struct task_struct *tsk, struct cpu_itimer *it, | 955 | static void check_cpu_itimer(struct task_struct *tsk, struct cpu_itimer *it, |
1033 | cputime_t *expires, cputime_t cur_time, int signo) | 956 | unsigned long long *expires, |
957 | unsigned long long cur_time, int signo) | ||
1034 | { | 958 | { |
1035 | if (!it->expires) | 959 | if (!it->expires) |
1036 | return; | 960 | return; |
@@ -1066,9 +990,8 @@ static void check_cpu_itimer(struct task_struct *tsk, struct cpu_itimer *it, | |||
1066 | static void check_process_timers(struct task_struct *tsk, | 990 | static void check_process_timers(struct task_struct *tsk, |
1067 | struct list_head *firing) | 991 | struct list_head *firing) |
1068 | { | 992 | { |
1069 | int maxfire; | ||
1070 | struct signal_struct *const sig = tsk->signal; | 993 | struct signal_struct *const sig = tsk->signal; |
1071 | cputime_t utime, ptime, virt_expires, prof_expires; | 994 | unsigned long long utime, ptime, virt_expires, prof_expires; |
1072 | unsigned long long sum_sched_runtime, sched_expires; | 995 | unsigned long long sum_sched_runtime, sched_expires; |
1073 | struct list_head *timers = sig->cpu_timers; | 996 | struct list_head *timers = sig->cpu_timers; |
1074 | struct task_cputime cputime; | 997 | struct task_cputime cputime; |
@@ -1078,52 +1001,13 @@ static void check_process_timers(struct task_struct *tsk, | |||
1078 | * Collect the current process totals. | 1001 | * Collect the current process totals. |
1079 | */ | 1002 | */ |
1080 | thread_group_cputimer(tsk, &cputime); | 1003 | thread_group_cputimer(tsk, &cputime); |
1081 | utime = cputime.utime; | 1004 | utime = cputime_to_expires(cputime.utime); |
1082 | ptime = utime + cputime.stime; | 1005 | ptime = utime + cputime_to_expires(cputime.stime); |
1083 | sum_sched_runtime = cputime.sum_exec_runtime; | 1006 | sum_sched_runtime = cputime.sum_exec_runtime; |
1084 | maxfire = 20; | ||
1085 | prof_expires = 0; | ||
1086 | while (!list_empty(timers)) { | ||
1087 | struct cpu_timer_list *tl = list_first_entry(timers, | ||
1088 | struct cpu_timer_list, | ||
1089 | entry); | ||
1090 | if (!--maxfire || ptime < tl->expires.cpu) { | ||
1091 | prof_expires = tl->expires.cpu; | ||
1092 | break; | ||
1093 | } | ||
1094 | tl->firing = 1; | ||
1095 | list_move_tail(&tl->entry, firing); | ||
1096 | } | ||
1097 | 1007 | ||
1098 | ++timers; | 1008 | prof_expires = check_timers_list(timers, firing, ptime); |
1099 | maxfire = 20; | 1009 | virt_expires = check_timers_list(++timers, firing, utime); |
1100 | virt_expires = 0; | 1010 | sched_expires = check_timers_list(++timers, firing, sum_sched_runtime); |
1101 | while (!list_empty(timers)) { | ||
1102 | struct cpu_timer_list *tl = list_first_entry(timers, | ||
1103 | struct cpu_timer_list, | ||
1104 | entry); | ||
1105 | if (!--maxfire || utime < tl->expires.cpu) { | ||
1106 | virt_expires = tl->expires.cpu; | ||
1107 | break; | ||
1108 | } | ||
1109 | tl->firing = 1; | ||
1110 | list_move_tail(&tl->entry, firing); | ||
1111 | } | ||
1112 | |||
1113 | ++timers; | ||
1114 | maxfire = 20; | ||
1115 | sched_expires = 0; | ||
1116 | while (!list_empty(timers)) { | ||
1117 | struct cpu_timer_list *tl = list_first_entry(timers, | ||
1118 | struct cpu_timer_list, | ||
1119 | entry); | ||
1120 | if (!--maxfire || sum_sched_runtime < tl->expires.sched) { | ||
1121 | sched_expires = tl->expires.sched; | ||
1122 | break; | ||
1123 | } | ||
1124 | tl->firing = 1; | ||
1125 | list_move_tail(&tl->entry, firing); | ||
1126 | } | ||
1127 | 1011 | ||
1128 | /* | 1012 | /* |
1129 | * Check for the special case process timers. | 1013 | * Check for the special case process timers. |
@@ -1162,8 +1046,8 @@ static void check_process_timers(struct task_struct *tsk, | |||
1162 | } | 1046 | } |
1163 | } | 1047 | } |
1164 | 1048 | ||
1165 | sig->cputime_expires.prof_exp = prof_expires; | 1049 | sig->cputime_expires.prof_exp = expires_to_cputime(prof_expires); |
1166 | sig->cputime_expires.virt_exp = virt_expires; | 1050 | sig->cputime_expires.virt_exp = expires_to_cputime(virt_expires); |
1167 | sig->cputime_expires.sched_exp = sched_expires; | 1051 | sig->cputime_expires.sched_exp = sched_expires; |
1168 | if (task_cputime_zero(&sig->cputime_expires)) | 1052 | if (task_cputime_zero(&sig->cputime_expires)) |
1169 | stop_process_timers(sig); | 1053 | stop_process_timers(sig); |
@@ -1176,7 +1060,7 @@ static void check_process_timers(struct task_struct *tsk, | |||
1176 | void posix_cpu_timer_schedule(struct k_itimer *timer) | 1060 | void posix_cpu_timer_schedule(struct k_itimer *timer) |
1177 | { | 1061 | { |
1178 | struct task_struct *p = timer->it.cpu.task; | 1062 | struct task_struct *p = timer->it.cpu.task; |
1179 | union cpu_time_count now; | 1063 | unsigned long long now; |
1180 | 1064 | ||
1181 | if (unlikely(p == NULL)) | 1065 | if (unlikely(p == NULL)) |
1182 | /* | 1066 | /* |
@@ -1205,7 +1089,7 @@ void posix_cpu_timer_schedule(struct k_itimer *timer) | |||
1205 | */ | 1089 | */ |
1206 | put_task_struct(p); | 1090 | put_task_struct(p); |
1207 | timer->it.cpu.task = p = NULL; | 1091 | timer->it.cpu.task = p = NULL; |
1208 | timer->it.cpu.expires.sched = 0; | 1092 | timer->it.cpu.expires = 0; |
1209 | goto out_unlock; | 1093 | goto out_unlock; |
1210 | } else if (unlikely(p->exit_state) && thread_group_empty(p)) { | 1094 | } else if (unlikely(p->exit_state) && thread_group_empty(p)) { |
1211 | /* | 1095 | /* |
@@ -1213,6 +1097,7 @@ void posix_cpu_timer_schedule(struct k_itimer *timer) | |||
1213 | * not yet reaped. Take this opportunity to | 1097 | * not yet reaped. Take this opportunity to |
1214 | * drop our task ref. | 1098 | * drop our task ref. |
1215 | */ | 1099 | */ |
1100 | cpu_timer_sample_group(timer->it_clock, p, &now); | ||
1216 | clear_dead_task(timer, now); | 1101 | clear_dead_task(timer, now); |
1217 | goto out_unlock; | 1102 | goto out_unlock; |
1218 | } | 1103 | } |
@@ -1387,7 +1272,7 @@ void run_posix_cpu_timers(struct task_struct *tsk) | |||
1387 | void set_process_cpu_timer(struct task_struct *tsk, unsigned int clock_idx, | 1272 | void set_process_cpu_timer(struct task_struct *tsk, unsigned int clock_idx, |
1388 | cputime_t *newval, cputime_t *oldval) | 1273 | cputime_t *newval, cputime_t *oldval) |
1389 | { | 1274 | { |
1390 | union cpu_time_count now; | 1275 | unsigned long long now; |
1391 | 1276 | ||
1392 | BUG_ON(clock_idx == CPUCLOCK_SCHED); | 1277 | BUG_ON(clock_idx == CPUCLOCK_SCHED); |
1393 | cpu_timer_sample_group(clock_idx, tsk, &now); | 1278 | cpu_timer_sample_group(clock_idx, tsk, &now); |
@@ -1399,17 +1284,17 @@ void set_process_cpu_timer(struct task_struct *tsk, unsigned int clock_idx, | |||
1399 | * it to be absolute. | 1284 | * it to be absolute. |
1400 | */ | 1285 | */ |
1401 | if (*oldval) { | 1286 | if (*oldval) { |
1402 | if (*oldval <= now.cpu) { | 1287 | if (*oldval <= now) { |
1403 | /* Just about to fire. */ | 1288 | /* Just about to fire. */ |
1404 | *oldval = cputime_one_jiffy; | 1289 | *oldval = cputime_one_jiffy; |
1405 | } else { | 1290 | } else { |
1406 | *oldval -= now.cpu; | 1291 | *oldval -= now; |
1407 | } | 1292 | } |
1408 | } | 1293 | } |
1409 | 1294 | ||
1410 | if (!*newval) | 1295 | if (!*newval) |
1411 | goto out; | 1296 | goto out; |
1412 | *newval += now.cpu; | 1297 | *newval += now; |
1413 | } | 1298 | } |
1414 | 1299 | ||
1415 | /* | 1300 | /* |
@@ -1459,7 +1344,7 @@ static int do_cpu_nanosleep(const clockid_t which_clock, int flags, | |||
1459 | } | 1344 | } |
1460 | 1345 | ||
1461 | while (!signal_pending(current)) { | 1346 | while (!signal_pending(current)) { |
1462 | if (timer.it.cpu.expires.sched == 0) { | 1347 | if (timer.it.cpu.expires == 0) { |
1463 | /* | 1348 | /* |
1464 | * Our timer fired and was reset, below | 1349 | * Our timer fired and was reset, below |
1465 | * deletion can not fail. | 1350 | * deletion can not fail. |