Subject: Performance tweak for m68k signal delivery
To: None <port-m68k@netbsd.org>
From: Jason R Thorpe <thorpej@wasabisystems.com>
List: port-m68k
Date: 07/01/2002 21:22:13
--XF85m9dhOBO43t/C
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline

Folks...

Some of you may have noticed that I'm working on signals, moving
the signal trampoline into libc (see my posts to tech-kern on the
subject).

As part of this, I'd like to make some tweaks to the signal trampolines
of the various ports before the ABI for them gets set in stone.  I've
done this for all but the m68k ports so far.

Attached is a patch to make the kernel directly invoke a signal handler,
rather than bouncing through the signal trampoline.  Now, the trampoline
is used only to return from the signal.  The net result is to save a few
instructions during signal delivery.

The way the patch (is supposed to :-) works: Set up the stack frame so
that it looks to the signal handler like it was called by the signal
trampoline.  The stack frame at the signal handler entry point looks
like this:

		signal context structure
	------------------------------------------------------------
		pointer to sigcontext structure			[12]
		signal specific code				[8]
		signal number					[4]
	SP->	return address (address of signal trampoline)	[0]

When the handler returns, we enter the beginning of the signal trampoline
with a stack that looks like this:

		signal context structure			[12]
		pointer to signal context structure		[8]
		signal specific code				[4]
	SP->	signal number					[0]

...i.e. like the trampoline had pushed the args in the first place.  Then
the trampoline computes the effective address of the sigcontext structure
and moves it into sp@(4) (the first argument slot) and does the sigreturn
trap.

I have one report that this patch doesn't quite work.  However, a similar
trick does work on the i386, and the m68k's calling convention is almost
identical to the i386's, so I'm a little puzzled as to why it would be
broken.

In any case, if there is anyone running -current, or simply willing to
test a -current kernel out with this change, I'd be grateful.  And, if
it does not work, I'd be even more grateful if you could fix the bug :-)

-- 
        -- Jason R. Thorpe <thorpej@wasabisystems.com>

--XF85m9dhOBO43t/C
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename=m68k-sig-patch

Index: include/signal.h
===================================================================
RCS file: /cvsroot/syssrc/sys/arch/m68k/include/signal.h,v
retrieving revision 1.9
diff -c -r1.9 signal.h
*** include/signal.h	2002/06/23 21:31:12	1.9
--- include/signal.h	2002/07/02 04:05:13
***************
*** 95,109 ****
  
  /*
   * Stack frame layout when delivering a signal.
-  *
-  * WARNING: code in locore.s assumes the layout shown for sf_signum
-  * thru sf_handler, so... don't screw with them!
   */
  struct sigframe {
  	int	sf_signum;		/* signal number for handler */
  	int	sf_code;		/* additional info for handler */
  	struct sigcontext *sf_scp;	/* context pointer for handler */
- 	sig_t	sf_handler;		/* handler address for u_sigc */
  	struct sigcontext sf_sc;	/* actual context */
  	struct sigstate sf_state;	/* state of the hardware */
  };
--- 95,106 ----
  
  /*
   * Stack frame layout when delivering a signal.
   */
  struct sigframe {
+ 	int	sf_ra;			/* handler return address */
  	int	sf_signum;		/* signal number for handler */
  	int	sf_code;		/* additional info for handler */
  	struct sigcontext *sf_scp;	/* context pointer for handler */
  	struct sigcontext sf_sc;	/* actual context */
  	struct sigstate sf_state;	/* state of the hardware */
  };
Index: m68k/sig_machdep.c
===================================================================
RCS file: /cvsroot/syssrc/sys/arch/m68k/m68k/sig_machdep.c,v
retrieving revision 1.15
diff -c -r1.15 sig_machdep.c
*** m68k/sig_machdep.c	2001/07/28 13:08:34	1.15
--- m68k/sig_machdep.c	2002/07/02 04:05:14
***************
*** 112,121 ****
  #endif
  
  	/* Build stack frame for signal trampoline. */
  	kf.sf_signum = sig;
  	kf.sf_code = code;
  	kf.sf_scp = &fp->sf_sc;
