aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/futex_compat.c
diff options
context:
space:
mode:
authorPierre Peiffer <pierre.peiffer@bull.net>2007-05-09 05:35:02 -0400
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-05-09 15:30:55 -0400
commitc19384b5b296905d4988c7c684ff540a0f9d65be (patch)
tree071cfe0855d409d63de80ec1b9b663738efb09de /kernel/futex_compat.c
parentec92d08292d3e9b0823eba138a4564d2d39f25c7 (diff)
Make futex_wait() use an hrtimer for timeout
This patch modifies futex_wait() to use an hrtimer + schedule() in place of schedule_timeout(). schedule_timeout() is tick based, therefore the timeout granularity is the tick (1 ms, 4 ms or 10 ms depending on HZ). By using a high resolution timer for timeout wakeup, we can attain a much finer timeout granularity (in the microsecond range). This parallels what is already done for futex_lock_pi(). The timeout passed to the syscall is no longer converted to jiffies and is therefore passed to do_futex() and futex_wait() as an absolute ktime_t therefore keeping nanosecond resolution. Also this removes the need to pass the nanoseconds timeout part to futex_lock_pi() in val2. In futex_wait(), if there is no timeout then a regular schedule() is performed. Otherwise, an hrtimer is fired before schedule() is called. [akpm@linux-foundation.org: fix `make headers_check'] Signed-off-by: Sebastien Dugue <sebastien.dugue@bull.net> Signed-off-by: Pierre Peiffer <pierre.peiffer@bull.net> Cc: Ingo Molnar <mingo@elte.hu> Cc: Ulrich Drepper <drepper@redhat.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'kernel/futex_compat.c')
-rw-r--r--kernel/futex_compat.c19
1 files changed, 9 insertions, 10 deletions
diff --git a/kernel/futex_compat.c b/kernel/futex_compat.c
index 50f24eea6cd0..dff27c471ea6 100644
--- a/kernel/futex_compat.c
+++ b/kernel/futex_compat.c
@@ -141,24 +141,23 @@ asmlinkage long compat_sys_futex(u32 __user *uaddr, int op, u32 val,
141 struct compat_timespec __user *utime, u32 __user *uaddr2, 141 struct compat_timespec __user *utime, u32 __user *uaddr2,
142 u32 val3) 142 u32 val3)
143{ 143{
144 struct timespec t; 144 struct timespec ts;
145 unsigned long timeout = MAX_SCHEDULE_TIMEOUT; 145 ktime_t t, *tp = NULL;
146 int val2 = 0; 146 int val2 = 0;
147 147
148 if (utime && (op == FUTEX_WAIT || op == FUTEX_LOCK_PI)) { 148 if (utime && (op == FUTEX_WAIT || op == FUTEX_LOCK_PI)) {
149 if (get_compat_timespec(&t, utime)) 149 if (get_compat_timespec(&ts, utime))
150 return -EFAULT; 150 return -EFAULT;
151 if (!timespec_valid(&t)) 151 if (!timespec_valid(&ts))
152 return -EINVAL; 152 return -EINVAL;
153
154 t = timespec_to_ktime(ts);
153 if (op == FUTEX_WAIT) 155 if (op == FUTEX_WAIT)
154 timeout = timespec_to_jiffies(&t) + 1; 156 t = ktime_add(ktime_get(), t);
155 else { 157 tp = &t;
156 timeout = t.tv_sec;
157 val2 = t.tv_nsec;
158 }
159 } 158 }
160 if (op == FUTEX_REQUEUE || op == FUTEX_CMP_REQUEUE) 159 if (op == FUTEX_REQUEUE || op == FUTEX_CMP_REQUEUE)
161 val2 = (int) (unsigned long) utime; 160 val2 = (int) (unsigned long) utime;
162 161
163 return do_futex(uaddr, op, val, timeout, uaddr2, val2, val3); 162 return do_futex(uaddr, op, val, tp, uaddr2, val2, val3);
164} 163}