[comp.unix.questions] Re^2: Using sigvec & sigcontext

seindal@skinfaxe.diku.dk (Rene' Seindal) (03/28/89)

chris@mimsy.UUCP (Chris Torek) writes:

> In article <4549@freja.diku.dk> seindal@skinfaxe.diku.dk (Rene' Seindal) writes:

> >On 4.3BSD on Vaxen, the struct sigcontext has the same contents as a
> >``jmp_buf'' (??),

> Not so:

> % egrep jmp_buf /usr/include/setjmp.h
> typedef int jmp_buf[10];
> % egrep sc\|\{\|\} /sys/h/signal.h
> struct	sigvec {
> };
> struct	sigstack {
> };
> struct	sigcontext {
> 	int	sc_onstack;		/* sigstack state to restore */
> 	int	sc_mask;		/* signal mask to restore */
> 	int	sc_sp;			/* sp to restore */
> 	int	sc_fp;			/* fp to restore */
> 	int	sc_ap;			/* ap to restore */
> 	int	sc_pc;			/* pc to restore */
> 	int	sc_ps;			/* psl to restore */
> };

> As you can see, sigcontext is not an array of 10 int's.

I hate to argue with you.  You are right too often :-)

I said same contents, not same type.  A close look at setjmp will reveal that
is only uses the first seven longwords of the jmp_buf, for exactly the values
shown above.  A comment even says "# construct sigcontext"!  jmp_buf is
probably only declared as an array, so people don't have to take the address
themselves. (I am looking in MORE/bsd sources from Mt. Xinu, marked
"@(#)setjmp.s	5.5 (Berkeley) 3/9/86").

> >Even more amusing, the is an undocumented system call (no. 139) in at least
> >4.3 (and 4.2) from Berkeley, Ultrix 2.0, and SunOS 3.X (and 4.0, according to
> >adb.  I haven't tried), which is used by longjmp(3) to restore the saved
> >context.  It takes a jmp_buf/struct sigcontext as the sole argument.  It is a
> >kind of simplified sigreturn(2).  Don't look in sysent for it, since it will
> >probably not be there.

> 139 is (was) the `sigcleanup' syscall, used in 4.2BSD to exit from
> signal handlers, and indeed undocumented.  It did not take *any*
> arguments; rather, it found a sigcontext structure via the user stack
> pointer pushed by the `chmk' trap, an awful and bloody thing to do,
> which is of course why it was fixed in 4.3BSD....

You are right about the argument passing.  It does, however, look the same
from user code.  Code like

	pushl	<addr of sigcontext or a jmp_buf>
	chmk	$139

will do a longjmp (without restoring register contents, as 4.[23] longjmp does).

Syscall 139 still exists in the 4.3 I use (MORE/bsd), even though it isn't
listed in sysent.  Look in the top of syscall().  That is an awful and bloody
thing to do too.  Was it left in only because of longjmp(), which is able to
use sigreturn() instead (more awful and bloody code), or because other
programs depended on it (even more awful and bloody)? 

> I have no idea how SunOS actually handles osigcleanup().

I haven't got sources to SunOS 4.0, but it look like it uses the 4.2 scheme.
It has sigcleanup listed as syscall 139 in sysent, taking no arguments.  The
code for sigcleanup looks similar, fetching a sigcontext pointer from the user
stack, followed by a copyin of the necessary parts of the sigcontext, and
assignment to the saved registers in the user structure.  SunOS hasn't got
sigreturn either, so those parts of the kernel might be from 4.2.

Rene' Seindal (seindal@diku.dk).

chris@mimsy.UUCP (Chris Torek) (03/30/89)

>>In article <4549@freja.diku.dk> seindal@skinfaxe.diku.dk (Rene' Seindal)
wrote:
>>>On 4.3BSD on Vaxen, the struct sigcontext has the same contents as a
>>>``jmp_buf'' (??),

>to which I said
>>Not so:

In article <4557@freja.diku.dk> seindal@skinfaxe.diku.dk (Rene' Seindal)
replies:
>I said same contents, not same type.

Ah: I misinterpreted.

>[setjmp] uses [only] the first seven longwords of the jmp_buf....

Indeed it does.

>jmp_buf is probably only declared as an array, so people don't have
>to take the address themselves.

Historically, jmp_buf has always been an array; and according to the
pANS for C, it must be so.  In fact the array was once used to hold
r6 through r15 (in the days of 4.1BSD), and its size is a holdover.

But the two are not interchangeable, aside from an accident of
implementation (well, of design, in this case).  It is reasonable for
setjmp and longjmp to want to preserve more state than a sigcontext
(register contents, for instance, on 680x0s, where the call frame does
not let you restore registers by unwinding).  Sticking with jmp_bufs
for longjmp and sigcontexts for signals is much safer.

>Syscall 139 still exists in the 4.3 I use (MORE/bsd) ...
(and in 4.3tahoe)
>Was it left in only because of longjmp() ... or because other
>programs depended on it ... ? 

It was left in for backwards compatibility.  4.3BSD-tahoe will still
run most 4.1BSD binaries.  (Exceptions are things using the jobs
library, and things using vread and/or vwrite.  There may be others.)
-- 
In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7163)
Domain:	chris@mimsy.umd.edu	Path:	uunet!mimsy!chris

guy@auspex.UUCP (Guy Harris) (03/31/89)

>I said same contents, not same type.  A close look at setjmp will reveal that
>is only uses the first seven longwords of the jmp_buf, for exactly the values
>shown above.  A comment even says "# construct sigcontext"!  jmp_buf is
>probably only declared as an array, so people don't have to take the address
>themselves.

Well, it's declared as an array because it antedates "struct
sigcontext", because it was done that way in good old V7, and because
you're supposed to use the name of the "jmp_buf" in calls to "setjmp",
which means that, since C generally supports call-by-value, the value
had better be a pointer into the "jmp_buf", which means that (unless
"setjmp" is a macro - which the dpANS for C says it must be - *and*
inserts the "&" for you), "jmp_buf" must be an array (in fact, said
dpANS says it's an array).

>> 139 is (was) the `sigcleanup' syscall, used in 4.2BSD to exit from
>> signal handlers, and indeed undocumented.  It did not take *any*
>> arguments; rather, it found a sigcontext structure via the user stack
>> pointer pushed by the `chmk' trap, an awful and bloody thing to do,
>> which is of course why it was fixed in 4.3BSD....
>
>You are right about the argument passing.  It does, however, look the same
>from user code.  Code like
>
>	pushl	<addr of sigcontext or a jmp_buf>
>	chmk	$139
>
>will do a longjmp (without restoring register contents, as 4.[23]
>longjmp does).

Which isn't quite the same as "finding the structure via the user stack
pointer pushed by the 'chmk' trap"; I read that as meaning that no
explicit argument is provided, and that the structure is assumed to be
at a specific location on the stack.  Instead, "syscall 139" *does* take
an argument; it just happens to be passed a little differently.

Given that neither it nor "sigreturn" are, in general, usable from
machine-independent code ("sigreturn" doesn't load up all the registers,
which means you need machine-dependent glue around it anyway, if you
want something that amounts to a "machine-independent user-mode context
switch" call), I don't see this as being particularly awful or bloody.

There *was* some problem with the 4.2BSD "syscall 139"; I don't remember
what it was, but as I remember it did *not* exist in the SunOS "syscall
139".

>Syscall 139 still exists in the 4.3 I use (MORE/bsd), even though it isn't
>listed in sysent.  Look in the top of syscall().  That is an awful and bloody
>thing to do too.  Was it left in only because of longjmp(), which is able to
>use sigreturn() instead (more awful and bloody code), or because other
>programs depended on it (even more awful and bloody)? 

"longjmp" in 4.3 *does* use "sigreturn".  I presume it was left in so
that 4.2BSD binaries would continue to run.

>I haven't got sources to SunOS 4.0, but it look like it uses the 4.2 scheme.
>It has sigcleanup listed as syscall 139 in sysent, taking no arguments.  The
>code for sigcleanup looks similar, fetching a sigcontext pointer from the user
>stack, followed by a copyin of the necessary parts of the sigcontext, and
>assignment to the saved registers in the user structure.  SunOS hasn't got
>sigreturn either, so those parts of the kernel might be from 4.2.

SunOS doesn't have "sigreturn" because it didn't need it; as indicated,
"sigreturn" isn't a machine-independent interface to a general "context
switch" function, and since making such a function out of "sigreturn"
would require additional machine-language glue to load up the other
registers anyway, it wasn't deemed worth adding as a "real" system call. 
That part of the kernel isn't from 4.2, though, except on those versions
of SunOS 3.0 ported to the VAX - neither VAX nor Tahoe code works as is
on the 68K, the 80386, or the SPARC....