xref: /aosp_15_r20/external/zstd/lib/common/threading.c (revision 01826a4963a0d8a59bc3812d29bdf0fb76416722)
1*01826a49SYabin Cui /**
2*01826a49SYabin Cui  * Copyright (c) 2016 Tino Reichardt
3*01826a49SYabin Cui  * All rights reserved.
4*01826a49SYabin Cui  *
5*01826a49SYabin Cui  * You can contact the author at:
6*01826a49SYabin Cui  * - zstdmt source repository: https://github.com/mcmilk/zstdmt
7*01826a49SYabin Cui  *
8*01826a49SYabin Cui  * This source code is licensed under both the BSD-style license (found in the
9*01826a49SYabin Cui  * LICENSE file in the root directory of this source tree) and the GPLv2 (found
10*01826a49SYabin Cui  * in the COPYING file in the root directory of this source tree).
11*01826a49SYabin Cui  * You may select, at your option, one of the above-listed licenses.
12*01826a49SYabin Cui  */
13*01826a49SYabin Cui 
14*01826a49SYabin Cui /**
15*01826a49SYabin Cui  * This file will hold wrapper for systems, which do not support pthreads
16*01826a49SYabin Cui  */
17*01826a49SYabin Cui 
18*01826a49SYabin Cui #include "threading.h"
19*01826a49SYabin Cui 
20*01826a49SYabin Cui /* create fake symbol to avoid empty translation unit warning */
21*01826a49SYabin Cui int g_ZSTD_threading_useless_symbol;
22*01826a49SYabin Cui 
23*01826a49SYabin Cui #if defined(ZSTD_MULTITHREAD) && defined(_WIN32)
24*01826a49SYabin Cui 
25*01826a49SYabin Cui /**
26*01826a49SYabin Cui  * Windows minimalist Pthread Wrapper
27*01826a49SYabin Cui  */
28*01826a49SYabin Cui 
29*01826a49SYabin Cui 
30*01826a49SYabin Cui /* ===  Dependencies  === */
31*01826a49SYabin Cui #include <process.h>
32*01826a49SYabin Cui #include <errno.h>
33*01826a49SYabin Cui 
34*01826a49SYabin Cui 
35*01826a49SYabin Cui /* ===  Implementation  === */
36*01826a49SYabin Cui 
37*01826a49SYabin Cui typedef struct {
38*01826a49SYabin Cui     void* (*start_routine)(void*);
39*01826a49SYabin Cui     void* arg;
40*01826a49SYabin Cui     int initialized;
41*01826a49SYabin Cui     ZSTD_pthread_cond_t initialized_cond;
42*01826a49SYabin Cui     ZSTD_pthread_mutex_t initialized_mutex;
43*01826a49SYabin Cui } ZSTD_thread_params_t;
44*01826a49SYabin Cui 
worker(void * arg)45*01826a49SYabin Cui static unsigned __stdcall worker(void *arg)
46*01826a49SYabin Cui {
47*01826a49SYabin Cui     void* (*start_routine)(void*);
48*01826a49SYabin Cui     void* thread_arg;
49*01826a49SYabin Cui 
50*01826a49SYabin Cui     /* Initialized thread_arg and start_routine and signal main thread that we don't need it
51*01826a49SYabin Cui      * to wait any longer.
52*01826a49SYabin Cui      */
53*01826a49SYabin Cui     {
54*01826a49SYabin Cui         ZSTD_thread_params_t*  thread_param = (ZSTD_thread_params_t*)arg;
55*01826a49SYabin Cui         thread_arg = thread_param->arg;
56*01826a49SYabin Cui         start_routine = thread_param->start_routine;
57*01826a49SYabin Cui 
58*01826a49SYabin Cui         /* Signal main thread that we are running and do not depend on its memory anymore */
59*01826a49SYabin Cui         ZSTD_pthread_mutex_lock(&thread_param->initialized_mutex);
60*01826a49SYabin Cui         thread_param->initialized = 1;
61*01826a49SYabin Cui         ZSTD_pthread_cond_signal(&thread_param->initialized_cond);
62*01826a49SYabin Cui         ZSTD_pthread_mutex_unlock(&thread_param->initialized_mutex);
63*01826a49SYabin Cui     }
64*01826a49SYabin Cui 
65*01826a49SYabin Cui     start_routine(thread_arg);
66*01826a49SYabin Cui 
67*01826a49SYabin Cui     return 0;
68*01826a49SYabin Cui }
69*01826a49SYabin Cui 
ZSTD_pthread_create(ZSTD_pthread_t * thread,const void * unused,void * (* start_routine)(void *),void * arg)70*01826a49SYabin Cui int ZSTD_pthread_create(ZSTD_pthread_t* thread, const void* unused,
71*01826a49SYabin Cui             void* (*start_routine) (void*), void* arg)
72*01826a49SYabin Cui {
73*01826a49SYabin Cui     ZSTD_thread_params_t thread_param;
74*01826a49SYabin Cui     (void)unused;
75*01826a49SYabin Cui 
76*01826a49SYabin Cui     if (thread==NULL) return -1;
77*01826a49SYabin Cui     *thread = NULL;
78*01826a49SYabin Cui 
79*01826a49SYabin Cui     thread_param.start_routine = start_routine;
80*01826a49SYabin Cui     thread_param.arg = arg;
81*01826a49SYabin Cui     thread_param.initialized = 0;
82*01826a49SYabin Cui 
83*01826a49SYabin Cui     /* Setup thread initialization synchronization */
84*01826a49SYabin Cui     if(ZSTD_pthread_cond_init(&thread_param.initialized_cond, NULL)) {
85*01826a49SYabin Cui         /* Should never happen on Windows */
86*01826a49SYabin Cui         return -1;
87*01826a49SYabin Cui     }
88*01826a49SYabin Cui     if(ZSTD_pthread_mutex_init(&thread_param.initialized_mutex, NULL)) {
89*01826a49SYabin Cui         /* Should never happen on Windows */
90*01826a49SYabin Cui         ZSTD_pthread_cond_destroy(&thread_param.initialized_cond);
91*01826a49SYabin Cui         return -1;
92*01826a49SYabin Cui     }
93*01826a49SYabin Cui 
94*01826a49SYabin Cui     /* Spawn thread */
95*01826a49SYabin Cui     *thread = (HANDLE)_beginthreadex(NULL, 0, worker, &thread_param, 0, NULL);
96*01826a49SYabin Cui     if (*thread==NULL) {
97*01826a49SYabin Cui         ZSTD_pthread_mutex_destroy(&thread_param.initialized_mutex);
98*01826a49SYabin Cui         ZSTD_pthread_cond_destroy(&thread_param.initialized_cond);
99*01826a49SYabin Cui         return errno;
100*01826a49SYabin Cui     }
101*01826a49SYabin Cui 
102*01826a49SYabin Cui     /* Wait for thread to be initialized */
103*01826a49SYabin Cui     ZSTD_pthread_mutex_lock(&thread_param.initialized_mutex);
104*01826a49SYabin Cui     while(!thread_param.initialized) {
105*01826a49SYabin Cui         ZSTD_pthread_cond_wait(&thread_param.initialized_cond, &thread_param.initialized_mutex);
106*01826a49SYabin Cui     }
107*01826a49SYabin Cui     ZSTD_pthread_mutex_unlock(&thread_param.initialized_mutex);
108*01826a49SYabin Cui     ZSTD_pthread_mutex_destroy(&thread_param.initialized_mutex);
109*01826a49SYabin Cui     ZSTD_pthread_cond_destroy(&thread_param.initialized_cond);
110*01826a49SYabin Cui 
111*01826a49SYabin Cui     return 0;
112*01826a49SYabin Cui }
113*01826a49SYabin Cui 
ZSTD_pthread_join(ZSTD_pthread_t thread)114*01826a49SYabin Cui int ZSTD_pthread_join(ZSTD_pthread_t thread)
115*01826a49SYabin Cui {
116*01826a49SYabin Cui     DWORD result;
117*01826a49SYabin Cui 
118*01826a49SYabin Cui     if (!thread) return 0;
119*01826a49SYabin Cui 
120*01826a49SYabin Cui     result = WaitForSingleObject(thread, INFINITE);
121*01826a49SYabin Cui     CloseHandle(thread);
122*01826a49SYabin Cui 
123*01826a49SYabin Cui     switch (result) {
124*01826a49SYabin Cui     case WAIT_OBJECT_0:
125*01826a49SYabin Cui         return 0;
126*01826a49SYabin Cui     case WAIT_ABANDONED:
127*01826a49SYabin Cui         return EINVAL;
128*01826a49SYabin Cui     default:
129*01826a49SYabin Cui         return GetLastError();
130*01826a49SYabin Cui     }
131*01826a49SYabin Cui }
132*01826a49SYabin Cui 
133*01826a49SYabin Cui #endif   /* ZSTD_MULTITHREAD */
134*01826a49SYabin Cui 
135*01826a49SYabin Cui #if defined(ZSTD_MULTITHREAD) && DEBUGLEVEL >= 1 && !defined(_WIN32)
136*01826a49SYabin Cui 
137*01826a49SYabin Cui #define ZSTD_DEPS_NEED_MALLOC
138*01826a49SYabin Cui #include "zstd_deps.h"
139*01826a49SYabin Cui 
ZSTD_pthread_mutex_init(ZSTD_pthread_mutex_t * mutex,pthread_mutexattr_t const * attr)140*01826a49SYabin Cui int ZSTD_pthread_mutex_init(ZSTD_pthread_mutex_t* mutex, pthread_mutexattr_t const* attr)
141*01826a49SYabin Cui {
142*01826a49SYabin Cui     assert(mutex != NULL);
143*01826a49SYabin Cui     *mutex = (pthread_mutex_t*)ZSTD_malloc(sizeof(pthread_mutex_t));
144*01826a49SYabin Cui     if (!*mutex)
145*01826a49SYabin Cui         return 1;
146*01826a49SYabin Cui     return pthread_mutex_init(*mutex, attr);
147*01826a49SYabin Cui }
148*01826a49SYabin Cui 
ZSTD_pthread_mutex_destroy(ZSTD_pthread_mutex_t * mutex)149*01826a49SYabin Cui int ZSTD_pthread_mutex_destroy(ZSTD_pthread_mutex_t* mutex)
150*01826a49SYabin Cui {
151*01826a49SYabin Cui     assert(mutex != NULL);
152*01826a49SYabin Cui     if (!*mutex)
153*01826a49SYabin Cui         return 0;
154*01826a49SYabin Cui     {
155*01826a49SYabin Cui         int const ret = pthread_mutex_destroy(*mutex);
156*01826a49SYabin Cui         ZSTD_free(*mutex);
157*01826a49SYabin Cui         return ret;
158*01826a49SYabin Cui     }
159*01826a49SYabin Cui }
160*01826a49SYabin Cui 
ZSTD_pthread_cond_init(ZSTD_pthread_cond_t * cond,pthread_condattr_t const * attr)161*01826a49SYabin Cui int ZSTD_pthread_cond_init(ZSTD_pthread_cond_t* cond, pthread_condattr_t const* attr)
162*01826a49SYabin Cui {
163*01826a49SYabin Cui     assert(cond != NULL);
164*01826a49SYabin Cui     *cond = (pthread_cond_t*)ZSTD_malloc(sizeof(pthread_cond_t));
165*01826a49SYabin Cui     if (!*cond)
166*01826a49SYabin Cui         return 1;
167*01826a49SYabin Cui     return pthread_cond_init(*cond, attr);
168*01826a49SYabin Cui }
169*01826a49SYabin Cui 
ZSTD_pthread_cond_destroy(ZSTD_pthread_cond_t * cond)170*01826a49SYabin Cui int ZSTD_pthread_cond_destroy(ZSTD_pthread_cond_t* cond)
171*01826a49SYabin Cui {
172*01826a49SYabin Cui     assert(cond != NULL);
173*01826a49SYabin Cui     if (!*cond)
174*01826a49SYabin Cui         return 0;
175*01826a49SYabin Cui     {
176*01826a49SYabin Cui         int const ret = pthread_cond_destroy(*cond);
177*01826a49SYabin Cui         ZSTD_free(*cond);
178*01826a49SYabin Cui         return ret;
179*01826a49SYabin Cui     }
180*01826a49SYabin Cui }
181*01826a49SYabin Cui 
182*01826a49SYabin Cui #endif
183