diff options
Diffstat (limited to 'kernel/posix-cpu-timers.c')
-rw-r--r-- | kernel/posix-cpu-timers.c | 124 |
1 files changed, 59 insertions, 65 deletions
diff --git a/kernel/posix-cpu-timers.c b/kernel/posix-cpu-timers.c index 6842eeba5879..58f405b581e7 100644 --- a/kernel/posix-cpu-timers.c +++ b/kernel/posix-cpu-timers.c | |||
@@ -37,13 +37,13 @@ static int check_clock(const clockid_t which_clock) | |||
37 | if (pid == 0) | 37 | if (pid == 0) |
38 | return 0; | 38 | return 0; |
39 | 39 | ||
40 | read_lock(&tasklist_lock); | 40 | rcu_read_lock(); |
41 | p = find_task_by_vpid(pid); | 41 | p = find_task_by_vpid(pid); |
42 | if (!p || !(CPUCLOCK_PERTHREAD(which_clock) ? | 42 | if (!p || !(CPUCLOCK_PERTHREAD(which_clock) ? |
43 | same_thread_group(p, current) : thread_group_leader(p))) { | 43 | same_thread_group(p, current) : has_group_leader_pid(p))) { |
44 | error = -EINVAL; | 44 | error = -EINVAL; |
45 | } | 45 | } |
46 | read_unlock(&tasklist_lock); | 46 | rcu_read_unlock(); |
47 | 47 | ||
48 | return error; | 48 | return error; |
49 | } | 49 | } |
@@ -176,7 +176,8 @@ static inline cputime_t virt_ticks(struct task_struct *p) | |||
176 | return p->utime; | 176 | return p->utime; |
177 | } | 177 | } |
178 | 178 | ||
179 | int posix_cpu_clock_getres(const clockid_t which_clock, struct timespec *tp) | 179 | static int |
180 | posix_cpu_clock_getres(const clockid_t which_clock, struct timespec *tp) | ||
180 | { | 181 | { |
181 | int error = check_clock(which_clock); | 182 | int error = check_clock(which_clock); |
182 | if (!error) { | 183 | if (!error) { |
@@ -194,7 +195,8 @@ int posix_cpu_clock_getres(const clockid_t which_clock, struct timespec *tp) | |||
194 | return error; | 195 | return error; |
195 | } | 196 | } |
196 | 197 | ||
197 | int posix_cpu_clock_set(const clockid_t which_clock, const struct timespec *tp) | 198 | static int |
199 | posix_cpu_clock_set(const clockid_t which_clock, const struct timespec *tp) | ||
198 | { | 200 | { |
199 | /* | 201 | /* |
200 | * You can never reset a CPU clock, but we check for other errors | 202 | * You can never reset a CPU clock, but we check for other errors |
@@ -317,7 +319,7 @@ static int cpu_clock_sample_group(const clockid_t which_clock, | |||
317 | } | 319 | } |
318 | 320 | ||
319 | 321 | ||
320 | int posix_cpu_clock_get(const clockid_t which_clock, struct timespec *tp) | 322 | static int posix_cpu_clock_get(const clockid_t which_clock, struct timespec *tp) |
321 | { | 323 | { |
322 | const pid_t pid = CPUCLOCK_PID(which_clock); | 324 | const pid_t pid = CPUCLOCK_PID(which_clock); |
323 | int error = -EINVAL; | 325 | int error = -EINVAL; |
@@ -379,7 +381,7 @@ int posix_cpu_clock_get(const clockid_t which_clock, struct timespec *tp) | |||
379 | * This is called from sys_timer_create() and do_cpu_nanosleep() with the | 381 | * This is called from sys_timer_create() and do_cpu_nanosleep() with the |
380 | * new timer already all-zeros initialized. | 382 | * new timer already all-zeros initialized. |
381 | */ | 383 | */ |
382 | int posix_cpu_timer_create(struct k_itimer *new_timer) | 384 | static int posix_cpu_timer_create(struct k_itimer *new_timer) |
383 | { | 385 | { |
384 | int ret = 0; | 386 | int ret = 0; |
385 | const pid_t pid = CPUCLOCK_PID(new_timer->it_clock); | 387 | const pid_t pid = CPUCLOCK_PID(new_timer->it_clock); |
@@ -390,7 +392,7 @@ int posix_cpu_timer_create(struct k_itimer *new_timer) | |||
390 | 392 | ||
391 | INIT_LIST_HEAD(&new_timer->it.cpu.entry); | 393 | INIT_LIST_HEAD(&new_timer->it.cpu.entry); |
392 | 394 | ||
393 | read_lock(&tasklist_lock); | 395 | rcu_read_lock(); |
394 | if (CPUCLOCK_PERTHREAD(new_timer->it_clock)) { | 396 | if (CPUCLOCK_PERTHREAD(new_timer->it_clock)) { |
395 | if (pid == 0) { | 397 | if (pid == 0) { |
396 | p = current; | 398 | p = current; |
@@ -404,7 +406,7 @@ int posix_cpu_timer_create(struct k_itimer *new_timer) | |||
404 | p = current->group_leader; | 406 | p = current->group_leader; |
405 | } else { | 407 | } else { |
406 | p = find_task_by_vpid(pid); | 408 | p = find_task_by_vpid(pid); |
407 | if (p && !thread_group_leader(p)) | 409 | if (p && !has_group_leader_pid(p)) |
408 | p = NULL; | 410 | p = NULL; |
409 | } | 411 | } |
410 | } | 412 | } |
@@ -414,7 +416,7 @@ int posix_cpu_timer_create(struct k_itimer *new_timer) | |||
414 | } else { | 416 | } else { |
415 | ret = -EINVAL; | 417 | ret = -EINVAL; |
416 | } | 418 | } |
417 | read_unlock(&tasklist_lock); | 419 | rcu_read_unlock(); |
418 | 420 | ||
419 | return ret; | 421 | return ret; |
420 | } | 422 | } |
@@ -425,7 +427,7 @@ int posix_cpu_timer_create(struct k_itimer *new_timer) | |||
425 | * If we return TIMER_RETRY, it's necessary to release the timer's lock | 427 | * If we return TIMER_RETRY, it's necessary to release the timer's lock |
426 | * and try again. (This happens when the timer is in the middle of firing.) | 428 | * and try again. (This happens when the timer is in the middle of firing.) |
427 | */ | 429 | */ |
428 | int posix_cpu_timer_del(struct k_itimer *timer) | 430 | static int posix_cpu_timer_del(struct k_itimer *timer) |
429 | { | 431 | { |
430 | struct task_struct *p = timer->it.cpu.task; | 432 | struct task_struct *p = timer->it.cpu.task; |
431 | int ret = 0; | 433 | int ret = 0; |
@@ -665,8 +667,8 @@ static int cpu_timer_sample_group(const clockid_t which_clock, | |||
665 | * If we return TIMER_RETRY, it's necessary to release the timer's lock | 667 | * If we return TIMER_RETRY, it's necessary to release the timer's lock |
666 | * and try again. (This happens when the timer is in the middle of firing.) | 668 | * and try again. (This happens when the timer is in the middle of firing.) |
667 | */ | 669 | */ |
668 | int posix_cpu_timer_set(struct k_itimer *timer, int flags, | 670 | static int posix_cpu_timer_set(struct k_itimer *timer, int flags, |
669 | struct itimerspec *new, struct itimerspec *old) | 671 | struct itimerspec *new, struct itimerspec *old) |
670 | { | 672 | { |
671 | struct task_struct *p = timer->it.cpu.task; | 673 | struct task_struct *p = timer->it.cpu.task; |
672 | union cpu_time_count old_expires, new_expires, old_incr, val; | 674 | union cpu_time_count old_expires, new_expires, old_incr, val; |
@@ -820,7 +822,7 @@ int posix_cpu_timer_set(struct k_itimer *timer, int flags, | |||
820 | return ret; | 822 | return ret; |
821 | } | 823 | } |
822 | 824 | ||
823 | void posix_cpu_timer_get(struct k_itimer *timer, struct itimerspec *itp) | 825 | static void posix_cpu_timer_get(struct k_itimer *timer, struct itimerspec *itp) |
824 | { | 826 | { |
825 | union cpu_time_count now; | 827 | union cpu_time_count now; |
826 | struct task_struct *p = timer->it.cpu.task; | 828 | struct task_struct *p = timer->it.cpu.task; |
@@ -1345,7 +1347,7 @@ void run_posix_cpu_timers(struct task_struct *tsk) | |||
1345 | 1347 | ||
1346 | /* | 1348 | /* |
1347 | * Now that all the timers on our list have the firing flag, | 1349 | * Now that all the timers on our list have the firing flag, |
1348 | * noone will touch their list entries but us. We'll take | 1350 | * no one will touch their list entries but us. We'll take |
1349 | * each timer's lock before clearing its firing flag, so no | 1351 | * each timer's lock before clearing its firing flag, so no |
1350 | * timer call will interfere. | 1352 | * timer call will interfere. |
1351 | */ | 1353 | */ |
@@ -1481,11 +1483,13 @@ static int do_cpu_nanosleep(const clockid_t which_clock, int flags, | |||
1481 | return error; | 1483 | return error; |
1482 | } | 1484 | } |
1483 | 1485 | ||
1484 | int posix_cpu_nsleep(const clockid_t which_clock, int flags, | 1486 | static long posix_cpu_nsleep_restart(struct restart_block *restart_block); |
1485 | struct timespec *rqtp, struct timespec __user *rmtp) | 1487 | |
1488 | static int posix_cpu_nsleep(const clockid_t which_clock, int flags, | ||
1489 | struct timespec *rqtp, struct timespec __user *rmtp) | ||
1486 | { | 1490 | { |
1487 | struct restart_block *restart_block = | 1491 | struct restart_block *restart_block = |
1488 | ¤t_thread_info()->restart_block; | 1492 | ¤t_thread_info()->restart_block; |
1489 | struct itimerspec it; | 1493 | struct itimerspec it; |
1490 | int error; | 1494 | int error; |
1491 | 1495 | ||
@@ -1501,56 +1505,47 @@ int posix_cpu_nsleep(const clockid_t which_clock, int flags, | |||
1501 | 1505 | ||
1502 | if (error == -ERESTART_RESTARTBLOCK) { | 1506 | if (error == -ERESTART_RESTARTBLOCK) { |
1503 | 1507 | ||
1504 | if (flags & TIMER_ABSTIME) | 1508 | if (flags & TIMER_ABSTIME) |
1505 | return -ERESTARTNOHAND; | 1509 | return -ERESTARTNOHAND; |
1506 | /* | 1510 | /* |
1507 | * Report back to the user the time still remaining. | 1511 | * Report back to the user the time still remaining. |
1508 | */ | 1512 | */ |
1509 | if (rmtp != NULL && copy_to_user(rmtp, &it.it_value, sizeof *rmtp)) | 1513 | if (rmtp && copy_to_user(rmtp, &it.it_value, sizeof *rmtp)) |
1510 | return -EFAULT; | 1514 | return -EFAULT; |
1511 | 1515 | ||
1512 | restart_block->fn = posix_cpu_nsleep_restart; | 1516 | restart_block->fn = posix_cpu_nsleep_restart; |
1513 | restart_block->arg0 = which_clock; | 1517 | restart_block->nanosleep.clockid = which_clock; |
1514 | restart_block->arg1 = (unsigned long) rmtp; | 1518 | restart_block->nanosleep.rmtp = rmtp; |
1515 | restart_block->arg2 = rqtp->tv_sec; | 1519 | restart_block->nanosleep.expires = timespec_to_ns(rqtp); |
1516 | restart_block->arg3 = rqtp->tv_nsec; | ||
1517 | } | 1520 | } |
1518 | return error; | 1521 | return error; |
1519 | } | 1522 | } |
1520 | 1523 | ||
1521 | long posix_cpu_nsleep_restart(struct restart_block *restart_block) | 1524 | static long posix_cpu_nsleep_restart(struct restart_block *restart_block) |
1522 | { | 1525 | { |
1523 | clockid_t which_clock = restart_block->arg0; | 1526 | clockid_t which_clock = restart_block->nanosleep.clockid; |
1524 | struct timespec __user *rmtp; | ||
1525 | struct timespec t; | 1527 | struct timespec t; |
1526 | struct itimerspec it; | 1528 | struct itimerspec it; |
1527 | int error; | 1529 | int error; |
1528 | 1530 | ||
1529 | rmtp = (struct timespec __user *) restart_block->arg1; | 1531 | t = ns_to_timespec(restart_block->nanosleep.expires); |
1530 | t.tv_sec = restart_block->arg2; | ||
1531 | t.tv_nsec = restart_block->arg3; | ||
1532 | 1532 | ||
1533 | restart_block->fn = do_no_restart_syscall; | ||
1534 | error = do_cpu_nanosleep(which_clock, TIMER_ABSTIME, &t, &it); | 1533 | error = do_cpu_nanosleep(which_clock, TIMER_ABSTIME, &t, &it); |
1535 | 1534 | ||
1536 | if (error == -ERESTART_RESTARTBLOCK) { | 1535 | if (error == -ERESTART_RESTARTBLOCK) { |
1536 | struct timespec __user *rmtp = restart_block->nanosleep.rmtp; | ||
1537 | /* | 1537 | /* |
1538 | * Report back to the user the time still remaining. | 1538 | * Report back to the user the time still remaining. |
1539 | */ | 1539 | */ |
1540 | if (rmtp != NULL && copy_to_user(rmtp, &it.it_value, sizeof *rmtp)) | 1540 | if (rmtp && copy_to_user(rmtp, &it.it_value, sizeof *rmtp)) |
1541 | return -EFAULT; | 1541 | return -EFAULT; |
1542 | 1542 | ||
1543 | restart_block->fn = posix_cpu_nsleep_restart; | 1543 | restart_block->nanosleep.expires = timespec_to_ns(&t); |
1544 | restart_block->arg0 = which_clock; | ||
1545 | restart_block->arg1 = (unsigned long) rmtp; | ||
1546 | restart_block->arg2 = t.tv_sec; | ||
1547 | restart_block->arg3 = t.tv_nsec; | ||
1548 | } | 1544 | } |
1549 | return error; | 1545 | return error; |
1550 | 1546 | ||
1551 | } | 1547 | } |
1552 | 1548 | ||
1553 | |||
1554 | #define PROCESS_CLOCK MAKE_PROCESS_CPUCLOCK(0, CPUCLOCK_SCHED) | 1549 | #define PROCESS_CLOCK MAKE_PROCESS_CPUCLOCK(0, CPUCLOCK_SCHED) |
1555 | #define THREAD_CLOCK MAKE_THREAD_CPUCLOCK(0, CPUCLOCK_SCHED) | 1550 | #define THREAD_CLOCK MAKE_THREAD_CPUCLOCK(0, CPUCLOCK_SCHED) |
1556 | 1551 | ||
@@ -1594,38 +1589,37 @@ static int thread_cpu_timer_create(struct k_itimer *timer) | |||
1594 | timer->it_clock = THREAD_CLOCK; | 1589 | timer->it_clock = THREAD_CLOCK; |
1595 | return posix_cpu_timer_create(timer); | 1590 | return posix_cpu_timer_create(timer); |
1596 | } | 1591 | } |
1597 | static int thread_cpu_nsleep(const clockid_t which_clock, int flags, | 1592 | |
1598 | struct timespec *rqtp, struct timespec __user *rmtp) | 1593 | struct k_clock clock_posix_cpu = { |
1599 | { | 1594 | .clock_getres = posix_cpu_clock_getres, |
1600 | return -EINVAL; | 1595 | .clock_set = posix_cpu_clock_set, |
1601 | } | 1596 | .clock_get = posix_cpu_clock_get, |
1602 | static long thread_cpu_nsleep_restart(struct restart_block *restart_block) | 1597 | .timer_create = posix_cpu_timer_create, |
1603 | { | 1598 | .nsleep = posix_cpu_nsleep, |
1604 | return -EINVAL; | 1599 | .nsleep_restart = posix_cpu_nsleep_restart, |
1605 | } | 1600 | .timer_set = posix_cpu_timer_set, |
1601 | .timer_del = posix_cpu_timer_del, | ||
1602 | .timer_get = posix_cpu_timer_get, | ||
1603 | }; | ||
1606 | 1604 | ||
1607 | static __init int init_posix_cpu_timers(void) | 1605 | static __init int init_posix_cpu_timers(void) |
1608 | { | 1606 | { |
1609 | struct k_clock process = { | 1607 | struct k_clock process = { |
1610 | .clock_getres = process_cpu_clock_getres, | 1608 | .clock_getres = process_cpu_clock_getres, |
1611 | .clock_get = process_cpu_clock_get, | 1609 | .clock_get = process_cpu_clock_get, |
1612 | .clock_set = do_posix_clock_nosettime, | 1610 | .timer_create = process_cpu_timer_create, |
1613 | .timer_create = process_cpu_timer_create, | 1611 | .nsleep = process_cpu_nsleep, |
1614 | .nsleep = process_cpu_nsleep, | 1612 | .nsleep_restart = process_cpu_nsleep_restart, |
1615 | .nsleep_restart = process_cpu_nsleep_restart, | ||
1616 | }; | 1613 | }; |
1617 | struct k_clock thread = { | 1614 | struct k_clock thread = { |
1618 | .clock_getres = thread_cpu_clock_getres, | 1615 | .clock_getres = thread_cpu_clock_getres, |
1619 | .clock_get = thread_cpu_clock_get, | 1616 | .clock_get = thread_cpu_clock_get, |
1620 | .clock_set = do_posix_clock_nosettime, | 1617 | .timer_create = thread_cpu_timer_create, |
1621 | .timer_create = thread_cpu_timer_create, | ||
1622 | .nsleep = thread_cpu_nsleep, | ||
1623 | .nsleep_restart = thread_cpu_nsleep_restart, | ||
1624 | }; | 1618 | }; |
1625 | struct timespec ts; | 1619 | struct timespec ts; |
1626 | 1620 | ||
1627 | register_posix_clock(CLOCK_PROCESS_CPUTIME_ID, &process); | 1621 | posix_timers_register_clock(CLOCK_PROCESS_CPUTIME_ID, &process); |
1628 | register_posix_clock(CLOCK_THREAD_CPUTIME_ID, &thread); | 1622 | posix_timers_register_clock(CLOCK_THREAD_CPUTIME_ID, &thread); |
1629 | 1623 | ||
1630 | cputime_to_timespec(cputime_one_jiffy, &ts); | 1624 | cputime_to_timespec(cputime_one_jiffy, &ts); |
1631 | onecputick = ts.tv_nsec; | 1625 | onecputick = ts.tv_nsec; |