diff options
author | Andrew Morton <akpm@osdl.org> | 2006-02-11 20:55:52 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-02-12 00:41:11 -0500 |
commit | 643a654540579b0dcc7a206a4a7475276a41aff0 (patch) | |
tree | e31d40e4362e4dc7823b7290c0de2a9353d3d117 /include/linux/compat.h | |
parent | 33042a9ff4d126ba944b9dc3076665a2029e0a34 (diff) |
[PATCH] select: fix returned timeval
With David Woodhouse <dwmw2@infradead.org>
select() presently has a habit of increasing the value of the user's
`timeout' argument on return.
We were writing back a timeout larger than the original. We _deliberately_
round up, since we know we must wait at _least_ as long as the caller asks
us to.
The patch adds a couple of helper functions for magnitude comparison of
timespecs and of timevals, and uses them to prevent the various poll and
select functions from returning a timeout which is larger than the one which
was passed in.
The patch also fixes a bug in compat_sys_pselect7(): it was adding the new
timeout value to the old one and was returning that. It should just return
the new timeout value.
(We have various handy timespec/timeval-to-from-nsec conversion functions in
time.h. But this code open-codes it all).
Cc: "David S. Miller" <davem@davemloft.net>
Cc: Andi Kleen <ak@muc.de>
Cc: Ulrich Drepper <drepper@redhat.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: george anzinger <george@mvista.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'include/linux/compat.h')
-rw-r--r-- | include/linux/compat.h | 20 |
1 files changed, 20 insertions, 0 deletions
diff --git a/include/linux/compat.h b/include/linux/compat.h index f9ca534787e2..c9ab2a26348c 100644 --- a/include/linux/compat.h +++ b/include/linux/compat.h | |||
@@ -161,5 +161,25 @@ int copy_siginfo_to_user32(struct compat_siginfo __user *to, siginfo_t *from); | |||
161 | int get_compat_sigevent(struct sigevent *event, | 161 | int get_compat_sigevent(struct sigevent *event, |
162 | const struct compat_sigevent __user *u_event); | 162 | const struct compat_sigevent __user *u_event); |
163 | 163 | ||
164 | static inline int compat_timeval_compare(struct compat_timeval *lhs, | ||
165 | struct compat_timeval *rhs) | ||
166 | { | ||
167 | if (lhs->tv_sec < rhs->tv_sec) | ||
168 | return -1; | ||
169 | if (lhs->tv_sec > rhs->tv_sec) | ||
170 | return 1; | ||
171 | return lhs->tv_usec - rhs->tv_usec; | ||
172 | } | ||
173 | |||
174 | static inline int compat_timespec_compare(struct compat_timespec *lhs, | ||
175 | struct compat_timespec *rhs) | ||
176 | { | ||
177 | if (lhs->tv_sec < rhs->tv_sec) | ||
178 | return -1; | ||
179 | if (lhs->tv_sec > rhs->tv_sec) | ||
180 | return 1; | ||
181 | return lhs->tv_nsec - rhs->tv_nsec; | ||
182 | } | ||
183 | |||
164 | #endif /* CONFIG_COMPAT */ | 184 | #endif /* CONFIG_COMPAT */ |
165 | #endif /* _LINUX_COMPAT_H */ | 185 | #endif /* _LINUX_COMPAT_H */ |