00001 /* The <setjmp.h> header relates to the C phenomenon known as setjmp/longjmp. 00002 * It is used to escape out of the current situation into a previous one. 00003 * A typical example is in an editor, where hitting DEL breaks off the current 00004 * command and puts the editor back in the main loop, though care has to be 00005 * taken when the DEL occurs while executing a library function, since 00006 * some of them are not reentrant. 00007 * 00008 * POSIX does not require the process signal mask to be saved and restored 00009 * during setjmp/longjmp. However, the current implementation does this 00010 * in order to agree with OSF/1 and other BSD derived systems. 00011 * 00012 * The pair of functions _setjmp/_longjmp may be used when the signal 00013 * mask is not to be saved/restored. These functions are traditional 00014 * in BSD systems. 00015 * 00016 * There are different ways of implementing setjmp/longjmp. Probably 00017 * the best way is to unify it with signal handling. This is true for the 00018 * following reasons: Both setjmp/longjmp and signal delivery must save 00019 * a context so that it may be restored later. The jmp_buf necessarily 00020 * contains signal information, namely the signal mask to restore. Both 00021 * longjmp and the return of a signal handler must trap to the operating 00022 * system to restore the previous signal mask. Finally, the jmp_buf 00023 * and the sigcontext structure contain the registers to restore. 00024 * 00025 * Some compilers, namely ACK, will not enregister any variables inside a 00026 * function containing a call to setjmp, even if those variables are 00027 * explicitly declared as register variables. Thus for ACK, the 00028 * identification of the jmp_buf with a sigcontext structure would cause 00029 * unnecessary overhead: the jmp_buf has room for all the registers, but 00030 * the only registers that need to be saved are the stack pointer, 00031 * frame pointer, and program counter. 00032 * 00033 * So, for ACK a jmp_buf is much smaller than a sigcontext structure, and 00034 * longjmp does not directly call sigreturn. Instead, longjmp calls a 00035 * front-end function which initializes the appropriate fields of a 00036 * sigcontext structure, marks this structure as containing no valid 00037 * general purpose registers, and then calls sigreturn. 00038 * 00039 * The POSIX sigjmp_buf is identical to the jmp_buf in all cases. 00040 * 00041 * Different compilers have different symbols that they recognize as 00042 * setjmp symbols. ACK recognizes __setjmp, the GNU C compiler 00043 * recognizes setjmp and _setjmp, and BCC recognizes all three. 00044 * When these symbols occur within a function, the compiler may keep 00045 * all local variables on the stack, avoid certain optimizations, or 00046 * pass hidden arguments to the setjmp function. 00047 * 00048 * Thus, setjmp implementations vary in two independent ways which may 00049 * be identified through the following preprocessor tokens: 00050 * 00051 * _SETJMP_SYMBOL -- If 0, this means the compiler treats setjmp and _setjmp 00052 * specially. If 1, this means the compiler treats __setjmp specially. 00053 * 00054 * _SETJMP_SAVES_REGS -- If 1, this means setjmp/longjmp must explicitly 00055 * save and restore all registers. This also implies that a jmp_buf is 00056 * different than a sigcontext structure. If 0, this means that the compiler 00057 * will not use register variables within a function that calls one of 00058 * its SETJMP_SYMBOLs. 00059 * 00060 * When _SETJMP_SYMBOL = 1, the implementation has a few dozen bytes of 00061 * unnecessary overhead. This happens in the following manner: a program uses 00062 * _setjmp/_longjmp because it is not interested in saving and restoring the 00063 * signal mask. Nevertheless, because _setjmp expands to the general purpose 00064 * function __setjmp, code for sigprocmask(2) is linked into the program. 00065 */ 00066 00067 #ifndef _SETJMP_H 00068 #define _SETJMP_H 00069 00070 #ifndef _ANSI_H 00071 #include <ansi.h> 00072 #endif 00073 00074 #if !defined(__ACK__) && !defined(__BCC__) && !defined(__GNUC__) 00075 #define __ACK__ 00076 #endif 00077 00078 #ifdef __ACK__ 00079 #define _SETJMP_SYMBOL 1 00080 #define _SETJMP_SAVES_REGS 0 00081 #endif 00082 #ifdef __BCC__ 00083 #define _SETJMP_SYMBOL 0 00084 #define _SETJMP_SAVES_REGS 1 00085 #endif 00086 #ifdef __GNUC__ 00087 #define _SETJMP_SYMBOL 1 00088 #define _SETJMP_SAVES_REGS 1 00089 #endif 00090 00091 /* The jmp_buf data type. Do not change the order of these fields -- some 00092 * C library code refers to these fields by name. When _SETJMP_SAVES_REGS 00093 * is 1, the file <sys/jmp_buf.h> gives the usage of the sixteen registers. 00094 */ 00095 typedef struct { 00096 int __flags; /* XXX - long might give better alignment */ 00097 long __mask; /* must have size >= sizeof(sigset_t) */ 00098 #if (_SETJMP_SAVES_REGS == 0) 00099 _PROTOTYPE(void (*__pc),(void)); /* program counter */ 00100 void *__sp; /* stack pointer */ 00101 void *__lb; /* local base (ACKspeak for frame pointer) */ 00102 #else 00103 void *__regs[16]; /* size is machine dependent */ 00104 #endif 00105 } jmp_buf[1]; 00106 00107 #if (_SETJMP_SYMBOL == 1) 00108 00109 _PROTOTYPE( int __setjmp, (jmp_buf _env, int _savemask) ); 00110 _PROTOTYPE( void longjmp, (jmp_buf _env, int _val) ); 00111 _PROTOTYPE(int sigjmp, (jmp_buf _jb, int _retval) ); 00112 00113 #define setjmp(env) __setjmp((env), 1) 00114 00115 #ifdef _MINIX 00116 #define _setjmp(env) __setjmp((env), 0) 00117 _PROTOTYPE(void _longjmp, (jmp_buf _env, int _val) ); 00118 #endif 00119 00120 #ifdef _POSIX_SOURCE 00121 typedef jmp_buf sigjmp_buf; 00122 #ifdef __GNUC__ 00123 #define siglongjmp longjmp 00124 #else 00125 _PROTOTYPE( void siglongjmp, (sigjmp_buf _env, int _val) ); 00126 #endif 00127 00128 #define sigsetjmp(env, savemask) __setjmp((env), (savemask)) 00129 #endif /* _POSIX_SOURCE */ 00130 00131 #endif /* _SETJMP_SYMBOL == 1 */ 00132 00133 #if (_SETJMP_SYMBOL == 0) 00134 00135 _PROTOTYPE( int setjmp, (jmp_buf _env) ); 00136 _PROTOTYPE( void longjmp, (jmp_buf _env, int _val) ); 00137 00138 #ifdef _MINIX 00139 _PROTOTYPE( int _setjmp, (jmp_buf _env) ); 00140 _PROTOTYPE( void _longjmp, (jmp_buf _env, int _val) ); 00141 #endif 00142 00143 #ifdef _POSIX_SOURCE 00144 #define sigjmp_buf jmp_buf 00145 _PROTOTYPE( void siglongjmp, (sigjmp_buf _env, int _val) ); 00146 /* XXX - the name _setjmp is no good - that's why ACK used __setjmp. */ 00147 #define sigsetjmp(env, savemask) ((savemask) ? setjmp(env) : _setjmp(env)) 00148 #endif /* _POSIX_SOURCE */ 00149 00150 #endif /* _SETJMP_SYMBOL == 0 */ 00151 00152 #endif /* _SETJMP_H */
1.4.6