Skip to content

Commit 5cbf5ee

Browse files
committed
Optimize loading of preallocated context
This caches the initialization state of preallocated context in a thread local variable to avoid atomics in subsequent accesses.
1 parent 36c96a9 commit 5cbf5ee

File tree

1 file changed

+21
-7
lines changed

1 file changed

+21
-7
lines changed

secp256k1-sys/src/lib.rs

+21-7
Original file line numberDiff line numberDiff line change
@@ -759,20 +759,34 @@ mod fuzz_dummy {
759759

760760
static HAVE_PREALLOCATED_CONTEXT: once::Once = once::Once::INIT;
761761
static mut PREALLOCATED_CONTEXT: [u8; CTX_SIZE] = [0; CTX_SIZE];
762+
#[cfg(feature = "std")]
763+
thread_local! {
764+
static CACHE_HAVE_PREALLOCATED_CONTEXT: std::cell::Cell<bool> = std::cell::Cell::new(false);
765+
}
762766
pub unsafe fn secp256k1_context_preallocated_create(prealloc: *mut c_void, flags: c_uint) -> *mut Context {
763767
// While applications should generally avoid creating too many contexts, sometimes fuzzers
764768
// perform tasks repeatedly which real applications may only do rarely. Thus, we want to
765769
// avoid being overly slow here. We do so by having a static context and copying it into
766770
// new buffers instead of recalculating it. Because we shouldn't rely on std, we use a
767771
// simple hand-written OnceFlag built out of an atomic to gate the global static.
768772

769-
HAVE_PREALLOCATED_CONTEXT.run(|| {
770-
assert!(rustsecp256k1_v0_4_1_context_preallocated_size(SECP256K1_START_SIGN | SECP256K1_START_VERIFY) + std::mem::size_of::<c_uint>() <= CTX_SIZE);
771-
assert_eq!(rustsecp256k1_v0_4_1_context_preallocated_create(
772-
PREALLOCATED_CONTEXT[..].as_ptr() as *mut c_void,
773-
SECP256K1_START_SIGN | SECP256K1_START_VERIFY),
774-
PREALLOCATED_CONTEXT[..].as_ptr() as *mut Context);
775-
});
773+
#[cfg(feature = "std")]
774+
let should_initialize = !CACHE_HAVE_PREALLOCATED_CONTEXT.with(|value| value.get());
775+
776+
#[cfg(not(feature = "std"))]
777+
let should_initialize = true;
778+
779+
if should_initialize {
780+
HAVE_PREALLOCATED_CONTEXT.run(|| {
781+
assert!(rustsecp256k1_v0_4_1_context_preallocated_size(SECP256K1_START_SIGN | SECP256K1_START_VERIFY) + std::mem::size_of::<c_uint>() <= CTX_SIZE);
782+
assert_eq!(rustsecp256k1_v0_4_1_context_preallocated_create(
783+
PREALLOCATED_CONTEXT[..].as_ptr() as *mut c_void,
784+
SECP256K1_START_SIGN | SECP256K1_START_VERIFY),
785+
PREALLOCATED_CONTEXT[..].as_ptr() as *mut Context);
786+
});
787+
#[cfg(feature = "std")]
788+
CACHE_HAVE_PREALLOCATED_CONTEXT.with(|value| value.set(true));
789+
}
776790

777791
ptr::copy_nonoverlapping(PREALLOCATED_CONTEXT[..].as_ptr(), prealloc as *mut u8, CTX_SIZE);
778792
let ptr = (prealloc as *mut u8).add(CTX_SIZE).sub(std::mem::size_of::<c_uint>());

0 commit comments

Comments
 (0)