Setjmp/longjmp updates and cleanup.
This commit is contained in:
parent
170a72fd61
commit
d4e6fe3546
@ -1,87 +0,0 @@
|
|||||||
/* This file is intended for use by assembly language programs that
|
|
||||||
* need to manipulate a jmp_buf. It may only be used by those systems
|
|
||||||
* for which a jmp_buf is identical to a struct sigcontext.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef _JMP_BUF_H
|
|
||||||
#define _JMP_BUF_H
|
|
||||||
|
|
||||||
#if !defined(CHIP)
|
|
||||||
#include "error, configuration is not known"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if (CHIP == INTEL)
|
|
||||||
#if _WORD_SIZE == 4
|
|
||||||
#define JB_FLAGS 0
|
|
||||||
#define JB_MASK 4
|
|
||||||
#define JB_GS 8
|
|
||||||
#define JB_FS 10
|
|
||||||
#define JB_ES 12
|
|
||||||
#define JB_DS 14
|
|
||||||
#define JB_DI 16
|
|
||||||
#define JB_SI 20
|
|
||||||
#define JB_BP 24
|
|
||||||
#define JB_ST 28
|
|
||||||
#define JB_BX 32
|
|
||||||
#define JB_DX 36
|
|
||||||
#define JB_CX 40
|
|
||||||
#define JB_AX 44
|
|
||||||
#define JB_RETADR 48
|
|
||||||
#define JB_IP 52
|
|
||||||
#define JB_CS 56
|
|
||||||
#define JB_PSW 60
|
|
||||||
#define JB_SP 64
|
|
||||||
#define JB_SS 68
|
|
||||||
#else /* _WORD_SIZE == 2 */
|
|
||||||
#define JB_FLAGS 0
|
|
||||||
#define JB_MASK 2
|
|
||||||
#define JB_ES 6
|
|
||||||
#define JB_DS 8
|
|
||||||
#define JB_DI 10
|
|
||||||
#define JB_SI 12
|
|
||||||
#define JB_BP 14
|
|
||||||
#define JB_ST 16
|
|
||||||
#define JB_BX 18
|
|
||||||
#define JB_DX 20
|
|
||||||
#define JB_CX 22
|
|
||||||
#define JB_AX 24
|
|
||||||
#define JB_RETADR 26
|
|
||||||
#define JB_IP 28
|
|
||||||
#define JB_CS 30
|
|
||||||
#define JB_PSW 32
|
|
||||||
#define JB_SP 34
|
|
||||||
#define JB_SS 36
|
|
||||||
#endif /* _WORD_SIZE == 2 */
|
|
||||||
#else /* !(CHIP == INTEL) */
|
|
||||||
#if (CHIP == M68000)
|
|
||||||
#define JB_FLAGS 0
|
|
||||||
#define JB_MASK 2
|
|
||||||
#define JB_RETREG 6
|
|
||||||
#define JB_D1 10
|
|
||||||
#define JB_D2 14
|
|
||||||
#define JB_D3 18
|
|
||||||
#define JB_D4 22
|
|
||||||
#define JB_D5 26
|
|
||||||
#define JB_D6 20
|
|
||||||
#define JB_D7 34
|
|
||||||
#define JB_A0 38
|
|
||||||
#define JB_A1 42
|
|
||||||
#define JB_A2 46
|
|
||||||
#define JB_A3 50
|
|
||||||
#define JB_A4 54
|
|
||||||
#define JB_A5 58
|
|
||||||
#define JB_A6 62
|
|
||||||
#define JB_SP 66
|
|
||||||
#define JB_PC 70
|
|
||||||
#define JB_PSW 74
|
|
||||||
#else /* !(CHIP == INTEL) && !(CHIP == M68000) */
|
|
||||||
#include "error, CHIP is not supported"
|
|
||||||
#endif /* (CHIP == INTEL) */
|
|
||||||
|
|
||||||
/* Defines from C headers needed in assembly code. The headers have too
|
|
||||||
* much C stuff to used directly.
|
|
||||||
*/
|
|
||||||
#define SIG_BLOCK 0 /* must agree with <signal.h> */
|
|
||||||
#define SC_SIGCONTEXT 2 /* must agree with <sys/sigcontext.h> */
|
|
||||||
#define SC_NOREGLOCALS 4 /* must agree with <sys/sigcontext.h> */
|
|
||||||
#endif /* _JMP_BUF_H */
|
|
158
include/setjmp.h
158
include/setjmp.h
@ -1,67 +1,51 @@
|
|||||||
/* The <setjmp.h> header relates to the C phenomenon known as setjmp/longjmp.
|
/* The <setjmp.h> header relates to the C phenomenon known as setjmp/longjmp.
|
||||||
* It is used to escape out of the current situation into a previous one.
|
* It is used to escape out of the current situation into a previous one.
|
||||||
* A typical example is in an editor, where hitting DEL breaks off the current
|
|
||||||
* command and puts the editor back in the main loop, though care has to be
|
|
||||||
* taken when the DEL occurs while executing a library function, since
|
|
||||||
* some of them are not reentrant.
|
|
||||||
*
|
*
|
||||||
* POSIX does not require the process signal mask to be saved and restored
|
* The actual implementations of all these functions and, by extension, parts
|
||||||
* during setjmp/longjmp. However, the current implementation does this
|
* of this header, are both compiler- and architecture-dependent. Currently
|
||||||
* in order to agree with OSF/1 and other BSD derived systems.
|
* two compilers are supported: ACK and GCC. Each of these has their own
|
||||||
|
* implementation of the functions in their runtime system library code.
|
||||||
|
* As it is impossible to predict the requirements for any other compilers,
|
||||||
|
* this header may not be compatible with such other compilers either.
|
||||||
*
|
*
|
||||||
* The pair of functions _setjmp/_longjmp may be used when the signal
|
* The ACK compiler will not enregister any variables inside a function
|
||||||
* mask is not to be saved/restored. These functions are traditional
|
* containing a setjmp call, even if those variables are explicitly declared
|
||||||
* in BSD systems.
|
* as register variables. Thus for ACK, of all the registers, only the
|
||||||
|
* program counter, stack pointer and frame pointer have to be saved into the
|
||||||
|
* jmp_buf structure. This makes the jmp_buf structure very small, and
|
||||||
|
* moreover, the implementation of the setjmp/longjmp calls (written in EM)
|
||||||
|
* architecture-independent and thus very portable. The ACK compiler
|
||||||
|
* recognizes only the symbol __setjmp as being such a setjmp call.
|
||||||
*
|
*
|
||||||
* There are different ways of implementing setjmp/longjmp. Probably
|
* The GCC compiler recognizes all of the setjmp/_setjmp/__setjmp name
|
||||||
* the best way is to unify it with signal handling. This is true for the
|
* variants as calls to setjmp functions, and treats them as special
|
||||||
* following reasons: Both setjmp/longjmp and signal delivery must save
|
* accordingly, but does require that the setjmp implementation save and
|
||||||
* a context so that it may be restored later. The jmp_buf necessarily
|
* restore most of the registers. It has no portable setjmp and longjmp
|
||||||
* contains signal information, namely the signal mask to restore. Both
|
* functions like ACK, and therefore has to have enough space in the jmp_buf
|
||||||
* longjmp and the return of a signal handler must trap to the operating
|
* structure to store the registers on any architecture it's ported to.
|
||||||
* system to restore the previous signal mask. Finally, the jmp_buf
|
|
||||||
* and the sigcontext structure contain the registers to restore.
|
|
||||||
*
|
*
|
||||||
* Some compilers, namely ACK, will not enregister any variables inside a
|
* Taking the common denominator of both compilers, the function definitions
|
||||||
* function containing a call to setjmp, even if those variables are
|
* in this header rely on the presence of merely two functions: __setjmp and
|
||||||
* explicitly declared as register variables. Thus for ACK, the
|
* longjmp. On the other hand, the size of jmp_buf depends on the compiler
|
||||||
* identification of the jmp_buf with a sigcontext structure would cause
|
* used: for ACK, jmp_buf is exactly big enough to store the three mentioned
|
||||||
* unnecessary overhead: the jmp_buf has room for all the registers, but
|
* registers; for GCC and any other compiler, the size is chosen in such a
|
||||||
* the only registers that need to be saved are the stack pointer,
|
* way that it's likely to offer enough room to store registers for any
|
||||||
* frame pointer, and program counter.
|
* architecture. The POSIX sigjmp_buf is identical to jmp_buf in all cases.
|
||||||
*
|
*
|
||||||
* So, for ACK a jmp_buf is much smaller than a sigcontext structure, and
|
* As far as porting is concerned --
|
||||||
* longjmp does not directly call sigreturn. Instead, longjmp calls a
|
|
||||||
* front-end function which initializes the appropriate fields of a
|
|
||||||
* sigcontext structure, marks this structure as containing no valid
|
|
||||||
* general purpose registers, and then calls sigreturn.
|
|
||||||
*
|
*
|
||||||
* The POSIX sigjmp_buf is identical to the jmp_buf in all cases.
|
* All code writers/porters that have to deal with the actual contents of the
|
||||||
|
* jmp_buf structure in one way or another, should look at <sys/jmp_buf.h>.
|
||||||
*
|
*
|
||||||
* Different compilers have different symbols that they recognize as
|
* Porters of a new compiler to Minix have to make sure the compiler
|
||||||
* setjmp symbols. ACK recognizes __setjmp, the GNU C compiler
|
* recognizes at least __setjmp as a setjmp call (if applicable) and provide
|
||||||
* recognizes setjmp and _setjmp, and BCC recognizes all three.
|
* library implementations of __setjmp and longjmp conforming to their
|
||||||
* When these symbols occur within a function, the compiler may keep
|
* declarations below; if this is not possible, compiler-specific code will
|
||||||
* all local variables on the stack, avoid certain optimizations, or
|
* have to be added to this header.
|
||||||
* pass hidden arguments to the setjmp function.
|
|
||||||
*
|
*
|
||||||
* Thus, setjmp implementations vary in two independent ways which may
|
* Porters of Minix+GCC to other architectures have to make sure that the
|
||||||
* be identified through the following preprocessor tokens:
|
* __regs array of the jmp_buf structure is large enough to hold all the
|
||||||
*
|
* registers the __setjmp implementation for that architecture has to save.
|
||||||
* _SETJMP_SYMBOL -- If 0, this means the compiler treats setjmp and _setjmp
|
|
||||||
* specially. If 1, this means the compiler treats __setjmp specially.
|
|
||||||
*
|
|
||||||
* _SETJMP_SAVES_REGS -- If 1, this means setjmp/longjmp must explicitly
|
|
||||||
* save and restore all registers. This also implies that a jmp_buf is
|
|
||||||
* different than a sigcontext structure. If 0, this means that the compiler
|
|
||||||
* will not use register variables within a function that calls one of
|
|
||||||
* its SETJMP_SYMBOLs.
|
|
||||||
*
|
|
||||||
* When _SETJMP_SYMBOL = 1, the implementation has a few dozen bytes of
|
|
||||||
* unnecessary overhead. This happens in the following manner: a program uses
|
|
||||||
* _setjmp/_longjmp because it is not interested in saving and restoring the
|
|
||||||
* signal mask. Nevertheless, because _setjmp expands to the general purpose
|
|
||||||
* function __setjmp, code for sigprocmask(2) is linked into the program.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef _SETJMP_H
|
#ifndef _SETJMP_H
|
||||||
@ -71,82 +55,34 @@
|
|||||||
#include <ansi.h>
|
#include <ansi.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if !defined(__ACK__) && !defined(__BCC__) && !defined(__GNUC__)
|
|
||||||
#define __ACK__
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef __ACK__
|
|
||||||
#define _SETJMP_SYMBOL 1
|
|
||||||
#define _SETJMP_SAVES_REGS 0
|
|
||||||
#endif
|
|
||||||
#ifdef __BCC__
|
|
||||||
#define _SETJMP_SYMBOL 0
|
|
||||||
#define _SETJMP_SAVES_REGS 1
|
|
||||||
#endif
|
|
||||||
#ifdef __GNUC__
|
|
||||||
#define _SETJMP_SYMBOL 1
|
|
||||||
#define _SETJMP_SAVES_REGS 1
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* The jmp_buf data type. Do not change the order of these fields -- some
|
|
||||||
* C library code refers to these fields by name. When _SETJMP_SAVES_REGS
|
|
||||||
* is 1, the file <sys/jmp_buf.h> gives the usage of the sixteen registers.
|
|
||||||
*/
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
int __flags; /* XXX - long might give better alignment */
|
#if defined(__ACK__)
|
||||||
long __mask; /* must have size >= sizeof(sigset_t) */
|
|
||||||
#if (_SETJMP_SAVES_REGS == 0)
|
|
||||||
_PROTOTYPE(void (*__pc),(void)); /* program counter */
|
_PROTOTYPE(void (*__pc),(void)); /* program counter */
|
||||||
void *__sp; /* stack pointer */
|
void *__sp; /* stack pointer */
|
||||||
void *__lb; /* local base (ACKspeak for frame pointer) */
|
void *__lb; /* local base (ACKspeak for frame pointer) */
|
||||||
#else
|
long __mask; /* must have size >= sizeof(sigset_t) */
|
||||||
void *__regs[16]; /* size is machine dependent */
|
int __flags;
|
||||||
|
#else /* GCC */
|
||||||
|
int __flags; /* XXX - long might give better alignment */
|
||||||
|
long __mask; /* must have size >= sizeof(sigset_t) */
|
||||||
|
void *__regs[16]; /* actual use is architecture dependent */
|
||||||
#endif
|
#endif
|
||||||
} jmp_buf[1];
|
} jmp_buf[1];
|
||||||
|
|
||||||
#if (_SETJMP_SYMBOL == 1)
|
|
||||||
|
|
||||||
_PROTOTYPE( int __setjmp, (jmp_buf _env, int _savemask) );
|
_PROTOTYPE( int __setjmp, (jmp_buf _env, int _savemask) );
|
||||||
_PROTOTYPE( void longjmp, (jmp_buf _env, int _val) );
|
_PROTOTYPE( void longjmp, (jmp_buf _env, int _val) );
|
||||||
_PROTOTYPE(int sigjmp, (jmp_buf _jb, int _retval) );
|
|
||||||
|
|
||||||
#define setjmp(env) __setjmp((env), 1)
|
#define setjmp(env) __setjmp((env), 1)
|
||||||
|
|
||||||
#ifdef _MINIX
|
#ifdef _MINIX
|
||||||
#define _setjmp(env) __setjmp((env), 0)
|
#define _setjmp(env) __setjmp((env), 0)
|
||||||
_PROTOTYPE(void _longjmp, (jmp_buf _env, int _val) );
|
#define _longjmp(env, val) longjmp((env), (val))
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef _POSIX_SOURCE
|
#ifdef _POSIX_SOURCE
|
||||||
typedef jmp_buf sigjmp_buf;
|
typedef jmp_buf sigjmp_buf;
|
||||||
#ifdef __GNUC__
|
|
||||||
#define siglongjmp longjmp
|
|
||||||
#else
|
|
||||||
_PROTOTYPE( void siglongjmp, (sigjmp_buf _env, int _val) );
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define sigsetjmp(env, savemask) __setjmp((env), (savemask))
|
#define sigsetjmp(env, savemask) __setjmp((env), (savemask))
|
||||||
|
#define siglongjmp(env, val) longjmp((env), (val))
|
||||||
#endif /* _POSIX_SOURCE */
|
#endif /* _POSIX_SOURCE */
|
||||||
|
|
||||||
#endif /* _SETJMP_SYMBOL == 1 */
|
|
||||||
|
|
||||||
#if (_SETJMP_SYMBOL == 0)
|
|
||||||
|
|
||||||
_PROTOTYPE( int setjmp, (jmp_buf _env) );
|
|
||||||
_PROTOTYPE( void longjmp, (jmp_buf _env, int _val) );
|
|
||||||
|
|
||||||
#ifdef _MINIX
|
|
||||||
_PROTOTYPE( int _setjmp, (jmp_buf _env) );
|
|
||||||
_PROTOTYPE( void _longjmp, (jmp_buf _env, int _val) );
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef _POSIX_SOURCE
|
|
||||||
#define sigjmp_buf jmp_buf
|
|
||||||
_PROTOTYPE( void siglongjmp, (sigjmp_buf _env, int _val) );
|
|
||||||
/* XXX - the name _setjmp is no good - that's why ACK used __setjmp. */
|
|
||||||
#define sigsetjmp(env, savemask) ((savemask) ? setjmp(env) : _setjmp(env))
|
|
||||||
#endif /* _POSIX_SOURCE */
|
|
||||||
|
|
||||||
#endif /* _SETJMP_SYMBOL == 0 */
|
|
||||||
|
|
||||||
#endif /* _SETJMP_H */
|
#endif /* _SETJMP_H */
|
||||||
|
45
include/sys/jmp_buf.h
Normal file
45
include/sys/jmp_buf.h
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
/* This file is intended for use by program code (possibly written in
|
||||||
|
* assembly) that needs to manipulate a jmp_buf or sigjmp_buf. The JB_*
|
||||||
|
* values are byte offsets into the jmp_buf and sigjmp_buf structures.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _JMP_BUF_H
|
||||||
|
#define _JMP_BUF_H
|
||||||
|
|
||||||
|
#include <minix/config.h>
|
||||||
|
|
||||||
|
#if defined(__ACK__)
|
||||||
|
/* as per lib/ack/rts/setjmp.e */
|
||||||
|
|
||||||
|
/* note the lack of parentheses, which would confuse 'as' */
|
||||||
|
#define JB_PC 0
|
||||||
|
#define JB_SP JB_PC + _EM_PSIZE
|
||||||
|
#define JB_LB JB_SP + _EM_PSIZE
|
||||||
|
#define JB_MASK JB_LB + _EM_PSIZE
|
||||||
|
#define JB_FLAGS JB_MASK + _EM_LSIZE
|
||||||
|
|
||||||
|
#if (CHIP == INTEL)
|
||||||
|
#define JB_BP JB_LB
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#elif defined(__GNUC__)
|
||||||
|
|
||||||
|
#if (CHIP == INTEL) && (_WORD_SIZE == 4)
|
||||||
|
/* as per lib/gnu/rts/__setjmp.gs */
|
||||||
|
|
||||||
|
#define JB_FLAGS 0
|
||||||
|
#define JB_MASK 4
|
||||||
|
#define JB_PC 8
|
||||||
|
#define JB_SP 12
|
||||||
|
#define JB_BP 16
|
||||||
|
#define JB_BX 20
|
||||||
|
#define JB_CX 24
|
||||||
|
#define JB_DX 28
|
||||||
|
#define JB_SI 32
|
||||||
|
#define JB_DI 36
|
||||||
|
|
||||||
|
#endif /* (CHIP == INTEL) && (_WORD_SIZE == 4) */
|
||||||
|
|
||||||
|
#endif /* __GNU__ */
|
||||||
|
|
||||||
|
#endif /* _JMP_BUF_H */
|
@ -136,11 +136,6 @@ struct sigcontext {
|
|||||||
#define sc_psw sc_regs.sr_psw
|
#define sc_psw sc_regs.sr_psw
|
||||||
#endif /* _MINIX_CHIP == M68000 */
|
#endif /* _MINIX_CHIP == M68000 */
|
||||||
|
|
||||||
/* Values for sc_flags. Must agree with <minix/jmp_buf.h>. */
|
|
||||||
#define SC_SIGCONTEXT 2 /* nonzero when signal context is included */
|
|
||||||
#define SC_NOREGLOCALS 4 /* nonzero when registers are not to be
|
|
||||||
saved and restored */
|
|
||||||
|
|
||||||
_PROTOTYPE( int sigreturn, (struct sigcontext *_scp) );
|
_PROTOTYPE( int sigreturn, (struct sigcontext *_scp) );
|
||||||
|
|
||||||
#endif /* _SIGCONTEXT_H */
|
#endif /* _SIGCONTEXT_H */
|
||||||
|
@ -38,19 +38,6 @@ message *m_ptr; /* pointer to request message */
|
|||||||
if (src_phys == 0) return(EFAULT);
|
if (src_phys == 0) return(EFAULT);
|
||||||
phys_copy(src_phys, vir2phys(&sc), (phys_bytes) sizeof(struct sigcontext));
|
phys_copy(src_phys, vir2phys(&sc), (phys_bytes) sizeof(struct sigcontext));
|
||||||
|
|
||||||
/* Make sure that this is not just a jump buffer. */
|
|
||||||
if ((sc.sc_flags & SC_SIGCONTEXT) == 0) return(EINVAL);
|
|
||||||
|
|
||||||
/* Fix up only certain key registers if the compiler doesn't use
|
|
||||||
* register variables within functions containing setjmp.
|
|
||||||
*/
|
|
||||||
if (sc.sc_flags & SC_NOREGLOCALS) {
|
|
||||||
rp->p_reg.retreg = sc.sc_retreg;
|
|
||||||
rp->p_reg.fp = sc.sc_fp;
|
|
||||||
rp->p_reg.pc = sc.sc_pc;
|
|
||||||
rp->p_reg.sp = sc.sc_sp;
|
|
||||||
return(OK);
|
|
||||||
}
|
|
||||||
sc.sc_psw = rp->p_reg.psw;
|
sc.sc_psw = rp->p_reg.psw;
|
||||||
|
|
||||||
#if (CHIP == INTEL)
|
#if (CHIP == INTEL)
|
||||||
|
@ -47,7 +47,7 @@ message *m_ptr; /* pointer to request message */
|
|||||||
memcpy(&sc.sc_regs, (char *) &rp->p_reg, sizeof(struct sigregs));
|
memcpy(&sc.sc_regs, (char *) &rp->p_reg, sizeof(struct sigregs));
|
||||||
|
|
||||||
/* Finish the sigcontext initialization. */
|
/* Finish the sigcontext initialization. */
|
||||||
sc.sc_flags = SC_SIGCONTEXT;
|
sc.sc_flags = 0; /* unused at this time */
|
||||||
sc.sc_mask = smsg.sm_mask;
|
sc.sc_mask = smsg.sm_mask;
|
||||||
|
|
||||||
/* Copy the sigcontext structure to the user's stack. */
|
/* Copy the sigcontext structure to the user's stack. */
|
||||||
|
@ -2,9 +2,7 @@
|
|||||||
LIBRARIES=libc
|
LIBRARIES=libc
|
||||||
|
|
||||||
libc_FILES=" \
|
libc_FILES=" \
|
||||||
_longjmp.gs \
|
__setjmp.gs \
|
||||||
_setjmp.gs \
|
longjmp.gs"
|
||||||
longjmp.gs \
|
|
||||||
setjmp.gs"
|
|
||||||
|
|
||||||
TYPE=gnu
|
TYPE=gnu
|
||||||
|
31
lib/gnu/rts/__setjmp.gs
Normal file
31
lib/gnu/rts/__setjmp.gs
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
/ __setjmp.gnu.s
|
||||||
|
/
|
||||||
|
/ Created: Oct 14, 1993 by Philip Homburg <philip@cs.vu.nl>
|
||||||
|
|
||||||
|
.text
|
||||||
|
.globl ___setjmp
|
||||||
|
___setjmp:
|
||||||
|
movl 4(%esp), %eax # jmp_buf
|
||||||
|
movl %edx, 28(%eax) # save edx
|
||||||
|
movl 0(%esp), %edx
|
||||||
|
movl %edx, 8(%eax) # save program counter
|
||||||
|
movl %esp, 12(%eax) # save stack pointer
|
||||||
|
movl %ebp, 16(%eax) # save frame pointer
|
||||||
|
movl %ebx, 20(%eax)
|
||||||
|
movl %ecx, 24(%eax)
|
||||||
|
movl %esi, 32(%eax)
|
||||||
|
movl %edi, 36(%eax)
|
||||||
|
|
||||||
|
movl 8(%esp), %edx # save mask?
|
||||||
|
movl %edx, 0(%eax) # save whether to restore mask
|
||||||
|
testl %edx, %edx
|
||||||
|
jz 1f
|
||||||
|
leal 4(%eax), %edx # pointer to sigset_t
|
||||||
|
pushl %edx
|
||||||
|
call ___newsigset # save mask
|
||||||
|
addl $4, %esp
|
||||||
|
1:
|
||||||
|
movl $0, %eax
|
||||||
|
ret
|
||||||
|
|
||||||
|
/ $PchId: __setjmp.gnu.s,v 1.4 1996/03/12 19:30:54 philip Exp $
|
@ -1,38 +0,0 @@
|
|||||||
/ _longjmp.gnu.s
|
|
||||||
/
|
|
||||||
/ Created: Oct 15, 1993 by Philip Homburg <philip@cs.vu.nl>
|
|
||||||
|
|
||||||
.text
|
|
||||||
.globl __longjmp
|
|
||||||
__longjmp:
|
|
||||||
movl 4(%esp), %eax # jmp_buf
|
|
||||||
cmpl $0, 0(%eax) # save mask?
|
|
||||||
je 1f
|
|
||||||
leal 4(%eax), %ebx # pointer to sigset_t
|
|
||||||
pushl %ebx
|
|
||||||
call ___oldsigset # restore mask
|
|
||||||
addl $4, %esp
|
|
||||||
movl 4(%esp), %eax # jmp_buf
|
|
||||||
1:
|
|
||||||
movl 8(%esp), %ecx # result value
|
|
||||||
movl 12(%eax), %esp # restore stack pointer
|
|
||||||
|
|
||||||
movl 8(%eax), %ebx # restore program counter
|
|
||||||
movl %ebx, 0(%esp)
|
|
||||||
|
|
||||||
pushl %ecx # save result code
|
|
||||||
|
|
||||||
movl 16(%eax), %ebp # restore frame pointer
|
|
||||||
movl 20(%eax), %ebx
|
|
||||||
movl 24(%eax), %ecx
|
|
||||||
movl 28(%eax), %edx
|
|
||||||
movl 32(%eax), %esi
|
|
||||||
movl 36(%eax), %edi
|
|
||||||
pop %eax
|
|
||||||
testl %eax, %eax
|
|
||||||
jz 1f
|
|
||||||
ret
|
|
||||||
1: movl $1, %eax
|
|
||||||
ret
|
|
||||||
|
|
||||||
/ $PchId: _longjmp.gnu.s,v 1.4 1996/03/12 19:30:02 philip Exp $
|
|
@ -1,35 +0,0 @@
|
|||||||
/ _setjmp.gnu.s
|
|
||||||
/
|
|
||||||
/ Created: Oct 14, 1993 by Philip Homburg <philip@cs.vu.nl>
|
|
||||||
|
|
||||||
.text
|
|
||||||
.globl ___setjmp
|
|
||||||
___setjmp:
|
|
||||||
movl 4(%esp), %eax # jmp_buf
|
|
||||||
movl %ebx, 20(%eax) # save ebx
|
|
||||||
movl 0(%esp), %ebx
|
|
||||||
movl %ebx, 8(%eax) # save program counter
|
|
||||||
movl %esp, 12(%eax) # save stack pointer
|
|
||||||
movl %ebp, 16(%eax) # save frame pointer
|
|
||||||
movl %ecx, 24(%eax)
|
|
||||||
movl %edx, 28(%eax)
|
|
||||||
movl %esi, 32(%eax)
|
|
||||||
movl %edi, 36(%eax)
|
|
||||||
|
|
||||||
movl 8(%esp), %ebx # save mask?
|
|
||||||
movl %ebx, 0(%eax) # save whether to restore mask
|
|
||||||
|
|
||||||
pushl 20(%eax) # save ebx
|
|
||||||
|
|
||||||
testl %ebx, %ebx
|
|
||||||
jz 1f
|
|
||||||
leal 4(%eax), %ebx # pointer to sigset_t
|
|
||||||
pushl %ebx
|
|
||||||
call ___newsigset # save mask
|
|
||||||
addl $4, %esp
|
|
||||||
1:
|
|
||||||
popl %ebx
|
|
||||||
movl $0, %eax
|
|
||||||
ret
|
|
||||||
|
|
||||||
/ $PchId: _setjmp.gnu.s,v 1.4 1996/03/12 19:30:54 philip Exp $
|
|
@ -1,6 +1,38 @@
|
|||||||
.text
|
/ longjmp.gnu.s
|
||||||
.globl _longjmp
|
/
|
||||||
_longjmp:
|
/ Created: Oct 15, 1993 by Philip Homburg <philip@cs.vu.nl>
|
||||||
jmp __longjmp
|
|
||||||
|
|
||||||
/ $PchId: longjmp.gnu.s,v 1.4 1996/03/12 19:31:18 philip Exp $
|
.text
|
||||||
|
.globl _longjmp
|
||||||
|
_longjmp:
|
||||||
|
movl 4(%esp), %eax # jmp_buf
|
||||||
|
cmpl $0, 0(%eax) # save mask?
|
||||||
|
je 1f
|
||||||
|
leal 4(%eax), %edx # pointer to sigset_t
|
||||||
|
pushl %edx
|
||||||
|
call ___oldsigset # restore mask
|
||||||
|
addl $4, %esp
|
||||||
|
movl 4(%esp), %eax # jmp_buf
|
||||||
|
1:
|
||||||
|
movl 8(%esp), %ecx # result value
|
||||||
|
movl 12(%eax), %esp # restore stack pointer
|
||||||
|
|
||||||
|
movl 8(%eax), %edx # restore program counter
|
||||||
|
movl %edx, 0(%esp)
|
||||||
|
|
||||||
|
pushl %ecx # save result code
|
||||||
|
|
||||||
|
movl 16(%eax), %ebp # restore frame pointer
|
||||||
|
movl 20(%eax), %ebx
|
||||||
|
movl 24(%eax), %ecx
|
||||||
|
movl 28(%eax), %edx
|
||||||
|
movl 32(%eax), %esi
|
||||||
|
movl 36(%eax), %edi
|
||||||
|
pop %eax
|
||||||
|
testl %eax, %eax
|
||||||
|
jz 1f
|
||||||
|
ret
|
||||||
|
1: movl $1, %eax
|
||||||
|
ret
|
||||||
|
|
||||||
|
/ $PchId: longjmp.gnu.s,v 1.4 1996/03/12 19:30:02 philip Exp $
|
||||||
|
@ -1,6 +0,0 @@
|
|||||||
.text
|
|
||||||
.globl _setjmp
|
|
||||||
_setjmp:
|
|
||||||
jmp ___setjmp
|
|
||||||
|
|
||||||
/ $PchId: setjmp.gnu.s,v 1.4 1996/03/12 19:31:18 philip Exp $
|
|
@ -1,42 +1,10 @@
|
|||||||
#include <lib.h>
|
#include <lib.h>
|
||||||
#define sigfillset _sigfillset
|
#define sigfillset _sigfillset
|
||||||
#define sigjmp _sigjmp
|
|
||||||
#define sigprocmask _sigprocmask
|
#define sigprocmask _sigprocmask
|
||||||
#define sigreturn _sigreturn
|
#define sigreturn _sigreturn
|
||||||
#include <sys/sigcontext.h>
|
#include <sys/sigcontext.h>
|
||||||
#include <setjmp.h>
|
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
|
|
||||||
_PROTOTYPE( int sigjmp, (jmp_buf jb, int retval));
|
|
||||||
|
|
||||||
#if (_SETJMP_SAVES_REGS == 0)
|
|
||||||
/* 'sigreturn' using a short format jmp_buf (no registers saved). */
|
|
||||||
PUBLIC int sigjmp(jb, retval)
|
|
||||||
jmp_buf jb;
|
|
||||||
int retval;
|
|
||||||
{
|
|
||||||
struct sigcontext sc;
|
|
||||||
|
|
||||||
sc.sc_flags = jb[0].__flags;
|
|
||||||
sc.sc_mask = jb[0].__mask;
|
|
||||||
|
|
||||||
#if (CHIP == INTEL)
|
|
||||||
sc.sc_pc = (int) jb[0].__pc;
|
|
||||||
sc.sc_sp = (int) jb[0].__sp;
|
|
||||||
sc.sc_fp = (int) jb[0].__lb;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if (CHIP == M68000)
|
|
||||||
sc.sc_pc = (long) jb[0].__pc;
|
|
||||||
sc.sc_sp = (long) jb[0].__sp;
|
|
||||||
sc.sc_fp = (long) jb[0].__lb;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
sc.sc_retreg = retval;
|
|
||||||
return sigreturn(&sc);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
PUBLIC int sigreturn(scp)
|
PUBLIC int sigreturn(scp)
|
||||||
register struct sigcontext *scp;
|
register struct sigcontext *scp;
|
||||||
{
|
{
|
||||||
|
@ -89,7 +89,6 @@ libc_FILES=" \
|
|||||||
sigemptyset.s \
|
sigemptyset.s \
|
||||||
sigfillset.s \
|
sigfillset.s \
|
||||||
sigismember.s \
|
sigismember.s \
|
||||||
siglongjmp.s \
|
|
||||||
sigpending.s \
|
sigpending.s \
|
||||||
sigprocmask.s \
|
sigprocmask.s \
|
||||||
sigreturn.s \
|
sigreturn.s \
|
||||||
|
@ -1,7 +0,0 @@
|
|||||||
.sect .text
|
|
||||||
.extern _longjmp
|
|
||||||
.define _siglongjmp
|
|
||||||
.align 2
|
|
||||||
|
|
||||||
_siglongjmp:
|
|
||||||
jmp _longjmp
|
|
69
man/man3/setjmp.3
Normal file
69
man/man3/setjmp.3
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
.TH SETJMP 3 "June 22, 2006"
|
||||||
|
.UC 4
|
||||||
|
.SH NAME
|
||||||
|
setjmp, longjmp, _setjmp, _longjmp, sigsetjmp, siglongjmp \- save and restore execution contexts
|
||||||
|
.SH SYNOPSIS
|
||||||
|
.nf
|
||||||
|
.ft B
|
||||||
|
#include <setjmp.h>
|
||||||
|
|
||||||
|
int setjmp(jmp_buf env);
|
||||||
|
void longjmp(jmp_buf env, int val);
|
||||||
|
|
||||||
|
int _setjmp(jmp_buf env);
|
||||||
|
void _longjmp(jmp_buf env, int val);
|
||||||
|
|
||||||
|
#define _POSIX_SOURCE
|
||||||
|
int sigsetjmp(sigjmp_buf env, int savemask);
|
||||||
|
void siglongjmp(sigjmp_buf env, int val);
|
||||||
|
.SH DESCRIPTION
|
||||||
|
These calls provide a way for a process to save an execution context into a
|
||||||
|
buffer, and later resume execution from that context, effectively performing
|
||||||
|
a non-local jump. The
|
||||||
|
.B setjmp
|
||||||
|
family of functions store the context into the \fIenv\fP data structure,
|
||||||
|
and return the value 0. The
|
||||||
|
.B longjmp
|
||||||
|
family of functions jump to the context saved in the given \fIenv\fP data
|
||||||
|
structure, causing the process to continue as if it returned from the
|
||||||
|
corresponding
|
||||||
|
.B setjmp
|
||||||
|
call again, but this time with the non-zero return value in \fIval\fP.
|
||||||
|
.PP
|
||||||
|
The difference between the three pairs of setjmp/longjmp functions lies in the
|
||||||
|
behaviour with respect to saving/restoring the process signal mask. POSIX does
|
||||||
|
not require the process signal mask to be saved and restored during
|
||||||
|
.B setjmp
|
||||||
|
/
|
||||||
|
.B longjmp
|
||||||
|
\. However, the current implementation does this in order to agree with OSF/1
|
||||||
|
and other BSD derived systems.
|
||||||
|
.PP
|
||||||
|
The pair of functions
|
||||||
|
.B _setjmp
|
||||||
|
/
|
||||||
|
.B _longjmp
|
||||||
|
, traditional in BSD systems, may be used when the signal mask is not to be
|
||||||
|
saved/restored.
|
||||||
|
.PP
|
||||||
|
Finally, the POSIX
|
||||||
|
.B sigsetjmp
|
||||||
|
/
|
||||||
|
.B siglongjmp
|
||||||
|
functions allow the programmer to specify explicitly whether the signal mask
|
||||||
|
is to be saved/restored, by means of the \fIsavemask\fP parameter. If this
|
||||||
|
parameter is zero, the signal mask will not be saved/restored, otherwise it
|
||||||
|
will.
|
||||||
|
.SH NOTES
|
||||||
|
After the function calling
|
||||||
|
.B setjmp
|
||||||
|
has returned, the saved context may not be used in a call to
|
||||||
|
.B longjmp
|
||||||
|
anymore, since the relevant portion of the stack may already have been wiped
|
||||||
|
out at that point.
|
||||||
|
.PP
|
||||||
|
Using these functions to return to a previous state from a signal handler
|
||||||
|
is possible but should be done with extreme care, as some interrupted library
|
||||||
|
routines may not be reentrant and/or temporarily allocate resources.
|
||||||
|
.PP
|
||||||
|
See the setjmp.h header file for more implementation details specific to Minix.
|
Loading…
x
Reference in New Issue
Block a user