diff options
| -rw-r--r-- | include/linux/hrtimer.h | 2 | ||||
| -rw-r--r-- | kernel/hrtimer.c | 29 | ||||
| -rw-r--r-- | kernel/posix-timers.c | 17 |
3 files changed, 31 insertions, 17 deletions
diff --git a/include/linux/hrtimer.h b/include/linux/hrtimer.h index 540799bc85f8..7a9398e19704 100644 --- a/include/linux/hrtimer.h +++ b/include/linux/hrtimer.h | |||
| @@ -300,7 +300,7 @@ hrtimer_forward(struct hrtimer *timer, ktime_t now, ktime_t interval); | |||
| 300 | 300 | ||
| 301 | /* Precise sleep: */ | 301 | /* Precise sleep: */ |
| 302 | extern long hrtimer_nanosleep(struct timespec *rqtp, | 302 | extern long hrtimer_nanosleep(struct timespec *rqtp, |
| 303 | struct timespec __user *rmtp, | 303 | struct timespec *rmtp, |
| 304 | const enum hrtimer_mode mode, | 304 | const enum hrtimer_mode mode, |
| 305 | const clockid_t clockid); | 305 | const clockid_t clockid); |
| 306 | extern long hrtimer_nanosleep_restart(struct restart_block *restart_block); | 306 | extern long hrtimer_nanosleep_restart(struct restart_block *restart_block); |
diff --git a/kernel/hrtimer.c b/kernel/hrtimer.c index dc8a4451d79b..b2b2c2b0a49b 100644 --- a/kernel/hrtimer.c +++ b/kernel/hrtimer.c | |||
| @@ -1286,8 +1286,7 @@ static int __sched do_nanosleep(struct hrtimer_sleeper *t, enum hrtimer_mode mod | |||
| 1286 | long __sched hrtimer_nanosleep_restart(struct restart_block *restart) | 1286 | long __sched hrtimer_nanosleep_restart(struct restart_block *restart) |
| 1287 | { | 1287 | { |
| 1288 | struct hrtimer_sleeper t; | 1288 | struct hrtimer_sleeper t; |
| 1289 | struct timespec __user *rmtp; | 1289 | struct timespec *rmtp; |
| 1290 | struct timespec tu; | ||
| 1291 | ktime_t time; | 1290 | ktime_t time; |
| 1292 | 1291 | ||
| 1293 | restart->fn = do_no_restart_syscall; | 1292 | restart->fn = do_no_restart_syscall; |
| @@ -1298,14 +1297,12 @@ long __sched hrtimer_nanosleep_restart(struct restart_block *restart) | |||
| 1298 | if (do_nanosleep(&t, HRTIMER_MODE_ABS)) | 1297 | if (do_nanosleep(&t, HRTIMER_MODE_ABS)) |
| 1299 | return 0; | 1298 | return 0; |
| 1300 | 1299 | ||
| 1301 | rmtp = (struct timespec __user *) restart->arg1; | 1300 | rmtp = (struct timespec *)restart->arg1; |
| 1302 | if (rmtp) { | 1301 | if (rmtp) { |
| 1303 | time = ktime_sub(t.timer.expires, t.timer.base->get_time()); | 1302 | time = ktime_sub(t.timer.expires, t.timer.base->get_time()); |
| 1304 | if (time.tv64 <= 0) | 1303 | if (time.tv64 <= 0) |
| 1305 | return 0; | 1304 | return 0; |
| 1306 | tu = ktime_to_timespec(time); | 1305 | *rmtp = ktime_to_timespec(time); |
| 1307 | if (copy_to_user(rmtp, &tu, sizeof(tu))) | ||
| 1308 | return -EFAULT; | ||
| 1309 | } | 1306 | } |
| 1310 | 1307 | ||
| 1311 | restart->fn = hrtimer_nanosleep_restart; | 1308 | restart->fn = hrtimer_nanosleep_restart; |
| @@ -1314,12 +1311,11 @@ long __sched hrtimer_nanosleep_restart(struct restart_block *restart) | |||
| 1314 | return -ERESTART_RESTARTBLOCK; | 1311 | return -ERESTART_RESTARTBLOCK; |
| 1315 | } | 1312 | } |
| 1316 | 1313 | ||
| 1317 | long hrtimer_nanosleep(struct timespec *rqtp, struct timespec __user *rmtp, | 1314 | long hrtimer_nanosleep(struct timespec *rqtp, struct timespec *rmtp, |
| 1318 | const enum hrtimer_mode mode, const clockid_t clockid) | 1315 | const enum hrtimer_mode mode, const clockid_t clockid) |
| 1319 | { | 1316 | { |
| 1320 | struct restart_block *restart; | 1317 | struct restart_block *restart; |
| 1321 | struct hrtimer_sleeper t; | 1318 | struct hrtimer_sleeper t; |
| 1322 | struct timespec tu; | ||
| 1323 | ktime_t rem; | 1319 | ktime_t rem; |
| 1324 | 1320 | ||
| 1325 | hrtimer_init(&t.timer, clockid, mode); | 1321 | hrtimer_init(&t.timer, clockid, mode); |
| @@ -1335,9 +1331,7 @@ long hrtimer_nanosleep(struct timespec *rqtp, struct timespec __user *rmtp, | |||
| 1335 | rem = ktime_sub(t.timer.expires, t.timer.base->get_time()); | 1331 | rem = ktime_sub(t.timer.expires, t.timer.base->get_time()); |
| 1336 | if (rem.tv64 <= 0) | 1332 | if (rem.tv64 <= 0) |
| 1337 | return 0; | 1333 | return 0; |
| 1338 | tu = ktime_to_timespec(rem); | 1334 | *rmtp = ktime_to_timespec(rem); |
| 1339 | if (copy_to_user(rmtp, &tu, sizeof(tu))) | ||
| 1340 | return -EFAULT; | ||
| 1341 | } | 1335 | } |
| 1342 | 1336 | ||
| 1343 | restart = ¤t_thread_info()->restart_block; | 1337 | restart = ¤t_thread_info()->restart_block; |
| @@ -1353,7 +1347,8 @@ long hrtimer_nanosleep(struct timespec *rqtp, struct timespec __user *rmtp, | |||
| 1353 | asmlinkage long | 1347 | asmlinkage long |
| 1354 | sys_nanosleep(struct timespec __user *rqtp, struct timespec __user *rmtp) | 1348 | sys_nanosleep(struct timespec __user *rqtp, struct timespec __user *rmtp) |
| 1355 | { | 1349 | { |
| 1356 | struct timespec tu; | 1350 | struct timespec tu, rmt; |
| 1351 | int ret; | ||
| 1357 | 1352 | ||
| 1358 | if (copy_from_user(&tu, rqtp, sizeof(tu))) | 1353 | if (copy_from_user(&tu, rqtp, sizeof(tu))) |
| 1359 | return -EFAULT; | 1354 | return -EFAULT; |
| @@ -1361,7 +1356,15 @@ sys_nanosleep(struct timespec __user *rqtp, struct timespec __user *rmtp) | |||
| 1361 | if (!timespec_valid(&tu)) | 1356 | if (!timespec_valid(&tu)) |
| 1362 | return -EINVAL; | 1357 | return -EINVAL; |
| 1363 | 1358 | ||
| 1364 | return hrtimer_nanosleep(&tu, rmtp, HRTIMER_MODE_REL, CLOCK_MONOTONIC); | 1359 | ret = hrtimer_nanosleep(&tu, rmtp ? &rmt : NULL, HRTIMER_MODE_REL, |
| 1360 | CLOCK_MONOTONIC); | ||
| 1361 | |||
| 1362 | if (ret && rmtp) { | ||
| 1363 | if (copy_to_user(rmtp, &rmt, sizeof(*rmtp))) | ||
| 1364 | return -EFAULT; | ||
| 1365 | } | ||
| 1366 | |||
| 1367 | return ret; | ||
| 1365 | } | 1368 | } |
| 1366 | 1369 | ||
| 1367 | /* | 1370 | /* |
diff --git a/kernel/posix-timers.c b/kernel/posix-timers.c index d71ed09fe1dd..d11f579d189a 100644 --- a/kernel/posix-timers.c +++ b/kernel/posix-timers.c | |||
| @@ -981,9 +981,20 @@ sys_clock_getres(const clockid_t which_clock, struct timespec __user *tp) | |||
| 981 | static int common_nsleep(const clockid_t which_clock, int flags, | 981 | static int common_nsleep(const clockid_t which_clock, int flags, |
| 982 | struct timespec *tsave, struct timespec __user *rmtp) | 982 | struct timespec *tsave, struct timespec __user *rmtp) |
| 983 | { | 983 | { |
| 984 | return hrtimer_nanosleep(tsave, rmtp, flags & TIMER_ABSTIME ? | 984 | struct timespec rmt; |
| 985 | HRTIMER_MODE_ABS : HRTIMER_MODE_REL, | 985 | int ret; |
| 986 | which_clock); | 986 | |
| 987 | ret = hrtimer_nanosleep(tsave, rmtp ? &rmt : NULL, | ||
| 988 | flags & TIMER_ABSTIME ? | ||
| 989 | HRTIMER_MODE_ABS : HRTIMER_MODE_REL, | ||
| 990 | which_clock); | ||
| 991 | |||
| 992 | if (ret && rmtp) { | ||
| 993 | if (copy_to_user(rmtp, &rmt, sizeof(*rmtp))) | ||
| 994 | return -EFAULT; | ||
| 995 | } | ||
| 996 | |||
| 997 | return ret; | ||
| 987 | } | 998 | } |
| 988 | 999 | ||
| 989 | asmlinkage long | 1000 | asmlinkage long |
