setjmp.h

Go to the documentation of this file.
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 */

Generated on Fri Apr 14 22:57:21 2006 for minix by  doxygen 1.4.6