diff options
author | Bryan Cantrill <bryan@joyent.com> | 2014-05-07 07:25:58 +0000 |
---|---|---|
committer | Bryan Cantrill <bryan@joyent.com> | 2014-05-07 07:25:58 +0000 |
commit | 06f5aa053f25bcef3d424c79eaeee748c3d29b9d (patch) | |
tree | 0ed0fb50f274780e762000a57c2b587bcef757f2 | |
parent | bc64171bf6edb0a45ff6b5dff70f344218c2fd38 (diff) | |
download | illumos-joyent-06f5aa053f25bcef3d424c79eaeee748c3d29b9d.tar.gz |
OS-2987 lx brand needs to support pselect6()
-rw-r--r-- | usr/src/lib/brand/lx/lx_brand/common/lx_brand.c | 7 | ||||
-rw-r--r-- | usr/src/lib/brand/lx/lx_brand/common/poll_select.c | 7 | ||||
-rw-r--r-- | usr/src/lib/brand/lx/lx_brand/common/signal.c | 108 | ||||
-rw-r--r-- | usr/src/lib/brand/lx/lx_brand/sys/lx_syscall.h | 7 |
4 files changed, 122 insertions, 7 deletions
diff --git a/usr/src/lib/brand/lx/lx_brand/common/lx_brand.c b/usr/src/lib/brand/lx/lx_brand/common/lx_brand.c index 64a6fcebd0..7758ec867a 100644 --- a/usr/src/lib/brand/lx/lx_brand/common/lx_brand.c +++ b/usr/src/lib/brand/lx/lx_brand/common/lx_brand.c @@ -22,7 +22,10 @@ /* * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. - * Copyright 2014 Joyent, Inc. All rights reserved. + */ + +/* + * Copyright (c) 2014, Joyent, Inc. All rights reserved. */ #include <sys/types.h> @@ -1224,7 +1227,7 @@ static struct lx_sysent sysents[] = { {"readlinkat", lx_readlinkat, 0, 4}, /* 305 */ {"fchmodat", lx_fchmodat, 0, 4}, /* 306 */ {"faccessat", lx_faccessat, 0, 4}, /* 307 */ - {"pselect6", NULL, NOSYS_NULL, 0}, /* 308 */ + {"pselect6", lx_pselect6, EBP_HAS_ARG6, 6}, /* 308 */ {"ppoll", NULL, NOSYS_NULL, 0}, /* 309 */ {"unshare", NULL, NOSYS_NULL, 0}, /* 310 */ {"set_robust_list", NULL, NOSYS_NULL, 0}, /* 311 */ diff --git a/usr/src/lib/brand/lx/lx_brand/common/poll_select.c b/usr/src/lib/brand/lx/lx_brand/common/poll_select.c index 5eba21c652..7d7ee9f0aa 100644 --- a/usr/src/lib/brand/lx/lx_brand/common/poll_select.c +++ b/usr/src/lib/brand/lx/lx_brand/common/poll_select.c @@ -24,7 +24,9 @@ * Use is subject to license terms. */ -#pragma ident "%Z%%M% %I% %E% SMI" +/* + * Copyright (c) 2014, Joyent, Inc. All rights reserved. + */ #include <assert.h> #include <unistd.h> @@ -61,8 +63,7 @@ lx_select(uintptr_t p1, uintptr_t p2, uintptr_t p3, uintptr_t p4, int r; hrtime_t start = NULL, end; - lx_debug("\tselect(%d, 0x%p, x%p, 0x%p. 0x%p, 0x%p)", - nfds, rfdsp, wfdsp, efdsp, tvp); + lx_debug("\tselect(%d, 0x%p, 0x%p, 0x%p, 0x%p)", p1, p2, p3, p4, p5); if (nfds > 0) { if (p2 != NULL) { diff --git a/usr/src/lib/brand/lx/lx_brand/common/signal.c b/usr/src/lib/brand/lx/lx_brand/common/signal.c index b6fea626b7..1b7c6f90fb 100644 --- a/usr/src/lib/brand/lx/lx_brand/common/signal.c +++ b/usr/src/lib/brand/lx/lx_brand/common/signal.c @@ -24,7 +24,9 @@ * Use is subject to license terms. */ -#pragma ident "%Z%%M% %I% %E% SMI" +/* + * Copyright (c) 2014, Joyent, Inc. All rights reserved. + */ #include <sys/types.h> #include <sys/param.h> @@ -49,6 +51,9 @@ #include <libintl.h> #include <ieeefp.h> +extern int pselect_large_fdset(int nfds, fd_set *in0, fd_set *out0, fd_set *ex0, + const timespec_t *tsp, const sigset_t *sp); + /* * Delivering signals to a Linux process is complicated by differences in * signal numbering, stack structure and contents, and the action taken when a @@ -1712,3 +1717,104 @@ lx_siginit(void) lx_debug("interposition handler setup for SIGPWR"); return (0); } + +/* + * This code stongly resemebles lx_select(), but is here to be able to take + * advantage of the Linux signal helper routines. + */ +int +lx_pselect6(uintptr_t p1, uintptr_t p2, uintptr_t p3, uintptr_t p4, + uintptr_t p5, uintptr_t p6) +{ + int nfds = (int)p1; + fd_set *rfdsp = NULL; + fd_set *wfdsp = NULL; + fd_set *efdsp = NULL; + timespec_t ts, *tsp = NULL; + int fd_set_len = howmany(nfds, 8); + int r; + sigset_t sigset, *sp = NULL; + + lx_debug("\tpselect6(%d, 0x%p, 0x%p, 0x%p, 0x%p, 0x%p)", + p1, p2, p3, p4, p4, p6); + + if (nfds > 0) { + if (p2 != NULL) { + rfdsp = SAFE_ALLOCA(fd_set_len); + if (rfdsp == NULL) + return (-ENOMEM); + if (uucopy((void *)p2, rfdsp, fd_set_len) != 0) + return (-errno); + } + if (p3 != NULL) { + wfdsp = SAFE_ALLOCA(fd_set_len); + if (wfdsp == NULL) + return (-ENOMEM); + if (uucopy((void *)p3, wfdsp, fd_set_len) != 0) + return (-errno); + } + if (p4 != NULL) { + efdsp = SAFE_ALLOCA(fd_set_len); + if (efdsp == NULL) + return (-ENOMEM); + if (uucopy((void *)p4, efdsp, fd_set_len) != 0) + return (-errno); + } + } + + if (p5 != NULL) { + if (uucopy((void *)p5, &ts, sizeof (ts)) != 0) + return (-errno); + + tsp = &ts; + } + + if (p6 != NULL) { + /* + * To force the number of arguments to be no more than six, + * Linux bundles both the sigset and the size into a structure + * that becomes the sixth argument. + */ + struct { + lx_sigset_t *addr; + size_t size; + } lx_sigset; + + if (uucopy((void *)p6, &lx_sigset, sizeof (lx_sigset)) != 0) + return (-errno); + + /* + * Yes, that's right: Linux forces a size to be passed only + * so it can check that it's the size of a sigset_t. + */ + if (lx_sigset.size != sizeof (lx_sigset_t)) + return (-EINVAL); + + if ((r = ltos_sigset(lx_sigset.addr, &sigset)) != 0) + return (r); + + sp = &sigset; + } + + if (nfds >= FD_SETSIZE) + r = pselect_large_fdset(nfds, rfdsp, wfdsp, efdsp, tsp, sp); + else + r = pselect(nfds, rfdsp, wfdsp, efdsp, tsp, sp); + + if (r < 0) + return (-errno); + + /* + * For pselect6(), we don't honor the strange Linux select() semantics + * with respect to the timestruc parameter because glibc ignores it + * anyway -- just copy out the fd pointers and return. + */ + if ((rfdsp != NULL) && (uucopy(rfdsp, (void *)p2, fd_set_len) != 0)) + return (-errno); + if ((wfdsp != NULL) && (uucopy(wfdsp, (void *)p3, fd_set_len) != 0)) + return (-errno); + if ((efdsp != NULL) && (uucopy(efdsp, (void *)p4, fd_set_len) != 0)) + return (-errno); + + return (r); +} diff --git a/usr/src/lib/brand/lx/lx_brand/sys/lx_syscall.h b/usr/src/lib/brand/lx/lx_brand/sys/lx_syscall.h index a6e061c42d..574d8eab6d 100644 --- a/usr/src/lib/brand/lx/lx_brand/sys/lx_syscall.h +++ b/usr/src/lib/brand/lx/lx_brand/sys/lx_syscall.h @@ -22,7 +22,10 @@ /* * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. - * Copyright 2014 Joyent, Inc. All rights reserved. + */ + +/* + * Copyright (c) 2014, Joyent, Inc. All rights reserved. */ #ifndef _SYS_LX_SYSCALL_H @@ -80,6 +83,8 @@ extern int lx_pwrite64(uintptr_t, uintptr_t, uintptr_t, uintptr_t, uintptr_t); extern int lx_socketcall(uintptr_t, uintptr_t); extern int lx_select(uintptr_t, uintptr_t, uintptr_t, uintptr_t, uintptr_t); +extern int lx_pselect6(uintptr_t, uintptr_t, uintptr_t, uintptr_t, + uintptr_t, uintptr_t); extern int lx_poll(uintptr_t, uintptr_t, uintptr_t); extern int lx_oldgetrlimit(uintptr_t, uintptr_t); extern int lx_getrlimit(uintptr_t, uintptr_t); |