refactor(mt): move input-range commit policy to Rust

Move the ready/wrap branch and synchronization ordering from ZSTDMT_tryGetInputRange into Rust. The Rust policy now waits for the prefix range, invokes the C-owned prefix move, waits for the selected source range, and publishes the buffer; C retains memmove, private buffer fields, round-buffer state, and LDM callbacks behind the projection. Add ABI assertions and focused wrapped/ordinary ordering tests.

Test Plan: git diff --cached --check; focused Rust tests added; full capped Rust/native/original-suite verification follows.
This commit is contained in:
2026-07-21 07:16:29 +02:00
parent fc9aeee92b
commit 3215458381
2 changed files with 304 additions and 37 deletions
+72 -34
View File
@@ -957,6 +957,19 @@ typedef struct {
size_t bufferCapacity;
size_t roundBufferPos;
} ZSTDMT_RustTryGetInputRangeResult;
typedef char ZSTDMT_rust_try_get_input_range_result_layout[
(offsetof(ZSTDMT_RustTryGetInputRangeResult, ready) == 0
&& offsetof(ZSTDMT_RustTryGetInputRangeResult, movePrefix)
== sizeof(unsigned)
&& offsetof(ZSTDMT_RustTryGetInputRangeResult, bufferStart)
== 2 * sizeof(unsigned)
&& offsetof(ZSTDMT_RustTryGetInputRangeResult, bufferCapacity)
== 2 * sizeof(unsigned) + sizeof(void*)
&& offsetof(ZSTDMT_RustTryGetInputRangeResult, roundBufferPos)
== 2 * sizeof(unsigned) + sizeof(void*) + sizeof(size_t)
&& sizeof(ZSTDMT_RustTryGetInputRangeResult)
== 2 * sizeof(unsigned) + sizeof(void*) + 2 * sizeof(size_t))
? 1 : -1];
typedef void (*ZSTDMT_jobProjectionFn)(void* opaque, unsigned jobID,
ZSTDMT_RustJobProjection* projection);
ZSTDMT_RustInputRange ZSTDMT_rust_getInputDataInUse(
@@ -965,6 +978,19 @@ ZSTDMT_RustInputRange ZSTDMT_rust_getInputDataInUse(
void* opaque, ZSTDMT_jobProjectionFn projectJob);
ZSTDMT_RustTryGetInputRangeResult ZSTDMT_rust_tryGetInputRange(
const ZSTDMT_RustTryGetInputRangeProjection* projection);
typedef void (*ZSTDMT_inputRangeWaitFn)(
void* opaque, void* bufferStart, size_t bufferCapacity);
typedef void (*ZSTDMT_inputRangeMovePrefixFn)(
void* opaque, void* destination, const void* source, size_t size,
size_t roundBufferPos);
typedef void (*ZSTDMT_inputRangePublishBufferFn)(
void* opaque, void* bufferStart, size_t bufferCapacity);
int ZSTDMT_rust_commitInputRange(
const ZSTDMT_RustTryGetInputRangeResult* result,
void* roundBufferStart, const void* prefixStart, size_t prefixSize,
void* opaque, ZSTDMT_inputRangeWaitFn waitForLdm,
ZSTDMT_inputRangeMovePrefixFn movePrefix,
ZSTDMT_inputRangePublishBufferFn publishBuffer);
size_t ZSTDMT_rust_toFlushNow(unsigned doneJobID, unsigned nextJobID,
unsigned jobIDMask, void* opaque,
ZSTDMT_jobProjectionFn projectJob);
@@ -3296,6 +3322,43 @@ static void ZSTDMT_waitForLdmComplete(ZSTDMT_CCtx* mtctx, Buffer buffer)
ZSTDMT_rust_waitForLdmComplete(&state);
}
static void ZSTDMT_inputRangeWaitForLdm(
void* opaque, void* bufferStart, size_t bufferCapacity)
{
ZSTDMT_waitForLdmComplete((ZSTDMT_CCtx*)opaque,
(Buffer){ bufferStart, bufferCapacity });
}
static void ZSTDMT_inputRangeMovePrefix(
void* opaque, void* destination, const void* source, size_t size,
size_t roundBufferPos)
{
ZSTDMT_CCtx* const mtctx = (ZSTDMT_CCtx*)opaque;
/* ZSTD_invalidateRepCodes() doesn't work for extDict variants.
* Simply copy the prefix to the beginning in that case. */
ZSTD_memmove(destination, source, size);
mtctx->inBuff.prefix.start = (const BYTE*)destination;
mtctx->roundBuff.pos = roundBufferPos;
}
static void ZSTDMT_inputRangePublishBuffer(
void* opaque, void* bufferStart, size_t bufferCapacity)
{
ZSTDMT_CCtx* const mtctx = (ZSTDMT_CCtx*)opaque;
Buffer const buffer = { bufferStart, bufferCapacity };
DEBUGLOG(5, "Using prefix range [%zx, %zx)",
(size_t)mtctx->inBuff.prefix.start,
(size_t)mtctx->inBuff.prefix.start + mtctx->inBuff.prefix.size);
DEBUGLOG(5, "Using source range [%zx, %zx)",
(size_t)buffer.start,
(size_t)buffer.start + buffer.capacity);
mtctx->inBuff.buffer = buffer;
mtctx->inBuff.filled = 0;
assert(mtctx->roundBuff.pos + buffer.capacity <= mtctx->roundBuff.capacity);
}
/**
* Attempts to set the inBuff to the next section to fill.
* If any part of the new section is still in use we give up.
@@ -3316,47 +3379,22 @@ static int ZSTDMT_tryGetInputRange(ZSTDMT_CCtx* mtctx)
};
ZSTDMT_RustTryGetInputRangeResult const result =
ZSTDMT_rust_tryGetInputRange(&projection);
Buffer buffer;
DEBUGLOG(5, "ZSTDMT_tryGetInputRange");
assert(mtctx->inBuff.buffer.start == NULL);
if (!result.ready) {
if (!ZSTDMT_rust_commitInputRange(
&result,
mtctx->roundBuff.buffer,
mtctx->inBuff.prefix.start,
mtctx->inBuff.prefix.size,
mtctx,
ZSTDMT_inputRangeWaitForLdm,
ZSTDMT_inputRangeMovePrefix,
ZSTDMT_inputRangePublishBuffer)) {
DEBUGLOG(5, "Waiting for buffer...");
return 0;
}
if (result.movePrefix) {
/* ZSTD_invalidateRepCodes() doesn't work for extDict variants.
* Simply copy the prefix to the beginning in that case.
*/
BYTE* const start = (BYTE*)mtctx->roundBuff.buffer;
size_t const prefixSize = mtctx->inBuff.prefix.size;
buffer.start = start;
buffer.capacity = prefixSize;
ZSTDMT_waitForLdmComplete(mtctx, buffer);
ZSTD_memmove(start, mtctx->inBuff.prefix.start, prefixSize);
mtctx->inBuff.prefix.start = start;
mtctx->roundBuff.pos = result.roundBufferPos;
}
buffer.start = (BYTE*)result.bufferStart;
buffer.capacity = result.bufferCapacity;
ZSTDMT_waitForLdmComplete(mtctx, buffer);
DEBUGLOG(5, "Using prefix range [%zx, %zx)",
(size_t)mtctx->inBuff.prefix.start,
(size_t)mtctx->inBuff.prefix.start + mtctx->inBuff.prefix.size);
DEBUGLOG(5, "Using source range [%zx, %zx)",
(size_t)buffer.start,
(size_t)buffer.start + buffer.capacity);
mtctx->inBuff.buffer = buffer;
mtctx->inBuff.filled = 0;
assert(mtctx->roundBuff.pos + buffer.capacity <= mtctx->roundBuff.capacity);
return 1;
}