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 */
|
---|