diff options
author | dchagin <dchagin@FreeBSD.org> | 2016-01-09 17:11:25 +0000 |
---|---|---|
committer | dchagin <dchagin@FreeBSD.org> | 2016-01-09 17:11:25 +0000 |
commit | 0e75fd64e782579dbb101bf9698adbedec1c2806 (patch) | |
tree | 490eeaf3e559443b63b2f3930818e57fdfd2a2ae /sys/compat | |
parent | f9c41e34075d6689e15e9bfd4ff205f852c56d8a (diff) | |
download | FreeBSD-src-0e75fd64e782579dbb101bf9698adbedec1c2806.zip FreeBSD-src-0e75fd64e782579dbb101bf9698adbedec1c2806.tar.gz |
MFC r283463:
Do not use struct l_timespec without conversion. While here move
args->timeout handling before acquiring the futex key at FUTEX_WAIT path.
Diffstat (limited to 'sys/compat')
-rw-r--r-- | sys/compat/linux/linux_futex.c | 67 | ||||
-rw-r--r-- | sys/compat/linux/linux_misc.c | 21 | ||||
-rw-r--r-- | sys/compat/linux/linux_time.c | 9 | ||||
-rw-r--r-- | sys/compat/linux/linux_timer.h | 5 |
4 files changed, 54 insertions, 48 deletions
diff --git a/sys/compat/linux/linux_futex.c b/sys/compat/linux/linux_futex.c index df9c7fd..56275d3 100644 --- a/sys/compat/linux/linux_futex.c +++ b/sys/compat/linux/linux_futex.c @@ -66,6 +66,7 @@ __KERNEL_RCSID(1, "$NetBSD: linux_futex.c,v 1.7 2006/07/24 19:01:49 manu Exp $") #include <compat/linux/linux_dtrace.h> #include <compat/linux/linux_emul.h> #include <compat/linux/linux_futex.h> +#include <compat/linux/linux_timer.h> #include <compat/linux/linux_util.h> /* DTrace init */ @@ -670,7 +671,8 @@ linux_sys_futex(struct thread *td, struct linux_sys_futex_args *args) struct linux_pemuldata *pem; struct waiting_proc *wp; struct futex *f, *f2; - struct l_timespec timeout; + struct l_timespec ltimeout; + struct timespec timeout; struct timeval utv, ctv; int timeout_hz; int error; @@ -714,6 +716,38 @@ linux_sys_futex(struct thread *td, struct linux_sys_futex_args *args) LINUX_CTR3(sys_futex, "WAIT uaddr %p val 0x%x bitset 0x%x", args->uaddr, args->val, args->val3); + if (args->timeout != NULL) { + error = copyin(args->timeout, <imeout, sizeof(ltimeout)); + if (error) { + LIN_SDT_PROBE1(futex, linux_sys_futex, copyin_error, + error); + LIN_SDT_PROBE1(futex, linux_sys_futex, return, error); + return (error); + } + error = linux_to_native_timespec(&timeout, <imeout); + if (error) + return (error); + TIMESPEC_TO_TIMEVAL(&utv, &timeout); + error = itimerfix(&utv); + if (error) { + LIN_SDT_PROBE1(futex, linux_sys_futex, itimerfix_error, + error); + LIN_SDT_PROBE1(futex, linux_sys_futex, return, error); + return (error); + } + if (clockrt) { + microtime(&ctv); + timevalsub(&utv, &ctv); + } else if (args->op == LINUX_FUTEX_WAIT_BITSET) { + microuptime(&ctv); + timevalsub(&utv, &ctv); + } + if (utv.tv_sec < 0) + timevalclear(&utv); + timeout_hz = tvtohz(&utv); + } else + timeout_hz = 0; + error = futex_get(args->uaddr, &wp, &f, flags | FUTEX_CREATE_WP); if (error) { @@ -746,37 +780,6 @@ linux_sys_futex(struct thread *td, struct linux_sys_futex_args *args) return (EWOULDBLOCK); } - if (args->timeout != NULL) { - error = copyin(args->timeout, &timeout, sizeof(timeout)); - if (error) { - LIN_SDT_PROBE1(futex, linux_sys_futex, copyin_error, - error); - LIN_SDT_PROBE1(futex, linux_sys_futex, return, error); - futex_put(f, wp); - return (error); - } - TIMESPEC_TO_TIMEVAL(&utv, &timeout); - error = itimerfix(&utv); - if (error) { - LIN_SDT_PROBE1(futex, linux_sys_futex, itimerfix_error, - error); - LIN_SDT_PROBE1(futex, linux_sys_futex, return, error); - futex_put(f, wp); - return (error); - } - if (clockrt) { - microtime(&ctv); - timevalsub(&utv, &ctv); - } else if (args->op == LINUX_FUTEX_WAIT_BITSET) { - microuptime(&ctv); - timevalsub(&utv, &ctv); - } - if (utv.tv_sec < 0) - timevalclear(&utv); - timeout_hz = tvtohz(&utv); - } else - timeout_hz = 0; - error = futex_wait(f, wp, timeout_hz, args->val3); break; diff --git a/sys/compat/linux/linux_misc.c b/sys/compat/linux/linux_misc.c index 45d6bb2..9806e03 100644 --- a/sys/compat/linux/linux_misc.c +++ b/sys/compat/linux/linux_misc.c @@ -89,6 +89,7 @@ __FBSDID("$FreeBSD$"); #include <compat/linux/linux_file.h> #include <compat/linux/linux_mib.h> #include <compat/linux/linux_signal.h> +#include <compat/linux/linux_timer.h> #include <compat/linux/linux_util.h> #include <compat/linux/linux_sysproto.h> #include <compat/linux/linux_emul.h> @@ -2166,8 +2167,9 @@ linux_pselect6(struct thread *td, struct linux_pselect6_args *args) error = copyin(args->tsp, <s, sizeof(lts)); if (error != 0) return (error); - uts.tv_sec = lts.tv_sec; - uts.tv_nsec = lts.tv_nsec; + error = linux_to_native_timespec(&uts, <s); + if (error != 0) + return (error); TIMESPEC_TO_TIMEVAL(&utv, &uts); if (itimerfix(&utv)) @@ -2199,8 +2201,8 @@ linux_pselect6(struct thread *td, struct linux_pselect6_args *args) timevalclear(&utv); TIMEVAL_TO_TIMESPEC(&utv, &uts); - lts.tv_sec = uts.tv_sec; - lts.tv_nsec = uts.tv_nsec; + + native_to_linux_timespec(<s, &uts); error = copyout(<s, args->tsp, sizeof(lts)); } @@ -2232,8 +2234,9 @@ linux_ppoll(struct thread *td, struct linux_ppoll_args *args) error = copyin(args->tsp, <s, sizeof(lts)); if (error) return (error); - uts.tv_sec = lts.tv_sec; - uts.tv_nsec = lts.tv_nsec; + error = linux_to_native_timespec(&uts, <s); + if (error != 0) + return (error); nanotime(&ts0); tsp = &uts; @@ -2252,8 +2255,7 @@ linux_ppoll(struct thread *td, struct linux_ppoll_args *args) } else timespecclear(&uts); - lts.tv_sec = uts.tv_sec; - lts.tv_nsec = uts.tv_nsec; + native_to_linux_timespec(<s, &uts); error = copyout(<s, args->tsp, sizeof(lts)); } @@ -2341,8 +2343,7 @@ linux_sched_rr_get_interval(struct thread *td, PROC_UNLOCK(tdt->td_proc); if (error != 0) return (error); - lts.tv_sec = ts.tv_sec; - lts.tv_nsec = ts.tv_nsec; + native_to_linux_timespec(<s, &ts); return (copyout(<s, uap->interval, sizeof(lts))); } diff --git a/sys/compat/linux/linux_time.c b/sys/compat/linux/linux_time.c index f658f8e..bffc9b70 100644 --- a/sys/compat/linux/linux_time.c +++ b/sys/compat/linux/linux_time.c @@ -120,13 +120,10 @@ LIN_SDT_PROBE_DEFINE1(time, linux_clock_nanosleep, unsupported_flags, "int"); LIN_SDT_PROBE_DEFINE1(time, linux_clock_nanosleep, unsupported_clockid, "int"); LIN_SDT_PROBE_DEFINE1(time, linux_clock_nanosleep, return, "int"); -static void native_to_linux_timespec(struct l_timespec *, - struct timespec *); -static int linux_to_native_timespec(struct timespec *, - struct l_timespec *); static int linux_to_native_clockid(clockid_t *, clockid_t); -static void + +void native_to_linux_timespec(struct l_timespec *ltp, struct timespec *ntp) { @@ -138,7 +135,7 @@ native_to_linux_timespec(struct l_timespec *ltp, struct timespec *ntp) LIN_SDT_PROBE0(time, native_to_linux_timespec, return); } -static int +int linux_to_native_timespec(struct timespec *ntp, struct l_timespec *ltp) { diff --git a/sys/compat/linux/linux_timer.h b/sys/compat/linux/linux_timer.h index 6067fc8..6ac61ec 100644 --- a/sys/compat/linux/linux_timer.h +++ b/sys/compat/linux/linux_timer.h @@ -111,4 +111,9 @@ struct l_itimerspec { struct l_timespec it_value; }; +void native_to_linux_timespec(struct l_timespec *, + struct timespec *); +int linux_to_native_timespec(struct timespec *, + struct l_timespec *); + #endif /* _LINUX_TIMER_H */ |