From c4af66cb483dbf741c89fee8503f47b387f47f4d Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Tue, 21 Feb 2006 19:26:44 -0800 Subject: [PATCH] hrtimer: Reverse patch to switch sys_nanosleep to hrtimer Patch 6ba1b91213e81aa92b5cf7539f7d2a94ff54947c hrtimer: switch sys_nanosleep to hrtimer breaks dynamic tick. All usleep calls will fail as the next_timer_interrupt currently does not scan hrtimer queues. This means the system will be potentially asleep in the idle mode when the next hrtimer is supposed to run. Until hrtimer_next_interrupt is implemented, we'll use the old sys_nanosleep. --- kernel/hrtimer.c | 14 ------------ kernel/timer.c | 56 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 56 insertions(+), 14 deletions(-) diff --git a/kernel/hrtimer.c b/kernel/hrtimer.c index 5ae51f1bc7c..47a6bc7e7e6 100644 --- a/kernel/hrtimer.c +++ b/kernel/hrtimer.c @@ -727,20 +727,6 @@ long hrtimer_nanosleep(struct timespec *rqtp, struct timespec __user *rmtp, return -ERESTART_RESTARTBLOCK; } -asmlinkage long -sys_nanosleep(struct timespec __user *rqtp, struct timespec __user *rmtp) -{ - struct timespec tu; - - if (copy_from_user(&tu, rqtp, sizeof(tu))) - return -EFAULT; - - if (!timespec_valid(&tu)) - return -EINVAL; - - return hrtimer_nanosleep(&tu, rmtp, HRTIMER_REL, CLOCK_MONOTONIC); -} - /* * Functions related to boot-time initialization: */ diff --git a/kernel/timer.c b/kernel/timer.c index fe3a9a9f832..bef6104f071 100644 --- a/kernel/timer.c +++ b/kernel/timer.c @@ -1149,6 +1149,62 @@ asmlinkage long sys_gettid(void) return current->pid; } +static long __sched nanosleep_restart(struct restart_block *restart) +{ + unsigned long expire = restart->arg0, now = jiffies; + struct timespec __user *rmtp = (struct timespec __user *) restart->arg1; + long ret; + + /* Did it expire while we handled signals? */ + if (!time_after(expire, now)) + return 0; + + expire = schedule_timeout_interruptible(expire - now); + + ret = 0; + if (expire) { + struct timespec t; + jiffies_to_timespec(expire, &t); + + ret = -ERESTART_RESTARTBLOCK; + if (rmtp && copy_to_user(rmtp, &t, sizeof(t))) + ret = -EFAULT; + /* The 'restart' block is already filled in */ + } + return ret; +} + +asmlinkage long sys_nanosleep(struct timespec __user *rqtp, struct timespec __user *rmtp) +{ + struct timespec t; + unsigned long expire; + long ret; + + if (copy_from_user(&t, rqtp, sizeof(t))) + return -EFAULT; + + if ((t.tv_nsec >= 1000000000L) || (t.tv_nsec < 0) || (t.tv_sec < 0)) + return -EINVAL; + + expire = timespec_to_jiffies(&t) + (t.tv_sec || t.tv_nsec); + expire = schedule_timeout_interruptible(expire); + + ret = 0; + if (expire) { + struct restart_block *restart; + jiffies_to_timespec(expire, &t); + if (rmtp && copy_to_user(rmtp, &t, sizeof(t))) + return -EFAULT; + + restart = ¤t_thread_info()->restart_block; + restart->fn = nanosleep_restart; + restart->arg0 = jiffies + expire; + restart->arg1 = (unsigned long) rmtp; + ret = -ERESTART_RESTARTBLOCK; + } + return ret; +} + /* * sys_sysinfo - fill in sysinfo struct */ -- 2.41.1