feat(compress): move CCtx workspace policy into Rust
Move the CCtx reset workspace resize decision, index-reset mutation, reservation order, private-pointer publication order, and clear boundary into Rust. Keep the workspace allocator and private ZSTD_CCtx layout operations in C behind callbacks, with matching C/Rust layout assertions. Add focused tests for the no-resize, resize, and static-resize error paths so the callback order and mutation boundaries remain explicit. 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 -j1` - `ulimit -v 41943040 && make -j1 -C tests test-zstream ZSTREAM_TESTTIME=-T2s` - `ulimit -v 41943040 && make -j1 -C tests test-fuzzer FUZZERTEST=-T3s FUZZER_FLAGS=--no-big-tests` - `ulimit -v 41943040 && cargo fmt --manifest-path rust/Cargo.toml -- --check` - `git diff --check`
This commit is contained in:
+120
-38
@@ -1443,6 +1443,10 @@ typedef int (*ZSTD_rust_resetCCtxStorageReserveFailed_f)(void* context);
|
||||
typedef void (*ZSTD_rust_resetCCtxStorageZero_f)(
|
||||
void* context, void* pointer, size_t size);
|
||||
typedef void (*ZSTD_rust_resetCCtxStorageCallback_f)(void* context);
|
||||
typedef size_t (*ZSTD_rust_resetCCtxWorkspaceCreate_f)(
|
||||
void* context, size_t neededSpace);
|
||||
typedef void* (*ZSTD_rust_resetCCtxWorkspaceReserveObject_f)(
|
||||
void* context, size_t size);
|
||||
typedef struct {
|
||||
void* callbackContext;
|
||||
int ldmEnable;
|
||||
@@ -1516,6 +1520,45 @@ typedef char ZSTD_rust_reset_cctx_storage_state_layout[
|
||||
== offsetof(ZSTD_rust_resetCCtxStorageState, resetExternalSequences)
|
||||
+ sizeof(void*))
|
||||
? 1 : -1];
|
||||
typedef struct {
|
||||
void* callbackContext;
|
||||
int isStatic;
|
||||
int workspaceTooSmall;
|
||||
int workspaceWasteful;
|
||||
size_t neededSpace;
|
||||
size_t compressedBlockStateSize;
|
||||
size_t tmpWorkspaceSize;
|
||||
int* needsIndexReset;
|
||||
ZSTD_rust_resetCCtxStorageCallback_f bumpOversizedDuration;
|
||||
ZSTD_rust_resetCCtxStorageCallback_f freeWorkspace;
|
||||
ZSTD_rust_resetCCtxWorkspaceCreate_f createWorkspace;
|
||||
ZSTD_rust_resetCCtxWorkspaceReserveObject_f reserveObject;
|
||||
ZSTD_rust_resetCCtxStorageSetPointer_f setPointer;
|
||||
ZSTD_rust_resetCCtxStorageSetSize_f setSize;
|
||||
ZSTD_rust_resetCCtxStorageCallback_f clearWorkspace;
|
||||
} ZSTD_rust_resetCCtxWorkspaceState;
|
||||
typedef char ZSTD_rust_reset_cctx_workspace_state_layout[
|
||||
(offsetof(ZSTD_rust_resetCCtxWorkspaceState, callbackContext) == 0
|
||||
&& offsetof(ZSTD_rust_resetCCtxWorkspaceState, isStatic) == sizeof(void*)
|
||||
&& offsetof(ZSTD_rust_resetCCtxWorkspaceState, workspaceTooSmall)
|
||||
== sizeof(void*) + sizeof(int)
|
||||
&& offsetof(ZSTD_rust_resetCCtxWorkspaceState, workspaceWasteful)
|
||||
== sizeof(void*) + 2 * sizeof(int)
|
||||
&& offsetof(ZSTD_rust_resetCCtxWorkspaceState, neededSpace)
|
||||
> offsetof(ZSTD_rust_resetCCtxWorkspaceState, workspaceWasteful)
|
||||
&& offsetof(ZSTD_rust_resetCCtxWorkspaceState, compressedBlockStateSize)
|
||||
== offsetof(ZSTD_rust_resetCCtxWorkspaceState, neededSpace)
|
||||
+ sizeof(size_t)
|
||||
&& offsetof(ZSTD_rust_resetCCtxWorkspaceState, tmpWorkspaceSize)
|
||||
== offsetof(ZSTD_rust_resetCCtxWorkspaceState, compressedBlockStateSize)
|
||||
+ sizeof(size_t)
|
||||
&& offsetof(ZSTD_rust_resetCCtxWorkspaceState, needsIndexReset)
|
||||
== offsetof(ZSTD_rust_resetCCtxWorkspaceState, tmpWorkspaceSize)
|
||||
+ sizeof(size_t)
|
||||
&& sizeof(ZSTD_rust_resetCCtxWorkspaceState)
|
||||
== offsetof(ZSTD_rust_resetCCtxWorkspaceState, clearWorkspace)
|
||||
+ sizeof(void*))
|
||||
? 1 : -1];
|
||||
enum {
|
||||
ZSTD_RUST_RESET_CCTX_RESERVE_ALIGNED64 = 0,
|
||||
ZSTD_RUST_RESET_CCTX_RESERVE_BUFFER = 1
|
||||
@@ -1531,7 +1574,10 @@ enum {
|
||||
ZSTD_RUST_RESET_CCTX_POINTER_LL_CODE = 7,
|
||||
ZSTD_RUST_RESET_CCTX_POINTER_ML_CODE = 8,
|
||||
ZSTD_RUST_RESET_CCTX_POINTER_OF_CODE = 9,
|
||||
ZSTD_RUST_RESET_CCTX_POINTER_LDM_BUCKETS = 10
|
||||
ZSTD_RUST_RESET_CCTX_POINTER_LDM_BUCKETS = 10,
|
||||
ZSTD_RUST_RESET_CCTX_POINTER_PREV_CBLOCK = 11,
|
||||
ZSTD_RUST_RESET_CCTX_POINTER_NEXT_CBLOCK = 12,
|
||||
ZSTD_RUST_RESET_CCTX_POINTER_TMP_WORKSPACE = 13
|
||||
};
|
||||
enum {
|
||||
ZSTD_RUST_RESET_CCTX_SIZE_MAX_NB_SEQ = 0,
|
||||
@@ -1539,13 +1585,16 @@ enum {
|
||||
ZSTD_RUST_RESET_CCTX_SIZE_MAX_NB_LDM_SEQ = 2,
|
||||
ZSTD_RUST_RESET_CCTX_SIZE_EXTERNAL_SEQ_CAPACITY = 3,
|
||||
ZSTD_RUST_RESET_CCTX_SIZE_INPUT_BUFFER = 4,
|
||||
ZSTD_RUST_RESET_CCTX_SIZE_OUTPUT_BUFFER = 5
|
||||
ZSTD_RUST_RESET_CCTX_SIZE_OUTPUT_BUFFER = 5,
|
||||
ZSTD_RUST_RESET_CCTX_SIZE_TMP_WORKSPACE = 6
|
||||
};
|
||||
enum {
|
||||
ZSTD_RUST_RESET_CCTX_INT_BUFFERED_POLICY = 0,
|
||||
ZSTD_RUST_RESET_CCTX_INT_INITIALIZED = 1
|
||||
};
|
||||
size_t ZSTD_rust_resetCCtxStorage(const ZSTD_rust_resetCCtxStorageState* state);
|
||||
size_t ZSTD_rust_resetCCtxWorkspace(
|
||||
const ZSTD_rust_resetCCtxWorkspaceState* state);
|
||||
size_t ZSTD_rust_estimateCCtxWorkspaceSize(
|
||||
ZSTD_compressionParameters cParams,
|
||||
int ldmEnable, U32 ldmHashLog, U32 ldmBucketSizeLog,
|
||||
@@ -4028,6 +4077,15 @@ static void ZSTD_rust_resetCCtxStorage_setPointer(
|
||||
case ZSTD_RUST_RESET_CCTX_POINTER_LDM_BUCKETS:
|
||||
cctx->ldmState.bucketOffsets = (BYTE*)pointer;
|
||||
break;
|
||||
case ZSTD_RUST_RESET_CCTX_POINTER_PREV_CBLOCK:
|
||||
cctx->blockState.prevCBlock = (ZSTD_compressedBlockState_t*)pointer;
|
||||
break;
|
||||
case ZSTD_RUST_RESET_CCTX_POINTER_NEXT_CBLOCK:
|
||||
cctx->blockState.nextCBlock = (ZSTD_compressedBlockState_t*)pointer;
|
||||
break;
|
||||
case ZSTD_RUST_RESET_CCTX_POINTER_TMP_WORKSPACE:
|
||||
cctx->tmpWorkspace = pointer;
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
break;
|
||||
@@ -4059,6 +4117,9 @@ static void ZSTD_rust_resetCCtxStorage_setSize(
|
||||
case ZSTD_RUST_RESET_CCTX_SIZE_OUTPUT_BUFFER:
|
||||
cctx->outBuffSize = value;
|
||||
break;
|
||||
case ZSTD_RUST_RESET_CCTX_SIZE_TMP_WORKSPACE:
|
||||
cctx->tmpWkspSize = value;
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
break;
|
||||
@@ -4129,6 +4190,44 @@ static void ZSTD_rust_resetCCtxStorage_resetExternalSequences(void* opaque)
|
||||
ZSTD_referenceExternalSequences(context->cctx, NULL, 0);
|
||||
}
|
||||
|
||||
static void ZSTD_rust_resetCCtxWorkspace_bumpOversizedDuration(void* opaque)
|
||||
{
|
||||
ZSTD_rust_resetCCtxStorageContext* const context =
|
||||
(ZSTD_rust_resetCCtxStorageContext*)opaque;
|
||||
ZSTD_cwksp_bump_oversized_duration(context->ws, 0);
|
||||
}
|
||||
|
||||
static void ZSTD_rust_resetCCtxWorkspace_free(void* opaque)
|
||||
{
|
||||
ZSTD_rust_resetCCtxStorageContext* const context =
|
||||
(ZSTD_rust_resetCCtxStorageContext*)opaque;
|
||||
ZSTD_cwksp_free(context->ws, context->cctx->customMem);
|
||||
}
|
||||
|
||||
static size_t ZSTD_rust_resetCCtxWorkspace_create(
|
||||
void* opaque, size_t neededSpace)
|
||||
{
|
||||
ZSTD_rust_resetCCtxStorageContext* const context =
|
||||
(ZSTD_rust_resetCCtxStorageContext*)opaque;
|
||||
return ZSTD_cwksp_create(
|
||||
context->ws, neededSpace, context->cctx->customMem);
|
||||
}
|
||||
|
||||
static void* ZSTD_rust_resetCCtxWorkspace_reserveObject(
|
||||
void* opaque, size_t size)
|
||||
{
|
||||
ZSTD_rust_resetCCtxStorageContext* const context =
|
||||
(ZSTD_rust_resetCCtxStorageContext*)opaque;
|
||||
return ZSTD_cwksp_reserve_object(context->ws, size);
|
||||
}
|
||||
|
||||
static void ZSTD_rust_resetCCtxWorkspace_clear(void* opaque)
|
||||
{
|
||||
ZSTD_rust_resetCCtxStorageContext* const context =
|
||||
(ZSTD_rust_resetCCtxStorageContext*)opaque;
|
||||
ZSTD_cwksp_clear(context->ws);
|
||||
}
|
||||
|
||||
/*! ZSTD_resetCCtx_internal() :
|
||||
* @param loadedDictSize The size of the dictionary to be loaded
|
||||
* into the context, if any. If no dictionary is used, or the
|
||||
@@ -4248,42 +4347,25 @@ static size_t ZSTD_resetCCtx_internal(ZSTD_CCtx* zc,
|
||||
storageState.resetExternalSequences =
|
||||
ZSTD_rust_resetCCtxStorage_resetExternalSequences;
|
||||
|
||||
if (!zc->staticSize) ZSTD_cwksp_bump_oversized_duration(ws, 0);
|
||||
|
||||
{ /* Check if workspace is large enough, alloc a new one if needed */
|
||||
int const workspaceTooSmall = ZSTD_cwksp_sizeof(ws) < neededSpace;
|
||||
int const workspaceWasteful = ZSTD_cwksp_check_wasteful(ws, neededSpace);
|
||||
int resizeWorkspace = workspaceTooSmall || workspaceWasteful;
|
||||
DEBUGLOG(4, "Need %zu B workspace", neededSpace);
|
||||
DEBUGLOG(4, "windowSize: %zu - blockSize: %zu", resetPlan.windowSize, blockSize);
|
||||
|
||||
if (resizeWorkspace) {
|
||||
DEBUGLOG(4, "Resize workspaceSize from %zuKB to %zuKB",
|
||||
ZSTD_cwksp_sizeof(ws) >> 10,
|
||||
neededSpace >> 10);
|
||||
|
||||
RETURN_ERROR_IF(zc->staticSize, memory_allocation, "static cctx : no resize");
|
||||
|
||||
needsIndexReset = ZSTDirp_reset;
|
||||
|
||||
ZSTD_cwksp_free(ws, zc->customMem);
|
||||
FORWARD_IF_ERROR(ZSTD_cwksp_create(ws, neededSpace, zc->customMem), "");
|
||||
|
||||
DEBUGLOG(5, "reserving object space");
|
||||
/* Statically sized space.
|
||||
* tmpWorkspace never moves,
|
||||
* though prev/next block swap places */
|
||||
assert(ZSTD_cwksp_check_available(ws, 2 * sizeof(ZSTD_compressedBlockState_t)));
|
||||
zc->blockState.prevCBlock = (ZSTD_compressedBlockState_t*) ZSTD_cwksp_reserve_object(ws, sizeof(ZSTD_compressedBlockState_t));
|
||||
RETURN_ERROR_IF(zc->blockState.prevCBlock == NULL, memory_allocation, "couldn't allocate prevCBlock");
|
||||
zc->blockState.nextCBlock = (ZSTD_compressedBlockState_t*) ZSTD_cwksp_reserve_object(ws, sizeof(ZSTD_compressedBlockState_t));
|
||||
RETURN_ERROR_IF(zc->blockState.nextCBlock == NULL, memory_allocation, "couldn't allocate nextCBlock");
|
||||
zc->tmpWorkspace = ZSTD_cwksp_reserve_object(ws, TMP_WORKSPACE_SIZE);
|
||||
RETURN_ERROR_IF(zc->tmpWorkspace == NULL, memory_allocation, "couldn't allocate tmpWorkspace");
|
||||
zc->tmpWkspSize = TMP_WORKSPACE_SIZE;
|
||||
} }
|
||||
|
||||
ZSTD_cwksp_clear(ws);
|
||||
{ ZSTD_rust_resetCCtxWorkspaceState workspaceState;
|
||||
workspaceState.callbackContext = &storageContext;
|
||||
workspaceState.isStatic = zc->staticSize != 0;
|
||||
workspaceState.workspaceTooSmall = ZSTD_cwksp_sizeof(ws) < neededSpace;
|
||||
workspaceState.workspaceWasteful = ZSTD_cwksp_check_wasteful(ws, neededSpace);
|
||||
workspaceState.neededSpace = neededSpace;
|
||||
workspaceState.compressedBlockStateSize = sizeof(ZSTD_compressedBlockState_t);
|
||||
workspaceState.tmpWorkspaceSize = TMP_WORKSPACE_SIZE;
|
||||
workspaceState.needsIndexReset = (int*)&needsIndexReset;
|
||||
workspaceState.bumpOversizedDuration =
|
||||
ZSTD_rust_resetCCtxWorkspace_bumpOversizedDuration;
|
||||
workspaceState.freeWorkspace = ZSTD_rust_resetCCtxWorkspace_free;
|
||||
workspaceState.createWorkspace = ZSTD_rust_resetCCtxWorkspace_create;
|
||||
workspaceState.reserveObject = ZSTD_rust_resetCCtxWorkspace_reserveObject;
|
||||
workspaceState.setPointer = ZSTD_rust_resetCCtxStorage_setPointer;
|
||||
workspaceState.setSize = ZSTD_rust_resetCCtxStorage_setSize;
|
||||
workspaceState.clearWorkspace = ZSTD_rust_resetCCtxWorkspace_clear;
|
||||
FORWARD_IF_ERROR(ZSTD_rust_resetCCtxWorkspace(&workspaceState), "");
|
||||
}
|
||||
|
||||
/* init params */
|
||||
zc->blockState.matchState.cParams = params->cParams;
|
||||
|
||||
Reference in New Issue
Block a user