feat(setjmp): x86_64 setjmp/longjmp/sigsetjmp
This commit is contained in:
@@ -0,0 +1,117 @@
|
||||
#ifndef VLIBC_SETJMP_H
|
||||
#define VLIBC_SETJMP_H
|
||||
|
||||
/*
|
||||
* vlibc — <setjmp.h>.
|
||||
*
|
||||
* Non-local jumps. setjmp(env) saves the calling environment and returns 0;
|
||||
* longjmp(env, val) makes that setjmp return val, with 0 coerced to 1 so the
|
||||
* two returns are distinguishable. sigsetjmp/siglongjmp additionally save and
|
||||
* restore the signal mask when the buffer's saved-mask flag is set.
|
||||
*
|
||||
* jmp_buf is an array type (C23 7.13.1 requires it); both types below are
|
||||
* arrays of unsigned long. The word layout is ABI: the x86_64 assembly in
|
||||
* src/setjmp/x86_64/{setjmp,longjmp,sigsetjmp,siglongjmp}.s reads and writes
|
||||
* exactly these slots. This comment is the single authoritative map — keep it
|
||||
* and those files in sync:
|
||||
*
|
||||
* [0] rbx callee-saved general registers (System V AMD64 ABI)
|
||||
* [1] rbp
|
||||
* [2] r12
|
||||
* [3] r13
|
||||
* [4] r14
|
||||
* [5] r15
|
||||
* [6] rsp the caller's stack pointer (just past the return address)
|
||||
* [7] rip the return address, where longjmp resumes execution
|
||||
* [8] mxcsr SSE control/status register (stmxcsr/ldmxcsr)
|
||||
* [9] x87 cw x87 control word (fnstcw/fldcw)
|
||||
*
|
||||
* sigjmp_buf extends the base layout with two more words:
|
||||
*
|
||||
* [10] saved-mask flag (1 when the signal mask was saved)
|
||||
* [11] signal mask (the x86_64 Linux sigset_t: a single 64-bit word)
|
||||
*
|
||||
* Because the base layout occupies words 0..9 of both types, the plain
|
||||
* setjmp/longjmp assembly works verbatim on sigjmp_buf storage as well.
|
||||
*/
|
||||
|
||||
#include <vlibc/features.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Word counts and per-slot indices (see the authoritative map above). */
|
||||
#define VLIBC_JMP_BUF_WORDS 10
|
||||
#define VLIBC_JMP_RBX 0
|
||||
#define VLIBC_JMP_RBP 1
|
||||
#define VLIBC_JMP_R12 2
|
||||
#define VLIBC_JMP_R13 3
|
||||
#define VLIBC_JMP_R14 4
|
||||
#define VLIBC_JMP_R15 5
|
||||
#define VLIBC_JMP_RSP 6
|
||||
#define VLIBC_JMP_RIP 7
|
||||
#define VLIBC_JMP_MXCSR 8
|
||||
#define VLIBC_JMP_X87CW 9
|
||||
|
||||
#define VLIBC_SIGJMP_BUF_WORDS 12
|
||||
#define VLIBC_SIGJMP_FLAG 10
|
||||
#define VLIBC_SIGJMP_MASK 11
|
||||
|
||||
typedef unsigned long jmp_buf[VLIBC_JMP_BUF_WORDS];
|
||||
typedef unsigned long sigjmp_buf[VLIBC_SIGJMP_BUF_WORDS];
|
||||
|
||||
/*
|
||||
* Save the calling environment and return 0; after longjmp(env, val) the
|
||||
* matching setjmp invocation returns val. A macro (C23 7.13.1: usable without
|
||||
* a prototype in scope); it expands to _setjmp(env).
|
||||
*/
|
||||
#define setjmp(env) _setjmp(env)
|
||||
|
||||
/*
|
||||
* Like setjmp, plus the current signal mask is saved into env when savemask is
|
||||
* nonzero (siglongjmp then restores it). Macro expanding to
|
||||
* __sigsetjmp(env, savemask).
|
||||
*/
|
||||
#define sigsetjmp(env, savemask) __sigsetjmp(env, savemask)
|
||||
|
||||
/*
|
||||
* The save behind the setjmp macro; identical semantics (POSIX _setjmp).
|
||||
*/
|
||||
int
|
||||
_setjmp(jmp_buf env); // NOLINT(bugprone-reserved-identifier)
|
||||
|
||||
/*
|
||||
* Restore the environment saved by _setjmp/setjmp and make it return val, with
|
||||
* 0 coerced to 1. Does not return.
|
||||
*/
|
||||
__attribute__((noreturn)) void
|
||||
_longjmp(jmp_buf env, int val); // NOLINT(bugprone-reserved-identifier)
|
||||
|
||||
/*
|
||||
* ISO C longjmp: same as _longjmp.
|
||||
*/
|
||||
__attribute__((noreturn)) void
|
||||
longjmp(jmp_buf env, int val);
|
||||
|
||||
/*
|
||||
* The save behind the sigsetjmp macro. Implementation-reserved name, so the
|
||||
* public API keeps only the macro; declared because the macro expansion must
|
||||
* have a prototype in scope (C23 removed implicit declarations).
|
||||
*/
|
||||
int
|
||||
__sigsetjmp(sigjmp_buf env, int savemask); // NOLINT(bugprone-reserved-identifier)
|
||||
|
||||
/*
|
||||
* Restore the environment saved by sigsetjmp and make it return val, with 0
|
||||
* coerced to 1; when the buffer's saved-mask flag is set, the signal mask is
|
||||
* restored first. Does not return.
|
||||
*/
|
||||
__attribute__((noreturn)) void
|
||||
siglongjmp(sigjmp_buf env, int val);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* VLIBC_SETJMP_H */
|
||||
Reference in New Issue
Block a user