fix(mt): preserve range state across job callback
The first MT state-publication fix made the C count current before job construction, but the Rust result still unconditionally copied its local pre-job fill count back into `mtctx` after the callback returned. Preparing a job clears `mtctx->inBuff.buffer` and `mtctx->inBuff.filled`, so the next stream pass then observed a consumed range as if it were still active and returned a generic error in the multi-file CLI test. Keep the C-cleared state whenever job preparation has detached the active range. Rust's filled count is published only while the C range remains active, which covers the blocked/table-full path where no job reset occurred. The callback still receives the current count before preparation, and the C90 projection declaration is kept before executable statements. Test Plan: - `cc -fsyntax-only -Werror=incompatible-pointer-types -Ilib -Ilib/common -Ilib/compress -Ilib/decompress -Ilib/dict -Ilib/legacy lib/compress/zstdmt_compress.c` -- passed - `git diff --check` and `git diff --cached --check` -- passed - The capped upstream suite reproduced a generic error in the multi-file CLI path before this correction; the full rerun is pending
This commit is contained in:
@@ -2723,12 +2723,13 @@ static size_t ZSTDMT_createCompressionJob(void* opaque, size_t srcSize, unsigned
|
|||||||
{
|
{
|
||||||
ZSTDMT_CCtx* const mtctx = (ZSTDMT_CCtx*)opaque;
|
ZSTDMT_CCtx* const mtctx = (ZSTDMT_CCtx*)opaque;
|
||||||
ZSTD_EndDirective const endOp = (ZSTD_EndDirective)end;
|
ZSTD_EndDirective const endOp = (ZSTD_EndDirective)end;
|
||||||
|
ZSTDMT_RustCreateJobProjection projection;
|
||||||
/* Rust fills the reusable input range in its local projection before
|
/* Rust fills the reusable input range in its local projection before
|
||||||
* calling this C-owned job-construction callback. Publish that count
|
* calling this C-owned job-construction callback. Publish that count
|
||||||
* before the callback prepares a job and checks the C context. */
|
* before the callback prepares a job and checks the C context. */
|
||||||
assert(srcSize <= mtctx->inBuff.buffer.capacity);
|
assert(srcSize <= mtctx->inBuff.buffer.capacity);
|
||||||
mtctx->inBuff.filled = srcSize;
|
mtctx->inBuff.filled = srcSize;
|
||||||
ZSTDMT_RustCreateJobProjection const projection = {
|
projection = (ZSTDMT_RustCreateJobProjection){
|
||||||
mtctx->doneJobID,
|
mtctx->doneJobID,
|
||||||
mtctx->nextJobID,
|
mtctx->nextJobID,
|
||||||
mtctx->jobIDMask,
|
mtctx->jobIDMask,
|
||||||
@@ -3099,7 +3100,11 @@ size_t ZSTDMT_compressStream_generic(ZSTDMT_CCtx* mtctx,
|
|||||||
(U32)endOp, (U32)(input->size - input->pos));
|
(U32)endOp, (U32)(input->size - input->pos));
|
||||||
assert(output->pos <= output->size);
|
assert(output->pos <= output->size);
|
||||||
assert(input->pos <= input->size);
|
assert(input->pos <= input->size);
|
||||||
mtctx->inBuff.filled = result.inBuffFilled;
|
/* A prepared job clears the C range while Rust still has the pre-job
|
||||||
|
* count in its local projection. Only publish the result when the range
|
||||||
|
* remains active, which is the no-job-created path. */
|
||||||
|
if (mtctx->inBuff.buffer.start != NULL)
|
||||||
|
mtctx->inBuff.filled = result.inBuffFilled;
|
||||||
input->pos = result.inputPos;
|
input->pos = result.inputPos;
|
||||||
output->pos = result.outputPos;
|
output->pos = result.outputPos;
|
||||||
DEBUGLOG(5, "end of ZSTDMT_compressStream_generic: remainingToFlush = %u", (U32)result.result);
|
DEBUGLOG(5, "end of ZSTDMT_compressStream_generic: remainingToFlush = %u", (U32)result.result);
|
||||||
|
|||||||
Reference in New Issue
Block a user