[PATCH] hrtimer: switch clock_nanosleep to hrtimer nanosleep API
authorThomas Gleixner <tglx@linutronix.de>
Tue, 10 Jan 2006 04:52:37 +0000 (20:52 -0800)
committerLinus Torvalds <torvalds@g5.osdl.org>
Tue, 10 Jan 2006 16:01:38 +0000 (08:01 -0800)
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>
include/linux/posix-timers.h
kernel/posix-cpu-timers.c
kernel/posix-timers.c

index ae51473..3c0a5be 100644 (file)
@@ -81,7 +81,7 @@ struct k_clock {
        int (*clock_get) (const clockid_t which_clock, struct timespec * tp);
        int (*timer_create) (struct k_itimer *timer);
        int (*nsleep) (const clockid_t which_clock, int flags,
-                      struct timespec *);
+                      struct timespec *, struct timespec __user *);
        int (*timer_set) (struct k_itimer * timr, int flags,
                          struct itimerspec * new_setting,
                          struct itimerspec * old_setting);
@@ -95,7 +95,8 @@ void register_posix_clock(const clockid_t clock_id, struct k_clock *new_clock);
 
 /* error handlers for timer_create, nanosleep and settime */
 int do_posix_clock_notimer_create(struct k_itimer *timer);
-int do_posix_clock_nonanosleep(const clockid_t, int flags, struct timespec *);
+int do_posix_clock_nonanosleep(const clockid_t, int flags, struct timespec *,
+                              struct timespec __user *);
 int do_posix_clock_nosettime(const clockid_t, struct timespec *tp);
 
 /* function to call to trigger timer event */
@@ -129,7 +130,7 @@ int posix_cpu_clock_get(const clockid_t which_clock, struct timespec *ts);
 int posix_cpu_clock_set(const clockid_t which_clock, const struct timespec *ts);
 int posix_cpu_timer_create(struct k_itimer *timer);
 int posix_cpu_nsleep(const clockid_t which_clock, int flags,
-                    struct timespec *ts);
+                    struct timespec *rqtp, struct timespec __user *rmtp);
 int posix_cpu_timer_set(struct k_itimer *timer, int flags,
                        struct itimerspec *new, struct itimerspec *old);
 int posix_cpu_timer_del(struct k_itimer *timer);
