diff options
author | Pierre Peiffer <pierre.peiffer@bull.net> | 2007-05-09 05:35:02 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-05-09 15:30:55 -0400 |
commit | c19384b5b296905d4988c7c684ff540a0f9d65be (patch) | |
tree | 071cfe0855d409d63de80ec1b9b663738efb09de /kernel/futex_compat.c | |
parent | ec92d08292d3e9b0823eba138a4564d2d39f25c7 (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.c | 19 |
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 | } |