diff options
| author | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-10-18 18:12:41 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-10-18 18:12:41 -0400 |
| commit | 58f9b52ee8712283f7ffedb661df678c61e88a91 (patch) | |
| tree | fe6d2e1bca6befd8ca347487a7c053b8136320ad | |
| parent | 2af170dd241810212cbdbdc802ba7d39e3fb23b9 (diff) | |
| parent | c70878b4e0b6cf8d2f1e46319e48e821ef4a8aba (diff) | |
Merge ssh://master.kernel.org/pub/scm/linux/kernel/git/tglx/linux-2.6-hrt
* ssh://master.kernel.org/pub/scm/linux/kernel/git/tglx/linux-2.6-hrt:
hrtimer: hook compat_sys_nanosleep up to high res timer code
hrtimer: Rework hrtimer_nanosleep to make sys_compat_nanosleep easier
| -rw-r--r-- | include/linux/hrtimer.h | 2 | ||||
| -rw-r--r-- | kernel/compat.c | 57 | ||||
| -rw-r--r-- | kernel/hrtimer.c | 29 | ||||
| -rw-r--r-- | kernel/posix-timers.c | 17 |
4 files changed, 42 insertions, 63 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/compat.c b/kernel/compat.c index b78328af19ad..42a1ed4b61b1 100644 --- a/kernel/compat.c +++ b/kernel/compat.c | |||
| @@ -40,62 +40,27 @@ int put_compat_timespec(const struct timespec *ts, struct compat_timespec __user | |||
| 40 | __put_user(ts->tv_nsec, &cts->tv_nsec)) ? -EFAULT : 0; | 40 | __put_user(ts->tv_nsec, &cts->tv_nsec)) ? -EFAULT : 0; |
| 41 | } | 41 | } |
| 42 | 42 | ||
| 43 | static long compat_nanosleep_restart(struct restart_block *restart) | ||
| 44 | { | ||
| 45 | unsigned long expire = restart->arg0, now = jiffies; | ||
| 46 | struct compat_timespec __user *rmtp; | ||
| 47 | |||
| 48 | /* Did it expire while we handled signals? */ | ||
| 49 | if (!time_after(expire, now)) | ||
| 50 | return 0; | ||
| 51 | |||
| 52 | expire = schedule_timeout_interruptible(expire - now); | ||
| 53 | if (expire == 0) | ||
| 54 | return 0; | ||
| 55 | |||
| 56 | rmtp = (struct compat_timespec __user *)restart->arg1; | ||
| 57 | if (rmtp) { | ||
| 58 | struct compat_timespec ct; | ||
| 59 | struct timespec t; | ||
| 60 | |||
| 61 | jiffies_to_timespec(expire, &t); | ||
| 62 | ct.tv_sec = t.tv_sec; | ||
| 63 | ct.tv_nsec = t.tv_nsec; | ||
| 64 | if (copy_to_user(rmtp, &ct, sizeof(ct))) | ||
| 65 | return -EFAULT; | ||
| 66 | } | ||
| 67 | /* The 'restart' block is already filled in */ | ||
| 68 | return -ERESTART_RESTARTBLOCK; | ||
| 69 | } | ||
| 70 | |||
| 71 | asmlinkage long compat_sys_nanosleep(struct compat_timespec __user *rqtp, | 43 | asmlinkage long compat_sys_nanosleep(struct compat_timespec __user *rqtp, |
| 72 | struct compat_timespec __user *rmtp) | 44 | struct compat_timespec __user *rmtp) |
| 73 | { | 45 | { |
| 74 | struct timespec t; | 46 | struct timespec tu, rmt; |
| 75 | struct restart_block *restart; | 47 | long ret; |
| 76 | unsigned long expire; | ||
| 77 | 48 | ||
| 78 | if (get_compat_timespec(&t, rqtp)) | 49 | if (get_compat_timespec(&tu, rqtp)) |
| 79 | return -EFAULT; | 50 | return -EFAULT; |
| 80 | 51 | ||
| 81 | if ((t.tv_nsec >= 1000000000L) || (t.tv_nsec < 0) || (t.tv_sec < 0)) | 52 | if (!timespec_valid(&tu)) |
| 82 | return -EINVAL; | 53 | return -EINVAL; |
| 83 | 54 | ||
| 84 | expire = timespec_to_jiffies(&t) + (t.tv_sec || t.tv_nsec); | 55 | ret = hrtimer_nanosleep(&tu, rmtp ? &rmt : NULL, HRTIMER_MODE_REL, |
| 85 | expire = schedule_timeout_interruptible(expire); | 56 | CLOCK_MONOTONIC); |
| 86 | if (expire == 0) | ||
| 87 | return 0; | ||
| 88 | 57 | ||
| 89 | if (rmtp) { | 58 | if (ret && rmtp) { |
| 90 | jiffies_to_timespec(expire, &t); | 59 | if (put_compat_timespec(&rmt, rmtp)) |
| 91 | if (put_compat_timespec(&t, rmtp)) | ||
| 92 | return -EFAULT; | 60 | return -EFAULT; |
| 93 | } | 61 | } |
| 94 | restart = ¤t_thread_info()->restart_block; | 62 | |
| 95 | restart->fn = compat_nanosleep_restart; | 63 | return ret; |
| 96 | restart->arg0 = jiffies + expire; | ||
| 97 | restart->arg1 = (unsigned long) rmtp; | ||
| 98 | return -ERESTART_RESTARTBLOCK; | ||
| 99 | } | 64 | } |
| 100 | 65 | ||
| 101 | static inline long get_compat_itimerval(struct itimerval *o, | 66 | static inline long get_compat_itimerval(struct itimerval *o, |
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 |
