Re: setjmp/longjmp implementations

chase@Think.COM (David Chase)
Wed, 16 Feb 1994 16:49:05 GMT

          From comp.compilers

Related articles
setjmp/longjmp implementations hbaker@netcom.com (1994-02-16)
Re: setjmp/longjmp implementations chase@Think.COM (1994-02-16)
Re: setjmp/longjmp implementations pardo@cs.washington.edu (1994-02-17)
Threads (WAS: setjmp/longjmp implementations) pardo@cs.washington.edu (1994-02-17)
| List of all articles for this month |

Newsgroups: comp.compilers
From: chase@Think.COM (David Chase)
Keywords: C, optimize, comment
Organization: Thinking Machines Corporation, Cambridge MA, USA
References: 94-02-097
Date: Wed, 16 Feb 1994 16:49:05 GMT

hbaker@netcom.com (Henry G. Baker) writes:
|> I have been working on a portable program in which longjmp is executed
|> frequently enough to be a possible bottleneck. I was wondering about the
|> efficiency of existing implementations.


|> Do setjmp or longjmp occur in any of the standard -- e.g., SPEC --
|> benchmarks?


Yes. 072.sc is one that comes to mind.


|> Do compiler writers stay up nights worrying about the speed of their
|> implementation?


Yes, sort of. In the case of 072.sc, attention is paid to what library
setjmp is obtained from, and whether or not it has the signal-preserving
behavior (which is unnecessary for that benchmark, I think, and takes more
time). On the other hand, compiler writers are not always responsible for
writing setjmp and longjmp (this may be a mistake).


|> Has anyone ever lost a sale due to poor setjmp/longjmp performance?


Don't know, probably couldn't say if I did.


|> Do compilers even notice when setjmp or longjmp occur in their programs?
|> E.g., the statement after longjmp isn't likely to be executed if it
|> doesn't have a label.


Yes. setjmp is death on flow analysis and register allocation, depending
upon what behavior you want to support in your compiler (the standards let
you get pretty sloppy, but not all implementations are that sloppy).


|> Are any longjmp's open-coded?


Don't know.


|> Does anyone know how fast his implementation of setjmp or longjmp is?


Not in real live numbers, but I do know that there is not a heck of a lot
of code in a Sparc "setjmp" and the major expense of a Sparc "longjmp" is
a flush-register-windows trap.


|> Apparently, longjmp implementations which checked for jumping 'up' the
|> stack were criticized by those using setjmp/longjmp for stack switching in
|> a multiple process environment.


Grumble. setjmp and longjmp are setjmp and longjmp. As I said at least
once before, since you had to write assembly language in the first place
to set up the stack to switch to, you might as well also write the
"switch_stack" code yourself to, rather than depending upon unportable
assumptions about the behavior of library routines.


For sparc, switch_stack(T here, T there) looks something like:


    typedef struct { int fp, pc; } * T;


_switch_stack: ! 4.x
switch_stack: ! Solaris 2.x


    save %sp,-96,%sp
    ta 3 ! I think it is 3 to flush the windows
    st %i6,[%i0]
    st %i7,[%i0+4]
    ld %i6,[%i1]
    ld %i7,[%i1+4]
    ret
    restore


which isn't much code at all, which is why I get so ticked off. Note that
this code doesn't preserve a thread's signal state, and there may be
additional state to preserve as well, but that can be taken care of in a C
wrapper.


|> A related question is whether global statics have to be declared
|> 'volatile'. The ANSI document gives the impression that one doesn't have
|> to do this, but implementations that care about such things seem to die if
|> static globals are not declared 'volatile'.


You don't have to do this, as long as there are no longjmp-transfers of
control. Otherwise, maybe. Writes to globals and statics should be
ordered w.r.t. procedure calls, assuming no interprocedural analysis,
because a foreign procedure could always call main. Where you get into
trouble is when you want two writes to be ordered with respect to some
external or unusual ("* (int *) 17 = 0;") event -- then, both assignments
should be volatile. It isn't necessarily the case that you must make the
variable itself volatile, if there are only certain assignments that you
care about. You can use casts on a case-by-case basis, as in:


    (* (volatile int *) &x)++; /* x is incremented */
    (* (volatile int *) &y)++; /* before y is incremented */


(I think I got the volatiles in the right place.)


David Chase, Thinking Machines Corp.
[The standard says that volatile local variables have to be restored properly
by longjmp. Does this cause trouble in practice, or is it sufficient to
store them into the stack frame on a call. -John]
--


Post a followup to this message

Return to the comp.compilers page.
Search the comp.compilers archives again.