Setjmp/longjmp updates and cleanup.

This commit is contained in:
David van Moolenbroek
2006-12-08 16:23:18 +00:00
parent 170a72fd61
commit d4e6fe3546
16 changed files with 232 additions and 345 deletions

View File

@@ -1,87 +0,0 @@
/* This file is intended for use by assembly language programs that
* need to manipulate a jmp_buf. It may only be used by those systems
* for which a jmp_buf is identical to a struct sigcontext.
*/
#ifndef _JMP_BUF_H
#define _JMP_BUF_H
#if !defined(CHIP)
#include "error, configuration is not known"
#endif
#if (CHIP == INTEL)
#if _WORD_SIZE == 4
#define JB_FLAGS 0
#define JB_MASK 4
#define JB_GS 8
#define JB_FS 10
#define JB_ES 12
#define JB_DS 14
#define JB_DI 16
#define JB_SI 20
#define JB_BP 24
#define JB_ST 28
#define JB_BX 32
#define JB_DX 36
#define JB_CX 40
#define JB_AX 44
#define JB_RETADR 48
#define JB_IP 52
#define JB_CS 56
#define JB_PSW 60
#define JB_SP 64
#define JB_SS 68
#else /* _WORD_SIZE == 2 */
#define JB_FLAGS 0
#define JB_MASK 2
#define JB_ES 6
#define JB_DS 8
#define JB_DI 10
#define JB_SI 12
#define JB_BP 14
#define JB_ST 16
#define JB_BX 18
#define JB_DX 20
#define JB_CX 22
#define JB_AX 24
#define JB_RETADR 26
#define JB_IP 28
#define JB_CS 30
#define JB_PSW 32
#define JB_SP 34
#define JB_SS 36
#endif /* _WORD_SIZE == 2 */
#else /* !(CHIP == INTEL) */
#if (CHIP == M68000)
#define JB_FLAGS 0
#define JB_MASK 2
#define JB_RETREG 6
#define JB_D1 10
#define JB_D2 14
#define JB_D3 18
#define JB_D4 22
#define JB_D5 26
#define JB_D6 20
#define JB_D7 34
#define JB_A0 38
#define JB_A1 42
#define JB_A2 46
#define JB_A3 50
#define JB_A4 54
#define JB_A5 58
#define JB_A6 62
#define JB_SP 66
#define JB_PC 70
#define JB_PSW 74
#else /* !(CHIP == INTEL) && !(CHIP == M68000) */
#include "error, CHIP is not supported"
#endif /* (CHIP == INTEL) */
/* Defines from C headers needed in assembly code. The headers have too
* much C stuff to used directly.
*/
#define SIG_BLOCK 0 /* must agree with <signal.h> */
#define SC_SIGCONTEXT 2 /* must agree with <sys/sigcontext.h> */
#define SC_NOREGLOCALS 4 /* must agree with <sys/sigcontext.h> */
#endif /* _JMP_BUF_H */

View File

