source: trunk/minix/include/setjmp.h@ 10

Last change on this file since 10 was 9, checked in by Mattia Monga, 14 years ago

Minix 3.1.2a

File size: 5.8 KB
RevLine 
[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 */
95typedef 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
121typedef 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 */
Note: See TracBrowser for help on using the repository browser.