[9] | 1 | /* The <setjmp.h> header relates to the C phenomenon known as setjmp/longjmp.
|
---|
| 2 | * It is used to escape out of the current situation into a previous one.
|
---|
| 3 | * A typical example is in an editor, where hitting DEL breaks off the current
|
---|
| 4 | * command and puts the editor back in the main loop, though care has to be
|
---|
| 5 | * taken when the DEL occurs while executing a library function, since
|
---|
| 6 | * some of them are not reentrant.
|
---|
| 7 | *
|
---|
| 8 | * POSIX does not require the process signal mask to be saved and restored
|
---|
| 9 | * during setjmp/longjmp. However, the current implementation does this
|
---|
| 10 | * in order to agree with OSF/1 and other BSD derived systems.
|
---|
| 11 | *
|
---|
| 12 | * The pair of functions _setjmp/_longjmp may be used when the signal
|
---|
| 13 | * mask is not to be saved/restored. These functions are traditional
|
---|
| 14 | * in BSD systems.
|
---|
| 15 | *
|
---|
| 16 | * There are different ways of implementing setjmp/longjmp. Probably
|
---|
| 17 | * the best way is to unify it with signal handling. This is true for the
|
---|
| 18 | * following reasons: Both setjmp/longjmp and signal delivery must save
|
---|
| 19 | * a context so that it may be restored later. The jmp_buf necessarily
|
---|
| 20 | * contains signal information, namely the signal mask to restore. Both
|
---|
| 21 | * longjmp and the return of a signal handler must trap to the operating
|
---|
| 22 | * system to restore the previous signal mask. Finally, the jmp_buf
|
---|
| 23 | * and the sigcontext structure contain the registers to restore.
|
---|
| 24 | *
|
---|
| 25 | * Some compilers, namely ACK, will not enregister any variables inside a
|
---|
| 26 | * function containing a call to setjmp, even if those variables are
|
---|
| 27 | * explicitly declared as register variables. Thus for ACK, the
|
---|
| 28 | * identification of the jmp_buf with a sigcontext structure would cause
|
---|
| 29 | * unnecessary overhead: the jmp_buf has room for all the registers, but
|
---|
| 30 | * the only registers that need to be saved are the stack pointer,
|
---|
| 31 | * frame pointer, and program counter.
|
---|
| 32 | *
|
---|
| 33 | * So, for ACK a jmp_buf is much smaller than a sigcontext structure, and
|
---|
| 34 | * longjmp does not directly call sigreturn. Instead, longjmp calls a
|
---|
| 35 | * front-end function which initializes the appropriate fields of a
|
---|
| 36 | * sigcontext structure, marks this structure as containing no valid
|
---|
| 37 | * general purpose registers, and then calls sigreturn.
|
---|
| 38 | *
|
---|
| 39 | * The POSIX sigjmp_buf is identical to the jmp_buf in all cases.
|
---|
| 40 | *
|
---|
| 41 | * Different compilers have different symbols that they recognize as
|
---|
| 42 | * setjmp symbols. ACK recognizes __setjmp, the GNU C compiler
|
---|
| 43 | * recognizes setjmp and _setjmp, and BCC recognizes all three.
|
---|
| 44 | * When these symbols occur within a function, the compiler may keep
|
---|
| 45 | * all local variables on the stack, avoid certain optimizations, or
|
---|
| 46 | * pass hidden arguments to the setjmp function.
|
---|
| 47 | *
|
---|
| 48 | * Thus, setjmp implementations vary in two independent ways which may
|
---|
| 49 | * be identified through the following preprocessor tokens:
|
---|
| 50 | *
|
---|
| 51 | * _SETJMP_SYMBOL -- If 0, this means the compiler treats setjmp and _setjmp
|
---|
| 52 | * specially. If 1, this means the compiler treats __setjmp specially.
|
---|
| 53 | *
|
---|
| 54 | * _SETJMP_SAVES_REGS -- If 1, this means setjmp/longjmp must explicitly
|
---|
| 55 | * save and restore all registers. This also implies that a jmp_buf is
|
---|
| 56 | * different than a sigcontext structure. If 0, this means that the compiler
|
---|
| 57 | * will not use register variables within a function that calls one of
|
---|
| 58 | * its SETJMP_SYMBOLs.
|
---|
| 59 | *
|
---|
| 60 | * When _SETJMP_SYMBOL = 1, the implementation has a few dozen bytes of
|
---|
| 61 | * unnecessary overhead. This happens in the following manner: a program uses
|
---|
| 62 | * _setjmp/_longjmp because it is not interested in saving and restoring the
|
---|
| 63 | * signal mask. Nevertheless, because _setjmp expands to the general purpose
|
---|
| 64 | * function __setjmp, code for sigprocmask(2) is linked into the program.
|
---|
| 65 | */
|
---|
| 66 |
|
---|
| 67 | #ifndef _SETJMP_H
|
---|
| 68 | #define _SETJMP_H
|
---|
| 69 |
|
---|
| 70 | #ifndef _ANSI_H
|
---|
| 71 | #include <ansi.h>
|
---|
| 72 | #endif
|
---|
| 73 |
|
---|
| 74 | #if !defined(__ACK__) && !defined(__BCC__) && !defined(__GNUC__)
|
---|
| 75 | #define __ACK__
|
---|
| 76 | #endif
|
---|
| 77 |
|
---|
| 78 | #ifdef __ACK__
|
---|
| 79 | #define _SETJMP_SYMBOL 1
|
---|
| 80 | #define _SETJMP_SAVES_REGS 0
|
---|
| 81 | #endif
|
---|
| 82 | #ifdef __BCC__
|
---|
| 83 | #define _SETJMP_SYMBOL 0
|
---|
| 84 | #define _SETJMP_SAVES_REGS 1
|
---|
| 85 | #endif
|
---|
| 86 | #ifdef __GNUC__
|
---|
| 87 | #define _SETJMP_SYMBOL 1
|
---|
| 88 | #define _SETJMP_SAVES_REGS 1
|
---|
| 89 | #endif
|
---|
| 90 |
|
---|
| 91 | /* The jmp_buf data type. Do not change the order of these fields -- some
|
---|
| 92 | * C library code refers to these fields by name. When _SETJMP_SAVES_REGS
|
---|
| 93 | * is 1, the file <sys/jmp_buf.h> gives the usage of the sixteen registers.
|
---|
| 94 | */
|
---|
| 95 | typedef struct {
|
---|
| 96 | int __flags; /* XXX - long might give better alignment */
|
---|
| 97 | long __mask; /* must have size >= sizeof(sigset_t) */
|
---|
| 98 | #if (_SETJMP_SAVES_REGS == 0)
|
---|
| 99 | _PROTOTYPE(void (*__pc),(void)); /* program counter */
|
---|
| 100 | void *__sp; /* stack pointer */
|
---|
| 101 | void *__lb; /* local base (ACKspeak for frame pointer) */
|
---|
| 102 | #else
|
---|
| 103 | void *__regs[16]; /* size is machine dependent */
|
---|
| 104 | #endif
|
---|
| 105 | } jmp_buf[1];
|
---|
| 106 |
|
---|
| 107 | #if (_SETJMP_SYMBOL == 1)
|
---|
| 108 |
|
---|
| 109 | _PROTOTYPE( int __setjmp, (jmp_buf _env, int _savemask) );
|
---|
| 110 | _PROTOTYPE( void longjmp, (jmp_buf _env, int _val) );
|
---|
| 111 | _PROTOTYPE(int sigjmp, (jmp_buf _jb, int _retval) );
|
---|
| 112 |
|
---|
| 113 | #define setjmp(env) __setjmp((env), 1)
|
---|
| 114 |
|
---|
| 115 | #ifdef _MINIX
|
---|
| 116 | #define _setjmp(env) __setjmp((env), 0)
|
---|
| 117 | _PROTOTYPE(void _longjmp, (jmp_buf _env, int _val) );
|
---|
| 118 | #endif
|
---|
| 119 |
|
---|
| 120 | #ifdef _POSIX_SOURCE
|
---|
| 121 | typedef jmp_buf sigjmp_buf;
|
---|
| 122 | #ifdef __GNUC__
|
---|
| 123 | #define siglongjmp longjmp
|
---|
| 124 | #else
|
---|
| 125 | _PROTOTYPE( void siglongjmp, (sigjmp_buf _env, int _val) );
|
---|
| 126 | #endif
|
---|
| 127 |
|
---|
| 128 | #define sigsetjmp(env, savemask) __setjmp((env), (savemask))
|
---|
| 129 | #endif /* _POSIX_SOURCE */
|
---|
| 130 |
|
---|
| 131 | #endif /* _SETJMP_SYMBOL == 1 */
|
---|
| 132 |
|
---|
| 133 | #if (_SETJMP_SYMBOL == 0)
|
---|
| 134 |
|
---|
| 135 | _PROTOTYPE( int setjmp, (jmp_buf _env) );
|
---|
| 136 | _PROTOTYPE( void longjmp, (jmp_buf _env, int _val) );
|
---|
| 137 |
|
---|
| 138 | #ifdef _MINIX
|
---|
| 139 | _PROTOTYPE( int _setjmp, (jmp_buf _env) );
|
---|
| 140 | _PROTOTYPE( void _longjmp, (jmp_buf _env, int _val) );
|
---|
| 141 | #endif
|
---|
| 142 |
|
---|
| 143 | #ifdef _POSIX_SOURCE
|
---|
| 144 | #define sigjmp_buf jmp_buf
|
---|
| 145 | _PROTOTYPE( void siglongjmp, (sigjmp_buf _env, int _val) );
|
---|
| 146 | /* XXX - the name _setjmp is no good - that's why ACK used __setjmp. */
|
---|
| 147 | #define sigsetjmp(env, savemask) ((savemask) ? setjmp(env) : _setjmp(env))
|
---|
| 148 | #endif /* _POSIX_SOURCE */
|
---|
| 149 |
|
---|
| 150 | #endif /* _SETJMP_SYMBOL == 0 */
|
---|
| 151 |
|
---|
| 152 | #endif /* _SETJMP_H */
|
---|