@@ -1,67 +1,51 @@
/* The <setjmp.h> header relates to the C phenomenon known as setjmp/longjmp.
* It is used to escape out of the current situation into a previous one.
* A typical example is in an editor, where hitting DEL breaks off the current
* command and puts the editor back in the main loop, though care has to be
* taken when the DEL occurs while executing a library function, since
* some of them are not reentrant.
*
* POSIX does not require the process signal mask to be saved and restored
* during setjmp/longjmp. However, the current implementation does this
* in order to agree with OSF/1 and other BSD derived systems.
* The actual implementations of all these functions and, by extension, parts
* of this header, are both compiler- and architecture-dependent. Currently
* two compilers are supported: ACK and GCC. Each of these has their own
* implementation of the functions in their runtime system library code.
* As it is impossible to predict the requirements for any other compilers,
* this header may not be compatible with such other compilers either.
*
* The pair of functions _setjmp/_longjmp may be used when the signal
* mask is not to be saved/restored. These functions are traditional
* in BSD systems.
* The ACK compiler will not enregister any variables inside a function
* containing a setjmp call, even if those variables are explicitly declared
* as register variables. Thus for ACK, of all the registers, only the
* program counter, stack pointer and frame pointer have to be saved into the
* jmp_buf structure. This makes the jmp_buf structure very small, and
* moreover, the implementation of the setjmp/longjmp calls (written in EM)
* architecture-independent and thus very portable. The ACK compiler
* recognizes only the symbol __setjmp as being such a setjmp call.
*
* There are different ways of implementing setjmp/longjmp. Probably
* the best way is to unify it with signal handling. This is true for the
* following reasons: Both setjmp/longjmp and signal delivery must save
* a context so that it may be restored later. The jmp_buf necessarily
* contains signal information, namely the signal mask to restore. Both
* longjmp and the return of a signal handler must trap to the operating
* system to restore the previous signal mask. Finally, the jmp_buf
* and the sigcontext structure contain the registers to restore.
* The GCC compiler recognizes all of the setjmp/_setjmp/__setjmp name
* variants as calls to setjmp functions, and treats them as special
* accordingly, but does require that the setjmp implementation save and
* restore most of the registers. It has no portable setjmp and longjmp
* functions like ACK, and therefore has to have enough space in the jmp_buf
* structure to store the registers on any architecture it's ported to.
*
* Some compilers, namely ACK, will not enregister any variables inside a
* function containing a call to setjmp, even if those variables are
* explicitly declared as register variables. Thus for ACK, the
* identification of the jmp_buf with a sigcontext structure would cause
* unnecessary overhead: the jmp_buf has room for all the registers, but
* the only registers that need to be saved are the stack pointer,
* frame pointer, and program counter.
* Taking the common denominator of both compilers, the function definitions
* in this header rely on the presence of merely two functions: __setjmp and
* longjmp. On the other hand, the size of jmp_buf depends on the compiler
* used: for ACK, jmp_buf is exactly big enough to store the three mentioned
* registers; for GCC and any other compiler, the size is chosen in such a
* way that it's likely to offer enough room to store registers for any
* architecture. The POSIX sigjmp_buf is identical to jmp_buf in all cases.
*
* So, for ACK a jmp_buf is much smaller than a sigcontext structure, and
* longjmp does not directly call sigreturn. Instead, longjmp calls a
* front-end function which initializes the appropriate fields of a
* sigcontext structure, marks this structure as containing no valid
* general purpose registers, and then calls sigreturn.
* As far as porting is concerned --
*
* The POSIX sigjmp_buf is identical to the jmp_buf in all cases.
* All code writers/porters that have to deal with the actual contents of the
* jmp_buf structure in one way or another, should look at <sys/jmp_buf.h>.
*
* Different compilers have different symbols that they recognize as
* setjmp symbols. ACK recognizes __setjmp, the GNU C compiler
* recognizes setjmp and _setjmp, and BCC recognizes all three.
* When these symbols occur within a function, the compiler may keep
* all local variables on the stack, avoid certain optimizations, or
* pass hidden arguments to the setjmp function.
*
* Thus, setjmp implementations vary in two independent ways which may
* be identified through the following preprocessor tokens:
* Porters of a new compiler to Minix have to make sure the compiler
* recognizes at least __setjmp as a setjmp call (if applicable) and provide
* library implementations of __setjmp and longjmp conforming to their
* declarations below; if this is not possible, compiler-specific code will
* have to be added to this header.
*
* _SETJMP_SYMBOL -- If 0, this means the compiler treats setjmp and _setjmp
* specially. If 1, this means the compiler treats __setjmp specially.
*
* _SETJMP_SAVES_REGS -- If 1, this means setjmp/longjmp must explicitly
* save and restore all registers. This also implies that a jmp_buf is
* different than a sigcontext structure. If 0, this means that the compiler
* will not use register variables within a function that calls one of
* its SETJMP_SYMBOLs.
*
* When _SETJMP_SYMBOL = 1, the implementation has a few dozen bytes of
* unnecessary overhead. This happens in the following manner: a program uses
* _setjmp/_longjmp because it is not interested in saving and restoring the
* signal mask. Nevertheless, because _setjmp expands to the general purpose
* function __setjmp, code for sigprocmask(2) is linked into the program.
* Porters of Minix+GCC to other architectures have to make sure that the
* __regs array of the jmp_buf structure is large enough to hold all the
* registers the __setjmp implementation for that architecture has to save.
*/
#ifndef _SETJMP_H
@@ -71,82 +55,34 @@
#include <ansi.h>
#endif
#if !defined(__ACK__) && !defined(__BCC__) && !defined(__GNUC__)
#define __ACK__
#endif
#ifdef __ACK__
#define _SETJMP_SYMBOL 1
#define _SETJMP_SAVES_REGS 0
#endif
#ifdef __BCC__
#define _SETJMP_SYMBOL 0
#define _SETJMP_SAVES_REGS 1
#endif
#ifdef __GNUC__
#define _SETJMP_SYMBOL 1
#define _SETJMP_SAVES_REGS 1
#endif
/* The jmp_buf data type. Do not change the order of these fields -- some
* C library code refers to these fields by name. When _SETJMP_SAVES_REGS
* is 1, the file <sys/jmp_buf.h> gives the usage of the sixteen registers.
*/
typedef struct {
int __flags; /* XXX - long might give better alignment */
long __mask; /* must have size >= sizeof(sigset_t) */
#if (_SETJMP_SAVES_REGS == 0)
#if defined(__ACK__)
_PROTOTYPE(void (*__pc),(void)); /* program counter */
void *__sp; /* stack pointer */
void *__lb; /* local base (ACKspeak for frame pointer) */
#else
void *__regs[16]; /* size is machine dependent */
long __mask; /* must have size >= sizeof(sigset_t) */
int __flags;
#else /* GCC */
int __flags; /* XXX - long might give better alignment */
long __mask; /* must have size >= sizeof(sigset_t) */
void *__regs[16]; /* actual use is architecture dependent */
#endif
} jmp_buf[1];
#if (_SETJMP_SYMBOL == 1)
_PROTOTYPE( int __setjmp, (jmp_buf _env, int _savemask) );
_PROTOTYPE( void longjmp, (jmp_buf _env, int _val) );
_PROTOTYPE(int sigjmp, (jmp_buf _jb, int _retval) );
#define setjmp(env) __setjmp((env), 1)
#ifdef _MINIX
#define _setjmp(env) __setjmp((env), 0)
_PROTOTYPE(void _longjmp, (jmp_buf _env, int _val) );
#define _longjmp(env, val) longjmp((env), (val))
#endif
#ifdef _POSIX_SOURCE
typedef jmp_buf sigjmp_buf;
#ifdef __GNUC__
#define siglongjmp longjmp
#else
_PROTOTYPE( void siglongjmp, (sigjmp_buf _env, int _val) );
#endif
#define sigsetjmp(env, savemask) __setjmp((env), (savemask))
#define siglongjmp(env, val) longjmp((env), (val))
#endif /* _POSIX_SOURCE */
#endif /* _SETJMP_SYMBOL == 1 */
#if (_SETJMP_SYMBOL == 0)
_PROTOTYPE( int setjmp, (jmp_buf _env) );
_PROTOTYPE( void longjmp, (jmp_buf _env, int _val) );
#ifdef _MINIX
_PROTOTYPE( int _setjmp, (jmp_buf _env) );
_PROTOTYPE( void _longjmp, (jmp_buf _env, int _val) );
#endif
#ifdef _POSIX_SOURCE
#define sigjmp_buf jmp_buf
_PROTOTYPE( void siglongjmp, (sigjmp_buf _env, int _val) );
/* XXX - the name _setjmp is no good - that's why ACK used __setjmp. */
#define sigsetjmp(env, savemask) ((savemask) ? setjmp(env) : _setjmp(env))
#endif /* _POSIX_SOURCE */
#endif /* _SETJMP_SYMBOL == 0 */
#endif /* _SETJMP_H */