index abf6990..520f6c5 100644 (file)
@@ -1400,7 +1400,7 @@ void set_process_cpu_timer(struct task_struct *tsk, unsigned int clock_idx,
 static long posix_cpu_clock_nanosleep_restart(struct restart_block *);
 
 int posix_cpu_nsleep(const clockid_t which_clock, int flags,
-                    struct timespec *rqtp)
+                    struct timespec *rqtp, struct timespec __user *rmtp)
 {
        struct restart_block *restart_block =
            &current_thread_info()->restart_block;
@@ -1425,7 +1425,6 @@ int posix_cpu_nsleep(const clockid_t which_clock, int flags,
        error = posix_cpu_timer_create(&timer);
        timer.it_process = current;
        if (!error) {
-               struct timespec __user *rmtp;
                static struct itimerspec zero_it;
                struct itimerspec it = { .it_value = *rqtp,
                                         .it_interval = {} };
@@ -1472,7 +1471,6 @@ int posix_cpu_nsleep(const clockid_t which_clock, int flags,
                /*
                 * Report back to the user the time still remaining.
                 */
-               rmtp = (struct timespec __user *) restart_block->arg1;
                if (rmtp != NULL && !(flags & TIMER_ABSTIME) &&
                    copy_to_user(rmtp, &it.it_value, sizeof *rmtp))
                        return -EFAULT;
@@ -1480,6 +1478,7 @@ int posix_cpu_nsleep(const clockid_t which_clock, int flags,
                restart_block->fn = posix_cpu_clock_nanosleep_restart;
                /* Caller already set restart_block->arg1 */
                restart_block->arg0 = which_clock;
+               restart_block->arg1 = (unsigned long) rmtp;
                restart_block->arg2 = rqtp->tv_sec;
                restart_block->arg3 = rqtp->tv_nsec;
 
@@ -1493,10 +1492,15 @@ static long
 posix_cpu_clock_nanosleep_restart(struct restart_block *restart_block)
 {
        clockid_t which_clock = restart_block->arg0;
-       struct timespec t = { .tv_sec = restart_block->arg2,
-                             .tv_nsec = restart_block->arg3 };
+       struct timespec __user *rmtp;
+       struct timespec t;
+
+       rmtp = (struct timespec __user *) restart_block->arg1;
+       t.tv_sec = restart_block->arg2;
+       t.tv_nsec = restart_block->arg3;
+
        restart_block->fn = do_no_restart_syscall;
-       return posix_cpu_nsleep(which_clock, TIMER_ABSTIME, &t);
+       return posix_cpu_nsleep(which_clock, TIMER_ABSTIME, &t, rmtp);
 }
 
 
@@ -1519,9 +1523,10 @@ static int process_cpu_timer_create(struct k_itimer *timer)
        return posix_cpu_timer_create(timer);
 }
 static int process_cpu_nsleep(const clockid_t which_clock, int flags,
-                             struct timespec *rqtp)
+                             struct timespec *rqtp,
+                             struct timespec __user *rmtp)
 {
-       return posix_cpu_nsleep(PROCESS_CLOCK, flags, rqtp);
+       return posix_cpu_nsleep(PROCESS_CLOCK, flags, rqtp, rmtp);
 }
 static int thread_cpu_clock_getres(const clockid_t which_clock,
                                   struct timespec *tp)
@@ -1539,7 +1544,7 @@ static int thread_cpu_timer_create(struct k_itimer *timer)
        return posix_cpu_timer_create(timer);
 }
 static int thread_cpu_nsleep(const clockid_t which_clock, int flags,
-                             struct timespec *rqtp)
+                             struct timespec *rqtp, struct timespec __user *rmtp)
 {
        return -EINVAL;
 }
index 6b851a1..ba90058 100644 (file)
@@ -209,7 +209,8 @@ static inline int common_timer_create(struct k_itimer *new_timer)
 /*
  * These ones are defined below.
  */
-static int common_nsleep(const clockid_t, int flags, struct timespec *t);
+static int common_nsleep(const clockid_t, int flags, struct timespec *t,
+                        struct timespec __user *rmtp);
 static void common_timer_get(struct k_itimer *, struct itimerspec *);
 static int common_timer_set(struct k_itimer *, int,
                            struct itimerspec *, struct itimerspec *);
@@ -1227,7 +1228,7 @@ int do_posix_clock_notimer_create(struct k_itimer *timer)
 EXPORT_SYMBOL_GPL(do_posix_clock_notimer_create);
 
 int do_posix_clock_nonanosleep(const clockid_t clock, int flags,
-                              struct timespec *t)
+                              struct timespec *t, struct timespec __user *r)
 {
 #ifndef ENOTSUP
        return -EOPNOTSUPP;     /* aka ENOTSUP in userland for POSIX */
@@ -1387,7 +1388,28 @@ void clock_was_set(void)
        up(&clock_was_set_lock);
 }
 
