diff options
Diffstat (limited to 'kernel/posix-cpu-timers.c')
| -rw-r--r-- | kernel/posix-cpu-timers.c | 76 |
1 files changed, 37 insertions, 39 deletions
diff --git a/kernel/posix-cpu-timers.c b/kernel/posix-cpu-timers.c index cae4f5728997..520f6c59948d 100644 --- a/kernel/posix-cpu-timers.c +++ b/kernel/posix-cpu-timers.c | |||
| @@ -7,7 +7,7 @@ | |||
| 7 | #include <asm/uaccess.h> | 7 | #include <asm/uaccess.h> |
| 8 | #include <linux/errno.h> | 8 | #include <linux/errno.h> |
| 9 | 9 | ||
| 10 | static int check_clock(clockid_t which_clock) | 10 | static int check_clock(const clockid_t which_clock) |
| 11 | { | 11 | { |
| 12 | int error = 0; | 12 | int error = 0; |
| 13 | struct task_struct *p; | 13 | struct task_struct *p; |
| @@ -31,7 +31,7 @@ static int check_clock(clockid_t which_clock) | |||
| 31 | } | 31 | } |
| 32 | 32 | ||
| 33 | static inline union cpu_time_count | 33 | static inline union cpu_time_count |
| 34 | timespec_to_sample(clockid_t which_clock, const struct timespec *tp) | 34 | timespec_to_sample(const clockid_t which_clock, const struct timespec *tp) |
| 35 | { | 35 | { |
| 36 | union cpu_time_count ret; | 36 | union cpu_time_count ret; |
| 37 | ret.sched = 0; /* high half always zero when .cpu used */ | 37 | ret.sched = 0; /* high half always zero when .cpu used */ |
| @@ -43,7 +43,7 @@ timespec_to_sample(clockid_t which_clock, const struct timespec *tp) | |||
| 43 | return ret; | 43 | return ret; |
| 44 | } | 44 | } |
| 45 | 45 | ||
| 46 | static void sample_to_timespec(clockid_t which_clock, | 46 | static void sample_to_timespec(const clockid_t which_clock, |
| 47 | union cpu_time_count cpu, | 47 | union cpu_time_count cpu, |
| 48 | struct timespec *tp) | 48 | struct timespec *tp) |
| 49 | { | 49 | { |
| @@ -55,7 +55,7 @@ static void sample_to_timespec(clockid_t which_clock, | |||
| 55 | } | 55 | } |
| 56 | } | 56 | } |
| 57 | 57 | ||
| 58 | static inline int cpu_time_before(clockid_t which_clock, | 58 | static inline int cpu_time_before(const clockid_t which_clock, |
| 59 | union cpu_time_count now, | 59 | union cpu_time_count now, |
| 60 | union cpu_time_count then) | 60 | union cpu_time_count then) |
| 61 | { | 61 | { |
| @@ -65,7 +65,7 @@ static inline int cpu_time_before(clockid_t which_clock, | |||
| 65 | return cputime_lt(now.cpu, then.cpu); | 65 | return cputime_lt(now.cpu, then.cpu); |
| 66 | } | 66 | } |
| 67 | } | 67 | } |
| 68 | static inline void cpu_time_add(clockid_t which_clock, | 68 | static inline void cpu_time_add(const clockid_t which_clock, |
| 69 | union cpu_time_count *acc, | 69 | union cpu_time_count *acc, |
| 70 | union cpu_time_count val) | 70 | union cpu_time_count val) |
| 71 | { | 71 | { |
| @@ -75,7 +75,7 @@ static inline void cpu_time_add(clockid_t which_clock, | |||
| 75 | acc->cpu = cputime_add(acc->cpu, val.cpu); | 75 | acc->cpu = cputime_add(acc->cpu, val.cpu); |
| 76 | } | 76 | } |
| 77 | } | 77 | } |
| 78 | static inline union cpu_time_count cpu_time_sub(clockid_t which_clock, | 78 | static inline union cpu_time_count cpu_time_sub(const clockid_t which_clock, |
| 79 | union cpu_time_count a, | 79 | union cpu_time_count a, |
| 80 | union cpu_time_count b) | 80 | union cpu_time_count b) |
| 81 | { | 81 | { |
| @@ -151,7 +151,7 @@ static inline unsigned long long sched_ns(struct task_struct *p) | |||
| 151 | return (p == current) ? current_sched_time(p) : p->sched_time; | 151 | return (p == current) ? current_sched_time(p) : p->sched_time; |
| 152 | } | 152 | } |
| 153 | 153 | ||
| 154 | int posix_cpu_clock_getres(clockid_t which_clock, struct timespec *tp) | 154 | int posix_cpu_clock_getres(const clockid_t which_clock, struct timespec *tp) |
| 155 | { | 155 | { |
| 156 | int error = check_clock(which_clock); | 156 | int error = check_clock(which_clock); |
| 157 | if (!error) { | 157 | if (!error) { |
| @@ -169,7 +169,7 @@ int posix_cpu_clock_getres(clockid_t which_clock, struct timespec *tp) | |||
| 169 | return error; | 169 | return error; |
| 170 | } | 170 | } |
| 171 | 171 | ||
| 172 | int posix_cpu_clock_set(clockid_t which_clock, const struct timespec *tp) | 172 | int posix_cpu_clock_set(const clockid_t which_clock, const struct timespec *tp) |
| 173 | { | 173 | { |
| 174 | /* | 174 | /* |
| 175 | * You can never reset a CPU clock, but we check for other errors | 175 | * You can never reset a CPU clock, but we check for other errors |
| @@ -186,7 +186,7 @@ int posix_cpu_clock_set(clockid_t which_clock, const struct timespec *tp) | |||
| 186 | /* | 186 | /* |
| 187 | * Sample a per-thread clock for the given task. | 187 | * Sample a per-thread clock for the given task. |
| 188 | */ | 188 | */ |
| 189 | static int cpu_clock_sample(clockid_t which_clock, struct task_struct *p, | 189 | static int cpu_clock_sample(const clockid_t which_clock, struct task_struct *p, |
| 190 | union cpu_time_count *cpu) | 190 | union cpu_time_count *cpu) |
| 191 | { | 191 | { |
| 192 | switch (CPUCLOCK_WHICH(which_clock)) { | 192 | switch (CPUCLOCK_WHICH(which_clock)) { |
| @@ -238,18 +238,7 @@ static int cpu_clock_sample_group_locked(unsigned int clock_idx, | |||
| 238 | while ((t = next_thread(t)) != p) { | 238 | while ((t = next_thread(t)) != p) { |
| 239 | cpu->sched += t->sched_time; | 239 | cpu->sched += t->sched_time; |
| 240 | } | 240 | } |
| 241 | if (p->tgid == current->tgid) { | 241 | cpu->sched += sched_ns(p); |
| 242 | /* | ||
| 243 | * We're sampling ourselves, so include the | ||
| 244 | * cycles not yet banked. We still omit | ||
| 245 | * other threads running on other CPUs, | ||
| 246 | * so the total can always be behind as | ||
| 247 | * much as max(nthreads-1,ncpus) * (NSEC_PER_SEC/HZ). | ||
| 248 | */ | ||
| 249 | cpu->sched += current_sched_time(current); | ||
| 250 | } else { | ||
| 251 | cpu->sched += p->sched_time; | ||
| 252 | } | ||
| 253 | break; | 242 | break; |
| 254 | } | 243 | } |
| 255 | return 0; | 244 | return 0; |
| @@ -259,7 +248,7 @@ static int cpu_clock_sample_group_locked(unsigned int clock_idx, | |||
| 259 | * Sample a process (thread group) clock for the given group_leader task. | 248 | * Sample a process (thread group) clock for the given group_leader task. |
| 260 | * Must be called with tasklist_lock held for reading. | 249 | * Must be called with tasklist_lock held for reading. |
| 261 | */ | 250 | */ |
| 262 | static int cpu_clock_sample_group(clockid_t which_clock, | 251 | static int cpu_clock_sample_group(const clockid_t which_clock, |
| 263 | struct task_struct *p, | 252 | struct task_struct *p, |
| 264 | union cpu_time_count *cpu) | 253 | union cpu_time_count *cpu) |
| 265 | { | 254 | { |
| @@ -273,7 +262,7 @@ static int cpu_clock_sample_group(clockid_t which_clock, | |||
| 273 | } | 262 | } |
| 274 | 263 | ||
| 275 | 264 | ||
| 276 | int posix_cpu_clock_get(clockid_t which_clock, struct timespec *tp) | 265 | int posix_cpu_clock_get(const clockid_t which_clock, struct timespec *tp) |
| 277 | { | 266 | { |
| 278 | const pid_t pid = CPUCLOCK_PID(which_clock); | 267 | const pid_t pid = CPUCLOCK_PID(which_clock); |
| 279 | int error = -EINVAL; | 268 | int error = -EINVAL; |
| @@ -1410,8 +1399,8 @@ void set_process_cpu_timer(struct task_struct *tsk, unsigned int clock_idx, | |||
| 1410 | 1399 | ||
| 1411 | static long posix_cpu_clock_nanosleep_restart(struct restart_block *); | 1400 | static long posix_cpu_clock_nanosleep_restart(struct restart_block *); |
| 1412 | 1401 | ||
| 1413 | int posix_cpu_nsleep(clockid_t which_clock, int flags, | 1402 | int posix_cpu_nsleep(const clockid_t which_clock, int flags, |
| 1414 | struct timespec *rqtp) | 1403 | struct timespec *rqtp, struct timespec __user *rmtp) |
| 1415 | { | 1404 | { |
| 1416 | struct restart_block *restart_block = | 1405 | struct restart_block *restart_block = |
| 1417 | ¤t_thread_info()->restart_block; | 1406 | ¤t_thread_info()->restart_block; |
| @@ -1436,7 +1425,6 @@ int posix_cpu_nsleep(clockid_t which_clock, int flags, | |||
| 1436 | error = posix_cpu_timer_create(&timer); | 1425 | error = posix_cpu_timer_create(&timer); |
| 1437 | timer.it_process = current; | 1426 | timer.it_process = current; |
| 1438 | if (!error) { | 1427 | if (!error) { |
| 1439 | struct timespec __user *rmtp; | ||
| 1440 | static struct itimerspec zero_it; | 1428 | static struct itimerspec zero_it; |
| 1441 | struct itimerspec it = { .it_value = *rqtp, | 1429 | struct itimerspec it = { .it_value = *rqtp, |
| 1442 | .it_interval = {} }; | 1430 | .it_interval = {} }; |
| @@ -1483,7 +1471,6 @@ int posix_cpu_nsleep(clockid_t which_clock, int flags, | |||
| 1483 | /* | 1471 | /* |
| 1484 | * Report back to the user the time still remaining. | 1472 | * Report back to the user the time still remaining. |
| 1485 | */ | 1473 | */ |
| 1486 | rmtp = (struct timespec __user *) restart_block->arg1; | ||
| 1487 | if (rmtp != NULL && !(flags & TIMER_ABSTIME) && | 1474 | if (rmtp != NULL && !(flags & TIMER_ABSTIME) && |
| 1488 | copy_to_user(rmtp, &it.it_value, sizeof *rmtp)) | 1475 | copy_to_user(rmtp, &it.it_value, sizeof *rmtp)) |
| 1489 | return -EFAULT; | 1476 | return -EFAULT; |
| @@ -1491,6 +1478,7 @@ int posix_cpu_nsleep(clockid_t which_clock, int flags, | |||
| 1491 | restart_block->fn = posix_cpu_clock_nanosleep_restart; | 1478 | restart_block->fn = posix_cpu_clock_nanosleep_restart; |
| 1492 | /* Caller already set restart_block->arg1 */ | 1479 | /* Caller already set restart_block->arg1 */ |
| 1493 | restart_block->arg0 = which_clock; | 1480 | restart_block->arg0 = which_clock; |
| 1481 | restart_block->arg1 = (unsigned long) rmtp; | ||
| 1494 | restart_block->arg2 = rqtp->tv_sec; | 1482 | restart_block->arg2 = rqtp->tv_sec; |
| 1495 | restart_block->arg3 = rqtp->tv_nsec; | 1483 | restart_block->arg3 = rqtp->tv_nsec; |
| 1496 | 1484 | ||
| @@ -1504,21 +1492,28 @@ static long | |||
| 1504 | posix_cpu_clock_nanosleep_restart(struct restart_block *restart_block) | 1492 | posix_cpu_clock_nanosleep_restart(struct restart_block *restart_block) |
| 1505 | { | 1493 | { |
| 1506 | clockid_t which_clock = restart_block->arg0; | 1494 | clockid_t which_clock = restart_block->arg0; |
| 1507 | struct timespec t = { .tv_sec = restart_block->arg2, | 1495 | struct timespec __user *rmtp; |
| 1508 | .tv_nsec = restart_block->arg3 }; | 1496 | struct timespec t; |
| 1497 | |||
| 1498 | rmtp = (struct timespec __user *) restart_block->arg1; | ||
| 1499 | t.tv_sec = restart_block->arg2; | ||
| 1500 | t.tv_nsec = restart_block->arg3; | ||
| 1501 | |||
| 1509 | restart_block->fn = do_no_restart_syscall; | 1502 | restart_block->fn = do_no_restart_syscall; |
| 1510 | return posix_cpu_nsleep(which_clock, TIMER_ABSTIME, &t); | 1503 | return posix_cpu_nsleep(which_clock, TIMER_ABSTIME, &t, rmtp); |
| 1511 | } | 1504 | } |
| 1512 | 1505 | ||
| 1513 | 1506 | ||
| 1514 | #define PROCESS_CLOCK MAKE_PROCESS_CPUCLOCK(0, CPUCLOCK_SCHED) | 1507 | #define PROCESS_CLOCK MAKE_PROCESS_CPUCLOCK(0, CPUCLOCK_SCHED) |
| 1515 | #define THREAD_CLOCK MAKE_THREAD_CPUCLOCK(0, CPUCLOCK_SCHED) | 1508 | #define THREAD_CLOCK MAKE_THREAD_CPUCLOCK(0, CPUCLOCK_SCHED) |
| 1516 | 1509 | ||
| 1517 | static int process_cpu_clock_getres(clockid_t which_clock, struct timespec *tp) | 1510 | static int process_cpu_clock_getres(const clockid_t which_clock, |
| 1511 | struct timespec *tp) | ||
| 1518 | { | 1512 | { |
| 1519 | return posix_cpu_clock_getres(PROCESS_CLOCK, tp); | 1513 | return posix_cpu_clock_getres(PROCESS_CLOCK, tp); |
| 1520 | } | 1514 | } |
| 1521 | static int process_cpu_clock_get(clockid_t which_clock, struct timespec *tp) | 1515 | static int process_cpu_clock_get(const clockid_t which_clock, |
| 1516 | struct timespec *tp) | ||
| 1522 | { | 1517 | { |
| 1523 | return posix_cpu_clock_get(PROCESS_CLOCK, tp); | 1518 | return posix_cpu_clock_get(PROCESS_CLOCK, tp); |
| 1524 | } | 1519 | } |
| @@ -1527,16 +1522,19 @@ static int process_cpu_timer_create(struct k_itimer *timer) | |||
| 1527 | timer->it_clock = PROCESS_CLOCK; | 1522 | timer->it_clock = PROCESS_CLOCK; |
| 1528 | return posix_cpu_timer_create(timer); | 1523 | return posix_cpu_timer_create(timer); |
| 1529 | } | 1524 | } |
| 1530 | static int process_cpu_nsleep(clockid_t which_clock, int flags, | 1525 | static int process_cpu_nsleep(const clockid_t which_clock, int flags, |
| 1531 | struct timespec *rqtp) | 1526 | struct timespec *rqtp, |
| 1527 | struct timespec __user *rmtp) | ||
| 1532 | { | 1528 | { |
| 1533 | return posix_cpu_nsleep(PROCESS_CLOCK, flags, rqtp); | 1529 | return posix_cpu_nsleep(PROCESS_CLOCK, flags, rqtp, rmtp); |
| 1534 | } | 1530 | } |
| 1535 | static int thread_cpu_clock_getres(clockid_t which_clock, struct timespec *tp) | 1531 | static int thread_cpu_clock_getres(const clockid_t which_clock, |
| 1532 | struct timespec *tp) | ||
| 1536 | { | 1533 | { |
| 1537 | return posix_cpu_clock_getres(THREAD_CLOCK, tp); | 1534 | return posix_cpu_clock_getres(THREAD_CLOCK, tp); |
| 1538 | } | 1535 | } |
| 1539 | static int thread_cpu_clock_get(clockid_t which_clock, struct timespec *tp) | 1536 | static int thread_cpu_clock_get(const clockid_t which_clock, |
| 1537 | struct timespec *tp) | ||
| 1540 | { | 1538 | { |
| 1541 | return posix_cpu_clock_get(THREAD_CLOCK, tp); | 1539 | return posix_cpu_clock_get(THREAD_CLOCK, tp); |
| 1542 | } | 1540 | } |
| @@ -1545,8 +1543,8 @@ static int thread_cpu_timer_create(struct k_itimer *timer) | |||
| 1545 | timer->it_clock = THREAD_CLOCK; | 1543 | timer->it_clock = THREAD_CLOCK; |
| 1546 | return posix_cpu_timer_create(timer); | 1544 | return posix_cpu_timer_create(timer); |
| 1547 | } | 1545 | } |
| 1548 | static int thread_cpu_nsleep(clockid_t which_clock, int flags, | 1546 | static int thread_cpu_nsleep(const clockid_t which_clock, int flags, |
| 1549 | struct timespec *rqtp) | 1547 | struct timespec *rqtp, struct timespec __user *rmtp) |
| 1550 | { | 1548 | { |
| 1551 | return -EINVAL; | 1549 | return -EINVAL; |
| 1552 | } | 1550 | } |