45
include/sys/jmp_buf.h Normal file
View File

@@ -0,0 +1,45 @@
/* This file is intended for use by program code (possibly written in
* assembly) that needs to manipulate a jmp_buf or sigjmp_buf. The JB_*
* values are byte offsets into the jmp_buf and sigjmp_buf structures.
*/
#ifndef _JMP_BUF_H
#define _JMP_BUF_H
#include <minix/config.h>
#if defined(__ACK__)
/* as per lib/ack/rts/setjmp.e */
/* note the lack of parentheses, which would confuse 'as' */
#define JB_PC 0
#define JB_SP JB_PC + _EM_PSIZE
#define JB_LB JB_SP + _EM_PSIZE
#define JB_MASK JB_LB + _EM_PSIZE
#define JB_FLAGS JB_MASK + _EM_LSIZE
#if (CHIP == INTEL)
#define JB_BP JB_LB
#endif
#elif defined(__GNUC__)
#if (CHIP == INTEL) && (_WORD_SIZE == 4)
/* as per lib/gnu/rts/__setjmp.gs */
#define JB_FLAGS 0
#define JB_MASK 4
#define JB_PC 8
#define JB_SP 12
#define JB_BP 16
#define JB_BX 20
#define JB_CX 24
#define JB_DX 28
#define JB_SI 32
#define JB_DI 36
#endif /* (CHIP == INTEL) && (_WORD_SIZE == 4) */
#endif /* __GNU__ */
#endif /* _JMP_BUF_H */

View File

@@ -136,11 +136,6 @@ struct sigcontext {
#define sc_psw sc_regs.sr_psw
#endif /* _MINIX_CHIP == M68000 */
/* Values for sc_flags. Must agree with <minix/jmp_buf.h>. */
#define SC_SIGCONTEXT 2 /* nonzero when signal context is included */
#define SC_NOREGLOCALS 4 /* nonzero when registers are not to be
saved and restored */
_PROTOTYPE( int sigreturn, (struct sigcontext *_scp) );
#endif /* _SIGCONTEXT_H */