- 	kf.sf_handler = catcher;
  
  	/*
  	 * Save necessary hardware state.  Currently this includes:
--- 112,121 ----
  #endif
  
  	/* Build stack frame for signal trampoline. */
+ 	kf.sf_ra = (int)p->p_sigctx.ps_sigcode;
  	kf.sf_signum = sig;
  	kf.sf_code = code;
  	kf.sf_scp = &fp->sf_sc;
  
  	/*
  	 * Save necessary hardware state.  Currently this includes:
***************
*** 209,217 ****
  		       kf.sf_sc.sc_sp, kf.sf_sc.sc_ap);
  #endif
  
! 	/* Set up the registers to return to sigcode. */
  	frame->f_regs[SP] = (int)fp;
! 	frame->f_pc = (int)p->p_sigctx.ps_sigcode;
  
  	/* Remember that we're now on the signal stack. */
  	if (onstack)
--- 209,220 ----
  		       kf.sf_sc.sc_sp, kf.sf_sc.sc_ap);
  #endif
  
! 	/*
! 	 * Set up the registers to return to the signal handler.  The
! 	 * handler will then return to the signal trampoline.
! 	 */
  	frame->f_regs[SP] = (int)fp;
! 	frame->f_pc = (int)catcher;
  
  	/* Remember that we're now on the signal stack. */
  	if (onstack)
Index: m68k/sigcode.s
===================================================================
RCS file: /cvsroot/syssrc/sys/arch/m68k/m68k/sigcode.s,v
retrieving revision 1.10
diff -c -r1.10 sigcode.s
*** m68k/sigcode.s	2000/11/26 11:47:25	1.10
--- m68k/sigcode.s	2002/07/02 04:05:14
***************
*** 50,79 ****
   */
  
  /*
!  * Signal "trampoline" code (18 bytes).  Invoked from RTE setup by sendsig().
   *
!  * Stack looks like:
   *
!  *	sp+0	->	signal number
!  *	sp+4		signal specific code
!  *	sp+8		pointer to signal context frame (scp)
!  *	sp+12		address of handler
!  *	sp+16		saved hardware state
!  *				.
!  *				.
!  *				.
!  *	scp+0	->	beginning of signal context frame
   */
  
  	.data
  	.align	2
  GLOBAL(sigcode)
! 	movl	%sp@(12),%a0	| signal handler addr		(4 bytes)
! 	jsr	%a0@		| call signal handler		(2 bytes)
! 	addql	#4,%sp		| pop signal number		(2 bytes)
! 	trap	#3		| special sigreturn trap	(2 bytes)
! 	movl	%d0,%sp@(4)	| save errno			(4 bytes)
! 	moveq	#SYS_exit,%d0	| syscall == exit		(2 bytes)
! 	trap	#0		| exit(errno)			(2 bytes)
  	.align	2
  GLOBAL(esigcode)
--- 50,76 ----
   */
  
  /*
!  * Signal trampoline; copied to top of user stack.
   *
!  * The handler has returned here as if we had called it.  On
!  * entry, the stack looks like:
   *
!  *		sigcontext structure			[12]
!  *		pointer to sigcontext structure		[8]
!  *		signal specific code			[4]
!  *	sp->	signal number				[0]
   */
  
  	.data
  	.align	2
  GLOBAL(sigcode)
! 	leal	%sp@(12),%a0	/* get pointer to sigcontext */
! 	movl	%a0,%sp@(4)	/* put it in the argument slot */
! 				/* fake return address already there */
! 	trap	#3		/* special sigreturn trap */
! 	movl	%d0,%sp@(4)	/* exit with errno */
! 	moveq	#SYS_exit,%d0	/* if sigreturn fails */
! 	trap	#0
! 
  	.align	2
  GLOBAL(esigcode)

--XF85m9dhOBO43t/C--