refactor(mt): move context teardown order to Rust

Move ZSTDMT_freeCCtx ownership branches and teardown ordering into Rust while
keeping the MT context, worker pool, synchronization, dictionary, and custom
allocator layouts private to C callbacks.  Preserve the original factory and
round-buffer conditions, release jobs before destroying the pools, and keep
free-on-null compatible with the C API.

Test Plan:
- ulimit -v 41943040; CARGO_BUILD_JOBS=1 cargo test --manifest-path rust/Cargo.toml free_cctx --lib
- ulimit -v 41943040; CARGO_BUILD_JOBS=1 cargo clippy --manifest-path rust/Cargo.toml --all-targets -- -D warnings
- ulimit -v 41943040; make -j1
This commit is contained in:
2026-07-20 04:49:27 +02:00
parent 6d164b7746
commit 907c3af89e
2 changed files with 322 additions and 14 deletions
+108 -14
View File
@@ -593,6 +593,39 @@ void ZSTDMT_rust_serialStateFree(
ZSTDMT_serialStateVoidFn destroyLdmMutex,
ZSTDMT_serialStateVoidFn destroyLdmCond,
ZSTDMT_serialStateVoidFn freeTables);
typedef void (*ZSTDMT_freeCCtxCallbackFn)(void* opaque);
typedef struct {
void* callbackContext;
size_t providedFactory;
size_t roundBuffPresent;
ZSTDMT_freeCCtxCallbackFn freeFactory;
ZSTDMT_freeCCtxCallbackFn releaseAllJobResources;
ZSTDMT_freeCCtxCallbackFn freeJobs;
ZSTDMT_freeCCtxCallbackFn freeBufferPool;
ZSTDMT_freeCCtxCallbackFn freeCCtxPool;
ZSTDMT_freeCCtxCallbackFn freeSeqPool;
ZSTDMT_freeCCtxCallbackFn freeSerialState;
ZSTDMT_freeCCtxCallbackFn freeCDict;
ZSTDMT_freeCCtxCallbackFn freeRoundBuffer;
ZSTDMT_freeCCtxCallbackFn freeMTctx;
} ZSTDMT_RustFreeCCtxState;
typedef char ZSTDMT_rust_free_cctx_state_layout[
(sizeof(ZSTDMT_freeCCtxCallbackFn) == sizeof(void*)
&& offsetof(ZSTDMT_RustFreeCCtxState, callbackContext) == 0
&& offsetof(ZSTDMT_RustFreeCCtxState, providedFactory) == sizeof(void*)
&& offsetof(ZSTDMT_RustFreeCCtxState, roundBuffPresent) == 2 * sizeof(void*)
&& offsetof(ZSTDMT_RustFreeCCtxState, freeFactory) == 3 * sizeof(void*)
&& offsetof(ZSTDMT_RustFreeCCtxState, releaseAllJobResources) == 4 * sizeof(void*)
&& offsetof(ZSTDMT_RustFreeCCtxState, freeJobs) == 5 * sizeof(void*)
&& offsetof(ZSTDMT_RustFreeCCtxState, freeBufferPool) == 6 * sizeof(void*)
&& offsetof(ZSTDMT_RustFreeCCtxState, freeCCtxPool) == 7 * sizeof(void*)
&& offsetof(ZSTDMT_RustFreeCCtxState, freeSeqPool) == 8 * sizeof(void*)
&& offsetof(ZSTDMT_RustFreeCCtxState, freeSerialState) == 9 * sizeof(void*)
&& offsetof(ZSTDMT_RustFreeCCtxState, freeCDict) == 10 * sizeof(void*)
&& offsetof(ZSTDMT_RustFreeCCtxState, freeRoundBuffer) == 11 * sizeof(void*)
&& offsetof(ZSTDMT_RustFreeCCtxState, freeMTctx) == 12 * sizeof(void*)
&& sizeof(ZSTDMT_RustFreeCCtxState) == 13 * sizeof(void*)) ? 1 : -1];
size_t ZSTDMT_rust_freeCCtx(const ZSTDMT_RustFreeCCtxState* state);
size_t ZSTDMT_rust_initCStream(
const ZSTDMT_RustInitCStreamProjection* projection, void* opaque,
ZSTDMT_initResizeFn resize, ZSTDMT_initDrainFn drain,
@@ -1885,22 +1918,83 @@ static void ZSTDMT_waitForAllJobsCompleted(ZSTDMT_CCtx* mtctx)
mtctx, ZSTDMT_waitForJobComplete);
}
static void ZSTDMT_rust_freeCCtxFactory(void* opaque)
{
ZSTDMT_CCtx* const mtctx = (ZSTDMT_CCtx*)opaque;
POOL_free(mtctx->factory); /* stop and free worker threads */
}
static void ZSTDMT_rust_freeCCtxReleaseJobResources(void* opaque)
{
ZSTDMT_releaseAllJobResources((ZSTDMT_CCtx*)opaque);
}
static void ZSTDMT_rust_freeCCtxJobs(void* opaque)
{
ZSTDMT_CCtx* const mtctx = (ZSTDMT_CCtx*)opaque;
ZSTDMT_freeJobsTable(mtctx->jobs, mtctx->jobIDMask+1, mtctx->cMem);
}
static void ZSTDMT_rust_freeCCtxBufferPool(void* opaque)
{
ZSTDMT_CCtx* const mtctx = (ZSTDMT_CCtx*)opaque;
ZSTDMT_freeBufferPool(mtctx->bufPool);
}
static void ZSTDMT_rust_freeCCtxPool(void* opaque)
{
ZSTDMT_CCtx* const mtctx = (ZSTDMT_CCtx*)opaque;
ZSTDMT_freeCCtxPool(mtctx->cctxPool);
}
static void ZSTDMT_rust_freeCCtxSeqPool(void* opaque)
{
ZSTDMT_CCtx* const mtctx = (ZSTDMT_CCtx*)opaque;
ZSTDMT_freeSeqPool(mtctx->seqPool);
}
static void ZSTDMT_rust_freeCCtxSerialState(void* opaque)
{
ZSTDMT_CCtx* const mtctx = (ZSTDMT_CCtx*)opaque;
ZSTDMT_serialState_free(&mtctx->serial);
}
static void ZSTDMT_rust_freeCCtxCDict(void* opaque)
{
ZSTDMT_CCtx* const mtctx = (ZSTDMT_CCtx*)opaque;
ZSTD_freeCDict(mtctx->cdictLocal);
}
static void ZSTDMT_rust_freeCCtxRoundBuffer(void* opaque)
{
ZSTDMT_CCtx* const mtctx = (ZSTDMT_CCtx*)opaque;
ZSTD_customFree(mtctx->roundBuff.buffer, mtctx->cMem);
}
static void ZSTDMT_rust_freeCCtxContext(void* opaque)
{
ZSTDMT_CCtx* const mtctx = (ZSTDMT_CCtx*)opaque;
ZSTD_customFree(mtctx, mtctx->cMem);
}
size_t ZSTDMT_freeCCtx(ZSTDMT_CCtx* mtctx)
{
if (mtctx==NULL) return 0; /* compatible with free on NULL */
if (!mtctx->providedFactory)
POOL_free(mtctx->factory); /* stop and free worker threads */
ZSTDMT_releaseAllJobResources(mtctx); /* release job resources into pools first */
ZSTDMT_freeJobsTable(mtctx->jobs, mtctx->jobIDMask+1, mtctx->cMem);
ZSTDMT_freeBufferPool(mtctx->bufPool);
ZSTDMT_freeCCtxPool(mtctx->cctxPool);
ZSTDMT_freeSeqPool(mtctx->seqPool);
ZSTDMT_serialState_free(&mtctx->serial);
ZSTD_freeCDict(mtctx->cdictLocal);
if (mtctx->roundBuff.buffer)
ZSTD_customFree(mtctx->roundBuff.buffer, mtctx->cMem);
ZSTD_customFree(mtctx, mtctx->cMem);
return 0;
ZSTDMT_RustFreeCCtxState const state = {
mtctx,
mtctx != NULL && mtctx->providedFactory,
mtctx != NULL && mtctx->roundBuff.buffer != NULL,
ZSTDMT_rust_freeCCtxFactory,
ZSTDMT_rust_freeCCtxReleaseJobResources,
ZSTDMT_rust_freeCCtxJobs,
ZSTDMT_rust_freeCCtxBufferPool,
ZSTDMT_rust_freeCCtxPool,
ZSTDMT_rust_freeCCtxSeqPool,
ZSTDMT_rust_freeCCtxSerialState,
ZSTDMT_rust_freeCCtxCDict,
ZSTDMT_rust_freeCCtxRoundBuffer,
ZSTDMT_rust_freeCCtxContext
};
return ZSTDMT_rust_freeCCtx(mtctx == NULL ? NULL : &state);
}
size_t ZSTDMT_sizeof_CCtx(ZSTDMT_CCtx* mtctx)