-long clock_nanosleep_restart(struct restart_block *restart_block);
+/*
+ * nanosleep for monotonic and realtime clocks
+ */
+static int common_nsleep(const clockid_t which_clock, int flags,
+                        struct timespec *tsave, struct timespec __user *rmtp)
+{
+       int mode = flags & TIMER_ABSTIME ? HRTIMER_ABS : HRTIMER_REL;
+       int clockid = which_clock;
+
+       switch (which_clock) {
+       case CLOCK_REALTIME:
+               /* Posix madness. Only absolute timers on clock realtime
+                  are affected by clock set. */
+               if (mode == HRTIMER_ABS)
+                       clockid = CLOCK_MONOTONIC;
+       case CLOCK_MONOTONIC:
+               break;
+       default:
+               return -EINVAL;
+       }
+       return hrtimer_nanosleep(tsave, rmtp, mode, clockid);
+}
 
 asmlinkage long
 sys_clock_nanosleep(const clockid_t which_clock, int flags,
@@ -1395,9 +1417,6 @@ sys_clock_nanosleep(const clockid_t which_clock, int flags,
                    struct timespec __user *rmtp)
 {
        struct timespec t;
-       struct restart_block *restart_block =
-           &(current_thread_info()->restart_block);
-       int ret;
 
        if (invalid_clockid(which_clock))
                return -EINVAL;
@@ -1408,122 +1427,6 @@ sys_clock_nanosleep(const clockid_t which_clock, int flags,
        if (!timespec_valid(&t))
                return -EINVAL;
 
-       /*
-        * Do this here as nsleep function does not have the real address.
-        */
-       restart_block->arg1 = (unsigned long)rmtp;
-
-       ret = CLOCK_DISPATCH(which_clock, nsleep, (which_clock, flags, &t));
-
-       if ((ret == -ERESTART_RESTARTBLOCK) && rmtp &&
-                                       copy_to_user(rmtp, &t, sizeof (t)))
-               return -EFAULT;
-       return ret;
-}
-
-
-static int common_nsleep(const clockid_t which_clock,
-                        int flags, struct timespec *tsave)
-{
-       struct timespec t, dum;
-       DECLARE_WAITQUEUE(abs_wqueue, current);
-       u64 rq_time = (u64)0;
-       s64 left;
-       int abs;
-       struct restart_block *restart_block =
-           &current_thread_info()->restart_block;
-
-       abs_wqueue.flags = 0;
-       abs = flags & TIMER_ABSTIME;
-
-       if (restart_block->fn == clock_nanosleep_restart) {
-               /*
-                * Interrupted by a non-delivered signal, pick up remaining
-                * time and continue.  Remaining time is in arg2 & 3.
-                */
-               restart_block->fn = do_no_restart_syscall;
-
-               rq_time = restart_block->arg3;
-               rq_time = (rq_time << 32) + restart_block->arg2;
-               if (!rq_time)
-                       return -EINTR;
-               left = rq_time - get_jiffies_64();
-               if (left <= (s64)0)
-                       return 0;       /* Already passed */
-       }
-
-       if (abs && (posix_clocks[which_clock].clock_get !=
-                           posix_clocks[CLOCK_MONOTONIC].clock_get))
-               add_wait_queue(&nanosleep_abs_wqueue, &abs_wqueue);
-
-       do {
-               t = *tsave;
-               if (abs || !rq_time) {
-                       adjust_abs_time(&posix_clocks[which_clock], &t, abs,
-                                       &rq_time, &dum);
-               }
-
-               left = rq_time - get_jiffies_64();
-               if (left >= (s64)MAX_JIFFY_OFFSET)
-                       left = (s64)MAX_JIFFY_OFFSET;
-               if (left < (s64)0)
-                       break;
-
-               schedule_timeout_interruptible(left);
-
-               left = rq_time - get_jiffies_64();
-       } while (left > (s64)0 && !test_thread_flag(TIF_SIGPENDING));
-
-       if (abs_wqueue.task_list.next)
-               finish_wait(&nanosleep_abs_wqueue, &abs_wqueue);
-
-       if (left > (s64)0) {
-
-               /*
-                * Always restart abs calls from scratch to pick up any
-                * clock shifting that happened while we are away.
-                */
-               if (abs)
-                       return -ERESTARTNOHAND;
-
-               left *= TICK_NSEC;
-               tsave->tv_sec = div_long_long_rem(left, 
-                                                 NSEC_PER_SEC, 
-                                                 &tsave->tv_nsec);
-               /*
-                * Restart works by saving the time remaing in 
-                * arg2 & 3 (it is 64-bits of jiffies).  The other
-                * info we need is the clock_id (saved in arg0). 
-                * The sys_call interface needs the users 
-                * timespec return address which _it_ saves in arg1.
-                * Since we have cast the nanosleep call to a clock_nanosleep
-                * both can be restarted with the same code.
-                */
-               restart_block->fn = clock_nanosleep_restart;
-               restart_block->arg0 = which_clock;
-               /*
-                * Caller sets arg1
-                */
-               restart_block->arg2 = rq_time & 0xffffffffLL;
-               restart_block->arg3 = rq_time >> 32;
-
-               return -ERESTART_RESTARTBLOCK;
-       }
-
-       return 0;
-}
-/*
- * This will restart clock_nanosleep.
- */
-long
-clock_nanosleep_restart(struct restart_block *restart_block)
-{
-       struct timespec t;
-       int ret = common_nsleep(restart_block->arg0, 0, &t);
-
-       if ((ret == -ERESTART_RESTARTBLOCK) && restart_block->arg1 &&
-           copy_to_user((struct timespec __user *)(restart_block->arg1), &t,
-                        sizeof (t)))
-               return -EFAULT;
-       return ret;
+       return CLOCK_DISPATCH(which_clock, nsleep,
+                             (which_clock, flags, &t, rmtp));
 }