diff options
Diffstat (limited to 'usr/src/lib/libc')
-rw-r--r-- | usr/src/lib/libc/amd64/gen/siglongjmp.c | 4 | ||||
-rw-r--r-- | usr/src/lib/libc/amd64/threads/asm_subr.s | 8 | ||||
-rw-r--r-- | usr/src/lib/libc/amd64/threads/machdep.c | 6 | ||||
-rw-r--r-- | usr/src/lib/libc/inc/sigjmp_struct.h | 15 |
4 files changed, 26 insertions, 7 deletions
diff --git a/usr/src/lib/libc/amd64/gen/siglongjmp.c b/usr/src/lib/libc/amd64/gen/siglongjmp.c index d71f40a034..dda4c945d6 100644 --- a/usr/src/lib/libc/amd64/gen/siglongjmp.c +++ b/usr/src/lib/libc/amd64/gen/siglongjmp.c @@ -29,6 +29,7 @@ #include <sys/ucontext.h> #include <setjmp.h> #include <ucontext.h> +#include "sigjmp_struct.h" #include "libc.h" #pragma weak _siglongjmp = siglongjmp @@ -36,8 +37,7 @@ void siglongjmp(sigjmp_buf env, int val) { - /* LINTED alignment */ - ucontext_t *ucp = (ucontext_t *)env; + ucontext_t *ucp = SIGJMP2UCONTEXT(env); if (val) ucp->uc_mcontext.gregs[REG_R0] = val; diff --git a/usr/src/lib/libc/amd64/threads/asm_subr.s b/usr/src/lib/libc/amd64/threads/asm_subr.s index 9feef4a2e2..3898e9c6e6 100644 --- a/usr/src/lib/libc/amd64/threads/asm_subr.s +++ b/usr/src/lib/libc/amd64/threads/asm_subr.s @@ -104,7 +104,11 @@ __sighndlrend: #undef sigsetjmp -#if SIZEOF_SIGJMP_BUF < SIZEOF_UCONTEXT_T +/* + * Ensure that a "ucontext_t" will fit within a "sigjmp_buf", including the + * extra 8 bytes we may need for correct alignment on AMD64. + */ +#if SIZEOF_SIGJMP_BUF - _LONG_ALIGNMENT < SIZEOF_UCONTEXT_T #error "sigjmp_buf is too small to contain a ucontext_t" @@ -171,4 +175,4 @@ __sighndlrend: SET_SIZE(sigsetjmp) SET_SIZE(_sigsetjmp) -#endif /* SIZEOF_SIGJMP_BUF < SIZEOF_UCONTEXT_T */ +#endif /* SIZEOF_SIGJMP_BUF - _LONG_ALIGNMENT < SIZEOF_UCONTEXT_T */ diff --git a/usr/src/lib/libc/amd64/threads/machdep.c b/usr/src/lib/libc/amd64/threads/machdep.c index b1638e0b31..81b8ee37ec 100644 --- a/usr/src/lib/libc/amd64/threads/machdep.c +++ b/usr/src/lib/libc/amd64/threads/machdep.c @@ -28,6 +28,7 @@ #include <procfs.h> #include <ucontext.h> #include <setjmp.h> +#include "sigjmp_struct.h" extern int getlwpstatus(thread_t, lwpstatus_t *); extern int putlwpregs(thread_t, prgregset_t); @@ -66,7 +67,7 @@ setup_top_frame(void *stk, size_t stksize, ulwp_t *ulwp) int setup_context(ucontext_t *ucp, void *(*func)(ulwp_t *), - ulwp_t *ulwp, caddr_t stk, size_t stksize) + ulwp_t *ulwp, caddr_t stk, size_t stksize) { uint64_t *stack; @@ -172,8 +173,7 @@ setgregs(ulwp_t *ulwp, gregset_t rs) int __csigsetjmp(sigjmp_buf env, int savemask, gregset_t rs) { - /* LINTED alignment */ - ucontext_t *ucp = (ucontext_t *)env; + ucontext_t *ucp = SIGJMP2UCONTEXT(env); ulwp_t *self = curthread; ucp->uc_link = self->ul_siglink; diff --git a/usr/src/lib/libc/inc/sigjmp_struct.h b/usr/src/lib/libc/inc/sigjmp_struct.h index 988e6ca14c..7d347c2d3c 100644 --- a/usr/src/lib/libc/inc/sigjmp_struct.h +++ b/usr/src/lib/libc/inc/sigjmp_struct.h @@ -32,6 +32,7 @@ extern "C" { #include <sys/types.h> #include <sys/stack.h> +#include <sys/sysmacros.h> #include <ucontext.h> #include <setjmp.h> @@ -73,6 +74,20 @@ typedef struct { #endif /* __sparc */ +#if defined(__amd64) +/* + * The "sigjmp_buf" type is an array of long and thus can have 8-byte alignment + * on AMD64 systems. The "ucontext_t" type has a stricter 16-byte alignment + * requirement, so we must round the pointer up when casting. + * + * This is not required on other architectures: + * - SPARC does not store the ucontext_t in the sigjmp_buf + * - i386 only requires 4-byte alignment for ucontext_t + */ +#define SIGJMP2UCONTEXT(x) \ + ((ucontext_t *)P2ROUNDUP((uintptr_t)(x), sizeof (upad128_t))) +#endif + #ifdef __cplusplus } #endif |