Use sigsetjmp instead of setjmp (#2645)

Apparently on macOS `setjmp` manipulates the process-wide signal mask
which adds a good deal of overhead. We don't actually need this
functionality so this commit switches to using the `sig` version of
setjmp/longjmp where we can explicitly ask the signal mask to not get
preserved. This came out of poking around on #2644 and on macOS locally
thi sdropped the overhead from 721ns to 55ns.
This commit is contained in:
Alex Crichton
2021-02-08 12:05:11 -06:00
committed by GitHub
parent 8ee0f09983
commit 5b55ba8053
2 changed files with 24 additions and 4 deletions

View File

@@ -1,7 +1,13 @@
use std::env;
fn main() { fn main() {
println!("cargo:rerun-if-changed=src/helpers.c"); println!("cargo:rerun-if-changed=src/helpers.c");
cc::Build::new() cc::Build::new()
.warnings(true) .warnings(true)
.define(
&format!("CFG_TARGET_OS_{}", env::var("CARGO_CFG_TARGET_OS").unwrap()),
None,
)
.file("src/helpers.c") .file("src/helpers.c")
.compile("helpers"); .compile("helpers");
} }

View File

@@ -1,11 +1,25 @@
#include <setjmp.h> #include <setjmp.h>
// Note that `sigsetjmp` and `siglongjmp` are used here where possible to
// explicitly pass a 0 argument to `sigsetjmp` that we don't need to preserve
// the process signal mask. This should make this call a bit faster b/c it
// doesn't need to touch the kernel signal handling routines.
#ifdef CFG_TARGET_OS_windows
#define platform_setjmp(buf) setjmp(buf)
#define platform_longjmp(buf, arg) longjmp(buf, arg)
#define platform_jmp_buf jmp_buf
#else
#define platform_setjmp(buf) sigsetjmp(buf, 0)
#define platform_longjmp(buf, arg) siglongjmp(buf, arg)
#define platform_jmp_buf sigjmp_buf
#endif
int RegisterSetjmp( int RegisterSetjmp(
void **buf_storage, void **buf_storage,
void (*body)(void*), void (*body)(void*),
void *payload) { void *payload) {
jmp_buf buf; platform_jmp_buf buf;
if (setjmp(buf) != 0) { if (platform_setjmp(buf) != 0) {
return 0; return 0;
} }
*buf_storage = &buf; *buf_storage = &buf;
@@ -14,6 +28,6 @@ int RegisterSetjmp(
} }
void Unwind(void *JmpBuf) { void Unwind(void *JmpBuf) {
jmp_buf *buf = (jmp_buf*) JmpBuf; platform_jmp_buf *buf = (platform_jmp_buf*) JmpBuf;
longjmp(*buf, 1); platform_longjmp(*buf, 1);
} }