xref: /freebsd/sys/contrib/openzfs/module/zstd/lib/common/pool.c (revision 61145dc2b94f12f6a47344fb9aac702321880e43)
1*61145dc2SMartin Matuska // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only
2c03c5b1cSMartin Matuska /*
3c03c5b1cSMartin Matuska  * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc.
4c03c5b1cSMartin Matuska  * All rights reserved.
5c03c5b1cSMartin Matuska  *
6c03c5b1cSMartin Matuska  * This source code is licensed under both the BSD-style license (found in the
7c03c5b1cSMartin Matuska  * LICENSE file in the root directory of this source tree) and the GPLv2 (found
8c03c5b1cSMartin Matuska  * in the COPYING file in the root directory of this source tree).
9c03c5b1cSMartin Matuska  * You may select, at your option, one of the above-listed licenses.
10c03c5b1cSMartin Matuska  */
11c03c5b1cSMartin Matuska 
12c03c5b1cSMartin Matuska 
13c03c5b1cSMartin Matuska /* ======   Dependencies   ======= */
14c03c5b1cSMartin Matuska #include <stddef.h>    /* size_t */
15c03c5b1cSMartin Matuska #include "debug.h"     /* assert */
16c03c5b1cSMartin Matuska #include "zstd_internal.h"  /* ZSTD_malloc, ZSTD_free */
17c03c5b1cSMartin Matuska #include "pool.h"
18c03c5b1cSMartin Matuska 
19c03c5b1cSMartin Matuska /* ======   Compiler specifics   ====== */
20c03c5b1cSMartin Matuska #if defined(_MSC_VER)
21c03c5b1cSMartin Matuska #  pragma warning(disable : 4204)        /* disable: C4204: non-constant aggregate initializer */
22c03c5b1cSMartin Matuska #endif
23c03c5b1cSMartin Matuska 
24c03c5b1cSMartin Matuska 
25c03c5b1cSMartin Matuska #ifdef ZSTD_MULTITHREAD
26c03c5b1cSMartin Matuska 
27c03c5b1cSMartin Matuska #include "threading.h"   /* pthread adaptation */
28c03c5b1cSMartin Matuska 
29c03c5b1cSMartin Matuska /* A job is a function and an opaque argument */
30c03c5b1cSMartin Matuska typedef struct POOL_job_s {
31c03c5b1cSMartin Matuska     POOL_function function;
32c03c5b1cSMartin Matuska     void *opaque;
33c03c5b1cSMartin Matuska } POOL_job;
34c03c5b1cSMartin Matuska 
35c03c5b1cSMartin Matuska struct POOL_ctx_s {
36c03c5b1cSMartin Matuska     ZSTD_customMem customMem;
37c03c5b1cSMartin Matuska     /* Keep track of the threads */
38c03c5b1cSMartin Matuska     ZSTD_pthread_t* threads;
39c03c5b1cSMartin Matuska     size_t threadCapacity;
40c03c5b1cSMartin Matuska     size_t threadLimit;
41c03c5b1cSMartin Matuska 
42c03c5b1cSMartin Matuska     /* The queue is a circular buffer */
43c03c5b1cSMartin Matuska     POOL_job *queue;
44c03c5b1cSMartin Matuska     size_t queueHead;
45c03c5b1cSMartin Matuska     size_t queueTail;
46c03c5b1cSMartin Matuska     size_t queueSize;
47c03c5b1cSMartin Matuska 
48c03c5b1cSMartin Matuska     /* The number of threads working on jobs */
49c03c5b1cSMartin Matuska     size_t numThreadsBusy;
50c03c5b1cSMartin Matuska     /* Indicates if the queue is empty */
51c03c5b1cSMartin Matuska     int queueEmpty;
52c03c5b1cSMartin Matuska 
53c03c5b1cSMartin Matuska     /* The mutex protects the queue */
54c03c5b1cSMartin Matuska     ZSTD_pthread_mutex_t queueMutex;
55c03c5b1cSMartin Matuska     /* Condition variable for pushers to wait on when the queue is full */
56c03c5b1cSMartin Matuska     ZSTD_pthread_cond_t queuePushCond;
57c03c5b1cSMartin Matuska     /* Condition variables for poppers to wait on when the queue is empty */
58c03c5b1cSMartin Matuska     ZSTD_pthread_cond_t queuePopCond;
59c03c5b1cSMartin Matuska     /* Indicates if the queue is shutting down */
60c03c5b1cSMartin Matuska     int shutdown;
61c03c5b1cSMartin Matuska };
62c03c5b1cSMartin Matuska 
63c03c5b1cSMartin Matuska /* POOL_thread() :
64c03c5b1cSMartin Matuska  * Work thread for the thread pool.
65c03c5b1cSMartin Matuska  * Waits for jobs and executes them.
66c03c5b1cSMartin Matuska  * @returns : NULL on failure else non-null.
67c03c5b1cSMartin Matuska  */
POOL_thread(void * opaque)68c03c5b1cSMartin Matuska static void* POOL_thread(void* opaque) {
69c03c5b1cSMartin Matuska     POOL_ctx* const ctx = (POOL_ctx*)opaque;
70c03c5b1cSMartin Matuska     if (!ctx) { return NULL; }
71c03c5b1cSMartin Matuska     for (;;) {
72c03c5b1cSMartin Matuska         /* Lock the mutex and wait for a non-empty queue or until shutdown */
73c03c5b1cSMartin Matuska         ZSTD_pthread_mutex_lock(&ctx->queueMutex);
74c03c5b1cSMartin Matuska 
75c03c5b1cSMartin Matuska         while ( ctx->queueEmpty
76c03c5b1cSMartin Matuska             || (ctx->numThreadsBusy >= ctx->threadLimit) ) {
77c03c5b1cSMartin Matuska             if (ctx->shutdown) {
78c03c5b1cSMartin Matuska                 /* even if !queueEmpty, (possible if numThreadsBusy >= threadLimit),
79c03c5b1cSMartin Matuska                  * a few threads will be shutdown while !queueEmpty,
80c03c5b1cSMartin Matuska                  * but enough threads will remain active to finish the queue */
81c03c5b1cSMartin Matuska                 ZSTD_pthread_mutex_unlock(&ctx->queueMutex);
82c03c5b1cSMartin Matuska                 return opaque;
83c03c5b1cSMartin Matuska             }
84c03c5b1cSMartin Matuska             ZSTD_pthread_cond_wait(&ctx->queuePopCond, &ctx->queueMutex);
85c03c5b1cSMartin Matuska         }
86c03c5b1cSMartin Matuska         /* Pop a job off the queue */
87c03c5b1cSMartin Matuska         {   POOL_job const job = ctx->queue[ctx->queueHead];
88c03c5b1cSMartin Matuska             ctx->queueHead = (ctx->queueHead + 1) % ctx->queueSize;
89c03c5b1cSMartin Matuska             ctx->numThreadsBusy++;
90c03c5b1cSMartin Matuska             ctx->queueEmpty = ctx->queueHead == ctx->queueTail;
91c03c5b1cSMartin Matuska             /* Unlock the mutex, signal a pusher, and run the job */
92c03c5b1cSMartin Matuska             ZSTD_pthread_cond_signal(&ctx->queuePushCond);
93c03c5b1cSMartin Matuska             ZSTD_pthread_mutex_unlock(&ctx->queueMutex);
94c03c5b1cSMartin Matuska 
95c03c5b1cSMartin Matuska             job.function(job.opaque);
96c03c5b1cSMartin Matuska 
97c03c5b1cSMartin Matuska             /* If the intended queue size was 0, signal after finishing job */
98c03c5b1cSMartin Matuska             ZSTD_pthread_mutex_lock(&ctx->queueMutex);
99c03c5b1cSMartin Matuska             ctx->numThreadsBusy--;
100c03c5b1cSMartin Matuska             if (ctx->queueSize == 1) {
101c03c5b1cSMartin Matuska                 ZSTD_pthread_cond_signal(&ctx->queuePushCond);
102c03c5b1cSMartin Matuska             }
103c03c5b1cSMartin Matuska             ZSTD_pthread_mutex_unlock(&ctx->queueMutex);
104c03c5b1cSMartin Matuska         }
105c03c5b1cSMartin Matuska     }  /* for (;;) */
106c03c5b1cSMartin Matuska     assert(0);  /* Unreachable */
107c03c5b1cSMartin Matuska }
108c03c5b1cSMartin Matuska 
POOL_create(size_t numThreads,size_t queueSize)109c03c5b1cSMartin Matuska POOL_ctx* POOL_create(size_t numThreads, size_t queueSize) {
110c03c5b1cSMartin Matuska     return POOL_create_advanced(numThreads, queueSize, ZSTD_defaultCMem);
111c03c5b1cSMartin Matuska }
112c03c5b1cSMartin Matuska 
POOL_create_advanced(size_t numThreads,size_t queueSize,ZSTD_customMem customMem)113c03c5b1cSMartin Matuska POOL_ctx* POOL_create_advanced(size_t numThreads, size_t queueSize,
114c03c5b1cSMartin Matuska                                ZSTD_customMem customMem) {
115c03c5b1cSMartin Matuska     POOL_ctx* ctx;
116c03c5b1cSMartin Matuska     /* Check parameters */
117c03c5b1cSMartin Matuska     if (!numThreads) { return NULL; }
118c03c5b1cSMartin Matuska     /* Allocate the context and zero initialize */
119c03c5b1cSMartin Matuska     ctx = (POOL_ctx*)ZSTD_calloc(sizeof(POOL_ctx), customMem);
120c03c5b1cSMartin Matuska     if (!ctx) { return NULL; }
121c03c5b1cSMartin Matuska     /* Initialize the job queue.
122c03c5b1cSMartin Matuska      * It needs one extra space since one space is wasted to differentiate
123c03c5b1cSMartin Matuska      * empty and full queues.
124c03c5b1cSMartin Matuska      */
125c03c5b1cSMartin Matuska     ctx->queueSize = queueSize + 1;
126c03c5b1cSMartin Matuska     ctx->queue = (POOL_job*)ZSTD_malloc(ctx->queueSize * sizeof(POOL_job), customMem);
127c03c5b1cSMartin Matuska     ctx->queueHead = 0;
128c03c5b1cSMartin Matuska     ctx->queueTail = 0;
129c03c5b1cSMartin Matuska     ctx->numThreadsBusy = 0;
130c03c5b1cSMartin Matuska     ctx->queueEmpty = 1;
131c03c5b1cSMartin Matuska     {
132c03c5b1cSMartin Matuska         int error = 0;
133c03c5b1cSMartin Matuska         error |= ZSTD_pthread_mutex_init(&ctx->queueMutex, NULL);
134c03c5b1cSMartin Matuska         error |= ZSTD_pthread_cond_init(&ctx->queuePushCond, NULL);
135c03c5b1cSMartin Matuska         error |= ZSTD_pthread_cond_init(&ctx->queuePopCond, NULL);
136c03c5b1cSMartin Matuska         if (error) { POOL_free(ctx); return NULL; }
137c03c5b1cSMartin Matuska     }
138c03c5b1cSMartin Matuska     ctx->shutdown = 0;
139c03c5b1cSMartin Matuska     /* Allocate space for the thread handles */
140c03c5b1cSMartin Matuska     ctx->threads = (ZSTD_pthread_t*)ZSTD_malloc(numThreads * sizeof(ZSTD_pthread_t), customMem);
141c03c5b1cSMartin Matuska     ctx->threadCapacity = 0;
142c03c5b1cSMartin Matuska     ctx->customMem = customMem;
143c03c5b1cSMartin Matuska     /* Check for errors */
144c03c5b1cSMartin Matuska     if (!ctx->threads || !ctx->queue) { POOL_free(ctx); return NULL; }
145c03c5b1cSMartin Matuska     /* Initialize the threads */
146c03c5b1cSMartin Matuska     {   size_t i;
147c03c5b1cSMartin Matuska         for (i = 0; i < numThreads; ++i) {
148c03c5b1cSMartin Matuska             if (ZSTD_pthread_create(&ctx->threads[i], NULL, &POOL_thread, ctx)) {
149c03c5b1cSMartin Matuska                 ctx->threadCapacity = i;
150c03c5b1cSMartin Matuska                 POOL_free(ctx);
151c03c5b1cSMartin Matuska                 return NULL;
152c03c5b1cSMartin Matuska         }   }
153c03c5b1cSMartin Matuska         ctx->threadCapacity = numThreads;
154c03c5b1cSMartin Matuska         ctx->threadLimit = numThreads;
155c03c5b1cSMartin Matuska     }
156c03c5b1cSMartin Matuska     return ctx;
157c03c5b1cSMartin Matuska }
158c03c5b1cSMartin Matuska 
159c03c5b1cSMartin Matuska /*! POOL_join() :
160c03c5b1cSMartin Matuska     Shutdown the queue, wake any sleeping threads, and join all of the threads.
161c03c5b1cSMartin Matuska */
POOL_join(POOL_ctx * ctx)162c03c5b1cSMartin Matuska static void POOL_join(POOL_ctx* ctx) {
163c03c5b1cSMartin Matuska     /* Shut down the queue */
164c03c5b1cSMartin Matuska     ZSTD_pthread_mutex_lock(&ctx->queueMutex);
165c03c5b1cSMartin Matuska     ctx->shutdown = 1;
166c03c5b1cSMartin Matuska     ZSTD_pthread_mutex_unlock(&ctx->queueMutex);
167c03c5b1cSMartin Matuska     /* Wake up sleeping threads */
168c03c5b1cSMartin Matuska     ZSTD_pthread_cond_broadcast(&ctx->queuePushCond);
169c03c5b1cSMartin Matuska     ZSTD_pthread_cond_broadcast(&ctx->queuePopCond);
170c03c5b1cSMartin Matuska     /* Join all of the threads */
171c03c5b1cSMartin Matuska     {   size_t i;
172c03c5b1cSMartin Matuska         for (i = 0; i < ctx->threadCapacity; ++i) {
173c03c5b1cSMartin Matuska             ZSTD_pthread_join(ctx->threads[i], NULL);  /* note : could fail */
174c03c5b1cSMartin Matuska     }   }
175c03c5b1cSMartin Matuska }
176c03c5b1cSMartin Matuska 
POOL_free(POOL_ctx * ctx)177c03c5b1cSMartin Matuska void POOL_free(POOL_ctx *ctx) {
178c03c5b1cSMartin Matuska     if (!ctx) { return; }
179c03c5b1cSMartin Matuska     POOL_join(ctx);
180c03c5b1cSMartin Matuska     ZSTD_pthread_mutex_destroy(&ctx->queueMutex);
181c03c5b1cSMartin Matuska     ZSTD_pthread_cond_destroy(&ctx->queuePushCond);
182c03c5b1cSMartin Matuska     ZSTD_pthread_cond_destroy(&ctx->queuePopCond);
183c03c5b1cSMartin Matuska     ZSTD_free(ctx->queue, ctx->customMem);
184c03c5b1cSMartin Matuska     ZSTD_free(ctx->threads, ctx->customMem);
185c03c5b1cSMartin Matuska     ZSTD_free(ctx, ctx->customMem);
186c03c5b1cSMartin Matuska }
187c03c5b1cSMartin Matuska 
188c03c5b1cSMartin Matuska 
189c03c5b1cSMartin Matuska 
POOL_sizeof(POOL_ctx * ctx)190c03c5b1cSMartin Matuska size_t POOL_sizeof(POOL_ctx *ctx) {
191c03c5b1cSMartin Matuska     if (ctx==NULL) return 0;  /* supports sizeof NULL */
192c03c5b1cSMartin Matuska     return sizeof(*ctx)
193c03c5b1cSMartin Matuska         + ctx->queueSize * sizeof(POOL_job)
194c03c5b1cSMartin Matuska         + ctx->threadCapacity * sizeof(ZSTD_pthread_t);
195c03c5b1cSMartin Matuska }
196c03c5b1cSMartin Matuska 
197c03c5b1cSMartin Matuska 
198c03c5b1cSMartin Matuska /* @return : 0 on success, 1 on error */
POOL_resize_internal(POOL_ctx * ctx,size_t numThreads)199c03c5b1cSMartin Matuska static int POOL_resize_internal(POOL_ctx* ctx, size_t numThreads)
200c03c5b1cSMartin Matuska {
201c03c5b1cSMartin Matuska     if (numThreads <= ctx->threadCapacity) {
202c03c5b1cSMartin Matuska         if (!numThreads) return 1;
203c03c5b1cSMartin Matuska         ctx->threadLimit = numThreads;
204c03c5b1cSMartin Matuska         return 0;
205c03c5b1cSMartin Matuska     }
206c03c5b1cSMartin Matuska     /* numThreads > threadCapacity */
207c03c5b1cSMartin Matuska     {   ZSTD_pthread_t* const threadPool = (ZSTD_pthread_t*)ZSTD_malloc(numThreads * sizeof(ZSTD_pthread_t), ctx->customMem);
208c03c5b1cSMartin Matuska         if (!threadPool) return 1;
209c03c5b1cSMartin Matuska         /* replace existing thread pool */
210c03c5b1cSMartin Matuska         memcpy(threadPool, ctx->threads, ctx->threadCapacity * sizeof(*threadPool));
211c03c5b1cSMartin Matuska         ZSTD_free(ctx->threads, ctx->customMem);
212c03c5b1cSMartin Matuska         ctx->threads = threadPool;
213c03c5b1cSMartin Matuska         /* Initialize additional threads */
214c03c5b1cSMartin Matuska         {   size_t threadId;
215c03c5b1cSMartin Matuska             for (threadId = ctx->threadCapacity; threadId < numThreads; ++threadId) {
216c03c5b1cSMartin Matuska                 if (ZSTD_pthread_create(&threadPool[threadId], NULL, &POOL_thread, ctx)) {
217c03c5b1cSMartin Matuska                     ctx->threadCapacity = threadId;
218c03c5b1cSMartin Matuska                     return 1;
219c03c5b1cSMartin Matuska             }   }
220c03c5b1cSMartin Matuska     }   }
221c03c5b1cSMartin Matuska     /* successfully expanded */
222c03c5b1cSMartin Matuska     ctx->threadCapacity = numThreads;
223c03c5b1cSMartin Matuska     ctx->threadLimit = numThreads;
224c03c5b1cSMartin Matuska     return 0;
225c03c5b1cSMartin Matuska }
226c03c5b1cSMartin Matuska 
227c03c5b1cSMartin Matuska /* @return : 0 on success, 1 on error */
POOL_resize(POOL_ctx * ctx,size_t numThreads)228c03c5b1cSMartin Matuska int POOL_resize(POOL_ctx* ctx, size_t numThreads)
229c03c5b1cSMartin Matuska {
230c03c5b1cSMartin Matuska     int result;
231c03c5b1cSMartin Matuska     if (ctx==NULL) return 1;
232c03c5b1cSMartin Matuska     ZSTD_pthread_mutex_lock(&ctx->queueMutex);
233c03c5b1cSMartin Matuska     result = POOL_resize_internal(ctx, numThreads);
234c03c5b1cSMartin Matuska     ZSTD_pthread_cond_broadcast(&ctx->queuePopCond);
235c03c5b1cSMartin Matuska     ZSTD_pthread_mutex_unlock(&ctx->queueMutex);
236c03c5b1cSMartin Matuska     return result;
237c03c5b1cSMartin Matuska }
238c03c5b1cSMartin Matuska 
239c03c5b1cSMartin Matuska /**
240c03c5b1cSMartin Matuska  * Returns 1 if the queue is full and 0 otherwise.
241c03c5b1cSMartin Matuska  *
242c03c5b1cSMartin Matuska  * When queueSize is 1 (pool was created with an intended queueSize of 0),
243c03c5b1cSMartin Matuska  * then a queue is empty if there is a thread free _and_ no job is waiting.
244c03c5b1cSMartin Matuska  */
isQueueFull(POOL_ctx const * ctx)245c03c5b1cSMartin Matuska static int isQueueFull(POOL_ctx const* ctx) {
246c03c5b1cSMartin Matuska     if (ctx->queueSize > 1) {
247c03c5b1cSMartin Matuska         return ctx->queueHead == ((ctx->queueTail + 1) % ctx->queueSize);
248c03c5b1cSMartin Matuska     } else {
249c03c5b1cSMartin Matuska         return (ctx->numThreadsBusy == ctx->threadLimit) ||
250c03c5b1cSMartin Matuska                !ctx->queueEmpty;
251c03c5b1cSMartin Matuska     }
252c03c5b1cSMartin Matuska }
253c03c5b1cSMartin Matuska 
254c03c5b1cSMartin Matuska 
POOL_add_internal(POOL_ctx * ctx,POOL_function function,void * opaque)255c03c5b1cSMartin Matuska static void POOL_add_internal(POOL_ctx* ctx, POOL_function function, void *opaque)
256c03c5b1cSMartin Matuska {
257c03c5b1cSMartin Matuska     POOL_job const job = {function, opaque};
258c03c5b1cSMartin Matuska     assert(ctx != NULL);
259c03c5b1cSMartin Matuska     if (ctx->shutdown) return;
260c03c5b1cSMartin Matuska 
261c03c5b1cSMartin Matuska     ctx->queueEmpty = 0;
262c03c5b1cSMartin Matuska     ctx->queue[ctx->queueTail] = job;
263c03c5b1cSMartin Matuska     ctx->queueTail = (ctx->queueTail + 1) % ctx->queueSize;
264c03c5b1cSMartin Matuska     ZSTD_pthread_cond_signal(&ctx->queuePopCond);
265c03c5b1cSMartin Matuska }
266c03c5b1cSMartin Matuska 
POOL_add(POOL_ctx * ctx,POOL_function function,void * opaque)267c03c5b1cSMartin Matuska void POOL_add(POOL_ctx* ctx, POOL_function function, void* opaque)
268c03c5b1cSMartin Matuska {
269c03c5b1cSMartin Matuska     assert(ctx != NULL);
270c03c5b1cSMartin Matuska     ZSTD_pthread_mutex_lock(&ctx->queueMutex);
271c03c5b1cSMartin Matuska     /* Wait until there is space in the queue for the new job */
272c03c5b1cSMartin Matuska     while (isQueueFull(ctx) && (!ctx->shutdown)) {
273c03c5b1cSMartin Matuska         ZSTD_pthread_cond_wait(&ctx->queuePushCond, &ctx->queueMutex);
274c03c5b1cSMartin Matuska     }
275c03c5b1cSMartin Matuska     POOL_add_internal(ctx, function, opaque);
276c03c5b1cSMartin Matuska     ZSTD_pthread_mutex_unlock(&ctx->queueMutex);
277c03c5b1cSMartin Matuska }
278c03c5b1cSMartin Matuska 
279c03c5b1cSMartin Matuska 
POOL_tryAdd(POOL_ctx * ctx,POOL_function function,void * opaque)280c03c5b1cSMartin Matuska int POOL_tryAdd(POOL_ctx* ctx, POOL_function function, void* opaque)
281c03c5b1cSMartin Matuska {
282c03c5b1cSMartin Matuska     assert(ctx != NULL);
283c03c5b1cSMartin Matuska     ZSTD_pthread_mutex_lock(&ctx->queueMutex);
284c03c5b1cSMartin Matuska     if (isQueueFull(ctx)) {
285c03c5b1cSMartin Matuska         ZSTD_pthread_mutex_unlock(&ctx->queueMutex);
286c03c5b1cSMartin Matuska         return 0;
287c03c5b1cSMartin Matuska     }
288c03c5b1cSMartin Matuska     POOL_add_internal(ctx, function, opaque);
289c03c5b1cSMartin Matuska     ZSTD_pthread_mutex_unlock(&ctx->queueMutex);
290c03c5b1cSMartin Matuska     return 1;
291c03c5b1cSMartin Matuska }
292c03c5b1cSMartin Matuska 
293c03c5b1cSMartin Matuska 
294c03c5b1cSMartin Matuska #else  /* ZSTD_MULTITHREAD  not defined */
295c03c5b1cSMartin Matuska 
296c03c5b1cSMartin Matuska /* ========================== */
297c03c5b1cSMartin Matuska /* No multi-threading support */
298c03c5b1cSMartin Matuska /* ========================== */
299c03c5b1cSMartin Matuska 
300c03c5b1cSMartin Matuska 
301c03c5b1cSMartin Matuska /* We don't need any data, but if it is empty, malloc() might return NULL. */
302c03c5b1cSMartin Matuska struct POOL_ctx_s {
303c03c5b1cSMartin Matuska     int dummy;
304c03c5b1cSMartin Matuska };
305c03c5b1cSMartin Matuska static POOL_ctx g_ctx;
306c03c5b1cSMartin Matuska 
POOL_create(size_t numThreads,size_t queueSize)307c03c5b1cSMartin Matuska POOL_ctx* POOL_create(size_t numThreads, size_t queueSize) {
308c03c5b1cSMartin Matuska     return POOL_create_advanced(numThreads, queueSize, ZSTD_defaultCMem);
309c03c5b1cSMartin Matuska }
310c03c5b1cSMartin Matuska 
POOL_create_advanced(size_t numThreads,size_t queueSize,ZSTD_customMem customMem)311c03c5b1cSMartin Matuska POOL_ctx* POOL_create_advanced(size_t numThreads, size_t queueSize, ZSTD_customMem customMem) {
312c03c5b1cSMartin Matuska     (void)numThreads;
313c03c5b1cSMartin Matuska     (void)queueSize;
314c03c5b1cSMartin Matuska     (void)customMem;
315c03c5b1cSMartin Matuska     return &g_ctx;
316c03c5b1cSMartin Matuska }
317c03c5b1cSMartin Matuska 
POOL_free(POOL_ctx * ctx)318c03c5b1cSMartin Matuska void POOL_free(POOL_ctx* ctx) {
319c03c5b1cSMartin Matuska     assert(!ctx || ctx == &g_ctx);
320c03c5b1cSMartin Matuska     (void)ctx;
321c03c5b1cSMartin Matuska }
322c03c5b1cSMartin Matuska 
POOL_resize(POOL_ctx * ctx,size_t numThreads)323c03c5b1cSMartin Matuska int POOL_resize(POOL_ctx* ctx, size_t numThreads) {
324c03c5b1cSMartin Matuska     (void)ctx; (void)numThreads;
325c03c5b1cSMartin Matuska     return 0;
326c03c5b1cSMartin Matuska }
327c03c5b1cSMartin Matuska 
POOL_add(POOL_ctx * ctx,POOL_function function,void * opaque)328c03c5b1cSMartin Matuska void POOL_add(POOL_ctx* ctx, POOL_function function, void* opaque) {
329c03c5b1cSMartin Matuska     (void)ctx;
330c03c5b1cSMartin Matuska     function(opaque);
331c03c5b1cSMartin Matuska }
332c03c5b1cSMartin Matuska 
POOL_tryAdd(POOL_ctx * ctx,POOL_function function,void * opaque)333c03c5b1cSMartin Matuska int POOL_tryAdd(POOL_ctx* ctx, POOL_function function, void* opaque) {
334c03c5b1cSMartin Matuska     (void)ctx;
335c03c5b1cSMartin Matuska     function(opaque);
336c03c5b1cSMartin Matuska     return 1;
337c03c5b1cSMartin Matuska }
338c03c5b1cSMartin Matuska 
POOL_sizeof(POOL_ctx * ctx)339c03c5b1cSMartin Matuska size_t POOL_sizeof(POOL_ctx* ctx) {
340c03c5b1cSMartin Matuska     if (ctx==NULL) return 0;  /* supports sizeof NULL */
341c03c5b1cSMartin Matuska     assert(ctx == &g_ctx);
342c03c5b1cSMartin Matuska     return sizeof(*ctx);
343c03c5b1cSMartin Matuska }
344c03c5b1cSMartin Matuska 
345c03c5b1cSMartin Matuska #endif  /* ZSTD_MULTITHREAD */
346