refactor(mt): export window overlap policy from Rust

Move the MT LDM overlap predicate behind the original
ZSTDMT_doesOverlapWindow() by-value ABI. Rust now owns the half-open range
calculation through a checked representation of Buffer and ZSTD_window_t;
C retains the synchronization and context orchestration around the callback.

Test Plan:
- `cc -fsyntax-only -Ilib -Ilib/common -Ilib/compress -Ilib/decompress -Ilib/dict -Ilib/legacy lib/compress/zstdmt_compress.c` -- passed.
- `cargo +nightly fmt --manifest-path rust/Cargo.toml --all -- --check` -- passed.
- `git diff --check` and `git diff --cached --check` -- passed.
- Heavy verification intentionally deferred until the combined seam set is ready.
This commit is contained in:
2026-07-20 13:59:15 +02:00
parent fe3587c637
commit 8919e0d292
2 changed files with 69 additions and 15 deletions
+1 -15
View File
@@ -2910,21 +2910,7 @@ static Range ZSTDMT_getInputDataInUse(ZSTDMT_CCtx* mtctx)
return (Range){ range.start, range.size };
}
static int ZSTDMT_doesOverlapWindow(Buffer buffer, ZSTD_window_t window)
{
DEBUGLOG(5, "ZSTDMT_doesOverlapWindow");
DEBUGLOG(5, "extDict [0x%zx, 0x%zx)",
(size_t)window.dictBase + window.lowLimit,
(size_t)window.dictBase + window.dictLimit);
DEBUGLOG(5, "prefix [0x%zx, 0x%zx)",
(size_t)window.base + window.dictLimit,
(size_t)window.nextSrc);
return ZSTDMT_rust_doesOverlapWindow(buffer.start, buffer.capacity,
window.nextSrc, window.base,
window.dictBase, window.dictLimit,
window.lowLimit);
}
int ZSTDMT_doesOverlapWindow(Buffer buffer, ZSTD_window_t window);
static void ZSTDMT_waitForLdmLock(void* opaque)
{
+68
View File
@@ -3420,6 +3420,27 @@ pub struct ZstdMtBuffer {
pub capacity: usize,
}
/// ABI-compatible representation of the private C `ZSTD_window_t` used by
/// the MT LDM overlap callback.
#[repr(C)]
#[derive(Clone, Copy, Default)]
pub struct ZstdMtWindow {
pub nextSrc: *const u8,
pub base: *const u8,
pub dictBase: *const u8,
pub dictLimit: u32,
pub lowLimit: u32,
pub nbOverflowCorrections: u32,
}
const _: () = {
assert!(std::mem::offset_of!(ZstdMtWindow, nextSrc) == 0);
assert!(std::mem::offset_of!(ZstdMtWindow, base) == size_of::<usize>());
assert!(std::mem::offset_of!(ZstdMtWindow, dictBase) == 2 * size_of::<usize>());
assert!(std::mem::offset_of!(ZstdMtWindow, dictLimit) == 3 * size_of::<usize>());
assert!(size_of::<ZstdMtWindow>() == if size_of::<usize>() == 8 { 40 } else { 24 });
};
/// ABI-compatible representation of `rawSeq` from `zstd_compress_internal.h`.
#[repr(C)]
#[derive(Clone, Copy, Default)]
@@ -3548,6 +3569,24 @@ pub extern "C" fn ZSTDMT_rust_doesOverlapWindow(
) != 0) as c_int
}
/// Return non-zero when a buffer overlaps either range in a C window.
///
/// This keeps the original by-value internal ABI while the scalar helper
/// above remains available to projections that cannot expose the private
/// window layout.
#[no_mangle]
pub extern "C" fn ZSTDMT_doesOverlapWindow(buffer: ZstdMtBuffer, window: ZstdMtWindow) -> c_int {
ZSTDMT_rust_doesOverlapWindow(
buffer.start as *const c_void,
buffer.capacity,
window.nextSrc.cast(),
window.base.cast(),
window.dictBase.cast(),
window.dictLimit,
window.lowLimit,
)
}
#[derive(Default)]
struct BufferPoolState {
buffer_size: usize,
@@ -7850,6 +7889,35 @@ mod tests {
);
}
#[test]
fn direct_overlap_window_abi_matches_scalar_policy() {
let bytes = [0u8; 32];
let base = bytes.as_ptr();
let window = ZstdMtWindow {
nextSrc: base.wrapping_add(16),
base,
dictBase: base.wrapping_add(16),
dictLimit: 8,
lowLimit: 4,
nbOverflowCorrections: 0,
};
let buffer = ZstdMtBuffer {
start: base.wrapping_add(20) as *mut c_void,
capacity: 4,
};
assert_eq!(ZSTDMT_doesOverlapWindow(buffer, window), 1);
assert_eq!(
ZSTDMT_doesOverlapWindow(
ZstdMtBuffer {
start: base as *mut u8 as *mut c_void,
capacity: 4,
},
window,
),
0
);
}
#[test]
fn buffer_pool_reuses_and_resizes_buffers() {
let pool = unsafe { ZSTDMT_rust_buffer_pool_create(2, DEFAULT_MEM) };