summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authordchagin <dchagin@FreeBSD.org>2016-01-09 15:39:41 +0000
committerdchagin <dchagin@FreeBSD.org>2016-01-09 15:39:41 +0000
commit4ed27590e5c71931347430107294760f55c94b9e (patch)
tree42187ebee28fff7da045c98e90310028b90dae10
parent4992ef5f9de6e092cc93ef0ef6ddd5d9424e101c (diff)
downloadFreeBSD-src-4ed27590e5c71931347430107294760f55c94b9e.zip
FreeBSD-src-4ed27590e5c71931347430107294760f55c94b9e.tar.gz
MFC r283403:
Implement pselect6() system call.
-rw-r--r--sys/amd64/linux32/linux32_dummy.c1
-rw-r--r--sys/amd64/linux32/syscalls.master4
-rw-r--r--sys/compat/linux/linux_misc.c84
-rw-r--r--sys/i386/linux/linux_dummy.c1
-rw-r--r--sys/i386/linux/syscalls.master4
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, &lts, 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(&lts, 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:
OpenPOWER on IntegriCloud