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:
@@ -2910,21 +2910,7 @@ static Range ZSTDMT_getInputDataInUse(ZSTDMT_CCtx* mtctx)
|
|||||||
return (Range){ range.start, range.size };
|
return (Range){ range.start, range.size };
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ZSTDMT_doesOverlapWindow(Buffer buffer, ZSTD_window_t window)
|
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void ZSTDMT_waitForLdmLock(void* opaque)
|
static void ZSTDMT_waitForLdmLock(void* opaque)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -3420,6 +3420,27 @@ pub struct ZstdMtBuffer {
|
|||||||
pub capacity: usize,
|
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`.
|
/// ABI-compatible representation of `rawSeq` from `zstd_compress_internal.h`.
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Clone, Copy, Default)]
|
#[derive(Clone, Copy, Default)]
|
||||||
@@ -3548,6 +3569,24 @@ pub extern "C" fn ZSTDMT_rust_doesOverlapWindow(
|
|||||||
) != 0) as c_int
|
) != 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)]
|
#[derive(Default)]
|
||||||
struct BufferPoolState {
|
struct BufferPoolState {
|
||||||
buffer_size: usize,
|
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]
|
#[test]
|
||||||
fn buffer_pool_reuses_and_resizes_buffers() {
|
fn buffer_pool_reuses_and_resizes_buffers() {
|
||||||
let pool = unsafe { ZSTDMT_rust_buffer_pool_create(2, DEFAULT_MEM) };
|
let pool = unsafe { ZSTDMT_rust_buffer_pool_create(2, DEFAULT_MEM) };
|
||||||
|
|||||||
Reference in New Issue
Block a user