feat(compress): move trace context reset to Rust
Keep the C-owned trace slot behind an explicit pointer projection so the Rust trace boundary owns the complete enabled-call lifecycle. Rust now reads the context, publishes the record, and clears the slot after the callback; C only supplies private CCtx fields and the weak callback adapter. Test Plan: - ulimit -v 41943040; CARGO_BUILD_JOBS=1 cargo check --tests (rust) - ulimit -v 41943040; CARGO_BUILD_JOBS=1 cargo clippy --tests -- -A clippy::manual-bits -D warnings (rust) - ulimit -v 41943040; make -j1 - ulimit -v 41943040; make -j1 -C tests test - Focused trace lifecycle test added; standalone cargo test remains link-blocked by the existing C-owned decompression view symbols.
This commit is contained in:
@@ -7362,7 +7362,7 @@ typedef void (*ZSTD_rust_traceEnd_f)(
|
||||
void* context, unsigned long long traceCtx, const void* trace);
|
||||
typedef struct {
|
||||
void* callbackContext;
|
||||
unsigned long long traceCtx;
|
||||
unsigned long long* traceCtx;
|
||||
int streaming;
|
||||
unsigned dictionaryID;
|
||||
size_t dictionarySize;
|
||||
@@ -7413,7 +7413,7 @@ void ZSTD_CCtx_trace(ZSTD_CCtx* cctx, size_t extraCSize)
|
||||
#if ZSTD_TRACE
|
||||
ZSTD_rust_traceEndState state;
|
||||
state.callbackContext = cctx;
|
||||
state.traceCtx = cctx->traceCtx;
|
||||
state.traceCtx = &cctx->traceCtx;
|
||||
state.streaming = cctx->inBuffSize > 0 || cctx->outBuffSize > 0
|
||||
|| cctx->appliedParams.nbWorkers > 0;
|
||||
state.dictionaryID = cctx->dictID;
|
||||
@@ -7424,7 +7424,6 @@ void ZSTD_CCtx_trace(ZSTD_CCtx* cctx, size_t extraCSize)
|
||||
state.cctx = cctx;
|
||||
state.traceEnd = ZSTD_rust_traceEnd_callback;
|
||||
ZSTD_rust_traceEnd(&state);
|
||||
cctx->traceCtx = 0;
|
||||
#else
|
||||
(void)cctx;
|
||||
(void)extraCSize;
|
||||
|
||||
@@ -2840,7 +2840,7 @@ const _: () = {
|
||||
#[repr(C)]
|
||||
pub struct ZSTD_rust_traceEndState {
|
||||
callback_context: *mut c_void,
|
||||
trace_ctx: u64,
|
||||
trace_ctx: *mut u64,
|
||||
streaming: c_int,
|
||||
dictionary_id: c_uint,
|
||||
dictionary_size: usize,
|
||||
@@ -2855,9 +2855,9 @@ const _: () = {
|
||||
assert!(size_of::<CompressTraceEndFn>() == size_of::<usize>());
|
||||
assert!(offset_of!(ZSTD_rust_traceEndState, callback_context) == 0);
|
||||
assert!(offset_of!(ZSTD_rust_traceEndState, trace_ctx) == size_of::<usize>());
|
||||
assert!(offset_of!(ZSTD_rust_traceEndState, streaming) == size_of::<usize>() + size_of::<u64>());
|
||||
assert!(offset_of!(ZSTD_rust_traceEndState, dictionary_id) == size_of::<usize>() + size_of::<u64>() + size_of::<c_int>());
|
||||
assert!(offset_of!(ZSTD_rust_traceEndState, dictionary_size) == size_of::<usize>() + size_of::<u64>() + 2 * size_of::<c_int>());
|
||||
assert!(offset_of!(ZSTD_rust_traceEndState, streaming) == 2 * size_of::<usize>());
|
||||
assert!(offset_of!(ZSTD_rust_traceEndState, dictionary_id) == 2 * size_of::<usize>() + size_of::<c_int>());
|
||||
assert!(offset_of!(ZSTD_rust_traceEndState, dictionary_size) == 2 * size_of::<usize>() + 2 * size_of::<c_int>());
|
||||
assert!(offset_of!(ZSTD_rust_traceEndState, uncompressed_size) == offset_of!(ZSTD_rust_traceEndState, dictionary_size) + size_of::<usize>());
|
||||
assert!(offset_of!(ZSTD_rust_traceEndState, compressed_size) == offset_of!(ZSTD_rust_traceEndState, dictionary_size) + 2 * size_of::<usize>());
|
||||
assert!(offset_of!(ZSTD_rust_traceEndState, params) == offset_of!(ZSTD_rust_traceEndState, dictionary_size) + 3 * size_of::<usize>());
|
||||
@@ -2872,7 +2872,10 @@ pub unsafe extern "C" fn ZSTD_rust_traceEnd(state: *const ZSTD_rust_traceEndStat
|
||||
let Some(state) = (unsafe { state.as_ref() }) else {
|
||||
return;
|
||||
};
|
||||
if state.trace_ctx == 0 {
|
||||
let Some(trace_ctx) = (unsafe { state.trace_ctx.as_ref() }).copied() else {
|
||||
return;
|
||||
};
|
||||
if trace_ctx == 0 {
|
||||
return;
|
||||
}
|
||||
let trace = ZSTD_Trace {
|
||||
@@ -2890,9 +2893,10 @@ pub unsafe extern "C" fn ZSTD_rust_traceEnd(state: *const ZSTD_rust_traceEndStat
|
||||
unsafe {
|
||||
(state.trace_end)(
|
||||
state.callback_context,
|
||||
state.trace_ctx,
|
||||
trace_ctx,
|
||||
(&trace as *const ZSTD_Trace).cast(),
|
||||
);
|
||||
*state.trace_ctx = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24277,4 +24281,49 @@ mod tests {
|
||||
drop(Box::from_raw(state.callbacks.cast_mut()));
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
struct TraceEndTestContext {
|
||||
calls: usize,
|
||||
trace_ctx: u64,
|
||||
version: c_uint,
|
||||
}
|
||||
|
||||
unsafe extern "C" fn trace_end_test_callback(
|
||||
context: *mut c_void,
|
||||
trace_ctx: u64,
|
||||
trace: *const c_void,
|
||||
) {
|
||||
let context = unsafe { &mut *context.cast::<TraceEndTestContext>() };
|
||||
context.calls += 1;
|
||||
context.trace_ctx = trace_ctx;
|
||||
context.version = unsafe { (*trace.cast::<ZSTD_Trace>()).version };
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn trace_end_publishes_once_and_clears_context() {
|
||||
let mut callback_context = TraceEndTestContext::default();
|
||||
let mut trace_ctx = 42;
|
||||
let state = ZSTD_rust_traceEndState {
|
||||
callback_context: (&mut callback_context as *mut TraceEndTestContext).cast(),
|
||||
trace_ctx: &mut trace_ctx,
|
||||
streaming: 1,
|
||||
dictionary_id: 7,
|
||||
dictionary_size: 11,
|
||||
uncompressed_size: 13,
|
||||
compressed_size: 17,
|
||||
params: ptr::null(),
|
||||
cctx: ptr::null(),
|
||||
trace_end: trace_end_test_callback,
|
||||
};
|
||||
|
||||
unsafe { ZSTD_rust_traceEnd(&state) };
|
||||
assert_eq!(trace_ctx, 0);
|
||||
assert_eq!(callback_context.calls, 1);
|
||||
assert_eq!(callback_context.trace_ctx, 42);
|
||||
assert_eq!(callback_context.version, ZSTD_VERSION_NUMBER as c_uint);
|
||||
|
||||
unsafe { ZSTD_rust_traceEnd(&state) };
|
||||
assert_eq!(callback_context.calls, 1);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user