jjw@celerity.UUCP (02/27/87)
x From <1881@homxc.UUCP> (sorry, I don't have the poster's name): >>>> The method used has a large effect on whether setjmp/longjmp can put >>>> the correct values back into register variables (SYSVID says they >>>> may be unpredictable :-(. <651@mcgill-vision.UUCP> mouse@mcgill-vision.UUCP: >>WHAT?!?! I can't see any reason that longjmp can't get the registers >>back - if it can't restore them easily on that architecture then just >>have setjmp save them in the jmp_buf! What's the problem? This will >>make longjmp basically useless, especially in the face of compilers >>that optimize non-"register" variables into registers! In <4160@utcsri.UUCP> greg@utcsri.UUCP (Gregory Smith) provides the sample program: >jmp_buf env; > >main(){ > register int i; > int j; > i = j = 1; > if(setjmp(env)){ > printf( "i==%d, j==%d\n", i, j ); > exit(0); > } > i = j = 2; > func(); >} > >func(){ > longjmp( env, 1 ); >} And says: >The above program should ideally report that i=2. Certainly it will say >that j is 2. If i is saved in the jmp_buf, and restored by longjmp, >then i will be reported as 1. Note that for "compilers that optimize non-'register' variables into registers" it can even report that j is 1 unless something is done. Code which relies on this behaviour is not infrequent. The most frequent use seems to be in interactive processes which loop making requests of the user and expect longjmp's out of subroutines which encounter errors. Some of the code in the (BSD 4.2) user commands even requires "ideal" restoration of register variables. The Celerity (RISC-like) architecture provides lots of registers and our compilers do some very heavy optimizing, putting everything in sight into registers, if possible. The possible solutions seem to require that the compiler recognize the setjmp: 1. If a function contains a setjmp it can keep all variables in memory. This can cause these functions to run much slower. 2. If a function contains a setjmp it can save all registers on any subroutine call where they can be picked up by the longjmp. Some architectures (e.g. VAX) provide subroutine call functions which automatically store registers and some compilers store the registers on all subroutine calls where they can be found by longjmp. We chose to save the registers where they can be found by longjmp but only in subroutines which call setjmp. The overhead of saving registers in all cases was felt to be excessive. However, we were faced with the problem of signal handlers which perform longjmp's. Since all registers are saved by the kernel before calling a signal handler it is also necessary for the lonjmp to be able to restore the registers from that saved state. This sounds easier than it is since there are potential "race" conditions involving signal handlers which occur inside setjmp, inside longjmp, or while saving the registers for a subroutine call. ---------- For those familiar with RISC architectures and who are wondering why there is a problem since RISC architectures usually have stackable registers. The Celerity architecture has stackable registers but its fastest registers are not stackable. -- J. J. Whelan Celerity Computing