diff options
author | dchagin <dchagin@FreeBSD.org> | 2016-01-09 15:39:41 +0000 |
---|---|---|
committer | dchagin <dchagin@FreeBSD.org> | 2016-01-09 15:39:41 +0000 |
commit | 4ed27590e5c71931347430107294760f55c94b9e (patch) | |
tree | 42187ebee28fff7da045c98e90310028b90dae10 | |
parent | 4992ef5f9de6e092cc93ef0ef6ddd5d9424e101c (diff) | |
download | FreeBSD-src-4ed27590e5c71931347430107294760f55c94b9e.zip FreeBSD-src-4ed27590e5c71931347430107294760f55c94b9e.tar.gz |
MFC r283403:
Implement pselect6() system call.
-rw-r--r-- | sys/amd64/linux32/linux32_dummy.c | 1 | ||||
-rw-r--r-- | sys/amd64/linux32/syscalls.master | 4 | ||||
-rw-r--r-- | sys/compat/linux/linux_misc.c | 84 | ||||
-rw-r--r-- | sys/i386/linux/linux_dummy.c | 1 | ||||
-rw-r--r-- | sys/i386/linux/syscalls.master | 4 |
5 files changed, 90 insertions, 4 deletions
diff --git a/sys/amd64/linux32/linux32_dummy.c b/sys/amd64/linux32/linux32_dummy.c index 46bb2a4..b02e113 100644 --- a/sys/amd64/linux32/linux32_dummy.c +++ b/sys/amd64/linux32/linux32_dummy.c @@ -96,7 +96,6 @@ DUMMY(inotify_add_watch); DUMMY(inotify_rm_watch); /* linux 2.6.16: */ DUMMY(migrate_pages); -DUMMY(pselect6); DUMMY(ppoll); DUMMY(unshare); /* linux 2.6.17: */ diff --git a/sys/amd64/linux32/syscalls.master b/sys/amd64/linux32/syscalls.master index a6e19f0..2e936c7 100644 --- a/sys/amd64/linux32/syscalls.master +++ b/sys/amd64/linux32/syscalls.master @@ -508,7 +508,9 @@ 306 AUE_FCHMODAT STD { int linux_fchmodat(l_int dfd, const char *filename, \ l_mode_t mode); } 307 AUE_FACCESSAT STD { int linux_faccessat(l_int dfd, const char *filename, l_int amode, int flag); } -308 AUE_NULL STD { int linux_pselect6(void); } +308 AUE_SELECT STD { int linux_pselect6(l_int nfds, l_fd_set *readfds, \ + l_fd_set *writefds, l_fd_set *exceptfds, \ + struct l_timespec *tsp, l_uintptr_t *sig); } 309 AUE_NULL STD { int linux_ppoll(void); } 310 AUE_NULL STD { int linux_unshare(void); } ; linux 2.6.17: diff --git a/sys/compat/linux/linux_misc.c b/sys/compat/linux/linux_misc.c index e128bb4..21e5bfc 100644 --- a/sys/compat/linux/linux_misc.c +++ b/sys/compat/linux/linux_misc.c @@ -117,6 +117,12 @@ struct l_sysinfo { l_uint mem_unit; char _f[20-2*sizeof(l_long)-sizeof(l_int)]; /* padding */ }; + +struct l_pselect6arg { + l_uintptr_t ss; + l_size_t ss_len; +}; + int linux_sysinfo(struct thread *td, struct linux_sysinfo_args *args) { @@ -2106,6 +2112,84 @@ linux_prlimit64(struct thread *td, struct linux_prlimit64_args *args) } int +linux_pselect6(struct thread *td, struct linux_pselect6_args *args) +{ + struct timeval utv, tv0, tv1, *tvp; + struct l_pselect6arg lpse6; + struct l_timespec lts; + struct timespec uts; + l_sigset_t l_ss; + sigset_t *ssp; + sigset_t ss; + int error; + + ssp = NULL; + if (args->sig != NULL) { + error = copyin(args->sig, &lpse6, sizeof(lpse6)); + if (error != 0) + return (error); + if (lpse6.ss_len != sizeof(l_ss)) + return (EINVAL); + if (lpse6.ss != 0) { + error = copyin(PTRIN(lpse6.ss), &l_ss, + sizeof(l_ss)); + if (error != 0) + return (error); + linux_to_bsd_sigset(&l_ss, &ss); + ssp = &ss; + } + } + + /* + * Currently glibc changes nanosecond number to microsecond. + * This mean losing precision but for now it is hardly seen. + */ + if (args->tsp != NULL) { + error = copyin(args->tsp, <s, sizeof(lts)); + if (error != 0) + return (error); + uts.tv_sec = lts.tv_sec; + uts.tv_nsec = lts.tv_nsec; + + TIMESPEC_TO_TIMEVAL(&utv, &uts); + if (itimerfix(&utv)) + return (EINVAL); + + microtime(&tv0); + tvp = &utv; + } else + tvp = NULL; + + error = kern_pselect(td, args->nfds, args->readfds, args->writefds, + args->exceptfds, tvp, ssp, sizeof(l_int) * 8); + + if (error == 0 && args->tsp != NULL) { + if (td->td_retval[0] != 0) { + /* + * Compute how much time was left of the timeout, + * by subtracting the current time and the time + * before we started the call, and subtracting + * that result from the user-supplied value. + */ + + microtime(&tv1); + timevalsub(&tv1, &tv0); + timevalsub(&utv, &tv1); + if (utv.tv_sec < 0) + timevalclear(&utv); + } else + timevalclear(&utv); + + TIMEVAL_TO_TIMESPEC(&utv, &uts); + lts.tv_sec = uts.tv_sec; + lts.tv_nsec = uts.tv_nsec; + error = copyout(<s, args->tsp, sizeof(lts)); + } + + return (error); +} + +int linux_sched_rr_get_interval(struct thread *td, struct linux_sched_rr_get_interval_args *uap) { diff --git a/sys/i386/linux/linux_dummy.c b/sys/i386/linux/linux_dummy.c index f59ae82..5e64a1f 100644 --- a/sys/i386/linux/linux_dummy.c +++ b/sys/i386/linux/linux_dummy.c @@ -92,7 +92,6 @@ DUMMY(inotify_add_watch); DUMMY(inotify_rm_watch); /* linux 2.6.16: */ DUMMY(migrate_pages); -DUMMY(pselect6); DUMMY(ppoll); DUMMY(unshare); /* linux 2.6.17: */ diff --git a/sys/i386/linux/syscalls.master b/sys/i386/linux/syscalls.master index a947e5a..4455c33 100644 --- a/sys/i386/linux/syscalls.master +++ b/sys/i386/linux/syscalls.master @@ -516,7 +516,9 @@ 306 AUE_FCHMODAT STD { int linux_fchmodat(l_int dfd, const char *filename, \ l_mode_t mode); } 307 AUE_FACCESSAT STD { int linux_faccessat(l_int dfd, const char *filename, l_int amode, l_int flag); } -308 AUE_NULL STD { int linux_pselect6(void); } +308 AUE_SELECT STD { int linux_pselect6(l_int nfds, l_fd_set *readfds, \ + l_fd_set *writefds, l_fd_set *exceptfds, \ + struct l_timespec *tsp, l_uintptr_t *sig); } 309 AUE_NULL STD { int linux_ppoll(void); } 310 AUE_NULL STD { int linux_unshare(void); } ; linux 2.6.17: |