Diff below simplifies setjmp(3) and longjmp(3) on sparc64 by not using
sigreturn(2). This basically uses the logic from _setjmp(3) and
_longjmp(3) to save and restore the state (but additionally saves and
restores the signal mask). I believe this may make us lose the
capability to longjmp() out of a signal handler when running on an
alternate stack. But that shouldn't be a big issue since on amd64 we
don't go through extra hoops to support that either.
The setjmp regression tests still pass with this, except for the
setjmp-fpu test which already fails on sparc64 (and amd64).
ok?
Index: libc/arch/sparc64/gen/setjmp.S
===================================================================
RCS file: /cvs/src/lib/libc/arch/sparc64/gen/setjmp.S,v
retrieving revision 1.5
diff -u -p -r1.5 setjmp.S
--- libc/arch/sparc64/gen/setjmp.S 29 Jan 2004 18:56:14 -0000 1.5
+++ libc/arch/sparc64/gen/setjmp.S 26 Apr 2016 13:00:51 -0000
@@ -34,9 +34,7 @@
* SUCH DAMAGE.
*/
-#define _LOCORE
#include <machine/asm.h>
-#include <machine/frame.h>
/*
* C library -- setjmp, longjmp
@@ -45,71 +43,39 @@
* will generate a "return(v)" from
* the last call to
* setjmp(a)
- * by restoring registers from the stack,
- * and a struct sigcontext, see <signal.h>
+ * by restoring the previous context.
+ * The previous signal state is restored.
*/
#include "SYS.h"
#define STACK_T_SZ
ENTRY(setjmp)
- /*
- * We use the part of the sigcontext structure, the sp, pc, and npc
- * fields, for the sigaltstack call so we don't need to get our own
- * stackframe. It won't be filled out till later anyway.
- */
mov %o0, %o3 /* Save our jmp_buf in %o3 */
- stx %sp, [%o3 + 0x08] /* sc.sc_sp = sp (both ours and
caller's) */
- add %o7, 8, %o0
- stx %o0, [%o3 + 0x10] /* sc.sc_pc = return_pc */
- add %o7, 12, %o0
- stx %o0, [%o3 + 0x18] /* sc.sc_npc = return_pc + 4 */
- stx %g0, [%o3 + 0x20] /* sc.sc_psr = (clean psr) */
- stx %fp, [%o3 + 0x28] /* sc.sc_g1 = %fp (misuse, but what the
heck) */
- /* sc.sc_o0 = random(), set in longjmp
*/
-
mov 1, %o0 /* SIG_BLOCK */
- mov SYS_sigprocmask, %g1
+ mov SYS_sigprocmask, %g1
clr %o1 /* sigprocmask(SIG_BLOCK, 0) */
t ST_SYSCALL
+ stx %o0, [%o3 + 0x10]
- st %o0, [%o3 + 0x38] /* sc.sc_mask = current mask; */
-
- mov SYS_sigaltstack, %g1
- clr %o0 /* sigaltstack(NULL, &foo) */
- add %o3, 0x40, %o1 /* (foo being the sigcontext sc_mask) */
- t ST_SYSCALL
-
- lduw [%o3 + 0x40+0x10], %o0 /* foo.ss_flags */
- and %o0, 1, %o1 /* onstack = foo.ss_flags & 1; */
- st %o1, [%o3 + 0x00] /* sc.sc_onstack = current onstack; */
-
- retl /* return 0 */
- clr %o0
+ stx %sp, [%o3 + 0x00] /* store caller's stack pointer */
+ stx %o7, [%o3 + 0x08] /* ... and return pc */
+ retl
+ clr %o0 /* return 0 */
-/*
- * All we need to do here is force sigreturn to load a new stack pointer,
- * new <pc,npc>, and appropriate %o0 return value from the sigcontext built
- * in setjmp. The %i and %l registers will be reloaded from the place to
- * which %sp points, due to sigreturn() semantics (sigreturn does not modify
- * the window pointer in the psr, hence it must force all windows to reload).
- */
ENTRY(longjmp)
save %sp, -CC64FSZ, %sp
- ldx [%i0 + 0x08], %o2 /* make sure sc->sc_sp, sc->sc_fp
nonzero */
- ldx [%i0 + 0x28], %o3
- orcc %o2, %o3, %g0
- bz,pn %xcc, Lbotch
- nop
- movrz %i1, 1, %i1 /* if (v == 0) v = 1; */
- st %i1, [%i0 + 0x34] /* sc.sc_o0 = v; */
- mov SYS_sigreturn, %g1
- mov %i0, %o0
- t ST_SYSCALL /* sigreturn(scp); */
-
-Lbotch:
- /* oops, caller botched it */
- call _C_LABEL(longjmperror)
- nop
- unimp 0
+ flushw
+
+ mov 3, %o0 /* SIG_SETMASK */
+ ldx [%i0 + 0x10], %o1
+ mov SYS_sigprocmask, %g1
+ t ST_SYSCALL
+
+ ldx [%i0 + 0x00], %fp
+ ldx [%i0 + 0x08], %i7
+ mov 1, %i0
+ movrnz %i1, %i1, %i0 ! compute v ? v : 1
+ ret
+ restore