diff options
author | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2008-02-10 15:02:45 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2008-02-10 15:02:45 -0500 |
commit | 58a14ee9c49aa2b9742c56a0477666335368e05e (patch) | |
tree | 01dae0e9458eea6289f78bd21cea056798e5c75e | |
parent | 712a30e63c8066ed84385b12edbfb804f49cbc44 (diff) | |
parent | c289b074b66e2e59c65aba73f40b99e797e92d2f (diff) |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/tglx/linux-2.6-hrt
* git://git.kernel.org/pub/scm/linux/kernel/git/tglx/linux-2.6-hrt:
hrtimer: don't modify restart_block->fn in restart functions
hrtimer: fix *rmtp/restarts handling in compat_sys_nanosleep()
hrtimer: fix *rmtp handling in hrtimer_nanosleep()
ntp: correct inconsistent interval/tick_length usage
-rw-r--r-- | include/linux/hrtimer.h | 2 | ||||
-rw-r--r-- | include/linux/timex.h | 9 | ||||
-rw-r--r-- | kernel/compat.c | 43 | ||||
-rw-r--r-- | kernel/hrtimer.c | 55 | ||||
-rw-r--r-- | kernel/posix-timers.c | 17 | ||||
-rw-r--r-- | kernel/time/ntp.c | 4 |
6 files changed, 78 insertions, 52 deletions
diff --git a/include/linux/hrtimer.h b/include/linux/hrtimer.h index 600fc3bcf63e..1ad56a7b2f74 100644 --- a/include/linux/hrtimer.h +++ b/include/linux/hrtimer.h | |||
@@ -316,7 +316,7 @@ static inline u64 hrtimer_forward_now(struct hrtimer *timer, | |||
316 | 316 | ||
317 | /* Precise sleep: */ | 317 | /* Precise sleep: */ |
318 | extern long hrtimer_nanosleep(struct timespec *rqtp, | 318 | extern long hrtimer_nanosleep(struct timespec *rqtp, |
319 | struct timespec *rmtp, | 319 | struct timespec __user *rmtp, |
320 | const enum hrtimer_mode mode, | 320 | const enum hrtimer_mode mode, |
321 | const clockid_t clockid); | 321 | const clockid_t clockid); |
322 | extern long hrtimer_nanosleep_restart(struct restart_block *restart_block); | 322 | extern long hrtimer_nanosleep_restart(struct restart_block *restart_block); |
diff --git a/include/linux/timex.h b/include/linux/timex.h index 8ea3e71ba7fa..c3f374786a43 100644 --- a/include/linux/timex.h +++ b/include/linux/timex.h | |||
@@ -232,7 +232,14 @@ static inline int ntp_synced(void) | |||
232 | #else | 232 | #else |
233 | #define NTP_INTERVAL_FREQ (HZ) | 233 | #define NTP_INTERVAL_FREQ (HZ) |
234 | #endif | 234 | #endif |
235 | #define NTP_INTERVAL_LENGTH (NSEC_PER_SEC/NTP_INTERVAL_FREQ) | 235 | |
236 | #define CLOCK_TICK_OVERFLOW (LATCH * HZ - CLOCK_TICK_RATE) | ||
237 | #define CLOCK_TICK_ADJUST (((s64)CLOCK_TICK_OVERFLOW * NSEC_PER_SEC) / \ | ||
238 | (s64)CLOCK_TICK_RATE) | ||
239 | |||
240 | /* Because using NSEC_PER_SEC would be too easy */ | ||
241 | #define NTP_INTERVAL_LENGTH ((((s64)TICK_USEC * NSEC_PER_USEC * USER_HZ) + \ | ||
242 | CLOCK_TICK_ADJUST) / NTP_INTERVAL_FREQ) | ||
236 | 243 | ||
237 | /* Returns how long ticks are at present, in ns / 2^(SHIFT_SCALE-10). */ | 244 | /* Returns how long ticks are at present, in ns / 2^(SHIFT_SCALE-10). */ |
238 | extern u64 current_tick_length(void); | 245 | extern u64 current_tick_length(void); |
diff --git a/kernel/compat.c b/kernel/compat.c index 42a1ed4b61b1..5f0e201bcfd3 100644 --- a/kernel/compat.c +++ b/kernel/compat.c | |||
@@ -40,10 +40,35 @@ 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 | struct compat_timespec __user *rmtp; | ||
46 | struct timespec rmt; | ||
47 | mm_segment_t oldfs; | ||
48 | long ret; | ||
49 | |||
50 | rmtp = (struct compat_timespec __user *)(restart->arg1); | ||
51 | restart->arg1 = (unsigned long)&rmt; | ||
52 | oldfs = get_fs(); | ||
53 | set_fs(KERNEL_DS); | ||
54 | ret = hrtimer_nanosleep_restart(restart); | ||
55 | set_fs(oldfs); | ||
56 | |||
57 | if (ret) { | ||
58 | restart->arg1 = (unsigned long)rmtp; | ||
59 | |||
60 | if (rmtp && put_compat_timespec(&rmt, rmtp)) | ||
61 | return -EFAULT; | ||
62 | } | ||
63 | |||
64 | return ret; | ||
65 | } | ||
66 | |||
43 | asmlinkage long compat_sys_nanosleep(struct compat_timespec __user *rqtp, | 67 | asmlinkage long compat_sys_nanosleep(struct compat_timespec __user *rqtp, |
44 | struct compat_timespec __user *rmtp) | 68 | struct compat_timespec __user *rmtp) |
45 | { | 69 | { |
46 | struct timespec tu, rmt; | 70 | struct timespec tu, rmt; |
71 | mm_segment_t oldfs; | ||
47 | long ret; | 72 | long ret; |
48 | 73 | ||
49 | if (get_compat_timespec(&tu, rqtp)) | 74 | if (get_compat_timespec(&tu, rqtp)) |
@@ -52,11 +77,21 @@ asmlinkage long compat_sys_nanosleep(struct compat_timespec __user *rqtp, | |||
52 | if (!timespec_valid(&tu)) | 77 | if (!timespec_valid(&tu)) |
53 | return -EINVAL; | 78 | return -EINVAL; |
54 | 79 | ||
55 | ret = hrtimer_nanosleep(&tu, rmtp ? &rmt : NULL, HRTIMER_MODE_REL, | 80 | oldfs = get_fs(); |
56 | CLOCK_MONOTONIC); | 81 | set_fs(KERNEL_DS); |
82 | ret = hrtimer_nanosleep(&tu, | ||
83 | rmtp ? (struct timespec __user *)&rmt : NULL, | ||
84 | HRTIMER_MODE_REL, CLOCK_MONOTONIC); | ||
85 | set_fs(oldfs); | ||
86 | |||
87 | if (ret) { | ||
88 | struct restart_block *restart | ||
89 | = ¤t_thread_info()->restart_block; | ||
90 | |||
91 | restart->fn = compat_nanosleep_restart; | ||
92 | restart->arg1 = (unsigned long)rmtp; | ||
57 | 93 | ||
58 | if (ret && rmtp) { | 94 | if (rmtp && put_compat_timespec(&rmt, rmtp)) |
59 | if (put_compat_timespec(&rmt, rmtp)) | ||
60 | return -EFAULT; | 95 | return -EFAULT; |
61 | } | 96 | } |
62 | 97 | ||
diff --git a/kernel/hrtimer.c b/kernel/hrtimer.c index 668f3967eb39..3f4a57c7895d 100644 --- a/kernel/hrtimer.c +++ b/kernel/hrtimer.c | |||
@@ -1319,13 +1319,26 @@ static int __sched do_nanosleep(struct hrtimer_sleeper *t, enum hrtimer_mode mod | |||
1319 | return t->task == NULL; | 1319 | return t->task == NULL; |
1320 | } | 1320 | } |
1321 | 1321 | ||
1322 | static int update_rmtp(struct hrtimer *timer, struct timespec __user *rmtp) | ||
1323 | { | ||
1324 | struct timespec rmt; | ||
1325 | ktime_t rem; | ||
1326 | |||
1327 | rem = ktime_sub(timer->expires, timer->base->get_time()); | ||
1328 | if (rem.tv64 <= 0) | ||
1329 | return 0; | ||
1330 | rmt = ktime_to_timespec(rem); | ||
1331 | |||
1332 | if (copy_to_user(rmtp, &rmt, sizeof(*rmtp))) | ||
1333 | return -EFAULT; | ||
1334 | |||
1335 | return 1; | ||
1336 | } | ||
1337 | |||
1322 | long __sched hrtimer_nanosleep_restart(struct restart_block *restart) | 1338 | long __sched hrtimer_nanosleep_restart(struct restart_block *restart) |
1323 | { | 1339 | { |
1324 | struct hrtimer_sleeper t; | 1340 | struct hrtimer_sleeper t; |
1325 | struct timespec *rmtp; | 1341 | struct timespec __user *rmtp; |
1326 | ktime_t time; | ||
1327 | |||
1328 | restart->fn = do_no_restart_syscall; | ||
1329 | 1342 | ||
1330 | hrtimer_init(&t.timer, restart->arg0, HRTIMER_MODE_ABS); | 1343 | hrtimer_init(&t.timer, restart->arg0, HRTIMER_MODE_ABS); |
1331 | t.timer.expires.tv64 = ((u64)restart->arg3 << 32) | (u64) restart->arg2; | 1344 | t.timer.expires.tv64 = ((u64)restart->arg3 << 32) | (u64) restart->arg2; |
@@ -1333,26 +1346,22 @@ long __sched hrtimer_nanosleep_restart(struct restart_block *restart) | |||
1333 | if (do_nanosleep(&t, HRTIMER_MODE_ABS)) | 1346 | if (do_nanosleep(&t, HRTIMER_MODE_ABS)) |
1334 | return 0; | 1347 | return 0; |
1335 | 1348 | ||
1336 | rmtp = (struct timespec *)restart->arg1; | 1349 | rmtp = (struct timespec __user *)restart->arg1; |
1337 | if (rmtp) { | 1350 | if (rmtp) { |
1338 | time = ktime_sub(t.timer.expires, t.timer.base->get_time()); | 1351 | int ret = update_rmtp(&t.timer, rmtp); |
1339 | if (time.tv64 <= 0) | 1352 | if (ret <= 0) |
1340 | return 0; | 1353 | return ret; |
1341 | *rmtp = ktime_to_timespec(time); | ||
1342 | } | 1354 | } |
1343 | 1355 | ||
1344 | restart->fn = hrtimer_nanosleep_restart; | ||
1345 | |||
1346 | /* The other values in restart are already filled in */ | 1356 | /* The other values in restart are already filled in */ |
1347 | return -ERESTART_RESTARTBLOCK; | 1357 | return -ERESTART_RESTARTBLOCK; |
1348 | } | 1358 | } |
1349 | 1359 | ||
1350 | long hrtimer_nanosleep(struct timespec *rqtp, struct timespec *rmtp, | 1360 | long hrtimer_nanosleep(struct timespec *rqtp, struct timespec __user *rmtp, |
1351 | const enum hrtimer_mode mode, const clockid_t clockid) | 1361 | const enum hrtimer_mode mode, const clockid_t clockid) |
1352 | { | 1362 | { |
1353 | struct restart_block *restart; | 1363 | struct restart_block *restart; |
1354 | struct hrtimer_sleeper t; | 1364 | struct hrtimer_sleeper t; |
1355 | ktime_t rem; | ||
1356 | 1365 | ||
1357 | hrtimer_init(&t.timer, clockid, mode); | 1366 | hrtimer_init(&t.timer, clockid, mode); |
1358 | t.timer.expires = timespec_to_ktime(*rqtp); | 1367 | t.timer.expires = timespec_to_ktime(*rqtp); |
@@ -1364,10 +1373,9 @@ long hrtimer_nanosleep(struct timespec *rqtp, struct timespec *rmtp, | |||
1364 | return -ERESTARTNOHAND; | 1373 | return -ERESTARTNOHAND; |
1365 | 1374 | ||
1366 | if (rmtp) { | 1375 | if (rmtp) { |
1367 | rem = ktime_sub(t.timer.expires, t.timer.base->get_time()); | 1376 | int ret = update_rmtp(&t.timer, rmtp); |
1368 | if (rem.tv64 <= 0) | 1377 | if (ret <= 0) |
1369 | return 0; | 1378 | return ret; |
1370 | *rmtp = ktime_to_timespec(rem); | ||
1371 | } | 1379 | } |
1372 | 1380 | ||
1373 | restart = ¤t_thread_info()->restart_block; | 1381 | restart = ¤t_thread_info()->restart_block; |
@@ -1383,8 +1391,7 @@ long hrtimer_nanosleep(struct timespec *rqtp, struct timespec *rmtp, | |||
1383 | asmlinkage long | 1391 | asmlinkage long |
1384 | sys_nanosleep(struct timespec __user *rqtp, struct timespec __user *rmtp) | 1392 | sys_nanosleep(struct timespec __user *rqtp, struct timespec __user *rmtp) |
1385 | { | 1393 | { |
1386 | struct timespec tu, rmt; | 1394 | struct timespec tu; |
1387 | int ret; | ||
1388 | 1395 | ||
1389 | if (copy_from_user(&tu, rqtp, sizeof(tu))) | 1396 | if (copy_from_user(&tu, rqtp, sizeof(tu))) |
1390 | return -EFAULT; | 1397 | return -EFAULT; |
@@ -1392,15 +1399,7 @@ sys_nanosleep(struct timespec __user *rqtp, struct timespec __user *rmtp) | |||
1392 | if (!timespec_valid(&tu)) | 1399 | if (!timespec_valid(&tu)) |
1393 | return -EINVAL; | 1400 | return -EINVAL; |
1394 | 1401 | ||
1395 | ret = hrtimer_nanosleep(&tu, rmtp ? &rmt : NULL, HRTIMER_MODE_REL, | 1402 | return hrtimer_nanosleep(&tu, rmtp, HRTIMER_MODE_REL, CLOCK_MONOTONIC); |
1396 | CLOCK_MONOTONIC); | ||
1397 | |||
1398 | if (ret && rmtp) { | ||
1399 | if (copy_to_user(rmtp, &rmt, sizeof(*rmtp))) | ||
1400 | return -EFAULT; | ||
1401 | } | ||
1402 | |||
1403 | return ret; | ||
1404 | } | 1403 | } |
1405 | 1404 | ||
1406 | /* | 1405 | /* |
diff --git a/kernel/posix-timers.c b/kernel/posix-timers.c index ce268966007d..022c9c3cee6f 100644 --- a/kernel/posix-timers.c +++ b/kernel/posix-timers.c | |||
@@ -982,20 +982,9 @@ sys_clock_getres(const clockid_t which_clock, struct timespec __user *tp) | |||
982 | static int common_nsleep(const clockid_t which_clock, int flags, | 982 | static int common_nsleep(const clockid_t which_clock, int flags, |
983 | struct timespec *tsave, struct timespec __user *rmtp) | 983 | struct timespec *tsave, struct timespec __user *rmtp) |
984 | { | 984 | { |
985 | struct timespec rmt; | 985 | return hrtimer_nanosleep(tsave, rmtp, flags & TIMER_ABSTIME ? |
986 | int ret; | 986 | HRTIMER_MODE_ABS : HRTIMER_MODE_REL, |
987 | 987 | which_clock); | |
988 | ret = hrtimer_nanosleep(tsave, rmtp ? &rmt : NULL, | ||
989 | flags & TIMER_ABSTIME ? | ||
990 | HRTIMER_MODE_ABS : HRTIMER_MODE_REL, | ||
991 | which_clock); | ||
992 | |||
993 | if (ret && rmtp) { | ||
994 | if (copy_to_user(rmtp, &rmt, sizeof(*rmtp))) | ||
995 | return -EFAULT; | ||
996 | } | ||
997 | |||
998 | return ret; | ||
999 | } | 988 | } |
1000 | 989 | ||
1001 | asmlinkage long | 990 | asmlinkage long |
diff --git a/kernel/time/ntp.c b/kernel/time/ntp.c index e64efaf957e8..c88b5910e7ab 100644 --- a/kernel/time/ntp.c +++ b/kernel/time/ntp.c | |||
@@ -43,10 +43,6 @@ long time_freq; /* frequency offset (scaled ppm)*/ | |||
43 | static long time_reftime; /* time at last adjustment (s) */ | 43 | static long time_reftime; /* time at last adjustment (s) */ |
44 | long time_adjust; | 44 | long time_adjust; |
45 | 45 | ||
46 | #define CLOCK_TICK_OVERFLOW (LATCH * HZ - CLOCK_TICK_RATE) | ||
47 | #define CLOCK_TICK_ADJUST (((s64)CLOCK_TICK_OVERFLOW * NSEC_PER_SEC) / \ | ||
48 | (s64)CLOCK_TICK_RATE) | ||
49 | |||
50 | static void ntp_update_frequency(void) | 46 | static void ntp_update_frequency(void) |
51 | { | 47 | { |
52 | u64 second_length = (u64)(tick_usec * NSEC_PER_USEC * USER_HZ) | 48 | u64 second_length = (u64)(tick_usec * NSEC_PER_USEC * USER_HZ) |