Blame view
kernel/posix-cpu-timers.c
38.2 KB
1da177e4c Linux-2.6.12-rc2 |
1 2 3 4 5 6 |
/* * Implement CPU time clocks for the POSIX clock interface. */ #include <linux/sched.h> #include <linux/posix-timers.h> |
1da177e4c Linux-2.6.12-rc2 |
7 |
#include <linux/errno.h> |
f8bd2258e remove div_long_l... |
8 9 |
#include <linux/math64.h> #include <asm/uaccess.h> |
bb34d92f6 timers: fix itime... |
10 |
#include <linux/kernel_stat.h> |
3f0a525eb itimers: Add trac... |
11 |
#include <trace/events/timer.h> |
613370549 random: Mix cputi... |
12 |
#include <linux/random.h> |
a85721601 posix_timers: Kic... |
13 14 |
#include <linux/tick.h> #include <linux/workqueue.h> |
1da177e4c Linux-2.6.12-rc2 |
15 |
|
f06febc96 timers: fix itime... |
16 |
/* |
f55db6090 cpu-timers: Simpl... |
17 18 19 20 |
* Called after updating RLIMIT_CPU to run cpu timer and update * tsk->signal->cputime_expires expiration cache if necessary. Needs * siglock protection since other code may update expiration cache as * well. |
f06febc96 timers: fix itime... |
21 |
*/ |
5ab46b345 rlimits: add task... |
22 |
void update_rlimit_cpu(struct task_struct *task, unsigned long rlim_new) |
f06febc96 timers: fix itime... |
23 |
{ |
42c4ab41a itimers: Merge IT... |
24 |
cputime_t cputime = secs_to_cputime(rlim_new); |
f06febc96 timers: fix itime... |
25 |
|
5ab46b345 rlimits: add task... |
26 27 28 |
spin_lock_irq(&task->sighand->siglock); set_process_cpu_timer(task, CPUCLOCK_PROF, &cputime, NULL); spin_unlock_irq(&task->sighand->siglock); |
f06febc96 timers: fix itime... |
29 |
} |
a924b04dd [PATCH] hrtimer: ... |
30 |
static int check_clock(const clockid_t which_clock) |
1da177e4c Linux-2.6.12-rc2 |
31 32 33 34 35 36 37 38 39 40 |
{ int error = 0; struct task_struct *p; const pid_t pid = CPUCLOCK_PID(which_clock); if (CPUCLOCK_WHICH(which_clock) >= CPUCLOCK_MAX) return -EINVAL; if (pid == 0) return 0; |
c0deae8c9 posix-cpu-timers:... |
41 |
rcu_read_lock(); |
8dc86af00 Use find_task_by_... |
42 |
p = find_task_by_vpid(pid); |
bac0abd61 Isolate some expl... |
43 |
if (!p || !(CPUCLOCK_PERTHREAD(which_clock) ? |
c0deae8c9 posix-cpu-timers:... |
44 |
same_thread_group(p, current) : has_group_leader_pid(p))) { |
1da177e4c Linux-2.6.12-rc2 |
45 46 |
error = -EINVAL; } |
c0deae8c9 posix-cpu-timers:... |
47 |
rcu_read_unlock(); |
1da177e4c Linux-2.6.12-rc2 |
48 49 50 |
return error; } |
55ccb616a posix_cpu_timer: ... |
51 |
static inline unsigned long long |
a924b04dd [PATCH] hrtimer: ... |
52 |
timespec_to_sample(const clockid_t which_clock, const struct timespec *tp) |
1da177e4c Linux-2.6.12-rc2 |
53 |
{ |
55ccb616a posix_cpu_timer: ... |
54 55 56 |
unsigned long long ret; ret = 0; /* high half always zero when .cpu used */ |
1da177e4c Linux-2.6.12-rc2 |
57 |
if (CPUCLOCK_WHICH(which_clock) == CPUCLOCK_SCHED) { |
55ccb616a posix_cpu_timer: ... |
58 |
ret = (unsigned long long)tp->tv_sec * NSEC_PER_SEC + tp->tv_nsec; |
1da177e4c Linux-2.6.12-rc2 |
59 |
} else { |
55ccb616a posix_cpu_timer: ... |
60 |
ret = cputime_to_expires(timespec_to_cputime(tp)); |
1da177e4c Linux-2.6.12-rc2 |
61 62 63 |
} return ret; } |
a924b04dd [PATCH] hrtimer: ... |
64 |
static void sample_to_timespec(const clockid_t which_clock, |
55ccb616a posix_cpu_timer: ... |
65 |
unsigned long long expires, |
1da177e4c Linux-2.6.12-rc2 |
66 67 |
struct timespec *tp) { |
f8bd2258e remove div_long_l... |
68 |
if (CPUCLOCK_WHICH(which_clock) == CPUCLOCK_SCHED) |
55ccb616a posix_cpu_timer: ... |
69 |
*tp = ns_to_timespec(expires); |
f8bd2258e remove div_long_l... |
70 |
else |
55ccb616a posix_cpu_timer: ... |
71 |
cputime_to_timespec((__force cputime_t)expires, tp); |
1da177e4c Linux-2.6.12-rc2 |
72 73 74 75 76 77 |
} /* * Update expiry time from increment, and increase overrun count, * given the current clock sample. */ |
7a4ed937a [PATCH] Fix cpu t... |
78 |
static void bump_cpu_timer(struct k_itimer *timer, |
55ccb616a posix_cpu_timer: ... |
79 |
unsigned long long now) |
1da177e4c Linux-2.6.12-rc2 |
80 81 |
{ int i; |
55ccb616a posix_cpu_timer: ... |
82 |
unsigned long long delta, incr; |
1da177e4c Linux-2.6.12-rc2 |
83 |
|
55ccb616a posix_cpu_timer: ... |
84 |
if (timer->it.cpu.incr == 0) |
1da177e4c Linux-2.6.12-rc2 |
85 |
return; |
55ccb616a posix_cpu_timer: ... |
86 87 |
if (now < timer->it.cpu.expires) return; |
1da177e4c Linux-2.6.12-rc2 |
88 |
|
55ccb616a posix_cpu_timer: ... |
89 90 |
incr = timer->it.cpu.incr; delta = now + incr - timer->it.cpu.expires; |
1da177e4c Linux-2.6.12-rc2 |
91 |
|
55ccb616a posix_cpu_timer: ... |
92 93 94 95 96 97 98 99 100 101 102 |
/* Don't use (incr*2 < delta), incr*2 might overflow. */ for (i = 0; incr < delta - incr; i++) incr = incr << 1; for (; i >= 0; incr >>= 1, i--) { if (delta < incr) continue; timer->it.cpu.expires += incr; timer->it_overrun += 1 << i; delta -= incr; |
1da177e4c Linux-2.6.12-rc2 |
103 104 |
} } |
555347f6c posix_timers: New... |
105 106 107 108 109 110 111 112 113 114 115 116 117 118 |
/** * task_cputime_zero - Check a task_cputime struct for all zero fields. * * @cputime: The struct to compare. * * Checks @cputime to see if all fields are zero. Returns true if all fields * are zero, false if any field is nonzero. */ static inline int task_cputime_zero(const struct task_cputime *cputime) { if (!cputime->utime && !cputime->stime && !cputime->sum_exec_runtime) return 1; return 0; } |
55ccb616a posix_cpu_timer: ... |
119 |
static inline unsigned long long prof_ticks(struct task_struct *p) |
1da177e4c Linux-2.6.12-rc2 |
120 |
{ |
6fac4829c cputime: Use acce... |
121 122 123 |
cputime_t utime, stime; task_cputime(p, &utime, &stime); |
55ccb616a posix_cpu_timer: ... |
124 |
return cputime_to_expires(utime + stime); |
1da177e4c Linux-2.6.12-rc2 |
125 |
} |
55ccb616a posix_cpu_timer: ... |
126 |
static inline unsigned long long virt_ticks(struct task_struct *p) |
1da177e4c Linux-2.6.12-rc2 |
127 |
{ |
6fac4829c cputime: Use acce... |
128 129 130 |
cputime_t utime; task_cputime(p, &utime, NULL); |
55ccb616a posix_cpu_timer: ... |
131 |
return cputime_to_expires(utime); |
1da177e4c Linux-2.6.12-rc2 |
132 |
} |
1da177e4c Linux-2.6.12-rc2 |
133 |
|
bc2c8ea48 posix-timers: Mak... |
134 135 |
static int posix_cpu_clock_getres(const clockid_t which_clock, struct timespec *tp) |
1da177e4c Linux-2.6.12-rc2 |
136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 |
{ int error = check_clock(which_clock); if (!error) { tp->tv_sec = 0; tp->tv_nsec = ((NSEC_PER_SEC + HZ - 1) / HZ); if (CPUCLOCK_WHICH(which_clock) == CPUCLOCK_SCHED) { /* * If sched_clock is using a cycle counter, we * don't have any idea of its true resolution * exported, but it is much more than 1s/HZ. */ tp->tv_nsec = 1; } } return error; } |
bc2c8ea48 posix-timers: Mak... |
152 153 |
static int posix_cpu_clock_set(const clockid_t which_clock, const struct timespec *tp) |
1da177e4c Linux-2.6.12-rc2 |
154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 |
{ /* * You can never reset a CPU clock, but we check for other errors * in the call before failing with EPERM. */ int error = check_clock(which_clock); if (error == 0) { error = -EPERM; } return error; } /* * Sample a per-thread clock for the given task. */ |
a924b04dd [PATCH] hrtimer: ... |
170 |
static int cpu_clock_sample(const clockid_t which_clock, struct task_struct *p, |
55ccb616a posix_cpu_timer: ... |
171 |
unsigned long long *sample) |
1da177e4c Linux-2.6.12-rc2 |
172 173 174 175 176 |
{ switch (CPUCLOCK_WHICH(which_clock)) { default: return -EINVAL; case CPUCLOCK_PROF: |
55ccb616a posix_cpu_timer: ... |
177 |
*sample = prof_ticks(p); |
1da177e4c Linux-2.6.12-rc2 |
178 179 |
break; case CPUCLOCK_VIRT: |
55ccb616a posix_cpu_timer: ... |
180 |
*sample = virt_ticks(p); |
1da177e4c Linux-2.6.12-rc2 |
181 182 |
break; case CPUCLOCK_SCHED: |
55ccb616a posix_cpu_timer: ... |
183 |
*sample = task_sched_runtime(p); |
1da177e4c Linux-2.6.12-rc2 |
184 185 186 187 |
break; } return 0; } |
4da94d49b timers: fix TIMER... |
188 189 |
static void update_gt_cputime(struct task_cputime *a, struct task_cputime *b) { |
648616343 [S390] cputime: a... |
190 |
if (b->utime > a->utime) |
4da94d49b timers: fix TIMER... |
191 |
a->utime = b->utime; |
648616343 [S390] cputime: a... |
192 |
if (b->stime > a->stime) |
4da94d49b timers: fix TIMER... |
193 194 195 196 197 198 199 200 201 202 203 |
a->stime = b->stime; if (b->sum_exec_runtime > a->sum_exec_runtime) a->sum_exec_runtime = b->sum_exec_runtime; } void thread_group_cputimer(struct task_struct *tsk, struct task_cputime *times) { struct thread_group_cputimer *cputimer = &tsk->signal->cputimer; struct task_cputime sum; unsigned long flags; |
4da94d49b timers: fix TIMER... |
204 |
if (!cputimer->running) { |
4da94d49b timers: fix TIMER... |
205 206 207 208 209 210 211 |
/* * The POSIX timer interface allows for absolute time expiry * values through the TIMER_ABSTIME flag, therefore we have * to synchronize the timer to the clock every time we start * it. */ thread_group_cputime(tsk, &sum); |
3cfef9524 Merge branch 'cor... |
212 |
raw_spin_lock_irqsave(&cputimer->lock, flags); |
bcd5cff72 cputimer: Cure lo... |
213 |
cputimer->running = 1; |
4da94d49b timers: fix TIMER... |
214 |
update_gt_cputime(&cputimer->cputime, &sum); |
bcd5cff72 cputimer: Cure lo... |
215 |
} else |
3cfef9524 Merge branch 'cor... |
216 |
raw_spin_lock_irqsave(&cputimer->lock, flags); |
4da94d49b timers: fix TIMER... |
217 |
*times = cputimer->cputime; |
ee30a7b2f locking, sched: A... |
218 |
raw_spin_unlock_irqrestore(&cputimer->lock, flags); |
4da94d49b timers: fix TIMER... |
219 |
} |
1da177e4c Linux-2.6.12-rc2 |
220 221 |
/* * Sample a process (thread group) clock for the given group_leader task. |
e73d84e33 posix-timers: Rem... |
222 223 |
* Must be called with task sighand lock held for safe while_each_thread() * traversal. |
1da177e4c Linux-2.6.12-rc2 |
224 |
*/ |
bb34d92f6 timers: fix itime... |
225 226 |
static int cpu_clock_sample_group(const clockid_t which_clock, struct task_struct *p, |
55ccb616a posix_cpu_timer: ... |
227 |
unsigned long long *sample) |
1da177e4c Linux-2.6.12-rc2 |
228 |
{ |
f06febc96 timers: fix itime... |
229 |
struct task_cputime cputime; |
eccdaeafa posix-cpu-timers:... |
230 |
switch (CPUCLOCK_WHICH(which_clock)) { |
1da177e4c Linux-2.6.12-rc2 |
231 232 233 |
default: return -EINVAL; case CPUCLOCK_PROF: |
c5f8d9958 posixtimers, sche... |
234 |
thread_group_cputime(p, &cputime); |
55ccb616a posix_cpu_timer: ... |
235 |
*sample = cputime_to_expires(cputime.utime + cputime.stime); |
1da177e4c Linux-2.6.12-rc2 |
236 237 |
break; case CPUCLOCK_VIRT: |
c5f8d9958 posixtimers, sche... |
238 |
thread_group_cputime(p, &cputime); |
55ccb616a posix_cpu_timer: ... |
239 |
*sample = cputime_to_expires(cputime.utime); |
1da177e4c Linux-2.6.12-rc2 |
240 241 |
break; case CPUCLOCK_SCHED: |
d670ec131 posix-cpu-timers:... |
242 |
thread_group_cputime(p, &cputime); |
55ccb616a posix_cpu_timer: ... |
243 |
*sample = cputime.sum_exec_runtime; |
1da177e4c Linux-2.6.12-rc2 |
244 245 246 247 |
break; } return 0; } |
33ab0fec3 posix-timers: Con... |
248 249 250 251 252 253 254 255 256 257 258 |
static int posix_cpu_clock_get_task(struct task_struct *tsk, const clockid_t which_clock, struct timespec *tp) { int err = -EINVAL; unsigned long long rtn; if (CPUCLOCK_PERTHREAD(which_clock)) { if (same_thread_group(tsk, current)) err = cpu_clock_sample(which_clock, tsk, &rtn); } else { |
50875788a posix-timers: Use... |
259 260 |
unsigned long flags; struct sighand_struct *sighand; |
33ab0fec3 posix-timers: Con... |
261 |
|
50875788a posix-timers: Use... |
262 263 264 265 266 267 268 269 270 271 |
/* * while_each_thread() is not yet entirely RCU safe, * keep locking the group while sampling process * clock for now. */ sighand = lock_task_sighand(tsk, &flags); if (!sighand) return err; if (tsk == current || thread_group_leader(tsk)) |
33ab0fec3 posix-timers: Con... |
272 |
err = cpu_clock_sample_group(which_clock, tsk, &rtn); |
50875788a posix-timers: Use... |
273 |
unlock_task_sighand(tsk, &flags); |
33ab0fec3 posix-timers: Con... |
274 275 276 277 278 279 280 |
} if (!err) sample_to_timespec(which_clock, rtn, tp); return err; } |
1da177e4c Linux-2.6.12-rc2 |
281 |
|
bc2c8ea48 posix-timers: Mak... |
282 |
static int posix_cpu_clock_get(const clockid_t which_clock, struct timespec *tp) |
1da177e4c Linux-2.6.12-rc2 |
283 284 |
{ const pid_t pid = CPUCLOCK_PID(which_clock); |
33ab0fec3 posix-timers: Con... |
285 |
int err = -EINVAL; |
1da177e4c Linux-2.6.12-rc2 |
286 287 288 289 290 291 |
if (pid == 0) { /* * Special case constant value for our own clocks. * We don't have to do any lookup to find ourselves. */ |
33ab0fec3 posix-timers: Con... |
292 |
err = posix_cpu_clock_get_task(current, which_clock, tp); |
1da177e4c Linux-2.6.12-rc2 |
293 294 295 296 297 298 |
} else { /* * Find the given PID, and validate that the caller * should be able to see it. */ struct task_struct *p; |
1f2ea0837 [PATCH] posix tim... |
299 |
rcu_read_lock(); |
8dc86af00 Use find_task_by_... |
300 |
p = find_task_by_vpid(pid); |
33ab0fec3 posix-timers: Con... |
301 302 |
if (p) err = posix_cpu_clock_get_task(p, which_clock, tp); |
1f2ea0837 [PATCH] posix tim... |
303 |
rcu_read_unlock(); |
1da177e4c Linux-2.6.12-rc2 |
304 |
} |
33ab0fec3 posix-timers: Con... |
305 |
return err; |
1da177e4c Linux-2.6.12-rc2 |
306 307 308 309 310 |
} /* * Validate the clockid_t for a new CPU-clock timer, and initialize the timer. |
ba5ea951d posix-cpu-timers:... |
311 312 |
* This is called from sys_timer_create() and do_cpu_nanosleep() with the * new timer already all-zeros initialized. |
1da177e4c Linux-2.6.12-rc2 |
313 |
*/ |
bc2c8ea48 posix-timers: Mak... |
314 |
static int posix_cpu_timer_create(struct k_itimer *new_timer) |
1da177e4c Linux-2.6.12-rc2 |
315 316 317 318 319 320 321 322 323 |
{ int ret = 0; const pid_t pid = CPUCLOCK_PID(new_timer->it_clock); struct task_struct *p; if (CPUCLOCK_WHICH(new_timer->it_clock) >= CPUCLOCK_MAX) return -EINVAL; INIT_LIST_HEAD(&new_timer->it.cpu.entry); |
1da177e4c Linux-2.6.12-rc2 |
324 |
|
c0deae8c9 posix-cpu-timers:... |
325 |
rcu_read_lock(); |
1da177e4c Linux-2.6.12-rc2 |
326 327 328 329 |
if (CPUCLOCK_PERTHREAD(new_timer->it_clock)) { if (pid == 0) { p = current; } else { |
8dc86af00 Use find_task_by_... |
330 |
p = find_task_by_vpid(pid); |
bac0abd61 Isolate some expl... |
331 |
if (p && !same_thread_group(p, current)) |
1da177e4c Linux-2.6.12-rc2 |
332 333 334 335 336 337 |
p = NULL; } } else { if (pid == 0) { p = current->group_leader; } else { |
8dc86af00 Use find_task_by_... |
338 |
p = find_task_by_vpid(pid); |
c0deae8c9 posix-cpu-timers:... |
339 |
if (p && !has_group_leader_pid(p)) |
1da177e4c Linux-2.6.12-rc2 |
340 341 342 343 344 345 346 347 348 |
p = NULL; } } new_timer->it.cpu.task = p; if (p) { get_task_struct(p); } else { ret = -EINVAL; } |
c0deae8c9 posix-cpu-timers:... |
349 |
rcu_read_unlock(); |
1da177e4c Linux-2.6.12-rc2 |
350 351 352 353 354 355 356 357 358 359 |
return ret; } /* * Clean up a CPU-clock timer that is about to be destroyed. * This is called from timer deletion with the timer already locked. * If we return TIMER_RETRY, it's necessary to release the timer's lock * and try again. (This happens when the timer is in the middle of firing.) */ |
bc2c8ea48 posix-timers: Mak... |
360 |
static int posix_cpu_timer_del(struct k_itimer *timer) |
1da177e4c Linux-2.6.12-rc2 |
361 |
{ |
108150ea7 [PATCH] posix-tim... |
362 |
int ret = 0; |
3d7a1427e posix-timers: Use... |
363 364 365 |
unsigned long flags; struct sighand_struct *sighand; struct task_struct *p = timer->it.cpu.task; |
1da177e4c Linux-2.6.12-rc2 |
366 |
|
a3222f88f posix-timers: Rem... |
367 |
WARN_ON_ONCE(p == NULL); |
108150ea7 [PATCH] posix-tim... |
368 |
|
3d7a1427e posix-timers: Use... |
369 370 371 372 373 374 |
/* * Protect against sighand release/switch in exit/exec and process/ * thread timer list entry concurrent read/writes. */ sighand = lock_task_sighand(p, &flags); if (unlikely(sighand == NULL)) { |
a3222f88f posix-timers: Rem... |
375 376 377 378 |
/* * We raced with the reaping of the task. * The deletion should have cleared us off the list. */ |
531f64fd6 posix-timers: Con... |
379 |
WARN_ON_ONCE(!list_empty(&timer->it.cpu.entry)); |
a3222f88f posix-timers: Rem... |
380 |
} else { |
a3222f88f posix-timers: Rem... |
381 382 383 384 |
if (timer->it.cpu.firing) ret = TIMER_RETRY; else list_del(&timer->it.cpu.entry); |
3d7a1427e posix-timers: Use... |
385 386 |
unlock_task_sighand(p, &flags); |
1da177e4c Linux-2.6.12-rc2 |
387 |
} |
a3222f88f posix-timers: Rem... |
388 389 390 |
if (!ret) put_task_struct(p); |
1da177e4c Linux-2.6.12-rc2 |
391 |
|
108150ea7 [PATCH] posix-tim... |
392 |
return ret; |
1da177e4c Linux-2.6.12-rc2 |
393 |
} |
af82eb3c3 posix-timers: Rem... |
394 |
static void cleanup_timers_list(struct list_head *head) |
1a7fa510b posix_cpu_timers:... |
395 396 |
{ struct cpu_timer_list *timer, *next; |
a0b2062b0 posix_timers: fix... |
397 |
list_for_each_entry_safe(timer, next, head, entry) |
1a7fa510b posix_cpu_timers:... |
398 |
list_del_init(&timer->entry); |
1a7fa510b posix_cpu_timers:... |
399 |
} |
1da177e4c Linux-2.6.12-rc2 |
400 401 402 403 404 405 |
/* * Clean out CPU timers still ticking when a thread exited. The task * pointer is cleared, and the expiry time is replaced with the residual * time for later timer_gettime calls to return. * This must be called with the siglock held. */ |
af82eb3c3 posix-timers: Rem... |
406 |
static void cleanup_timers(struct list_head *head) |
1da177e4c Linux-2.6.12-rc2 |
407 |
{ |
af82eb3c3 posix-timers: Rem... |
408 409 410 |
cleanup_timers_list(head); cleanup_timers_list(++head); cleanup_timers_list(++head); |
1da177e4c Linux-2.6.12-rc2 |
411 412 413 414 415 416 417 418 419 |
} /* * These are both called with the siglock held, when the current thread * is being reaped. When the final (leader) thread in the group is reaped, * posix_cpu_timers_exit_group will be called after posix_cpu_timers_exit. */ void posix_cpu_timers_exit(struct task_struct *tsk) { |
613370549 random: Mix cputi... |
420 421 |
add_device_randomness((const void*) &tsk->se.sum_exec_runtime, sizeof(unsigned long long)); |
af82eb3c3 posix-timers: Rem... |
422 |
cleanup_timers(tsk->cpu_timers); |
1da177e4c Linux-2.6.12-rc2 |
423 424 425 426 |
} void posix_cpu_timers_exit_group(struct task_struct *tsk) { |
af82eb3c3 posix-timers: Rem... |
427 |
cleanup_timers(tsk->signal->cpu_timers); |
1da177e4c Linux-2.6.12-rc2 |
428 |
} |
d1e3b6d19 itimers: Simplify... |
429 430 |
static inline int expires_gt(cputime_t expires, cputime_t new_exp) { |
648616343 [S390] cputime: a... |
431 |
return expires == 0 || expires > new_exp; |
d1e3b6d19 itimers: Simplify... |
432 |
} |
1da177e4c Linux-2.6.12-rc2 |
433 434 |
/* * Insert the timer on the appropriate list before any timers that |
e73d84e33 posix-timers: Rem... |
435 |
* expire later. This must be called with the sighand lock held. |
1da177e4c Linux-2.6.12-rc2 |
436 |
*/ |
5eb9aa641 cpu-timers: Clean... |
437 |
static void arm_timer(struct k_itimer *timer) |
1da177e4c Linux-2.6.12-rc2 |
438 439 440 |
{ struct task_struct *p = timer->it.cpu.task; struct list_head *head, *listpos; |
5eb9aa641 cpu-timers: Clean... |
441 |
struct task_cputime *cputime_expires; |
1da177e4c Linux-2.6.12-rc2 |
442 443 |
struct cpu_timer_list *const nt = &timer->it.cpu; struct cpu_timer_list *next; |
1da177e4c Linux-2.6.12-rc2 |
444 |
|
5eb9aa641 cpu-timers: Clean... |
445 446 447 448 449 450 451 |
if (CPUCLOCK_PERTHREAD(timer->it_clock)) { head = p->cpu_timers; cputime_expires = &p->cputime_expires; } else { head = p->signal->cpu_timers; cputime_expires = &p->signal->cputime_expires; } |
1da177e4c Linux-2.6.12-rc2 |
452 |
head += CPUCLOCK_WHICH(timer->it_clock); |
1da177e4c Linux-2.6.12-rc2 |
453 |
listpos = head; |
5eb9aa641 cpu-timers: Clean... |
454 |
list_for_each_entry(next, head, entry) { |
55ccb616a posix_cpu_timer: ... |
455 |
if (nt->expires < next->expires) |
5eb9aa641 cpu-timers: Clean... |
456 457 |
break; listpos = &next->entry; |
1da177e4c Linux-2.6.12-rc2 |
458 459 460 461 |
} list_add(&nt->entry, listpos); if (listpos == head) { |
55ccb616a posix_cpu_timer: ... |
462 |
unsigned long long exp = nt->expires; |
5eb9aa641 cpu-timers: Clean... |
463 |
|
1da177e4c Linux-2.6.12-rc2 |
464 |
/* |
5eb9aa641 cpu-timers: Clean... |
465 466 467 468 |
* We are the new earliest-expiring POSIX 1.b timer, hence * need to update expiration cache. Take into account that * for process timers we share expiration cache with itimers * and RLIMIT_CPU and for thread timers with RLIMIT_RTTIME. |
1da177e4c Linux-2.6.12-rc2 |
469 |
*/ |
5eb9aa641 cpu-timers: Clean... |
470 471 |
switch (CPUCLOCK_WHICH(timer->it_clock)) { case CPUCLOCK_PROF: |
55ccb616a posix_cpu_timer: ... |
472 473 |
if (expires_gt(cputime_expires->prof_exp, expires_to_cputime(exp))) cputime_expires->prof_exp = expires_to_cputime(exp); |
5eb9aa641 cpu-timers: Clean... |
474 475 |
break; case CPUCLOCK_VIRT: |
55ccb616a posix_cpu_timer: ... |
476 477 |
if (expires_gt(cputime_expires->virt_exp, expires_to_cputime(exp))) cputime_expires->virt_exp = expires_to_cputime(exp); |
5eb9aa641 cpu-timers: Clean... |
478 479 480 |
break; case CPUCLOCK_SCHED: if (cputime_expires->sched_exp == 0 || |
55ccb616a posix_cpu_timer: ... |
481 482 |
cputime_expires->sched_exp > exp) cputime_expires->sched_exp = exp; |
5eb9aa641 cpu-timers: Clean... |
483 |
break; |
1da177e4c Linux-2.6.12-rc2 |
484 485 |
} } |
1da177e4c Linux-2.6.12-rc2 |
486 487 488 489 490 491 492 |
} /* * The timer is locked, fire it and arrange for its reload. */ static void cpu_timer_fire(struct k_itimer *timer) { |
1f169f84d cpu-timers: Chang... |
493 494 495 496 |
if ((timer->it_sigev_notify & ~SIGEV_THREAD_ID) == SIGEV_NONE) { /* * User don't want any signal. */ |
55ccb616a posix_cpu_timer: ... |
497 |
timer->it.cpu.expires = 0; |
1f169f84d cpu-timers: Chang... |
498 |
} else if (unlikely(timer->sigq == NULL)) { |
1da177e4c Linux-2.6.12-rc2 |
499 500 501 502 503 |
/* * This a special case for clock_nanosleep, * not a normal timer from sys_timer_create. */ wake_up_process(timer->it_process); |
55ccb616a posix_cpu_timer: ... |
504 505 |
timer->it.cpu.expires = 0; } else if (timer->it.cpu.incr == 0) { |
1da177e4c Linux-2.6.12-rc2 |
506 507 508 509 |
/* * One-shot timer. Clear it as soon as it's fired. */ posix_timer_event(timer, 0); |
55ccb616a posix_cpu_timer: ... |
510 |
timer->it.cpu.expires = 0; |
1da177e4c Linux-2.6.12-rc2 |
511 512 513 514 515 516 517 518 519 520 521 522 |
} else if (posix_timer_event(timer, ++timer->it_requeue_pending)) { /* * The signal did not get queued because the signal * was ignored, so we won't get any callback to * reload the timer. But we need to keep it * ticking in case the signal is deliverable next time. */ posix_cpu_timer_schedule(timer); } } /* |
3997ad317 timers: more cons... |
523 |
* Sample a process (thread group) timer for the given group_leader task. |
e73d84e33 posix-timers: Rem... |
524 525 |
* Must be called with task sighand lock held for safe while_each_thread() * traversal. |
3997ad317 timers: more cons... |
526 527 528 |
*/ static int cpu_timer_sample_group(const clockid_t which_clock, struct task_struct *p, |
55ccb616a posix_cpu_timer: ... |
529 |
unsigned long long *sample) |
3997ad317 timers: more cons... |
530 531 532 533 534 535 536 537 |
{ struct task_cputime cputime; thread_group_cputimer(p, &cputime); switch (CPUCLOCK_WHICH(which_clock)) { default: return -EINVAL; case CPUCLOCK_PROF: |
55ccb616a posix_cpu_timer: ... |
538 |
*sample = cputime_to_expires(cputime.utime + cputime.stime); |
3997ad317 timers: more cons... |
539 540 |
break; case CPUCLOCK_VIRT: |
55ccb616a posix_cpu_timer: ... |
541 |
*sample = cputime_to_expires(cputime.utime); |
3997ad317 timers: more cons... |
542 543 |
break; case CPUCLOCK_SCHED: |
55ccb616a posix_cpu_timer: ... |
544 |
*sample = cputime.sum_exec_runtime + task_delta_exec(p); |
3997ad317 timers: more cons... |
545 546 547 548 |
break; } return 0; } |
a85721601 posix_timers: Kic... |
549 550 551 552 553 554 555 556 557 558 559 560 561 562 |
#ifdef CONFIG_NO_HZ_FULL static void nohz_kick_work_fn(struct work_struct *work) { tick_nohz_full_kick_all(); } static DECLARE_WORK(nohz_kick_work, nohz_kick_work_fn); /* * We need the IPIs to be sent from sane process context. * The posix cpu timers are always set with irqs disabled. */ static void posix_cpu_timer_kick_nohz(void) { |
d4283c654 posix-timers: Spa... |
563 564 |
if (context_tracking_is_enabled()) schedule_work(&nohz_kick_work); |
a85721601 posix_timers: Kic... |
565 |
} |
555347f6c posix_timers: New... |
566 567 568 569 |
bool posix_cpu_timers_can_stop_tick(struct task_struct *tsk) { if (!task_cputime_zero(&tsk->cputime_expires)) |
6ac29178b posix_timers: Fix... |
570 |
return false; |
555347f6c posix_timers: New... |
571 572 |
if (tsk->signal->cputimer.running) |
6ac29178b posix_timers: Fix... |
573 |
return false; |
555347f6c posix_timers: New... |
574 |
|
6ac29178b posix_timers: Fix... |
575 |
return true; |
555347f6c posix_timers: New... |
576 |
} |
a85721601 posix_timers: Kic... |
577 578 579 |
#else static inline void posix_cpu_timer_kick_nohz(void) { } #endif |
3997ad317 timers: more cons... |
580 |
/* |
1da177e4c Linux-2.6.12-rc2 |
581 582 583 584 585 |
* Guts of sys_timer_settime for CPU timers. * This is called with the timer locked and interrupts disabled. * If we return TIMER_RETRY, it's necessary to release the timer's lock * and try again. (This happens when the timer is in the middle of firing.) */ |
e73d84e33 posix-timers: Rem... |
586 |
static int posix_cpu_timer_set(struct k_itimer *timer, int timer_flags, |
bc2c8ea48 posix-timers: Mak... |
587 |
struct itimerspec *new, struct itimerspec *old) |
1da177e4c Linux-2.6.12-rc2 |
588 |
{ |
e73d84e33 posix-timers: Rem... |
589 590 |
unsigned long flags; struct sighand_struct *sighand; |
1da177e4c Linux-2.6.12-rc2 |
591 |
struct task_struct *p = timer->it.cpu.task; |
55ccb616a posix_cpu_timer: ... |
592 |
unsigned long long old_expires, new_expires, old_incr, val; |
1da177e4c Linux-2.6.12-rc2 |
593 |
int ret; |
a3222f88f posix-timers: Rem... |
594 |
WARN_ON_ONCE(p == NULL); |
1da177e4c Linux-2.6.12-rc2 |
595 596 |
new_expires = timespec_to_sample(timer->it_clock, &new->it_value); |
1da177e4c Linux-2.6.12-rc2 |
597 |
/* |
e73d84e33 posix-timers: Rem... |
598 599 600 601 602 603 |
* Protect against sighand release/switch in exit/exec and p->cpu_timers * and p->signal->cpu_timers read/write in arm_timer() */ sighand = lock_task_sighand(p, &flags); /* * If p has just been reaped, we can no |
1da177e4c Linux-2.6.12-rc2 |
604 605 |
* longer get any information about it at all. */ |
e73d84e33 posix-timers: Rem... |
606 |
if (unlikely(sighand == NULL)) { |
1da177e4c Linux-2.6.12-rc2 |
607 608 609 610 611 612 |
return -ESRCH; } /* * Disarm any old timer after extracting its expiry time. */ |
531f64fd6 posix-timers: Con... |
613 |
WARN_ON_ONCE(!irqs_disabled()); |
a69ac4a78 [PATCH] posix-tim... |
614 615 |
ret = 0; |
ae1a78eec cpu-timers: Retur... |
616 |
old_incr = timer->it.cpu.incr; |
1da177e4c Linux-2.6.12-rc2 |
617 |
old_expires = timer->it.cpu.expires; |
a69ac4a78 [PATCH] posix-tim... |
618 619 620 621 622 |
if (unlikely(timer->it.cpu.firing)) { timer->it.cpu.firing = -1; ret = TIMER_RETRY; } else list_del_init(&timer->it.cpu.entry); |
1da177e4c Linux-2.6.12-rc2 |
623 624 625 626 627 628 629 630 631 632 633 634 |
/* * We need to sample the current value to convert the new * value from to relative and absolute, and to convert the * old value from absolute to relative. To set a process * timer, we need a sample to balance the thread expiry * times (in arm_timer). With an absolute time, we must * check if it's already passed. In short, we need a sample. */ if (CPUCLOCK_PERTHREAD(timer->it_clock)) { cpu_clock_sample(timer->it_clock, p, &val); } else { |
3997ad317 timers: more cons... |
635 |
cpu_timer_sample_group(timer->it_clock, p, &val); |
1da177e4c Linux-2.6.12-rc2 |
636 637 638 |
} if (old) { |
55ccb616a posix_cpu_timer: ... |
639 |
if (old_expires == 0) { |
1da177e4c Linux-2.6.12-rc2 |
640 641 642 643 644 645 646 647 648 649 650 651 652 653 |
old->it_value.tv_sec = 0; old->it_value.tv_nsec = 0; } else { /* * Update the timer in case it has * overrun already. If it has, * we'll report it as having overrun * and with the next reloaded timer * already ticking, though we are * swallowing that pending * notification here to install the * new setting. */ bump_cpu_timer(timer, val); |
55ccb616a posix_cpu_timer: ... |
654 655 |
if (val < timer->it.cpu.expires) { old_expires = timer->it.cpu.expires - val; |
1da177e4c Linux-2.6.12-rc2 |
656 657 658 659 660 661 662 663 664 |
sample_to_timespec(timer->it_clock, old_expires, &old->it_value); } else { old->it_value.tv_nsec = 1; old->it_value.tv_sec = 0; } } } |
a69ac4a78 [PATCH] posix-tim... |
665 |
if (unlikely(ret)) { |
1da177e4c Linux-2.6.12-rc2 |
666 667 668 669 670 671 |
/* * We are colliding with the timer actually firing. * Punt after filling in the timer's old value, and * disable this firing since we are already reporting * it as an overrun (thanks to bump_cpu_timer above). */ |
e73d84e33 posix-timers: Rem... |
672 |
unlock_task_sighand(p, &flags); |
1da177e4c Linux-2.6.12-rc2 |
673 674 |
goto out; } |
e73d84e33 posix-timers: Rem... |
675 |
if (new_expires != 0 && !(timer_flags & TIMER_ABSTIME)) { |
55ccb616a posix_cpu_timer: ... |
676 |
new_expires += val; |
1da177e4c Linux-2.6.12-rc2 |
677 678 679 680 681 682 683 684 |
} /* * Install the new expiry time (or zero). * For a timer with no notification action, we don't actually * arm the timer (we'll just fake it for timer_gettime). */ timer->it.cpu.expires = new_expires; |
55ccb616a posix_cpu_timer: ... |
685 |
if (new_expires != 0 && val < new_expires) { |
5eb9aa641 cpu-timers: Clean... |
686 |
arm_timer(timer); |
1da177e4c Linux-2.6.12-rc2 |
687 |
} |
e73d84e33 posix-timers: Rem... |
688 |
unlock_task_sighand(p, &flags); |
1da177e4c Linux-2.6.12-rc2 |
689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 |
/* * Install the new reload setting, and * set up the signal and overrun bookkeeping. */ timer->it.cpu.incr = timespec_to_sample(timer->it_clock, &new->it_interval); /* * This acts as a modification timestamp for the timer, * so any automatic reload attempt will punt on seeing * that we have reset the timer manually. */ timer->it_requeue_pending = (timer->it_requeue_pending + 2) & ~REQUEUE_PENDING; timer->it_overrun_last = 0; timer->it_overrun = -1; |
55ccb616a posix_cpu_timer: ... |
705 |
if (new_expires != 0 && !(val < new_expires)) { |
1da177e4c Linux-2.6.12-rc2 |
706 707 708 709 710 711 712 713 714 715 716 717 |
/* * The designated time already passed, so we notify * immediately, even if the thread never runs to * accumulate more time on this clock. */ cpu_timer_fire(timer); } ret = 0; out: if (old) { sample_to_timespec(timer->it_clock, |
ae1a78eec cpu-timers: Retur... |
718 |
old_incr, &old->it_interval); |
1da177e4c Linux-2.6.12-rc2 |
719 |
} |
a85721601 posix_timers: Kic... |
720 721 |
if (!ret) posix_cpu_timer_kick_nohz(); |
1da177e4c Linux-2.6.12-rc2 |
722 723 |
return ret; } |
bc2c8ea48 posix-timers: Mak... |
724 |
static void posix_cpu_timer_get(struct k_itimer *timer, struct itimerspec *itp) |
1da177e4c Linux-2.6.12-rc2 |
725 |
{ |
55ccb616a posix_cpu_timer: ... |
726 |
unsigned long long now; |
1da177e4c Linux-2.6.12-rc2 |
727 |
struct task_struct *p = timer->it.cpu.task; |
1da177e4c Linux-2.6.12-rc2 |
728 |
|
a3222f88f posix-timers: Rem... |
729 |
WARN_ON_ONCE(p == NULL); |
1da177e4c Linux-2.6.12-rc2 |
730 731 732 733 734 |
/* * Easy part: convert the reload time. */ sample_to_timespec(timer->it_clock, timer->it.cpu.incr, &itp->it_interval); |
55ccb616a posix_cpu_timer: ... |
735 |
if (timer->it.cpu.expires == 0) { /* Timer not armed at all. */ |
1da177e4c Linux-2.6.12-rc2 |
736 737 738 |
itp->it_value.tv_sec = itp->it_value.tv_nsec = 0; return; } |
1da177e4c Linux-2.6.12-rc2 |
739 740 741 742 743 |
/* * Sample the clock to take the difference with the expiry time. */ if (CPUCLOCK_PERTHREAD(timer->it_clock)) { cpu_clock_sample(timer->it_clock, p, &now); |
1da177e4c Linux-2.6.12-rc2 |
744 |
} else { |
e73d84e33 posix-timers: Rem... |
745 746 747 748 749 750 751 752 753 754 |
struct sighand_struct *sighand; unsigned long flags; /* * Protect against sighand release/switch in exit/exec and * also make timer sampling safe if it ends up calling * thread_group_cputime(). */ sighand = lock_task_sighand(p, &flags); if (unlikely(sighand == NULL)) { |
1da177e4c Linux-2.6.12-rc2 |
755 756 757 758 759 |
/* * The process has been reaped. * We can't even collect a sample any more. * Call the timer disarmed, nothing else to do. */ |
55ccb616a posix_cpu_timer: ... |
760 |
timer->it.cpu.expires = 0; |
a3222f88f posix-timers: Rem... |
761 762 |
sample_to_timespec(timer->it_clock, timer->it.cpu.expires, &itp->it_value); |
1da177e4c Linux-2.6.12-rc2 |
763 |
} else { |
3997ad317 timers: more cons... |
764 |
cpu_timer_sample_group(timer->it_clock, p, &now); |
e73d84e33 posix-timers: Rem... |
765 |
unlock_task_sighand(p, &flags); |
1da177e4c Linux-2.6.12-rc2 |
766 |
} |
1da177e4c Linux-2.6.12-rc2 |
767 |
} |
55ccb616a posix_cpu_timer: ... |
768 |
if (now < timer->it.cpu.expires) { |
1da177e4c Linux-2.6.12-rc2 |
769 |
sample_to_timespec(timer->it_clock, |
55ccb616a posix_cpu_timer: ... |
770 |
timer->it.cpu.expires - now, |
1da177e4c Linux-2.6.12-rc2 |
771 772 773 774 775 776 777 778 779 780 |
&itp->it_value); } else { /* * The timer should have expired already, but the firing * hasn't taken place yet. Say it's just about to expire. */ itp->it_value.tv_nsec = 1; itp->it_value.tv_sec = 0; } } |
2473f3e7a posix_cpu_timers:... |
781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 |
static unsigned long long check_timers_list(struct list_head *timers, struct list_head *firing, unsigned long long curr) { int maxfire = 20; while (!list_empty(timers)) { struct cpu_timer_list *t; t = list_first_entry(timers, struct cpu_timer_list, entry); if (!--maxfire || curr < t->expires) return t->expires; t->firing = 1; list_move_tail(&t->entry, firing); } return 0; } |
1da177e4c Linux-2.6.12-rc2 |
802 803 804 805 806 807 808 809 810 |
/* * Check for any per-thread CPU timers that have fired and move them off * the tsk->cpu_timers[N] list onto the firing list. Here we update the * tsk->it_*_expires values to reflect the remaining thread CPU timers. */ static void check_thread_timers(struct task_struct *tsk, struct list_head *firing) { struct list_head *timers = tsk->cpu_timers; |
78f2c7db6 sched: SCHED_FIFO... |
811 |
struct signal_struct *const sig = tsk->signal; |
2473f3e7a posix_cpu_timers:... |
812 813 |
struct task_cputime *tsk_expires = &tsk->cputime_expires; unsigned long long expires; |
d4bb52743 posix-cpu-timers:... |
814 |
unsigned long soft; |
1da177e4c Linux-2.6.12-rc2 |
815 |
|
2473f3e7a posix_cpu_timers:... |
816 817 |
expires = check_timers_list(timers, firing, prof_ticks(tsk)); tsk_expires->prof_exp = expires_to_cputime(expires); |
1da177e4c Linux-2.6.12-rc2 |
818 |
|
2473f3e7a posix_cpu_timers:... |
819 820 |
expires = check_timers_list(++timers, firing, virt_ticks(tsk)); tsk_expires->virt_exp = expires_to_cputime(expires); |
1da177e4c Linux-2.6.12-rc2 |
821 |
|
2473f3e7a posix_cpu_timers:... |
822 823 |
tsk_expires->sched_exp = check_timers_list(++timers, firing, tsk->se.sum_exec_runtime); |
78f2c7db6 sched: SCHED_FIFO... |
824 825 826 827 |
/* * Check for the special case thread timers. */ |
78d7d407b kernel core: use ... |
828 |
soft = ACCESS_ONCE(sig->rlim[RLIMIT_RTTIME].rlim_cur); |
d4bb52743 posix-cpu-timers:... |
829 |
if (soft != RLIM_INFINITY) { |
78d7d407b kernel core: use ... |
830 831 |
unsigned long hard = ACCESS_ONCE(sig->rlim[RLIMIT_RTTIME].rlim_max); |
78f2c7db6 sched: SCHED_FIFO... |
832 |
|
5a52dd500 sched: rt-watchdo... |
833 834 |
if (hard != RLIM_INFINITY && tsk->rt.timeout > DIV_ROUND_UP(hard, USEC_PER_SEC/HZ)) { |
78f2c7db6 sched: SCHED_FIFO... |
835 836 837 838 839 840 841 |
/* * At the hard limit, we just die. * No need to calculate anything else now. */ __group_send_sig_info(SIGKILL, SEND_SIG_PRIV, tsk); return; } |
d4bb52743 posix-cpu-timers:... |
842 |
if (tsk->rt.timeout > DIV_ROUND_UP(soft, USEC_PER_SEC/HZ)) { |
78f2c7db6 sched: SCHED_FIFO... |
843 844 845 |
/* * At the soft limit, send a SIGXCPU every second. */ |
d4bb52743 posix-cpu-timers:... |
846 847 848 |
if (soft < hard) { soft += USEC_PER_SEC; sig->rlim[RLIMIT_RTTIME].rlim_cur = soft; |
78f2c7db6 sched: SCHED_FIFO... |
849 |
} |
81d50bb25 posix-timers: pri... |
850 851 852 853 |
printk(KERN_INFO "RT Watchdog Timeout: %s[%d] ", tsk->comm, task_pid_nr(tsk)); |
78f2c7db6 sched: SCHED_FIFO... |
854 855 856 |
__group_send_sig_info(SIGXCPU, SEND_SIG_PRIV, tsk); } } |
1da177e4c Linux-2.6.12-rc2 |
857 |
} |
15365c108 posix-cpu-timers:... |
858 |
static void stop_process_timers(struct signal_struct *sig) |
3fccfd67d timers: split pro... |
859 |
{ |
15365c108 posix-cpu-timers:... |
860 |
struct thread_group_cputimer *cputimer = &sig->cputimer; |
3fccfd67d timers: split pro... |
861 |
unsigned long flags; |
ee30a7b2f locking, sched: A... |
862 |
raw_spin_lock_irqsave(&cputimer->lock, flags); |
3fccfd67d timers: split pro... |
863 |
cputimer->running = 0; |
ee30a7b2f locking, sched: A... |
864 |
raw_spin_unlock_irqrestore(&cputimer->lock, flags); |
3fccfd67d timers: split pro... |
865 |
} |
8356b5f9c itimers: Fix peri... |
866 |
static u32 onecputick; |
42c4ab41a itimers: Merge IT... |
867 |
static void check_cpu_itimer(struct task_struct *tsk, struct cpu_itimer *it, |
55ccb616a posix_cpu_timer: ... |
868 869 |
unsigned long long *expires, unsigned long long cur_time, int signo) |
42c4ab41a itimers: Merge IT... |
870 |
{ |
648616343 [S390] cputime: a... |
871 |
if (!it->expires) |
42c4ab41a itimers: Merge IT... |
872 |
return; |
648616343 [S390] cputime: a... |
873 874 875 |
if (cur_time >= it->expires) { if (it->incr) { it->expires += it->incr; |
8356b5f9c itimers: Fix peri... |
876 877 |
it->error += it->incr_error; if (it->error >= onecputick) { |
648616343 [S390] cputime: a... |
878 |
it->expires -= cputime_one_jiffy; |
8356b5f9c itimers: Fix peri... |
879 880 |
it->error -= onecputick; } |
3f0a525eb itimers: Add trac... |
881 |
} else { |
648616343 [S390] cputime: a... |
882 |
it->expires = 0; |
3f0a525eb itimers: Add trac... |
883 |
} |
42c4ab41a itimers: Merge IT... |
884 |
|
3f0a525eb itimers: Add trac... |
885 886 887 |
trace_itimer_expire(signo == SIGPROF ? ITIMER_PROF : ITIMER_VIRTUAL, tsk->signal->leader_pid, cur_time); |
42c4ab41a itimers: Merge IT... |
888 889 |
__group_send_sig_info(signo, SEND_SIG_PRIV, tsk); } |
648616343 [S390] cputime: a... |
890 |
if (it->expires && (!*expires || it->expires < *expires)) { |
42c4ab41a itimers: Merge IT... |
891 892 893 |
*expires = it->expires; } } |
1da177e4c Linux-2.6.12-rc2 |
894 895 896 897 898 899 900 901 902 |
/* * Check for any per-thread CPU timers that have fired and move them * off the tsk->*_timers list onto the firing list. Per-thread timers * have already been taken off. */ static void check_process_timers(struct task_struct *tsk, struct list_head *firing) { struct signal_struct *const sig = tsk->signal; |
55ccb616a posix_cpu_timer: ... |
903 |
unsigned long long utime, ptime, virt_expires, prof_expires; |
41b86e9c5 sched: make posix... |
904 |
unsigned long long sum_sched_runtime, sched_expires; |
1da177e4c Linux-2.6.12-rc2 |
905 |
struct list_head *timers = sig->cpu_timers; |
f06febc96 timers: fix itime... |
906 |
struct task_cputime cputime; |
d4bb52743 posix-cpu-timers:... |
907 |
unsigned long soft; |
1da177e4c Linux-2.6.12-rc2 |
908 909 |
/* |
1da177e4c Linux-2.6.12-rc2 |
910 911 |
* Collect the current process totals. */ |
4cd4c1b40 timers: split pro... |
912 |
thread_group_cputimer(tsk, &cputime); |
55ccb616a posix_cpu_timer: ... |
913 914 |
utime = cputime_to_expires(cputime.utime); ptime = utime + cputime_to_expires(cputime.stime); |
f06febc96 timers: fix itime... |
915 |
sum_sched_runtime = cputime.sum_exec_runtime; |
1da177e4c Linux-2.6.12-rc2 |
916 |
|
2473f3e7a posix_cpu_timers:... |
917 918 919 |
prof_expires = check_timers_list(timers, firing, ptime); virt_expires = check_timers_list(++timers, firing, utime); sched_expires = check_timers_list(++timers, firing, sum_sched_runtime); |
1da177e4c Linux-2.6.12-rc2 |
920 921 922 923 |
/* * Check for the special case process timers. */ |
42c4ab41a itimers: Merge IT... |
924 925 926 927 |
check_cpu_itimer(tsk, &sig->it[CPUCLOCK_PROF], &prof_expires, ptime, SIGPROF); check_cpu_itimer(tsk, &sig->it[CPUCLOCK_VIRT], &virt_expires, utime, SIGVTALRM); |
78d7d407b kernel core: use ... |
928 |
soft = ACCESS_ONCE(sig->rlim[RLIMIT_CPU].rlim_cur); |
d4bb52743 posix-cpu-timers:... |
929 |
if (soft != RLIM_INFINITY) { |
1da177e4c Linux-2.6.12-rc2 |
930 |
unsigned long psecs = cputime_to_secs(ptime); |
78d7d407b kernel core: use ... |
931 932 |
unsigned long hard = ACCESS_ONCE(sig->rlim[RLIMIT_CPU].rlim_max); |
1da177e4c Linux-2.6.12-rc2 |
933 |
cputime_t x; |
d4bb52743 posix-cpu-timers:... |
934 |
if (psecs >= hard) { |
1da177e4c Linux-2.6.12-rc2 |
935 936 937 938 939 940 941 |
/* * At the hard limit, we just die. * No need to calculate anything else now. */ __group_send_sig_info(SIGKILL, SEND_SIG_PRIV, tsk); return; } |
d4bb52743 posix-cpu-timers:... |
942 |
if (psecs >= soft) { |
1da177e4c Linux-2.6.12-rc2 |
943 944 945 946 |
/* * At the soft limit, send a SIGXCPU every second. */ __group_send_sig_info(SIGXCPU, SEND_SIG_PRIV, tsk); |
d4bb52743 posix-cpu-timers:... |
947 948 949 |
if (soft < hard) { soft++; sig->rlim[RLIMIT_CPU].rlim_cur = soft; |
1da177e4c Linux-2.6.12-rc2 |
950 951 |
} } |
d4bb52743 posix-cpu-timers:... |
952 |
x = secs_to_cputime(soft); |
648616343 [S390] cputime: a... |
953 |
if (!prof_expires || x < prof_expires) { |
1da177e4c Linux-2.6.12-rc2 |
954 955 956 |
prof_expires = x; } } |
55ccb616a posix_cpu_timer: ... |
957 958 |
sig->cputime_expires.prof_exp = expires_to_cputime(prof_expires); sig->cputime_expires.virt_exp = expires_to_cputime(virt_expires); |
29f87b793 posix-cpu-timers:... |
959 960 961 |
sig->cputime_expires.sched_exp = sched_expires; if (task_cputime_zero(&sig->cputime_expires)) stop_process_timers(sig); |
1da177e4c Linux-2.6.12-rc2 |
962 963 964 965 966 967 968 969 |
} /* * This is called from the signal code (via do_schedule_next_timer) * when the last timer signal was delivered and we have to reload the timer. */ void posix_cpu_timer_schedule(struct k_itimer *timer) { |
e73d84e33 posix-timers: Rem... |
970 971 |
struct sighand_struct *sighand; unsigned long flags; |
1da177e4c Linux-2.6.12-rc2 |
972 |
struct task_struct *p = timer->it.cpu.task; |
55ccb616a posix_cpu_timer: ... |
973 |
unsigned long long now; |
1da177e4c Linux-2.6.12-rc2 |
974 |
|
a3222f88f posix-timers: Rem... |
975 |
WARN_ON_ONCE(p == NULL); |
1da177e4c Linux-2.6.12-rc2 |
976 977 978 979 980 981 982 |
/* * Fetch the current sample and update the timer's expiry time. */ if (CPUCLOCK_PERTHREAD(timer->it_clock)) { cpu_clock_sample(timer->it_clock, p, &now); bump_cpu_timer(timer, now); |
724a37139 posix-timers: Rem... |
983 |
if (unlikely(p->exit_state)) |
708f430dc [PATCH] posix-cpu... |
984 |
goto out; |
724a37139 posix-timers: Rem... |
985 |
|
e73d84e33 posix-timers: Rem... |
986 987 988 989 |
/* Protect timer list r/w in arm_timer() */ sighand = lock_task_sighand(p, &flags); if (!sighand) goto out; |
1da177e4c Linux-2.6.12-rc2 |
990 |
} else { |
e73d84e33 posix-timers: Rem... |
991 992 993 994 995 996 |
/* * Protect arm_timer() and timer sampling in case of call to * thread_group_cputime(). */ sighand = lock_task_sighand(p, &flags); if (unlikely(sighand == NULL)) { |
1da177e4c Linux-2.6.12-rc2 |
997 998 999 1000 |
/* * The process has been reaped. * We can't even collect a sample any more. */ |
55ccb616a posix_cpu_timer: ... |
1001 |
timer->it.cpu.expires = 0; |
c925077c3 posix-timers: Fix... |
1002 |
goto out; |
1da177e4c Linux-2.6.12-rc2 |
1003 |
} else if (unlikely(p->exit_state) && thread_group_empty(p)) { |
e73d84e33 posix-timers: Rem... |
1004 |
unlock_task_sighand(p, &flags); |
d430b9173 posix-timers: Rem... |
1005 |
/* Optimizations: if the process is dying, no need to rearm */ |
c925077c3 posix-timers: Fix... |
1006 |
goto out; |
1da177e4c Linux-2.6.12-rc2 |
1007 |
} |
3997ad317 timers: more cons... |
1008 |
cpu_timer_sample_group(timer->it_clock, p, &now); |
1da177e4c Linux-2.6.12-rc2 |
1009 |
bump_cpu_timer(timer, now); |
e73d84e33 posix-timers: Rem... |
1010 |
/* Leave the sighand locked for the call below. */ |
1da177e4c Linux-2.6.12-rc2 |
1011 1012 1013 1014 1015 |
} /* * Now re-arm for the new expiry time. */ |
531f64fd6 posix-timers: Con... |
1016 |
WARN_ON_ONCE(!irqs_disabled()); |
5eb9aa641 cpu-timers: Clean... |
1017 |
arm_timer(timer); |
e73d84e33 posix-timers: Rem... |
1018 |
unlock_task_sighand(p, &flags); |
708f430dc [PATCH] posix-cpu... |
1019 |
|
c925077c3 posix-timers: Fix... |
1020 1021 |
/* Kick full dynticks CPUs in case they need to tick on the new timer */ posix_cpu_timer_kick_nohz(); |
708f430dc [PATCH] posix-cpu... |
1022 1023 1024 1025 |
out: timer->it_overrun_last = timer->it_overrun; timer->it_overrun = -1; ++timer->it_requeue_pending; |
1da177e4c Linux-2.6.12-rc2 |
1026 |
} |
f06febc96 timers: fix itime... |
1027 |
/** |
f06febc96 timers: fix itime... |
1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 |
* task_cputime_expired - Compare two task_cputime entities. * * @sample: The task_cputime structure to be checked for expiration. * @expires: Expiration times, against which @sample will be checked. * * Checks @sample against @expires to see if any field of @sample has expired. * Returns true if any field of the former is greater than the corresponding * field of the latter if the latter field is set. Otherwise returns false. */ static inline int task_cputime_expired(const struct task_cputime *sample, const struct task_cputime *expires) { |
648616343 [S390] cputime: a... |
1040 |
if (expires->utime && sample->utime >= expires->utime) |
f06febc96 timers: fix itime... |
1041 |
return 1; |
648616343 [S390] cputime: a... |
1042 |
if (expires->stime && sample->utime + sample->stime >= expires->stime) |
f06febc96 timers: fix itime... |
1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 |
return 1; if (expires->sum_exec_runtime != 0 && sample->sum_exec_runtime >= expires->sum_exec_runtime) return 1; return 0; } /** * fastpath_timer_check - POSIX CPU timers fast path. * * @tsk: The task (thread) being checked. |
f06febc96 timers: fix itime... |
1054 |
* |
bb34d92f6 timers: fix itime... |
1055 1056 1057 1058 |
* Check the task and thread group timers. If both are zero (there are no * timers set) return false. Otherwise snapshot the task and thread group * timers and compare them with the corresponding expiration times. Return * true if a timer has expired, else return false. |
f06febc96 timers: fix itime... |
1059 |
*/ |
bb34d92f6 timers: fix itime... |
1060 |
static inline int fastpath_timer_check(struct task_struct *tsk) |
f06febc96 timers: fix itime... |
1061 |
{ |
ad133ba3d sched, signals: f... |
1062 |
struct signal_struct *sig; |
6fac4829c cputime: Use acce... |
1063 1064 1065 |
cputime_t utime, stime; task_cputime(tsk, &utime, &stime); |
bb34d92f6 timers: fix itime... |
1066 |
|
bb34d92f6 timers: fix itime... |
1067 1068 |
if (!task_cputime_zero(&tsk->cputime_expires)) { struct task_cputime task_sample = { |
6fac4829c cputime: Use acce... |
1069 1070 |
.utime = utime, .stime = stime, |
bb34d92f6 timers: fix itime... |
1071 1072 1073 1074 1075 1076 |
.sum_exec_runtime = tsk->se.sum_exec_runtime }; if (task_cputime_expired(&task_sample, &tsk->cputime_expires)) return 1; } |
ad133ba3d sched, signals: f... |
1077 1078 |
sig = tsk->signal; |
29f87b793 posix-cpu-timers:... |
1079 |
if (sig->cputimer.running) { |
bb34d92f6 timers: fix itime... |
1080 |
struct task_cputime group_sample; |
ee30a7b2f locking, sched: A... |
1081 |
raw_spin_lock(&sig->cputimer.lock); |
8d1f431cb sched: Fix the ra... |
1082 |
group_sample = sig->cputimer.cputime; |
ee30a7b2f locking, sched: A... |
1083 |
raw_spin_unlock(&sig->cputimer.lock); |
8d1f431cb sched: Fix the ra... |
1084 |
|
bb34d92f6 timers: fix itime... |
1085 1086 1087 |
if (task_cputime_expired(&group_sample, &sig->cputime_expires)) return 1; } |
37bebc70d posix timers: fix... |
1088 |
|
f55db6090 cpu-timers: Simpl... |
1089 |
return 0; |
f06febc96 timers: fix itime... |
1090 |
} |
1da177e4c Linux-2.6.12-rc2 |
1091 1092 1093 1094 1095 1096 1097 1098 1099 |
/* * This is called from the timer interrupt handler. The irq handler has * already updated our counts. We need to check if any timers fire now. * Interrupts are disabled. */ void run_posix_cpu_timers(struct task_struct *tsk) { LIST_HEAD(firing); struct k_itimer *timer, *next; |
0bdd2ed41 sched: run_posix_... |
1100 |
unsigned long flags; |
1da177e4c Linux-2.6.12-rc2 |
1101 |
|
531f64fd6 posix-timers: Con... |
1102 |
WARN_ON_ONCE(!irqs_disabled()); |
1da177e4c Linux-2.6.12-rc2 |
1103 |
|
1da177e4c Linux-2.6.12-rc2 |
1104 |
/* |
f06febc96 timers: fix itime... |
1105 |
* The fast path checks that there are no expired thread or thread |
bb34d92f6 timers: fix itime... |
1106 |
* group timers. If that's so, just return. |
1da177e4c Linux-2.6.12-rc2 |
1107 |
*/ |
bb34d92f6 timers: fix itime... |
1108 |
if (!fastpath_timer_check(tsk)) |
f06febc96 timers: fix itime... |
1109 |
return; |
5ce73a4a5 timers: fix itime... |
1110 |
|
0bdd2ed41 sched: run_posix_... |
1111 1112 |
if (!lock_task_sighand(tsk, &flags)) return; |
bb34d92f6 timers: fix itime... |
1113 1114 1115 1116 1117 1118 |
/* * Here we take off tsk->signal->cpu_timers[N] and * tsk->cpu_timers[N] all the timers that are firing, and * put them on the firing list. */ check_thread_timers(tsk, &firing); |
29f87b793 posix-cpu-timers:... |
1119 1120 1121 1122 1123 1124 |
/* * If there are any active process wide timers (POSIX 1.b, itimers, * RLIMIT_CPU) cputimer must be running. */ if (tsk->signal->cputimer.running) check_process_timers(tsk, &firing); |
1da177e4c Linux-2.6.12-rc2 |
1125 |
|
bb34d92f6 timers: fix itime... |
1126 1127 1128 1129 1130 1131 1132 1133 |
/* * We must release these locks before taking any timer's lock. * There is a potential race with timer deletion here, as the * siglock now protects our private firing list. We have set * the firing flag in each timer, so that a deletion attempt * that gets the timer lock before we do will give it up and * spin until we've taken care of that timer below. */ |
0bdd2ed41 sched: run_posix_... |
1134 |
unlock_task_sighand(tsk, &flags); |
1da177e4c Linux-2.6.12-rc2 |
1135 1136 1137 |
/* * Now that all the timers on our list have the firing flag, |
25985edce Fix common misspe... |
1138 |
* no one will touch their list entries but us. We'll take |
1da177e4c Linux-2.6.12-rc2 |
1139 1140 1141 1142 |
* each timer's lock before clearing its firing flag, so no * timer call will interfere. */ list_for_each_entry_safe(timer, next, &firing, it.cpu.entry) { |
6e85c5ba7 kernel/posix-cpu-... |
1143 |
int cpu_firing; |
1da177e4c Linux-2.6.12-rc2 |
1144 1145 |
spin_lock(&timer->it_lock); list_del_init(&timer->it.cpu.entry); |
6e85c5ba7 kernel/posix-cpu-... |
1146 |
cpu_firing = timer->it.cpu.firing; |
1da177e4c Linux-2.6.12-rc2 |
1147 1148 1149 1150 1151 1152 |
timer->it.cpu.firing = 0; /* * The firing flag is -1 if we collided with a reset * of the timer, which already reported this * almost-firing as an overrun. So don't generate an event. */ |
6e85c5ba7 kernel/posix-cpu-... |
1153 |
if (likely(cpu_firing >= 0)) |
1da177e4c Linux-2.6.12-rc2 |
1154 |
cpu_timer_fire(timer); |
1da177e4c Linux-2.6.12-rc2 |
1155 1156 1157 1158 1159 |
spin_unlock(&timer->it_lock); } } /* |
f55db6090 cpu-timers: Simpl... |
1160 |
* Set one of the process-wide special case CPU timers or RLIMIT_CPU. |
f06febc96 timers: fix itime... |
1161 |
* The tsk->sighand->siglock must be held by the caller. |
1da177e4c Linux-2.6.12-rc2 |
1162 1163 1164 1165 |
*/ void set_process_cpu_timer(struct task_struct *tsk, unsigned int clock_idx, cputime_t *newval, cputime_t *oldval) { |
55ccb616a posix_cpu_timer: ... |
1166 |
unsigned long long now; |
1da177e4c Linux-2.6.12-rc2 |
1167 |
|
531f64fd6 posix-timers: Con... |
1168 |
WARN_ON_ONCE(clock_idx == CPUCLOCK_SCHED); |
4cd4c1b40 timers: split pro... |
1169 |
cpu_timer_sample_group(clock_idx, tsk, &now); |
1da177e4c Linux-2.6.12-rc2 |
1170 1171 |
if (oldval) { |
f55db6090 cpu-timers: Simpl... |
1172 1173 1174 1175 1176 |
/* * We are setting itimer. The *oldval is absolute and we update * it to be relative, *newval argument is relative and we update * it to be absolute. */ |
648616343 [S390] cputime: a... |
1177 |
if (*oldval) { |
55ccb616a posix_cpu_timer: ... |
1178 |
if (*oldval <= now) { |
1da177e4c Linux-2.6.12-rc2 |
1179 |
/* Just about to fire. */ |
a42548a18 cputime: Optimize... |
1180 |
*oldval = cputime_one_jiffy; |
1da177e4c Linux-2.6.12-rc2 |
1181 |
} else { |
55ccb616a posix_cpu_timer: ... |
1182 |
*oldval -= now; |
1da177e4c Linux-2.6.12-rc2 |
1183 1184 |
} } |
648616343 [S390] cputime: a... |
1185 |
if (!*newval) |
a85721601 posix_timers: Kic... |
1186 |
goto out; |
55ccb616a posix_cpu_timer: ... |
1187 |
*newval += now; |
1da177e4c Linux-2.6.12-rc2 |
1188 1189 1190 |
} /* |
f55db6090 cpu-timers: Simpl... |
1191 1192 |
* Update expiration cache if we are the earliest timer, or eventually * RLIMIT_CPU limit is earlier than prof_exp cpu timer expire. |
1da177e4c Linux-2.6.12-rc2 |
1193 |
*/ |
f55db6090 cpu-timers: Simpl... |
1194 1195 1196 |
switch (clock_idx) { case CPUCLOCK_PROF: if (expires_gt(tsk->signal->cputime_expires.prof_exp, *newval)) |
f06febc96 timers: fix itime... |
1197 |
tsk->signal->cputime_expires.prof_exp = *newval; |
f55db6090 cpu-timers: Simpl... |
1198 1199 1200 |
break; case CPUCLOCK_VIRT: if (expires_gt(tsk->signal->cputime_expires.virt_exp, *newval)) |
f06febc96 timers: fix itime... |
1201 |
tsk->signal->cputime_expires.virt_exp = *newval; |
f55db6090 cpu-timers: Simpl... |
1202 |
break; |
1da177e4c Linux-2.6.12-rc2 |
1203 |
} |
a85721601 posix_timers: Kic... |
1204 1205 |
out: posix_cpu_timer_kick_nohz(); |
1da177e4c Linux-2.6.12-rc2 |
1206 |
} |
e4b765551 [PATCH] posix-tim... |
1207 1208 |
static int do_cpu_nanosleep(const clockid_t which_clock, int flags, struct timespec *rqtp, struct itimerspec *it) |
1da177e4c Linux-2.6.12-rc2 |
1209 |
{ |
1da177e4c Linux-2.6.12-rc2 |
1210 1211 1212 1213 |
struct k_itimer timer; int error; /* |
1da177e4c Linux-2.6.12-rc2 |
1214 1215 1216 1217 1218 1219 1220 1221 1222 |
* Set up a temporary timer and then wait for it to go off. */ memset(&timer, 0, sizeof timer); spin_lock_init(&timer.it_lock); timer.it_clock = which_clock; timer.it_overrun = -1; error = posix_cpu_timer_create(&timer); timer.it_process = current; if (!error) { |
1da177e4c Linux-2.6.12-rc2 |
1223 |
static struct itimerspec zero_it; |
e4b765551 [PATCH] posix-tim... |
1224 1225 1226 |
memset(it, 0, sizeof *it); it->it_value = *rqtp; |
1da177e4c Linux-2.6.12-rc2 |
1227 1228 |
spin_lock_irq(&timer.it_lock); |
e4b765551 [PATCH] posix-tim... |
1229 |
error = posix_cpu_timer_set(&timer, flags, it, NULL); |
1da177e4c Linux-2.6.12-rc2 |
1230 1231 1232 1233 1234 1235 |
if (error) { spin_unlock_irq(&timer.it_lock); return error; } while (!signal_pending(current)) { |
55ccb616a posix_cpu_timer: ... |
1236 |
if (timer.it.cpu.expires == 0) { |
1da177e4c Linux-2.6.12-rc2 |
1237 |
/* |
e6c42c295 posix-cpu-timers:... |
1238 1239 |
* Our timer fired and was reset, below * deletion can not fail. |
1da177e4c Linux-2.6.12-rc2 |
1240 |
*/ |
e6c42c295 posix-cpu-timers:... |
1241 |
posix_cpu_timer_del(&timer); |
1da177e4c Linux-2.6.12-rc2 |
1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 |
spin_unlock_irq(&timer.it_lock); return 0; } /* * Block until cpu_timer_fire (or a signal) wakes us. */ __set_current_state(TASK_INTERRUPTIBLE); spin_unlock_irq(&timer.it_lock); schedule(); spin_lock_irq(&timer.it_lock); } /* * We were interrupted by a signal. */ sample_to_timespec(which_clock, timer.it.cpu.expires, rqtp); |
e6c42c295 posix-cpu-timers:... |
1259 1260 1261 1262 1263 1264 1265 |
error = posix_cpu_timer_set(&timer, 0, &zero_it, it); if (!error) { /* * Timer is now unarmed, deletion can not fail. */ posix_cpu_timer_del(&timer); } |
1da177e4c Linux-2.6.12-rc2 |
1266 |
spin_unlock_irq(&timer.it_lock); |
e6c42c295 posix-cpu-timers:... |
1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 |
while (error == TIMER_RETRY) { /* * We need to handle case when timer was or is in the * middle of firing. In other cases we already freed * resources. */ spin_lock_irq(&timer.it_lock); error = posix_cpu_timer_del(&timer); spin_unlock_irq(&timer.it_lock); } |
e4b765551 [PATCH] posix-tim... |
1277 |
if ((it->it_value.tv_sec | it->it_value.tv_nsec) == 0) { |
1da177e4c Linux-2.6.12-rc2 |
1278 1279 1280 1281 1282 |
/* * It actually did fire already. */ return 0; } |
e4b765551 [PATCH] posix-tim... |
1283 1284 1285 1286 1287 |
error = -ERESTART_RESTARTBLOCK; } return error; } |
bc2c8ea48 posix-timers: Mak... |
1288 1289 1290 1291 |
static long posix_cpu_nsleep_restart(struct restart_block *restart_block); static int posix_cpu_nsleep(const clockid_t which_clock, int flags, struct timespec *rqtp, struct timespec __user *rmtp) |
e4b765551 [PATCH] posix-tim... |
1292 1293 |
{ struct restart_block *restart_block = |
3751f9f29 posix-timers: Cle... |
1294 |
¤t_thread_info()->restart_block; |
e4b765551 [PATCH] posix-tim... |
1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 |
struct itimerspec it; int error; /* * Diagnose required errors first. */ if (CPUCLOCK_PERTHREAD(which_clock) && (CPUCLOCK_PID(which_clock) == 0 || CPUCLOCK_PID(which_clock) == current->pid)) return -EINVAL; error = do_cpu_nanosleep(which_clock, flags, rqtp, &it); if (error == -ERESTART_RESTARTBLOCK) { |
3751f9f29 posix-timers: Cle... |
1309 |
if (flags & TIMER_ABSTIME) |
e4b765551 [PATCH] posix-tim... |
1310 |
return -ERESTARTNOHAND; |
1da177e4c Linux-2.6.12-rc2 |
1311 |
/* |
3751f9f29 posix-timers: Cle... |
1312 1313 1314 |
* Report back to the user the time still remaining. */ if (rmtp && copy_to_user(rmtp, &it.it_value, sizeof *rmtp)) |
1da177e4c Linux-2.6.12-rc2 |
1315 |
return -EFAULT; |
1711ef386 [PATCH] posix-tim... |
1316 |
restart_block->fn = posix_cpu_nsleep_restart; |
ab8177bc5 hrtimers: Avoid t... |
1317 |
restart_block->nanosleep.clockid = which_clock; |
3751f9f29 posix-timers: Cle... |
1318 1319 |
restart_block->nanosleep.rmtp = rmtp; restart_block->nanosleep.expires = timespec_to_ns(rqtp); |
1da177e4c Linux-2.6.12-rc2 |
1320 |
} |
1da177e4c Linux-2.6.12-rc2 |
1321 1322 |
return error; } |
bc2c8ea48 posix-timers: Mak... |
1323 |
static long posix_cpu_nsleep_restart(struct restart_block *restart_block) |
1da177e4c Linux-2.6.12-rc2 |
1324 |
{ |
ab8177bc5 hrtimers: Avoid t... |
1325 |
clockid_t which_clock = restart_block->nanosleep.clockid; |
97735f25d [PATCH] hrtimer: ... |
1326 |
struct timespec t; |
e4b765551 [PATCH] posix-tim... |
1327 1328 |
struct itimerspec it; int error; |
97735f25d [PATCH] hrtimer: ... |
1329 |
|
3751f9f29 posix-timers: Cle... |
1330 |
t = ns_to_timespec(restart_block->nanosleep.expires); |
97735f25d [PATCH] hrtimer: ... |
1331 |
|
e4b765551 [PATCH] posix-tim... |
1332 1333 1334 |
error = do_cpu_nanosleep(which_clock, TIMER_ABSTIME, &t, &it); if (error == -ERESTART_RESTARTBLOCK) { |
3751f9f29 posix-timers: Cle... |
1335 |
struct timespec __user *rmtp = restart_block->nanosleep.rmtp; |
e4b765551 [PATCH] posix-tim... |
1336 |
/* |
3751f9f29 posix-timers: Cle... |
1337 1338 1339 |
* Report back to the user the time still remaining. */ if (rmtp && copy_to_user(rmtp, &it.it_value, sizeof *rmtp)) |
e4b765551 [PATCH] posix-tim... |
1340 |
return -EFAULT; |
3751f9f29 posix-timers: Cle... |
1341 |
restart_block->nanosleep.expires = timespec_to_ns(&t); |
e4b765551 [PATCH] posix-tim... |
1342 1343 |
} return error; |
1da177e4c Linux-2.6.12-rc2 |
1344 |
} |
1da177e4c Linux-2.6.12-rc2 |
1345 1346 |
#define PROCESS_CLOCK MAKE_PROCESS_CPUCLOCK(0, CPUCLOCK_SCHED) #define THREAD_CLOCK MAKE_THREAD_CPUCLOCK(0, CPUCLOCK_SCHED) |
a924b04dd [PATCH] hrtimer: ... |
1347 1348 |
static int process_cpu_clock_getres(const clockid_t which_clock, struct timespec *tp) |
1da177e4c Linux-2.6.12-rc2 |
1349 1350 1351 |
{ return posix_cpu_clock_getres(PROCESS_CLOCK, tp); } |
a924b04dd [PATCH] hrtimer: ... |
1352 1353 |
static int process_cpu_clock_get(const clockid_t which_clock, struct timespec *tp) |
1da177e4c Linux-2.6.12-rc2 |
1354 1355 1356 1357 1358 1359 1360 1361 |
{ return posix_cpu_clock_get(PROCESS_CLOCK, tp); } static int process_cpu_timer_create(struct k_itimer *timer) { timer->it_clock = PROCESS_CLOCK; return posix_cpu_timer_create(timer); } |
a924b04dd [PATCH] hrtimer: ... |
1362 |
static int process_cpu_nsleep(const clockid_t which_clock, int flags, |
97735f25d [PATCH] hrtimer: ... |
1363 1364 |
struct timespec *rqtp, struct timespec __user *rmtp) |
1da177e4c Linux-2.6.12-rc2 |
1365 |
{ |
97735f25d [PATCH] hrtimer: ... |
1366 |
return posix_cpu_nsleep(PROCESS_CLOCK, flags, rqtp, rmtp); |
1da177e4c Linux-2.6.12-rc2 |
1367 |
} |
1711ef386 [PATCH] posix-tim... |
1368 1369 1370 1371 |
static long process_cpu_nsleep_restart(struct restart_block *restart_block) { return -EINVAL; } |
a924b04dd [PATCH] hrtimer: ... |
1372 1373 |
static int thread_cpu_clock_getres(const clockid_t which_clock, struct timespec *tp) |
1da177e4c Linux-2.6.12-rc2 |
1374 1375 1376 |
{ return posix_cpu_clock_getres(THREAD_CLOCK, tp); } |
a924b04dd [PATCH] hrtimer: ... |
1377 1378 |
static int thread_cpu_clock_get(const clockid_t which_clock, struct timespec *tp) |
1da177e4c Linux-2.6.12-rc2 |
1379 1380 1381 1382 1383 1384 1385 1386 |
{ return posix_cpu_clock_get(THREAD_CLOCK, tp); } static int thread_cpu_timer_create(struct k_itimer *timer) { timer->it_clock = THREAD_CLOCK; return posix_cpu_timer_create(timer); } |
1da177e4c Linux-2.6.12-rc2 |
1387 |
|
1976945ee posix-timers: Int... |
1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 |
struct k_clock clock_posix_cpu = { .clock_getres = posix_cpu_clock_getres, .clock_set = posix_cpu_clock_set, .clock_get = posix_cpu_clock_get, .timer_create = posix_cpu_timer_create, .nsleep = posix_cpu_nsleep, .nsleep_restart = posix_cpu_nsleep_restart, .timer_set = posix_cpu_timer_set, .timer_del = posix_cpu_timer_del, .timer_get = posix_cpu_timer_get, }; |
1da177e4c Linux-2.6.12-rc2 |
1399 1400 1401 |
static __init int init_posix_cpu_timers(void) { struct k_clock process = { |
2fd1f0408 posix-timers: Cle... |
1402 1403 |
.clock_getres = process_cpu_clock_getres, .clock_get = process_cpu_clock_get, |
2fd1f0408 posix-timers: Cle... |
1404 1405 1406 |
.timer_create = process_cpu_timer_create, .nsleep = process_cpu_nsleep, .nsleep_restart = process_cpu_nsleep_restart, |
1da177e4c Linux-2.6.12-rc2 |
1407 1408 |
}; struct k_clock thread = { |
2fd1f0408 posix-timers: Cle... |
1409 1410 |
.clock_getres = thread_cpu_clock_getres, .clock_get = thread_cpu_clock_get, |
2fd1f0408 posix-timers: Cle... |
1411 |
.timer_create = thread_cpu_timer_create, |
1da177e4c Linux-2.6.12-rc2 |
1412 |
}; |
8356b5f9c itimers: Fix peri... |
1413 |
struct timespec ts; |
1da177e4c Linux-2.6.12-rc2 |
1414 |
|
527087374 posix-timers: Cle... |
1415 1416 |
posix_timers_register_clock(CLOCK_PROCESS_CPUTIME_ID, &process); posix_timers_register_clock(CLOCK_THREAD_CPUTIME_ID, &thread); |
1da177e4c Linux-2.6.12-rc2 |
1417 |
|
a42548a18 cputime: Optimize... |
1418 |
cputime_to_timespec(cputime_one_jiffy, &ts); |
8356b5f9c itimers: Fix peri... |
1419 1420 |
onecputick = ts.tv_nsec; WARN_ON(ts.tv_sec != 0); |
1da177e4c Linux-2.6.12-rc2 |
1421 1422 1423 |
return 0; } __initcall(init_posix_cpu_timers); |