The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/contrib/openzfs/module/zstd/lib/compress/zstd_cwksp.h

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*
    2  * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc.
    3  * All rights reserved.
    4  *
    5  * This source code is licensed under both the BSD-style license (found in the
    6  * LICENSE file in the root directory of this source tree) and the GPLv2 (found
    7  * in the COPYING file in the root directory of this source tree).
    8  * You may select, at your option, one of the above-listed licenses.
    9  */
   10 
   11 #ifndef ZSTD_CWKSP_H
   12 #define ZSTD_CWKSP_H
   13 
   14 /*-*************************************
   15 *  Dependencies
   16 ***************************************/
   17 #include "../common/zstd_internal.h"
   18 
   19 #if defined (__cplusplus)
   20 extern "C" {
   21 #endif
   22 
   23 /*-*************************************
   24 *  Constants
   25 ***************************************/
   26 
   27 /* Since the workspace is effectively its own little malloc implementation /
   28  * arena, when we run under ASAN, we should similarly insert redzones between
   29  * each internal element of the workspace, so ASAN will catch overruns that
   30  * reach outside an object but that stay inside the workspace.
   31  *
   32  * This defines the size of that redzone.
   33  */
   34 #ifndef ZSTD_CWKSP_ASAN_REDZONE_SIZE
   35 #define ZSTD_CWKSP_ASAN_REDZONE_SIZE 128
   36 #endif
   37 
   38 /*-*************************************
   39 *  Structures
   40 ***************************************/
   41 typedef enum {
   42     ZSTD_cwksp_alloc_objects,
   43     ZSTD_cwksp_alloc_buffers,
   44     ZSTD_cwksp_alloc_aligned
   45 } ZSTD_cwksp_alloc_phase_e;
   46 
   47 /**
   48  * Zstd fits all its internal datastructures into a single continuous buffer,
   49  * so that it only needs to perform a single OS allocation (or so that a buffer
   50  * can be provided to it and it can perform no allocations at all). This buffer
   51  * is called the workspace.
   52  *
   53  * Several optimizations complicate that process of allocating memory ranges
   54  * from this workspace for each internal datastructure:
   55  *
   56  * - These different internal datastructures have different setup requirements:
   57  *
   58  *   - The static objects need to be cleared once and can then be trivially
   59  *     reused for each compression.
   60  *
   61  *   - Various buffers don't need to be initialized at all--they are always
   62  *     written into before they're read.
   63  *
   64  *   - The matchstate tables have a unique requirement that they don't need
   65  *     their memory to be totally cleared, but they do need the memory to have
   66  *     some bound, i.e., a guarantee that all values in the memory they've been
   67  *     allocated is less than some maximum value (which is the starting value
   68  *     for the indices that they will then use for compression). When this
   69  *     guarantee is provided to them, they can use the memory without any setup
   70  *     work. When it can't, they have to clear the area.
   71  *
   72  * - These buffers also have different alignment requirements.
   73  *
   74  * - We would like to reuse the objects in the workspace for multiple
   75  *   compressions without having to perform any expensive reallocation or
   76  *   reinitialization work.
   77  *
   78  * - We would like to be able to efficiently reuse the workspace across
   79  *   multiple compressions **even when the compression parameters change** and
   80  *   we need to resize some of the objects (where possible).
   81  *
   82  * To attempt to manage this buffer, given these constraints, the ZSTD_cwksp
   83  * abstraction was created. It works as follows:
   84  *
   85  * Workspace Layout:
   86  *
   87  * [                        ... workspace ...                         ]
   88  * [objects][tables ... ->] free space [<- ... aligned][<- ... buffers]
   89  *
   90  * The various objects that live in the workspace are divided into the
   91  * following categories, and are allocated separately:
   92  *
   93  * - Static objects: this is optionally the enclosing ZSTD_CCtx or ZSTD_CDict,
   94  *   so that literally everything fits in a single buffer. Note: if present,
   95  *   this must be the first object in the workspace, since ZSTD_free{CCtx,
   96  *   CDict}() rely on a pointer comparison to see whether one or two frees are
   97  *   required.
   98  *
   99  * - Fixed size objects: these are fixed-size, fixed-count objects that are
  100  *   nonetheless "dynamically" allocated in the workspace so that we can
  101  *   control how they're initialized separately from the broader ZSTD_CCtx.
  102  *   Examples:
  103  *   - Entropy Workspace
  104  *   - 2 x ZSTD_compressedBlockState_t
  105  *   - CDict dictionary contents
  106  *
  107  * - Tables: these are any of several different datastructures (hash tables,
  108  *   chain tables, binary trees) that all respect a common format: they are
  109  *   uint32_t arrays, all of whose values are between 0 and (nextSrc - base).
  110  *   Their sizes depend on the cparams.
  111  *
  112  * - Aligned: these buffers are used for various purposes that require 4 byte
  113  *   alignment, but don't require any initialization before they're used.
  114  *
  115  * - Buffers: these buffers are used for various purposes that don't require
  116  *   any alignment or initialization before they're used. This means they can
  117  *   be moved around at no cost for a new compression.
  118  *
  119  * Allocating Memory:
  120  *
  121  * The various types of objects must be allocated in order, so they can be
  122  * correctly packed into the workspace buffer. That order is:
  123  *
  124  * 1. Objects
  125  * 2. Buffers
  126  * 3. Aligned
  127  * 4. Tables
  128  *
  129  * Attempts to reserve objects of different types out of order will fail.
  130  */
  131 typedef struct {
  132     void* workspace;
  133     void* workspaceEnd;
  134 
  135     void* objectEnd;
  136     void* tableEnd;
  137     void* tableValidEnd;
  138     void* allocStart;
  139 
  140     int allocFailed;
  141     int workspaceOversizedDuration;
  142     ZSTD_cwksp_alloc_phase_e phase;
  143 } ZSTD_cwksp;
  144 
  145 /*-*************************************
  146 *  Functions
  147 ***************************************/
  148 
  149 MEM_STATIC size_t ZSTD_cwksp_available_space(ZSTD_cwksp* ws);
  150 
  151 MEM_STATIC void ZSTD_cwksp_assert_internal_consistency(ZSTD_cwksp* ws) {
  152     (void)ws;
  153     assert(ws->workspace <= ws->objectEnd);
  154     assert(ws->objectEnd <= ws->tableEnd);
  155     assert(ws->objectEnd <= ws->tableValidEnd);
  156     assert(ws->tableEnd <= ws->allocStart);
  157     assert(ws->tableValidEnd <= ws->allocStart);
  158     assert(ws->allocStart <= ws->workspaceEnd);
  159 }
  160 
  161 /**
  162  * Align must be a power of 2.
  163  */
  164 MEM_STATIC size_t ZSTD_cwksp_align(size_t size, size_t const align) {
  165     size_t const mask = align - 1;
  166     assert((align & mask) == 0);
  167     return (size + mask) & ~mask;
  168 }
  169 
  170 /**
  171  * Use this to determine how much space in the workspace we will consume to
  172  * allocate this object. (Normally it should be exactly the size of the object,
  173  * but under special conditions, like ASAN, where we pad each object, it might
  174  * be larger.)
  175  *
  176  * Since tables aren't currently redzoned, you don't need to call through this
  177  * to figure out how much space you need for the matchState tables. Everything
  178  * else is though.
  179  */
  180 MEM_STATIC size_t ZSTD_cwksp_alloc_size(size_t size) {
  181 #if defined (ADDRESS_SANITIZER) && !defined (ZSTD_ASAN_DONT_POISON_WORKSPACE)
  182     return size + 2 * ZSTD_CWKSP_ASAN_REDZONE_SIZE;
  183 #else
  184     return size;
  185 #endif
  186 }
  187 
  188 MEM_STATIC void ZSTD_cwksp_internal_advance_phase(
  189         ZSTD_cwksp* ws, ZSTD_cwksp_alloc_phase_e phase) {
  190     assert(phase >= ws->phase);
  191     if (phase > ws->phase) {
  192         if (ws->phase < ZSTD_cwksp_alloc_buffers &&
  193                 phase >= ZSTD_cwksp_alloc_buffers) {
  194             ws->tableValidEnd = ws->objectEnd;
  195         }
  196         if (ws->phase < ZSTD_cwksp_alloc_aligned &&
  197                 phase >= ZSTD_cwksp_alloc_aligned) {
  198             /* If unaligned allocations down from a too-large top have left us
  199              * unaligned, we need to realign our alloc ptr. Technically, this
  200              * can consume space that is unaccounted for in the neededSpace
  201              * calculation. However, I believe this can only happen when the
  202              * workspace is too large, and specifically when it is too large
  203              * by a larger margin than the space that will be consumed. */
  204             /* TODO: cleaner, compiler warning friendly way to do this??? */
  205             ws->allocStart = (BYTE*)ws->allocStart - ((size_t)ws->allocStart & (sizeof(U32)-1));
  206             if (ws->allocStart < ws->tableValidEnd) {
  207                 ws->tableValidEnd = ws->allocStart;
  208             }
  209         }
  210         ws->phase = phase;
  211     }
  212 }
  213 
  214 /**
  215  * Returns whether this object/buffer/etc was allocated in this workspace.
  216  */
  217 MEM_STATIC int ZSTD_cwksp_owns_buffer(const ZSTD_cwksp* ws, const void* ptr) {
  218     return (ptr != NULL) && (ws->workspace <= ptr) && (ptr <= ws->workspaceEnd);
  219 }
  220 
  221 /**
  222  * Internal function. Do not use directly.
  223  */
  224 MEM_STATIC void* ZSTD_cwksp_reserve_internal(
  225         ZSTD_cwksp* ws, size_t bytes, ZSTD_cwksp_alloc_phase_e phase) {
  226     void* alloc;
  227     void* bottom = ws->tableEnd;
  228     ZSTD_cwksp_internal_advance_phase(ws, phase);
  229     alloc = (BYTE *)ws->allocStart - bytes;
  230 
  231 #if defined (ADDRESS_SANITIZER) && !defined (ZSTD_ASAN_DONT_POISON_WORKSPACE)
  232     /* over-reserve space */
  233     alloc = (BYTE *)alloc - 2 * ZSTD_CWKSP_ASAN_REDZONE_SIZE;
  234 #endif
  235 
  236     DEBUGLOG(5, "cwksp: reserving %p %zd bytes, %zd bytes remaining",
  237         alloc, bytes, ZSTD_cwksp_available_space(ws) - bytes);
  238     ZSTD_cwksp_assert_internal_consistency(ws);
  239     assert(alloc >= bottom);
  240     if (alloc < bottom) {
  241         DEBUGLOG(4, "cwksp: alloc failed!");
  242         ws->allocFailed = 1;
  243         return NULL;
  244     }
  245     if (alloc < ws->tableValidEnd) {
  246         ws->tableValidEnd = alloc;
  247     }
  248     ws->allocStart = alloc;
  249 
  250 #if defined (ADDRESS_SANITIZER) && !defined (ZSTD_ASAN_DONT_POISON_WORKSPACE)
  251     /* Move alloc so there's ZSTD_CWKSP_ASAN_REDZONE_SIZE unused space on
  252      * either size. */
  253     alloc = (BYTE *)alloc + ZSTD_CWKSP_ASAN_REDZONE_SIZE;
  254     __asan_unpoison_memory_region(alloc, bytes);
  255 #endif
  256 
  257     return alloc;
  258 }
  259 
  260 /**
  261  * Reserves and returns unaligned memory.
  262  */
  263 MEM_STATIC BYTE* ZSTD_cwksp_reserve_buffer(ZSTD_cwksp* ws, size_t bytes) {
  264     return (BYTE*)ZSTD_cwksp_reserve_internal(ws, bytes, ZSTD_cwksp_alloc_buffers);
  265 }
  266 
  267 /**
  268  * Reserves and returns memory sized on and aligned on sizeof(unsigned).
  269  */
  270 MEM_STATIC void* ZSTD_cwksp_reserve_aligned(ZSTD_cwksp* ws, size_t bytes) {
  271     assert((bytes & (sizeof(U32)-1)) == 0);
  272     return ZSTD_cwksp_reserve_internal(ws, ZSTD_cwksp_align(bytes, sizeof(U32)), ZSTD_cwksp_alloc_aligned);
  273 }
  274 
  275 /**
  276  * Aligned on sizeof(unsigned). These buffers have the special property that
  277  * their values remain constrained, allowing us to re-use them without
  278  * memset()-ing them.
  279  */
  280 MEM_STATIC void* ZSTD_cwksp_reserve_table(ZSTD_cwksp* ws, size_t bytes) {
  281     const ZSTD_cwksp_alloc_phase_e phase = ZSTD_cwksp_alloc_aligned;
  282     void* alloc = ws->tableEnd;
  283     void* end = (BYTE *)alloc + bytes;
  284     void* top = ws->allocStart;
  285 
  286     DEBUGLOG(5, "cwksp: reserving %p table %zd bytes, %zd bytes remaining",
  287         alloc, bytes, ZSTD_cwksp_available_space(ws) - bytes);
  288     assert((bytes & (sizeof(U32)-1)) == 0);
  289     ZSTD_cwksp_internal_advance_phase(ws, phase);
  290     ZSTD_cwksp_assert_internal_consistency(ws);
  291     assert(end <= top);
  292     if (end > top) {
  293         DEBUGLOG(4, "cwksp: table alloc failed!");
  294         ws->allocFailed = 1;
  295         return NULL;
  296     }
  297     ws->tableEnd = end;
  298 
  299 #if defined (ADDRESS_SANITIZER) && !defined (ZSTD_ASAN_DONT_POISON_WORKSPACE)
  300     __asan_unpoison_memory_region(alloc, bytes);
  301 #endif
  302 
  303     return alloc;
  304 }
  305 
  306 /**
  307  * Aligned on sizeof(void*).
  308  */
  309 MEM_STATIC void* ZSTD_cwksp_reserve_object(ZSTD_cwksp* ws, size_t bytes) {
  310     size_t roundedBytes = ZSTD_cwksp_align(bytes, sizeof(void*));
  311     void* alloc = ws->objectEnd;
  312     void* end = (BYTE*)alloc + roundedBytes;
  313 
  314 #if defined (ADDRESS_SANITIZER) && !defined (ZSTD_ASAN_DONT_POISON_WORKSPACE)
  315     /* over-reserve space */
  316     end = (BYTE *)end + 2 * ZSTD_CWKSP_ASAN_REDZONE_SIZE;
  317 #endif
  318 
  319     DEBUGLOG(5,
  320         "cwksp: reserving %p object %zd bytes (rounded to %zd), %zd bytes remaining",
  321         alloc, bytes, roundedBytes, ZSTD_cwksp_available_space(ws) - roundedBytes);
  322     assert(((size_t)alloc & (sizeof(void*)-1)) == 0);
  323     assert((bytes & (sizeof(void*)-1)) == 0);
  324     ZSTD_cwksp_assert_internal_consistency(ws);
  325     /* we must be in the first phase, no advance is possible */
  326     if (ws->phase != ZSTD_cwksp_alloc_objects || end > ws->workspaceEnd) {
  327         DEBUGLOG(4, "cwksp: object alloc failed!");
  328         ws->allocFailed = 1;
  329         return NULL;
  330     }
  331     ws->objectEnd = end;
  332     ws->tableEnd = end;
  333     ws->tableValidEnd = end;
  334 
  335 #if defined (ADDRESS_SANITIZER) && !defined (ZSTD_ASAN_DONT_POISON_WORKSPACE)
  336     /* Move alloc so there's ZSTD_CWKSP_ASAN_REDZONE_SIZE unused space on
  337      * either size. */
  338     alloc = (BYTE *)alloc + ZSTD_CWKSP_ASAN_REDZONE_SIZE;
  339     __asan_unpoison_memory_region(alloc, bytes);
  340 #endif
  341 
  342     return alloc;
  343 }
  344 
  345 MEM_STATIC void ZSTD_cwksp_mark_tables_dirty(ZSTD_cwksp* ws) {
  346     DEBUGLOG(4, "cwksp: ZSTD_cwksp_mark_tables_dirty");
  347 
  348 #if defined (MEMORY_SANITIZER) && !defined (ZSTD_MSAN_DONT_POISON_WORKSPACE)
  349     /* To validate that the table re-use logic is sound, and that we don't
  350      * access table space that we haven't cleaned, we re-"poison" the table
  351      * space every time we mark it dirty. */
  352     {
  353         size_t size = (BYTE*)ws->tableValidEnd - (BYTE*)ws->objectEnd;
  354         assert(__msan_test_shadow(ws->objectEnd, size) == -1);
  355         __msan_poison(ws->objectEnd, size);
  356     }
  357 #endif
  358 
  359     assert(ws->tableValidEnd >= ws->objectEnd);
  360     assert(ws->tableValidEnd <= ws->allocStart);
  361     ws->tableValidEnd = ws->objectEnd;
  362     ZSTD_cwksp_assert_internal_consistency(ws);
  363 }
  364 
  365 MEM_STATIC void ZSTD_cwksp_mark_tables_clean(ZSTD_cwksp* ws) {
  366     DEBUGLOG(4, "cwksp: ZSTD_cwksp_mark_tables_clean");
  367     assert(ws->tableValidEnd >= ws->objectEnd);
  368     assert(ws->tableValidEnd <= ws->allocStart);
  369     if (ws->tableValidEnd < ws->tableEnd) {
  370         ws->tableValidEnd = ws->tableEnd;
  371     }
  372     ZSTD_cwksp_assert_internal_consistency(ws);
  373 }
  374 
  375 /**
  376  * Zero the part of the allocated tables not already marked clean.
  377  */
  378 MEM_STATIC void ZSTD_cwksp_clean_tables(ZSTD_cwksp* ws) {
  379     DEBUGLOG(4, "cwksp: ZSTD_cwksp_clean_tables");
  380     assert(ws->tableValidEnd >= ws->objectEnd);
  381     assert(ws->tableValidEnd <= ws->allocStart);
  382     if (ws->tableValidEnd < ws->tableEnd) {
  383         memset(ws->tableValidEnd, 0, (BYTE*)ws->tableEnd - (BYTE*)ws->tableValidEnd);
  384     }
  385     ZSTD_cwksp_mark_tables_clean(ws);
  386 }
  387 
  388 /**
  389  * Invalidates table allocations.
  390  * All other allocations remain valid.
  391  */
  392 MEM_STATIC void ZSTD_cwksp_clear_tables(ZSTD_cwksp* ws) {
  393     DEBUGLOG(4, "cwksp: clearing tables!");
  394 
  395 #if defined (ADDRESS_SANITIZER) && !defined (ZSTD_ASAN_DONT_POISON_WORKSPACE)
  396     {
  397         size_t size = (BYTE*)ws->tableValidEnd - (BYTE*)ws->objectEnd;
  398         __asan_poison_memory_region(ws->objectEnd, size);
  399     }
  400 #endif
  401 
  402     ws->tableEnd = ws->objectEnd;
  403     ZSTD_cwksp_assert_internal_consistency(ws);
  404 }
  405 
  406 /**
  407  * Invalidates all buffer, aligned, and table allocations.
  408  * Object allocations remain valid.
  409  */
  410 MEM_STATIC void ZSTD_cwksp_clear(ZSTD_cwksp* ws) {
  411     DEBUGLOG(4, "cwksp: clearing!");
  412 
  413 #if defined (MEMORY_SANITIZER) && !defined (ZSTD_MSAN_DONT_POISON_WORKSPACE)
  414     /* To validate that the context re-use logic is sound, and that we don't
  415      * access stuff that this compression hasn't initialized, we re-"poison"
  416      * the workspace (or at least the non-static, non-table parts of it)
  417      * every time we start a new compression. */
  418     {
  419         size_t size = (BYTE*)ws->workspaceEnd - (BYTE*)ws->tableValidEnd;
  420         __msan_poison(ws->tableValidEnd, size);
  421     }
  422 #endif
  423 
  424 #if defined (ADDRESS_SANITIZER) && !defined (ZSTD_ASAN_DONT_POISON_WORKSPACE)
  425     {
  426         size_t size = (BYTE*)ws->workspaceEnd - (BYTE*)ws->objectEnd;
  427         __asan_poison_memory_region(ws->objectEnd, size);
  428     }
  429 #endif
  430 
  431     ws->tableEnd = ws->objectEnd;
  432     ws->allocStart = ws->workspaceEnd;
  433     ws->allocFailed = 0;
  434     if (ws->phase > ZSTD_cwksp_alloc_buffers) {
  435         ws->phase = ZSTD_cwksp_alloc_buffers;
  436     }
  437     ZSTD_cwksp_assert_internal_consistency(ws);
  438 }
  439 
  440 /**
  441  * The provided workspace takes ownership of the buffer [start, start+size).
  442  * Any existing values in the workspace are ignored (the previously managed
  443  * buffer, if present, must be separately freed).
  444  */
  445 MEM_STATIC void ZSTD_cwksp_init(ZSTD_cwksp* ws, void* start, size_t size) {
  446     DEBUGLOG(4, "cwksp: init'ing workspace with %zd bytes", size);
  447     assert(((size_t)start & (sizeof(void*)-1)) == 0); /* ensure correct alignment */
  448     ws->workspace = start;
  449     ws->workspaceEnd = (BYTE*)start + size;
  450     ws->objectEnd = ws->workspace;
  451     ws->tableValidEnd = ws->objectEnd;
  452     ws->phase = ZSTD_cwksp_alloc_objects;
  453     ZSTD_cwksp_clear(ws);
  454     ws->workspaceOversizedDuration = 0;
  455     ZSTD_cwksp_assert_internal_consistency(ws);
  456 }
  457 
  458 MEM_STATIC size_t ZSTD_cwksp_create(ZSTD_cwksp* ws, size_t size, ZSTD_customMem customMem) {
  459     void* workspace = ZSTD_malloc(size, customMem);
  460     DEBUGLOG(4, "cwksp: creating new workspace with %zd bytes", size);
  461     RETURN_ERROR_IF(workspace == NULL, memory_allocation, "NULL pointer!");
  462     ZSTD_cwksp_init(ws, workspace, size);
  463     return 0;
  464 }
  465 
  466 MEM_STATIC void ZSTD_cwksp_free(ZSTD_cwksp* ws, ZSTD_customMem customMem) {
  467     void *ptr = ws->workspace;
  468     DEBUGLOG(4, "cwksp: freeing workspace");
  469     memset(ws, 0, sizeof(ZSTD_cwksp));
  470     ZSTD_free(ptr, customMem);
  471 }
  472 
  473 /**
  474  * Moves the management of a workspace from one cwksp to another. The src cwksp
  475  * is left in an invalid state (src must be re-init()'ed before its used again).
  476  */
  477 MEM_STATIC void ZSTD_cwksp_move(ZSTD_cwksp* dst, ZSTD_cwksp* src) {
  478     *dst = *src;
  479     memset(src, 0, sizeof(ZSTD_cwksp));
  480 }
  481 
  482 MEM_STATIC size_t ZSTD_cwksp_sizeof(const ZSTD_cwksp* ws) {
  483     return (size_t)((BYTE*)ws->workspaceEnd - (BYTE*)ws->workspace);
  484 }
  485 
  486 MEM_STATIC int ZSTD_cwksp_reserve_failed(const ZSTD_cwksp* ws) {
  487     return ws->allocFailed;
  488 }
  489 
  490 /*-*************************************
  491 *  Functions Checking Free Space
  492 ***************************************/
  493 
  494 MEM_STATIC size_t ZSTD_cwksp_available_space(ZSTD_cwksp* ws) {
  495     return (size_t)((BYTE*)ws->allocStart - (BYTE*)ws->tableEnd);
  496 }
  497 
  498 MEM_STATIC int ZSTD_cwksp_check_available(ZSTD_cwksp* ws, size_t additionalNeededSpace) {
  499     return ZSTD_cwksp_available_space(ws) >= additionalNeededSpace;
  500 }
  501 
  502 MEM_STATIC int ZSTD_cwksp_check_too_large(ZSTD_cwksp* ws, size_t additionalNeededSpace) {
  503     return ZSTD_cwksp_check_available(
  504         ws, additionalNeededSpace * ZSTD_WORKSPACETOOLARGE_FACTOR);
  505 }
  506 
  507 MEM_STATIC int ZSTD_cwksp_check_wasteful(ZSTD_cwksp* ws, size_t additionalNeededSpace) {
  508     return ZSTD_cwksp_check_too_large(ws, additionalNeededSpace)
  509         && ws->workspaceOversizedDuration > ZSTD_WORKSPACETOOLARGE_MAXDURATION;
  510 }
  511 
  512 MEM_STATIC void ZSTD_cwksp_bump_oversized_duration(
  513         ZSTD_cwksp* ws, size_t additionalNeededSpace) {
  514     if (ZSTD_cwksp_check_too_large(ws, additionalNeededSpace)) {
  515         ws->workspaceOversizedDuration++;
  516     } else {
  517         ws->workspaceOversizedDuration = 0;
  518     }
  519 }
  520 
  521 #if defined (__cplusplus)
  522 }
  523 #endif
  524 
  525 #endif /* ZSTD_CWKSP_H */

Cache object: 3664cd1b129572e8e93a8cbde655a613


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.