feat(mt): move serial lifecycle ordering into Rust

Move serial-state synchronization initialization and destruction order into Rust, including the original bitwise initialization-error aggregation. C retains pthread operations, state zeroing, and custom-memory table cleanup behind callbacks.

Test Plan:
- ulimit -v 41943040; CARGO_BUILD_JOBS=1; cargo test --manifest-path rust/Cargo.toml
- ulimit -v 41943040; CARGO_BUILD_JOBS=1; cargo clippy --manifest-path rust/Cargo.toml --all-targets -- -D warnings
- ulimit -v 41943040; make -B -C programs -j1 zstd
- ulimit -v 41943040; make -C tests -j1 test-zstream ZSTREAM_TESTTIME=-T1s
This commit is contained in:
2026-07-19 20:15:37 +02:00
parent e3fe5b5a24
commit b7fccafc0a
2 changed files with 292 additions and 14 deletions
+89 -14
View File
@@ -464,6 +464,20 @@ int ZSTDMT_rust_serialStateReset(
ZSTDMT_serialResetVoidFn zeroTables,
ZSTDMT_serialResetVoidFn loadDictionary,
ZSTDMT_serialResetVoidFn copyWindow);
typedef void (*ZSTDMT_serialStateVoidFn)(void* opaque);
typedef int (*ZSTDMT_serialStateInitFn)(void* opaque);
int ZSTDMT_rust_serialStateInit(
void* opaque, ZSTDMT_serialStateVoidFn zeroState,
ZSTDMT_serialStateInitFn initMutex,
ZSTDMT_serialStateInitFn initCond,
ZSTDMT_serialStateInitFn initLdmMutex,
ZSTDMT_serialStateInitFn initLdmCond);
void ZSTDMT_rust_serialStateFree(
void* opaque, ZSTDMT_serialStateVoidFn destroyMutex,
ZSTDMT_serialStateVoidFn destroyCond,
ZSTDMT_serialStateVoidFn destroyLdmMutex,
ZSTDMT_serialStateVoidFn destroyLdmCond,
ZSTDMT_serialStateVoidFn freeTables);
size_t ZSTDMT_rust_initCStream(
const ZSTDMT_RustInitCStreamProjection* projection, void* opaque,
ZSTDMT_initResizeFn resize, ZSTDMT_initDrainFn drain,
@@ -992,26 +1006,87 @@ ZSTDMT_serialState_reset(SerialState* serialState,
return 0;
}
static void ZSTDMT_serialState_zero(void* opaque)
{
ZSTD_memset(opaque, 0, sizeof(SerialState));
}
static int ZSTDMT_serialState_initMutex(void* opaque)
{
SerialState* const serialState = (SerialState*)opaque;
return ZSTD_pthread_mutex_init(&serialState->mutex, NULL);
}
static int ZSTDMT_serialState_initCond(void* opaque)
{
SerialState* const serialState = (SerialState*)opaque;
return ZSTD_pthread_cond_init(&serialState->cond, NULL);
}
static int ZSTDMT_serialState_initLdmMutex(void* opaque)
{
SerialState* const serialState = (SerialState*)opaque;
return ZSTD_pthread_mutex_init(&serialState->ldmWindowMutex, NULL);
}
static int ZSTDMT_serialState_initLdmCond(void* opaque)
{
SerialState* const serialState = (SerialState*)opaque;
return ZSTD_pthread_cond_init(&serialState->ldmWindowCond, NULL);
}
static void ZSTDMT_serialState_destroyMutex(void* opaque)
{
SerialState* const serialState = (SerialState*)opaque;
ZSTD_pthread_mutex_destroy(&serialState->mutex);
}
static void ZSTDMT_serialState_destroyCond(void* opaque)
{
SerialState* const serialState = (SerialState*)opaque;
ZSTD_pthread_cond_destroy(&serialState->cond);
}
static void ZSTDMT_serialState_destroyLdmMutex(void* opaque)
{
SerialState* const serialState = (SerialState*)opaque;
ZSTD_pthread_mutex_destroy(&serialState->ldmWindowMutex);
}
static void ZSTDMT_serialState_destroyLdmCond(void* opaque)
{
SerialState* const serialState = (SerialState*)opaque;
ZSTD_pthread_cond_destroy(&serialState->ldmWindowCond);
}
static void ZSTDMT_serialState_freeTables(void* opaque)
{
SerialState* const serialState = (SerialState*)opaque;
ZSTD_customMem const cMem = serialState->params.customMem;
ZSTD_customFree(serialState->ldmState.hashTable, cMem);
ZSTD_customFree(serialState->ldmState.bucketOffsets, cMem);
}
static int ZSTDMT_serialState_init(SerialState* serialState)
{
int initError = 0;
ZSTD_memset(serialState, 0, sizeof(*serialState));
initError |= ZSTD_pthread_mutex_init(&serialState->mutex, NULL);
initError |= ZSTD_pthread_cond_init(&serialState->cond, NULL);
initError |= ZSTD_pthread_mutex_init(&serialState->ldmWindowMutex, NULL);
initError |= ZSTD_pthread_cond_init(&serialState->ldmWindowCond, NULL);
return initError;
return ZSTDMT_rust_serialStateInit(
serialState,
ZSTDMT_serialState_zero,
ZSTDMT_serialState_initMutex,
ZSTDMT_serialState_initCond,
ZSTDMT_serialState_initLdmMutex,
ZSTDMT_serialState_initLdmCond);
}
static void ZSTDMT_serialState_free(SerialState* serialState)
{
ZSTD_customMem cMem = serialState->params.customMem;
ZSTD_pthread_mutex_destroy(&serialState->mutex);
ZSTD_pthread_cond_destroy(&serialState->cond);
ZSTD_pthread_mutex_destroy(&serialState->ldmWindowMutex);
ZSTD_pthread_cond_destroy(&serialState->ldmWindowCond);
ZSTD_customFree(serialState->ldmState.hashTable, cMem);
ZSTD_customFree(serialState->ldmState.bucketOffsets, cMem);
ZSTDMT_rust_serialStateFree(
serialState,
ZSTDMT_serialState_destroyMutex,
ZSTDMT_serialState_destroyCond,
ZSTDMT_serialState_destroyLdmMutex,
ZSTDMT_serialState_destroyLdmCond,
ZSTDMT_serialState_freeTables);
}
/* Rust owns the serial turn/skip decision and operation ordering. The wait