aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThomas Gleixner <tglx@linutronix.de>2006-01-09 23:52:37 -0500
committerLinus Torvalds <torvalds@g5.osdl.org>2006-01-10 11:01:38 -0500
commit97735f25d2ba898ec5e13746451525580631c834 (patch)
treea6da1078f04bec45967bd83f340b6f7bde731f5d
parent6ba1b91213e81aa92b5cf7539f7d2a94ff54947c (diff)
[PATCH] hrtimer: switch clock_nanosleep to hrtimer nanosleep API
Switch clock_nanosleep to use the new nanosleep functions in hrtimer.c Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Signed-off-by: Ingo Molnar <mingo@elte.hu> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-rw-r--r--include/linux/posix-timers.h7
-rw-r--r--kernel/posix-cpu-timers.c23
-rw-r--r--kernel/posix-timers.c151
3 files changed, 45 insertions, 136 deletions
diff --git a/include/linux/posix-timers.h b/include/linux/posix-timers.h
index ae51473d3d48..3c0a5beb7f0d 100644
--- a/include/linux/posix-timers.h
+++ b/include/linux/posix-timers.h
@@ -81,7 +81,7 @@ struct k_clock {
81 int (*clock_get) (const clockid_t which_clock, struct timespec * tp); 81 int (*clock_get) (const clockid_t which_clock, struct timespec * tp);
82 int (*timer_create) (struct k_itimer *timer); 82 int (*timer_create) (struct k_itimer *timer);
83 int (*nsleep) (const clockid_t which_clock, int flags, 83 int (*nsleep) (const clockid_t which_clock, int flags,
84 struct timespec *); 84 struct timespec *, struct timespec __user *);
85 int (*timer_set) (struct k_itimer * timr, int flags, 85 int (*timer_set) (struct k_itimer * timr, int flags,
86 struct itimerspec * new_setting, 86 struct itimerspec * new_setting,
87 struct itimerspec * old_setting); 87 struct itimerspec * old_setting);
@@ -95,7 +95,8 @@ void register_posix_clock(const clockid_t clock_id, struct k_clock *new_clock);
95 95
96/* error handlers for timer_create, nanosleep and settime */ 96/* error handlers for timer_create, nanosleep and settime */
97int do_posix_clock_notimer_create(struct k_itimer *timer); 97int do_posix_clock_notimer_create(struct k_itimer *timer);
98int do_posix_clock_nonanosleep(const clockid_t, int flags, struct timespec *); 98int do_posix_clock_nonanosleep(const clockid_t, int flags, struct timespec *,
99 struct timespec __user *);
99int do_posix_clock_nosettime(const clockid_t, struct timespec *tp); 100int do_posix_clock_nosettime(const clockid_t, struct timespec *tp);
100 101
101/* function to call to trigger timer event */ 102/* function to call to trigger timer event */
@@ -129,7 +130,7 @@ int posix_cpu_clock_get(const clockid_t which_clock, struct timespec *ts);
129int posix_cpu_clock_set(const clockid_t which_clock, const struct timespec *ts); 130int posix_cpu_clock_set(const clockid_t which_clock, const struct timespec *ts);
130int posix_cpu_timer_create(struct k_itimer *timer); 131int posix_cpu_timer_create(struct k_itimer *timer);
131int posix_cpu_nsleep(const clockid_t which_clock, int flags, 132int posix_cpu_nsleep(const clockid_t which_clock, int flags,
132 struct timespec *ts); 133 struct timespec *rqtp, struct timespec __user *rmtp);
133int posix_cpu_timer_set(struct k_itimer *timer, int flags, 134int posix_cpu_timer_set(struct k_itimer *timer, int flags,
134 struct itimerspec *new, struct itimerspec *old); 135 struct itimerspec *new, struct itimerspec *old);
135int posix_cpu_timer_del(struct k_itimer *timer); 136int posix_cpu_timer_del(struct k_itimer *timer);
diff --git a/kernel/posix-cpu-timers.c b/kernel/posix-cpu-timers.c
index abf6990c6eb5..520f6c59948d 100644
--- a/kernel/posix-cpu-timers.c
+++ b/kernel/posix-cpu-timers.c
@@ -1400,7 +1400,7 @@ void set_process_cpu_timer(struct task_struct *tsk, unsigned int clock_idx,
1400static long posix_cpu_clock_nanosleep_restart(struct restart_block *); 1400static long posix_cpu_clock_nanosleep_restart(struct restart_block *);
1401 1401
1402int posix_cpu_nsleep(const clockid_t which_clock, int flags, 1402int posix_cpu_nsleep(const clockid_t which_clock, int flags,
1403 struct timespec *rqtp) 1403 struct timespec *rqtp, struct timespec __user *rmtp)
1404{ 1404{
1405 struct restart_block *restart_block = 1405 struct restart_block *restart_block =
1406 &current_thread_info()->restart_block; 1406 &current_thread_info()->restart_block;
@@ -1425,7 +1425,6 @@ int posix_cpu_nsleep(const clockid_t which_clock, int flags,
1425 error = posix_cpu_timer_create(&timer); 1425 error = posix_cpu_timer_create(&timer);
1426 timer.it_process = current; 1426 timer.it_process = current;
1427 if (!error) { 1427 if (!error) {
1428 struct timespec __user *rmtp;
1429 static struct itimerspec zero_it; 1428 static struct itimerspec zero_it;
1430 struct itimerspec it = { .it_value = *rqtp, 1429 struct itimerspec it = { .it_value = *rqtp,
1431 .it_interval = {} }; 1430 .it_interval = {} };
@@ -1472,7 +1471,6 @@ int posix_cpu_nsleep(const clockid_t which_clock, int flags,
1472 /* 1471 /*
1473 * Report back to the user the time still remaining. 1472 * Report back to the user the time still remaining.
1474 */ 1473 */
1475 rmtp = (struct timespec __user *) restart_block->arg1;
1476 if (rmtp != NULL && !(flags & TIMER_ABSTIME) && 1474 if (rmtp != NULL && !(flags & TIMER_ABSTIME) &&
1477 copy_to_user(rmtp, &it.it_value, sizeof *rmtp)) 1475 copy_to_user(rmtp, &it.it_value, sizeof *rmtp))
1478 return -EFAULT; 1476 return -EFAULT;
@@ -1480,6 +1478,7 @@ int posix_cpu_nsleep(const clockid_t which_clock, int flags,
1480 restart_block->fn = posix_cpu_clock_nanosleep_restart; 1478 restart_block->fn = posix_cpu_clock_nanosleep_restart;
1481 /* Caller already set restart_block->arg1 */ 1479 /* Caller already set restart_block->arg1 */
1482 restart_block->arg0 = which_clock; 1480 restart_block->arg0 = which_clock;
1481 restart_block->arg1 = (unsigned long) rmtp;
1483 restart_block->arg2 = rqtp->tv_sec; 1482 restart_block->arg2 = rqtp->tv_sec;
1484 restart_block->arg3 = rqtp->tv_nsec; 1483 restart_block->arg3 = rqtp->tv_nsec;
1485 1484
@@ -1493,10 +1492,15 @@ static long
1493posix_cpu_clock_nanosleep_restart(struct restart_block *restart_block) 1492posix_cpu_clock_nanosleep_restart(struct restart_block *restart_block)
1494{ 1493{
1495 clockid_t which_clock = restart_block->arg0; 1494 clockid_t which_clock = restart_block->arg0;
1496 struct timespec t = { .tv_sec = restart_block->arg2, 1495 struct timespec __user *rmtp;
1497 .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
1498 restart_block->fn = do_no_restart_syscall; 1502 restart_block->fn = do_no_restart_syscall;
1499 return posix_cpu_nsleep(which_clock, TIMER_ABSTIME, &t); 1503 return posix_cpu_nsleep(which_clock, TIMER_ABSTIME, &t, rmtp);
1500} 1504}
1501 1505
1502 1506
@@ -1519,9 +1523,10 @@ static int process_cpu_timer_create(struct k_itimer *timer)
1519 return posix_cpu_timer_create(timer); 1523 return posix_cpu_timer_create(timer);
1520} 1524}
1521static int process_cpu_nsleep(const clockid_t which_clock, int flags, 1525static int process_cpu_nsleep(const clockid_t which_clock, int flags,
1522 struct timespec *rqtp) 1526 struct timespec *rqtp,
1527 struct timespec __user *rmtp)
1523{ 1528{
1524 return posix_cpu_nsleep(PROCESS_CLOCK, flags, rqtp); 1529 return posix_cpu_nsleep(PROCESS_CLOCK, flags, rqtp, rmtp);
1525} 1530}
1526static int thread_cpu_clock_getres(const clockid_t which_clock, 1531static int thread_cpu_clock_getres(const clockid_t which_clock,
1527 struct timespec *tp) 1532 struct timespec *tp)
@@ -1539,7 +1544,7 @@ static int thread_cpu_timer_create(struct k_itimer *timer)
1539 return posix_cpu_timer_create(timer); 1544 return posix_cpu_timer_create(timer);
1540} 1545}
1541static int thread_cpu_nsleep(const clockid_t which_clock, int flags, 1546static int thread_cpu_nsleep(const clockid_t which_clock, int flags,
1542 struct timespec *rqtp) 1547 struct timespec *rqtp, struct timespec __user *rmtp)
1543{ 1548{
1544 return -EINVAL; 1549 return -EINVAL;
1545} 1550}
diff --git a/kernel/posix-timers.c b/kernel/posix-timers.c
index 6b851a1bf4b0..ba900587b815 100644
--- a/kernel/posix-timers.c
+++ b/kernel/posix-timers.c
@@ -209,7 +209,8 @@ static inline int common_timer_create(struct k_itimer *new_timer)
209/* 209/*
210 * These ones are defined below. 210 * These ones are defined below.
211 */ 211 */
212static int common_nsleep(const clockid_t, int flags, struct timespec *t); 212static int common_nsleep(const clockid_t, int flags, struct timespec *t,
213 struct timespec __user *rmtp);
213static void common_timer_get(struct k_itimer *, struct itimerspec *); 214static void common_timer_get(struct k_itimer *, struct itimerspec *);
214static int common_timer_set(struct k_itimer *, int, 215static int common_timer_set(struct k_itimer *, int,
215 struct itimerspec *, struct itimerspec *); 216 struct itimerspec *, struct itimerspec *);
@@ -1227,7 +1228,7 @@ int do_posix_clock_notimer_create(struct k_itimer *timer)
1227EXPORT_SYMBOL_GPL(do_posix_clock_notimer_create); 1228EXPORT_SYMBOL_GPL(do_posix_clock_notimer_create);
1228 1229
1229int do_posix_clock_nonanosleep(const clockid_t clock, int flags, 1230int do_posix_clock_nonanosleep(const clockid_t clock, int flags,
1230 struct timespec *t) 1231 struct timespec *t, struct timespec __user *r)
1231{ 1232{
1232#ifndef ENOTSUP 1233#ifndef ENOTSUP
1233 return -EOPNOTSUPP; /* aka ENOTSUP in userland for POSIX */ 1234 return -EOPNOTSUPP; /* aka ENOTSUP in userland for POSIX */
@@ -1387,7 +1388,28 @@ void clock_was_set(void)
1387 up(&clock_was_set_lock); 1388 up(&clock_was_set_lock);
1388} 1389}
1389 1390
1390long clock_nanosleep_restart(struct restart_block *restart_block); 1391/*
1392 * nanosleep for monotonic and realtime clocks
1393 */
1394static int common_nsleep(const clockid_t which_clock, int flags,
1395 struct timespec *tsave, struct timespec __user *rmtp)
1396{
1397 int mode = flags & TIMER_ABSTIME ? HRTIMER_ABS : HRTIMER_REL;
1398 int clockid = which_clock;
1399
1400 switch (which_clock) {
1401 case CLOCK_REALTIME:
1402 /* Posix madness. Only absolute timers on clock realtime
1403 are affected by clock set. */
1404 if (mode == HRTIMER_ABS)
1405 clockid = CLOCK_MONOTONIC;
1406 case CLOCK_MONOTONIC:
1407 break;
1408 default:
1409 return -EINVAL;
1410 }
1411 return hrtimer_nanosleep(tsave, rmtp, mode, clockid);
1412}
1391 1413
1392asmlinkage long 1414asmlinkage long
1393sys_clock_nanosleep(const clockid_t which_clock, int flags, 1415sys_clock_nanosleep(const clockid_t which_clock, int flags,
@@ -1395,9 +1417,6 @@ sys_clock_nanosleep(const clockid_t which_clock, int flags,
1395 struct timespec __user *rmtp) 1417 struct timespec __user *rmtp)
1396{ 1418{
1397 struct timespec t; 1419 struct timespec t;
1398 struct restart_block *restart_block =
1399 &(current_thread_info()->restart_block);
1400 int ret;
1401 1420
1402 if (invalid_clockid(which_clock)) 1421 if (invalid_clockid(which_clock))
1403 return -EINVAL; 1422 return -EINVAL;
@@ -1408,122 +1427,6 @@ sys_clock_nanosleep(const clockid_t which_clock, int flags,
1408 if (!timespec_valid(&t)) 1427 if (!timespec_valid(&t))
1409 return -EINVAL; 1428 return -EINVAL;
1410 1429
1411 /* 1430 return CLOCK_DISPATCH(which_clock, nsleep,
1412 * Do this here as nsleep function does not have the real address. 1431 (which_clock, flags, &t, rmtp));
1413 */
1414 restart_block->arg1 = (unsigned long)rmtp;
1415
1416 ret = CLOCK_DISPATCH(which_clock, nsleep, (which_clock, flags, &t));
1417
1418 if ((ret == -ERESTART_RESTARTBLOCK) && rmtp &&
1419 copy_to_user(rmtp, &t, sizeof (t)))
1420 return -EFAULT;
1421 return ret;
1422}
1423
1424
1425static int common_nsleep(const clockid_t which_clock,
1426 int flags, struct timespec *tsave)
1427{
1428 struct timespec t, dum;
1429 DECLARE_WAITQUEUE(abs_wqueue, current);
1430 u64 rq_time = (u64)0;
1431 s64 left;
1432 int abs;
1433 struct restart_block *restart_block =
1434 &current_thread_info()->restart_block;
1435
1436 abs_wqueue.flags = 0;
1437 abs = flags & TIMER_ABSTIME;
1438
1439 if (restart_block->fn == clock_nanosleep_restart) {
1440 /*
1441 * Interrupted by a non-delivered signal, pick up remaining
1442 * time and continue. Remaining time is in arg2 & 3.
1443 */
1444 restart_block->fn = do_no_restart_syscall;
1445
1446 rq_time = restart_block->arg3;
1447 rq_time = (rq_time << 32) + restart_block->arg2;
1448 if (!rq_time)
1449 return -EINTR;
1450 left = rq_time - get_jiffies_64();
1451 if (left <= (s64)0)
1452 return 0; /* Already passed */
1453 }
1454
1455 if (abs && (posix_clocks[which_clock].clock_get !=
1456 posix_clocks[CLOCK_MONOTONIC].clock_get))
1457 add_wait_queue(&nanosleep_abs_wqueue, &abs_wqueue);
1458
1459 do {
1460 t = *tsave;
1461 if (abs || !rq_time) {
1462 adjust_abs_time(&posix_clocks[which_clock], &t, abs,
1463 &rq_time, &dum);
1464 }
1465
1466 left = rq_time - get_jiffies_64();
1467 if (left >= (s64)MAX_JIFFY_OFFSET)
1468 left = (s64)MAX_JIFFY_OFFSET;
1469 if (left < (s64)0)
1470 break;
1471
1472 schedule_timeout_interruptible(left);
1473
1474 left = rq_time - get_jiffies_64();
1475 } while (left > (s64)0 && !test_thread_flag(TIF_SIGPENDING));
1476
1477 if (abs_wqueue.task_list.next)
1478 finish_wait(&nanosleep_abs_wqueue, &abs_wqueue);
1479
1480 if (left > (s64)0) {
1481
1482 /*
1483 * Always restart abs calls from scratch to pick up any
1484 * clock shifting that happened while we are away.
1485 */
1486 if (abs)
1487 return -ERESTARTNOHAND;
1488
1489 left *= TICK_NSEC;
1490 tsave->tv_sec = div_long_long_rem(left,
1491 NSEC_PER_SEC,
1492 &tsave->tv_nsec);
1493 /*
1494 * Restart works by saving the time remaing in
1495 * arg2 & 3 (it is 64-bits of jiffies). The other
1496 * info we need is the clock_id (saved in arg0).
1497 * The sys_call interface needs the users
1498 * timespec return address which _it_ saves in arg1.
1499 * Since we have cast the nanosleep call to a clock_nanosleep
1500 * both can be restarted with the same code.
1501 */
1502 restart_block->fn = clock_nanosleep_restart;
1503 restart_block->arg0 = which_clock;
1504 /*
1505 * Caller sets arg1
1506 */
1507 restart_block->arg2 = rq_time & 0xffffffffLL;
1508 restart_block->arg3 = rq_time >> 32;
1509
1510 return -ERESTART_RESTARTBLOCK;
1511 }
1512
1513 return 0;
1514}
1515/*
1516 * This will restart clock_nanosleep.
1517 */
1518long
1519clock_nanosleep_restart(struct restart_block *restart_block)
1520{
1521 struct timespec t;
1522 int ret = common_nsleep(restart_block->arg0, 0, &t);
1523
1524 if ((ret == -ERESTART_RESTARTBLOCK) && restart_block->arg1 &&
1525 copy_to_user((struct timespec __user *)(restart_block->arg1), &t,
1526 sizeof (t)))
1527 return -EFAULT;
1528 return ret;
1529} 1432}