xref: /aosp_15_r20/external/pdfium/third_party/libopenjpeg/thread.c (revision 3ac0a46f773bac49fa9476ec2b1cf3f8da5ec3a4)
1*3ac0a46fSAndroid Build Coastguard Worker /*
2*3ac0a46fSAndroid Build Coastguard Worker  * The copyright in this software is being made available under the 2-clauses
3*3ac0a46fSAndroid Build Coastguard Worker  * BSD License, included below. This software may be subject to other third
4*3ac0a46fSAndroid Build Coastguard Worker  * party and contributor rights, including patent rights, and no such rights
5*3ac0a46fSAndroid Build Coastguard Worker  * are granted under this license.
6*3ac0a46fSAndroid Build Coastguard Worker  *
7*3ac0a46fSAndroid Build Coastguard Worker  * Copyright (c) 2016, Even Rouault
8*3ac0a46fSAndroid Build Coastguard Worker  * All rights reserved.
9*3ac0a46fSAndroid Build Coastguard Worker  *
10*3ac0a46fSAndroid Build Coastguard Worker  * Redistribution and use in source and binary forms, with or without
11*3ac0a46fSAndroid Build Coastguard Worker  * modification, are permitted provided that the following conditions
12*3ac0a46fSAndroid Build Coastguard Worker  * are met:
13*3ac0a46fSAndroid Build Coastguard Worker  * 1. Redistributions of source code must retain the above copyright
14*3ac0a46fSAndroid Build Coastguard Worker  *    notice, this list of conditions and the following disclaimer.
15*3ac0a46fSAndroid Build Coastguard Worker  * 2. Redistributions in binary form must reproduce the above copyright
16*3ac0a46fSAndroid Build Coastguard Worker  *    notice, this list of conditions and the following disclaimer in the
17*3ac0a46fSAndroid Build Coastguard Worker  *    documentation and/or other materials provided with the distribution.
18*3ac0a46fSAndroid Build Coastguard Worker  *
19*3ac0a46fSAndroid Build Coastguard Worker  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'
20*3ac0a46fSAndroid Build Coastguard Worker  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21*3ac0a46fSAndroid Build Coastguard Worker  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22*3ac0a46fSAndroid Build Coastguard Worker  * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
23*3ac0a46fSAndroid Build Coastguard Worker  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24*3ac0a46fSAndroid Build Coastguard Worker  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25*3ac0a46fSAndroid Build Coastguard Worker  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26*3ac0a46fSAndroid Build Coastguard Worker  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27*3ac0a46fSAndroid Build Coastguard Worker  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28*3ac0a46fSAndroid Build Coastguard Worker  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29*3ac0a46fSAndroid Build Coastguard Worker  * POSSIBILITY OF SUCH DAMAGE.
30*3ac0a46fSAndroid Build Coastguard Worker  */
31*3ac0a46fSAndroid Build Coastguard Worker 
32*3ac0a46fSAndroid Build Coastguard Worker #include <assert.h>
33*3ac0a46fSAndroid Build Coastguard Worker 
34*3ac0a46fSAndroid Build Coastguard Worker #ifdef MUTEX_win32
35*3ac0a46fSAndroid Build Coastguard Worker 
36*3ac0a46fSAndroid Build Coastguard Worker /* Some versions of x86_64-w64-mingw32-gc -m32 resolve InterlockedCompareExchange() */
37*3ac0a46fSAndroid Build Coastguard Worker /* as __sync_val_compare_and_swap_4 but fails to link it. As this protects against */
38*3ac0a46fSAndroid Build Coastguard Worker /* a rather unlikely race, skip it */
39*3ac0a46fSAndroid Build Coastguard Worker #if !(defined(__MINGW32__) && defined(__i386__))
40*3ac0a46fSAndroid Build Coastguard Worker #define HAVE_INTERLOCKED_COMPARE_EXCHANGE 1
41*3ac0a46fSAndroid Build Coastguard Worker #endif
42*3ac0a46fSAndroid Build Coastguard Worker 
43*3ac0a46fSAndroid Build Coastguard Worker #include <windows.h>
44*3ac0a46fSAndroid Build Coastguard Worker #include <process.h>
45*3ac0a46fSAndroid Build Coastguard Worker 
46*3ac0a46fSAndroid Build Coastguard Worker #include "opj_includes.h"
47*3ac0a46fSAndroid Build Coastguard Worker 
opj_has_thread_support(void)48*3ac0a46fSAndroid Build Coastguard Worker OPJ_BOOL OPJ_CALLCONV opj_has_thread_support(void)
49*3ac0a46fSAndroid Build Coastguard Worker {
50*3ac0a46fSAndroid Build Coastguard Worker     return OPJ_TRUE;
51*3ac0a46fSAndroid Build Coastguard Worker }
52*3ac0a46fSAndroid Build Coastguard Worker 
opj_get_num_cpus(void)53*3ac0a46fSAndroid Build Coastguard Worker int OPJ_CALLCONV opj_get_num_cpus(void)
54*3ac0a46fSAndroid Build Coastguard Worker {
55*3ac0a46fSAndroid Build Coastguard Worker     SYSTEM_INFO info;
56*3ac0a46fSAndroid Build Coastguard Worker     DWORD dwNum;
57*3ac0a46fSAndroid Build Coastguard Worker     GetSystemInfo(&info);
58*3ac0a46fSAndroid Build Coastguard Worker     dwNum = info.dwNumberOfProcessors;
59*3ac0a46fSAndroid Build Coastguard Worker     if (dwNum < 1) {
60*3ac0a46fSAndroid Build Coastguard Worker         return 1;
61*3ac0a46fSAndroid Build Coastguard Worker     }
62*3ac0a46fSAndroid Build Coastguard Worker     return (int)dwNum;
63*3ac0a46fSAndroid Build Coastguard Worker }
64*3ac0a46fSAndroid Build Coastguard Worker 
65*3ac0a46fSAndroid Build Coastguard Worker struct opj_mutex_t {
66*3ac0a46fSAndroid Build Coastguard Worker     CRITICAL_SECTION cs;
67*3ac0a46fSAndroid Build Coastguard Worker };
68*3ac0a46fSAndroid Build Coastguard Worker 
opj_mutex_create(void)69*3ac0a46fSAndroid Build Coastguard Worker opj_mutex_t* opj_mutex_create(void)
70*3ac0a46fSAndroid Build Coastguard Worker {
71*3ac0a46fSAndroid Build Coastguard Worker     opj_mutex_t* mutex = (opj_mutex_t*) opj_malloc(sizeof(opj_mutex_t));
72*3ac0a46fSAndroid Build Coastguard Worker     if (!mutex) {
73*3ac0a46fSAndroid Build Coastguard Worker         return NULL;
74*3ac0a46fSAndroid Build Coastguard Worker     }
75*3ac0a46fSAndroid Build Coastguard Worker     InitializeCriticalSectionAndSpinCount(&(mutex->cs), 4000);
76*3ac0a46fSAndroid Build Coastguard Worker     return mutex;
77*3ac0a46fSAndroid Build Coastguard Worker }
78*3ac0a46fSAndroid Build Coastguard Worker 
opj_mutex_lock(opj_mutex_t * mutex)79*3ac0a46fSAndroid Build Coastguard Worker void opj_mutex_lock(opj_mutex_t* mutex)
80*3ac0a46fSAndroid Build Coastguard Worker {
81*3ac0a46fSAndroid Build Coastguard Worker     EnterCriticalSection(&(mutex->cs));
82*3ac0a46fSAndroid Build Coastguard Worker }
83*3ac0a46fSAndroid Build Coastguard Worker 
opj_mutex_unlock(opj_mutex_t * mutex)84*3ac0a46fSAndroid Build Coastguard Worker void opj_mutex_unlock(opj_mutex_t* mutex)
85*3ac0a46fSAndroid Build Coastguard Worker {
86*3ac0a46fSAndroid Build Coastguard Worker     LeaveCriticalSection(&(mutex->cs));
87*3ac0a46fSAndroid Build Coastguard Worker }
88*3ac0a46fSAndroid Build Coastguard Worker 
opj_mutex_destroy(opj_mutex_t * mutex)89*3ac0a46fSAndroid Build Coastguard Worker void opj_mutex_destroy(opj_mutex_t* mutex)
90*3ac0a46fSAndroid Build Coastguard Worker {
91*3ac0a46fSAndroid Build Coastguard Worker     if (!mutex) {
92*3ac0a46fSAndroid Build Coastguard Worker         return;
93*3ac0a46fSAndroid Build Coastguard Worker     }
94*3ac0a46fSAndroid Build Coastguard Worker     DeleteCriticalSection(&(mutex->cs));
95*3ac0a46fSAndroid Build Coastguard Worker     opj_free(mutex);
96*3ac0a46fSAndroid Build Coastguard Worker }
97*3ac0a46fSAndroid Build Coastguard Worker 
98*3ac0a46fSAndroid Build Coastguard Worker struct opj_cond_waiter_list_t {
99*3ac0a46fSAndroid Build Coastguard Worker     HANDLE hEvent;
100*3ac0a46fSAndroid Build Coastguard Worker     struct opj_cond_waiter_list_t* next;
101*3ac0a46fSAndroid Build Coastguard Worker };
102*3ac0a46fSAndroid Build Coastguard Worker typedef struct opj_cond_waiter_list_t opj_cond_waiter_list_t;
103*3ac0a46fSAndroid Build Coastguard Worker 
104*3ac0a46fSAndroid Build Coastguard Worker struct opj_cond_t {
105*3ac0a46fSAndroid Build Coastguard Worker     opj_mutex_t             *internal_mutex;
106*3ac0a46fSAndroid Build Coastguard Worker     opj_cond_waiter_list_t  *waiter_list;
107*3ac0a46fSAndroid Build Coastguard Worker };
108*3ac0a46fSAndroid Build Coastguard Worker 
109*3ac0a46fSAndroid Build Coastguard Worker static DWORD TLSKey = 0;
110*3ac0a46fSAndroid Build Coastguard Worker static volatile LONG inTLSLockedSection = 0;
111*3ac0a46fSAndroid Build Coastguard Worker static volatile int TLSKeyInit = OPJ_FALSE;
112*3ac0a46fSAndroid Build Coastguard Worker 
opj_cond_create(void)113*3ac0a46fSAndroid Build Coastguard Worker opj_cond_t* opj_cond_create(void)
114*3ac0a46fSAndroid Build Coastguard Worker {
115*3ac0a46fSAndroid Build Coastguard Worker     opj_cond_t* cond = (opj_cond_t*) opj_malloc(sizeof(opj_cond_t));
116*3ac0a46fSAndroid Build Coastguard Worker     if (!cond) {
117*3ac0a46fSAndroid Build Coastguard Worker         return NULL;
118*3ac0a46fSAndroid Build Coastguard Worker     }
119*3ac0a46fSAndroid Build Coastguard Worker 
120*3ac0a46fSAndroid Build Coastguard Worker     /* Make sure that the TLS key is allocated in a thread-safe way */
121*3ac0a46fSAndroid Build Coastguard Worker     /* We cannot use a global mutex/critical section since its creation itself would not be */
122*3ac0a46fSAndroid Build Coastguard Worker     /* thread-safe, so use InterlockedCompareExchange trick */
123*3ac0a46fSAndroid Build Coastguard Worker     while (OPJ_TRUE) {
124*3ac0a46fSAndroid Build Coastguard Worker 
125*3ac0a46fSAndroid Build Coastguard Worker #if HAVE_INTERLOCKED_COMPARE_EXCHANGE
126*3ac0a46fSAndroid Build Coastguard Worker         if (InterlockedCompareExchange(&inTLSLockedSection, 1, 0) == 0)
127*3ac0a46fSAndroid Build Coastguard Worker #endif
128*3ac0a46fSAndroid Build Coastguard Worker         {
129*3ac0a46fSAndroid Build Coastguard Worker             if (!TLSKeyInit) {
130*3ac0a46fSAndroid Build Coastguard Worker                 TLSKey = TlsAlloc();
131*3ac0a46fSAndroid Build Coastguard Worker                 TLSKeyInit = OPJ_TRUE;
132*3ac0a46fSAndroid Build Coastguard Worker             }
133*3ac0a46fSAndroid Build Coastguard Worker #if HAVE_INTERLOCKED_COMPARE_EXCHANGE
134*3ac0a46fSAndroid Build Coastguard Worker             InterlockedCompareExchange(&inTLSLockedSection, 0, 1);
135*3ac0a46fSAndroid Build Coastguard Worker #endif
136*3ac0a46fSAndroid Build Coastguard Worker             break;
137*3ac0a46fSAndroid Build Coastguard Worker         }
138*3ac0a46fSAndroid Build Coastguard Worker     }
139*3ac0a46fSAndroid Build Coastguard Worker 
140*3ac0a46fSAndroid Build Coastguard Worker     if (TLSKey == TLS_OUT_OF_INDEXES) {
141*3ac0a46fSAndroid Build Coastguard Worker         opj_free(cond);
142*3ac0a46fSAndroid Build Coastguard Worker         return NULL;
143*3ac0a46fSAndroid Build Coastguard Worker     }
144*3ac0a46fSAndroid Build Coastguard Worker     cond->internal_mutex = opj_mutex_create();
145*3ac0a46fSAndroid Build Coastguard Worker     if (cond->internal_mutex == NULL) {
146*3ac0a46fSAndroid Build Coastguard Worker         opj_free(cond);
147*3ac0a46fSAndroid Build Coastguard Worker         return NULL;
148*3ac0a46fSAndroid Build Coastguard Worker     }
149*3ac0a46fSAndroid Build Coastguard Worker     cond->waiter_list = NULL;
150*3ac0a46fSAndroid Build Coastguard Worker     return cond;
151*3ac0a46fSAndroid Build Coastguard Worker }
152*3ac0a46fSAndroid Build Coastguard Worker 
opj_cond_wait(opj_cond_t * cond,opj_mutex_t * mutex)153*3ac0a46fSAndroid Build Coastguard Worker void opj_cond_wait(opj_cond_t* cond, opj_mutex_t* mutex)
154*3ac0a46fSAndroid Build Coastguard Worker {
155*3ac0a46fSAndroid Build Coastguard Worker     opj_cond_waiter_list_t* item;
156*3ac0a46fSAndroid Build Coastguard Worker     HANDLE hEvent = (HANDLE) TlsGetValue(TLSKey);
157*3ac0a46fSAndroid Build Coastguard Worker     if (hEvent == NULL) {
158*3ac0a46fSAndroid Build Coastguard Worker         hEvent = CreateEvent(NULL, /* security attributes */
159*3ac0a46fSAndroid Build Coastguard Worker                              0,    /* manual reset = no */
160*3ac0a46fSAndroid Build Coastguard Worker                              0,    /* initial state = unsignaled */
161*3ac0a46fSAndroid Build Coastguard Worker                              NULL  /* no name */);
162*3ac0a46fSAndroid Build Coastguard Worker         assert(hEvent);
163*3ac0a46fSAndroid Build Coastguard Worker 
164*3ac0a46fSAndroid Build Coastguard Worker         TlsSetValue(TLSKey, hEvent);
165*3ac0a46fSAndroid Build Coastguard Worker     }
166*3ac0a46fSAndroid Build Coastguard Worker 
167*3ac0a46fSAndroid Build Coastguard Worker     /* Insert the waiter into the waiter list of the condition */
168*3ac0a46fSAndroid Build Coastguard Worker     opj_mutex_lock(cond->internal_mutex);
169*3ac0a46fSAndroid Build Coastguard Worker 
170*3ac0a46fSAndroid Build Coastguard Worker     item = (opj_cond_waiter_list_t*)opj_malloc(sizeof(opj_cond_waiter_list_t));
171*3ac0a46fSAndroid Build Coastguard Worker     assert(item != NULL);
172*3ac0a46fSAndroid Build Coastguard Worker 
173*3ac0a46fSAndroid Build Coastguard Worker     item->hEvent = hEvent;
174*3ac0a46fSAndroid Build Coastguard Worker     item->next = cond->waiter_list;
175*3ac0a46fSAndroid Build Coastguard Worker 
176*3ac0a46fSAndroid Build Coastguard Worker     cond->waiter_list = item;
177*3ac0a46fSAndroid Build Coastguard Worker 
178*3ac0a46fSAndroid Build Coastguard Worker     opj_mutex_unlock(cond->internal_mutex);
179*3ac0a46fSAndroid Build Coastguard Worker 
180*3ac0a46fSAndroid Build Coastguard Worker     /* Release the client mutex before waiting for the event being signaled */
181*3ac0a46fSAndroid Build Coastguard Worker     opj_mutex_unlock(mutex);
182*3ac0a46fSAndroid Build Coastguard Worker 
183*3ac0a46fSAndroid Build Coastguard Worker     /* Ideally we would check that we do not get WAIT_FAILED but it is hard */
184*3ac0a46fSAndroid Build Coastguard Worker     /* to report a failure. */
185*3ac0a46fSAndroid Build Coastguard Worker     WaitForSingleObject(hEvent, INFINITE);
186*3ac0a46fSAndroid Build Coastguard Worker 
187*3ac0a46fSAndroid Build Coastguard Worker     /* Reacquire the client mutex */
188*3ac0a46fSAndroid Build Coastguard Worker     opj_mutex_lock(mutex);
189*3ac0a46fSAndroid Build Coastguard Worker }
190*3ac0a46fSAndroid Build Coastguard Worker 
opj_cond_signal(opj_cond_t * cond)191*3ac0a46fSAndroid Build Coastguard Worker void opj_cond_signal(opj_cond_t* cond)
192*3ac0a46fSAndroid Build Coastguard Worker {
193*3ac0a46fSAndroid Build Coastguard Worker     opj_cond_waiter_list_t* psIter;
194*3ac0a46fSAndroid Build Coastguard Worker 
195*3ac0a46fSAndroid Build Coastguard Worker     /* Signal the first registered event, and remove it from the list */
196*3ac0a46fSAndroid Build Coastguard Worker     opj_mutex_lock(cond->internal_mutex);
197*3ac0a46fSAndroid Build Coastguard Worker 
198*3ac0a46fSAndroid Build Coastguard Worker     psIter = cond->waiter_list;
199*3ac0a46fSAndroid Build Coastguard Worker     if (psIter != NULL) {
200*3ac0a46fSAndroid Build Coastguard Worker         SetEvent(psIter->hEvent);
201*3ac0a46fSAndroid Build Coastguard Worker         cond->waiter_list = psIter->next;
202*3ac0a46fSAndroid Build Coastguard Worker         opj_free(psIter);
203*3ac0a46fSAndroid Build Coastguard Worker     }
204*3ac0a46fSAndroid Build Coastguard Worker 
205*3ac0a46fSAndroid Build Coastguard Worker     opj_mutex_unlock(cond->internal_mutex);
206*3ac0a46fSAndroid Build Coastguard Worker }
207*3ac0a46fSAndroid Build Coastguard Worker 
opj_cond_destroy(opj_cond_t * cond)208*3ac0a46fSAndroid Build Coastguard Worker void opj_cond_destroy(opj_cond_t* cond)
209*3ac0a46fSAndroid Build Coastguard Worker {
210*3ac0a46fSAndroid Build Coastguard Worker     if (!cond) {
211*3ac0a46fSAndroid Build Coastguard Worker         return;
212*3ac0a46fSAndroid Build Coastguard Worker     }
213*3ac0a46fSAndroid Build Coastguard Worker     opj_mutex_destroy(cond->internal_mutex);
214*3ac0a46fSAndroid Build Coastguard Worker     assert(cond->waiter_list == NULL);
215*3ac0a46fSAndroid Build Coastguard Worker     opj_free(cond);
216*3ac0a46fSAndroid Build Coastguard Worker }
217*3ac0a46fSAndroid Build Coastguard Worker 
218*3ac0a46fSAndroid Build Coastguard Worker struct opj_thread_t {
219*3ac0a46fSAndroid Build Coastguard Worker     opj_thread_fn thread_fn;
220*3ac0a46fSAndroid Build Coastguard Worker     void* user_data;
221*3ac0a46fSAndroid Build Coastguard Worker     HANDLE hThread;
222*3ac0a46fSAndroid Build Coastguard Worker };
223*3ac0a46fSAndroid Build Coastguard Worker 
opj_thread_callback_adapter(void * info)224*3ac0a46fSAndroid Build Coastguard Worker unsigned int __stdcall opj_thread_callback_adapter(void *info)
225*3ac0a46fSAndroid Build Coastguard Worker {
226*3ac0a46fSAndroid Build Coastguard Worker     opj_thread_t* thread = (opj_thread_t*) info;
227*3ac0a46fSAndroid Build Coastguard Worker     HANDLE hEvent = NULL;
228*3ac0a46fSAndroid Build Coastguard Worker 
229*3ac0a46fSAndroid Build Coastguard Worker     thread->thread_fn(thread->user_data);
230*3ac0a46fSAndroid Build Coastguard Worker 
231*3ac0a46fSAndroid Build Coastguard Worker     /* Free the handle possible allocated by a cond */
232*3ac0a46fSAndroid Build Coastguard Worker     while (OPJ_TRUE) {
233*3ac0a46fSAndroid Build Coastguard Worker         /* Make sure TLSKey is not being created just at that moment... */
234*3ac0a46fSAndroid Build Coastguard Worker #if HAVE_INTERLOCKED_COMPARE_EXCHANGE
235*3ac0a46fSAndroid Build Coastguard Worker         if (InterlockedCompareExchange(&inTLSLockedSection, 1, 0) == 0)
236*3ac0a46fSAndroid Build Coastguard Worker #endif
237*3ac0a46fSAndroid Build Coastguard Worker         {
238*3ac0a46fSAndroid Build Coastguard Worker             if (TLSKeyInit) {
239*3ac0a46fSAndroid Build Coastguard Worker                 hEvent = (HANDLE) TlsGetValue(TLSKey);
240*3ac0a46fSAndroid Build Coastguard Worker             }
241*3ac0a46fSAndroid Build Coastguard Worker #if HAVE_INTERLOCKED_COMPARE_EXCHANGE
242*3ac0a46fSAndroid Build Coastguard Worker             InterlockedCompareExchange(&inTLSLockedSection, 0, 1);
243*3ac0a46fSAndroid Build Coastguard Worker #endif
244*3ac0a46fSAndroid Build Coastguard Worker             break;
245*3ac0a46fSAndroid Build Coastguard Worker         }
246*3ac0a46fSAndroid Build Coastguard Worker     }
247*3ac0a46fSAndroid Build Coastguard Worker     if (hEvent) {
248*3ac0a46fSAndroid Build Coastguard Worker         CloseHandle(hEvent);
249*3ac0a46fSAndroid Build Coastguard Worker     }
250*3ac0a46fSAndroid Build Coastguard Worker 
251*3ac0a46fSAndroid Build Coastguard Worker     return 0;
252*3ac0a46fSAndroid Build Coastguard Worker }
253*3ac0a46fSAndroid Build Coastguard Worker 
opj_thread_create(opj_thread_fn thread_fn,void * user_data)254*3ac0a46fSAndroid Build Coastguard Worker opj_thread_t* opj_thread_create(opj_thread_fn thread_fn, void* user_data)
255*3ac0a46fSAndroid Build Coastguard Worker {
256*3ac0a46fSAndroid Build Coastguard Worker     opj_thread_t* thread;
257*3ac0a46fSAndroid Build Coastguard Worker 
258*3ac0a46fSAndroid Build Coastguard Worker     assert(thread_fn);
259*3ac0a46fSAndroid Build Coastguard Worker 
260*3ac0a46fSAndroid Build Coastguard Worker     thread = (opj_thread_t*) opj_malloc(sizeof(opj_thread_t));
261*3ac0a46fSAndroid Build Coastguard Worker     if (!thread) {
262*3ac0a46fSAndroid Build Coastguard Worker         return NULL;
263*3ac0a46fSAndroid Build Coastguard Worker     }
264*3ac0a46fSAndroid Build Coastguard Worker     thread->thread_fn = thread_fn;
265*3ac0a46fSAndroid Build Coastguard Worker     thread->user_data = user_data;
266*3ac0a46fSAndroid Build Coastguard Worker 
267*3ac0a46fSAndroid Build Coastguard Worker     thread->hThread = (HANDLE)_beginthreadex(NULL, 0,
268*3ac0a46fSAndroid Build Coastguard Worker                       opj_thread_callback_adapter, thread, 0, NULL);
269*3ac0a46fSAndroid Build Coastguard Worker 
270*3ac0a46fSAndroid Build Coastguard Worker     if (thread->hThread == NULL) {
271*3ac0a46fSAndroid Build Coastguard Worker         opj_free(thread);
272*3ac0a46fSAndroid Build Coastguard Worker         return NULL;
273*3ac0a46fSAndroid Build Coastguard Worker     }
274*3ac0a46fSAndroid Build Coastguard Worker     return thread;
275*3ac0a46fSAndroid Build Coastguard Worker }
276*3ac0a46fSAndroid Build Coastguard Worker 
opj_thread_join(opj_thread_t * thread)277*3ac0a46fSAndroid Build Coastguard Worker void opj_thread_join(opj_thread_t* thread)
278*3ac0a46fSAndroid Build Coastguard Worker {
279*3ac0a46fSAndroid Build Coastguard Worker     WaitForSingleObject(thread->hThread, INFINITE);
280*3ac0a46fSAndroid Build Coastguard Worker     CloseHandle(thread->hThread);
281*3ac0a46fSAndroid Build Coastguard Worker 
282*3ac0a46fSAndroid Build Coastguard Worker     opj_free(thread);
283*3ac0a46fSAndroid Build Coastguard Worker }
284*3ac0a46fSAndroid Build Coastguard Worker 
285*3ac0a46fSAndroid Build Coastguard Worker #elif MUTEX_pthread
286*3ac0a46fSAndroid Build Coastguard Worker 
287*3ac0a46fSAndroid Build Coastguard Worker #include <pthread.h>
288*3ac0a46fSAndroid Build Coastguard Worker #include <stdlib.h>
289*3ac0a46fSAndroid Build Coastguard Worker #include <unistd.h>
290*3ac0a46fSAndroid Build Coastguard Worker 
291*3ac0a46fSAndroid Build Coastguard Worker /* Moved after all system includes, and in particular pthread.h, so as to */
292*3ac0a46fSAndroid Build Coastguard Worker /* avoid poisoning issuing with malloc() use in pthread.h with ulibc (#1013) */
293*3ac0a46fSAndroid Build Coastguard Worker #include "opj_includes.h"
294*3ac0a46fSAndroid Build Coastguard Worker 
opj_has_thread_support(void)295*3ac0a46fSAndroid Build Coastguard Worker OPJ_BOOL OPJ_CALLCONV opj_has_thread_support(void)
296*3ac0a46fSAndroid Build Coastguard Worker {
297*3ac0a46fSAndroid Build Coastguard Worker     return OPJ_TRUE;
298*3ac0a46fSAndroid Build Coastguard Worker }
299*3ac0a46fSAndroid Build Coastguard Worker 
opj_get_num_cpus(void)300*3ac0a46fSAndroid Build Coastguard Worker int OPJ_CALLCONV opj_get_num_cpus(void)
301*3ac0a46fSAndroid Build Coastguard Worker {
302*3ac0a46fSAndroid Build Coastguard Worker #ifdef _SC_NPROCESSORS_ONLN
303*3ac0a46fSAndroid Build Coastguard Worker     return (int)sysconf(_SC_NPROCESSORS_ONLN);
304*3ac0a46fSAndroid Build Coastguard Worker #else
305*3ac0a46fSAndroid Build Coastguard Worker     return 1;
306*3ac0a46fSAndroid Build Coastguard Worker #endif
307*3ac0a46fSAndroid Build Coastguard Worker }
308*3ac0a46fSAndroid Build Coastguard Worker 
309*3ac0a46fSAndroid Build Coastguard Worker struct opj_mutex_t {
310*3ac0a46fSAndroid Build Coastguard Worker     pthread_mutex_t mutex;
311*3ac0a46fSAndroid Build Coastguard Worker };
312*3ac0a46fSAndroid Build Coastguard Worker 
opj_mutex_create(void)313*3ac0a46fSAndroid Build Coastguard Worker opj_mutex_t* opj_mutex_create(void)
314*3ac0a46fSAndroid Build Coastguard Worker {
315*3ac0a46fSAndroid Build Coastguard Worker     opj_mutex_t* mutex = (opj_mutex_t*) opj_calloc(1U, sizeof(opj_mutex_t));
316*3ac0a46fSAndroid Build Coastguard Worker     if (mutex != NULL) {
317*3ac0a46fSAndroid Build Coastguard Worker         if (pthread_mutex_init(&mutex->mutex, NULL) != 0) {
318*3ac0a46fSAndroid Build Coastguard Worker             opj_free(mutex);
319*3ac0a46fSAndroid Build Coastguard Worker             mutex = NULL;
320*3ac0a46fSAndroid Build Coastguard Worker         }
321*3ac0a46fSAndroid Build Coastguard Worker     }
322*3ac0a46fSAndroid Build Coastguard Worker     return mutex;
323*3ac0a46fSAndroid Build Coastguard Worker }
324*3ac0a46fSAndroid Build Coastguard Worker 
opj_mutex_lock(opj_mutex_t * mutex)325*3ac0a46fSAndroid Build Coastguard Worker void opj_mutex_lock(opj_mutex_t* mutex)
326*3ac0a46fSAndroid Build Coastguard Worker {
327*3ac0a46fSAndroid Build Coastguard Worker     pthread_mutex_lock(&(mutex->mutex));
328*3ac0a46fSAndroid Build Coastguard Worker }
329*3ac0a46fSAndroid Build Coastguard Worker 
opj_mutex_unlock(opj_mutex_t * mutex)330*3ac0a46fSAndroid Build Coastguard Worker void opj_mutex_unlock(opj_mutex_t* mutex)
331*3ac0a46fSAndroid Build Coastguard Worker {
332*3ac0a46fSAndroid Build Coastguard Worker     pthread_mutex_unlock(&(mutex->mutex));
333*3ac0a46fSAndroid Build Coastguard Worker }
334*3ac0a46fSAndroid Build Coastguard Worker 
opj_mutex_destroy(opj_mutex_t * mutex)335*3ac0a46fSAndroid Build Coastguard Worker void opj_mutex_destroy(opj_mutex_t* mutex)
336*3ac0a46fSAndroid Build Coastguard Worker {
337*3ac0a46fSAndroid Build Coastguard Worker     if (!mutex) {
338*3ac0a46fSAndroid Build Coastguard Worker         return;
339*3ac0a46fSAndroid Build Coastguard Worker     }
340*3ac0a46fSAndroid Build Coastguard Worker     pthread_mutex_destroy(&(mutex->mutex));
341*3ac0a46fSAndroid Build Coastguard Worker     opj_free(mutex);
342*3ac0a46fSAndroid Build Coastguard Worker }
343*3ac0a46fSAndroid Build Coastguard Worker 
344*3ac0a46fSAndroid Build Coastguard Worker struct opj_cond_t {
345*3ac0a46fSAndroid Build Coastguard Worker     pthread_cond_t cond;
346*3ac0a46fSAndroid Build Coastguard Worker };
347*3ac0a46fSAndroid Build Coastguard Worker 
opj_cond_create(void)348*3ac0a46fSAndroid Build Coastguard Worker opj_cond_t* opj_cond_create(void)
349*3ac0a46fSAndroid Build Coastguard Worker {
350*3ac0a46fSAndroid Build Coastguard Worker     opj_cond_t* cond = (opj_cond_t*) opj_malloc(sizeof(opj_cond_t));
351*3ac0a46fSAndroid Build Coastguard Worker     if (!cond) {
352*3ac0a46fSAndroid Build Coastguard Worker         return NULL;
353*3ac0a46fSAndroid Build Coastguard Worker     }
354*3ac0a46fSAndroid Build Coastguard Worker     if (pthread_cond_init(&(cond->cond), NULL) != 0) {
355*3ac0a46fSAndroid Build Coastguard Worker         opj_free(cond);
356*3ac0a46fSAndroid Build Coastguard Worker         return NULL;
357*3ac0a46fSAndroid Build Coastguard Worker     }
358*3ac0a46fSAndroid Build Coastguard Worker     return cond;
359*3ac0a46fSAndroid Build Coastguard Worker }
360*3ac0a46fSAndroid Build Coastguard Worker 
opj_cond_wait(opj_cond_t * cond,opj_mutex_t * mutex)361*3ac0a46fSAndroid Build Coastguard Worker void opj_cond_wait(opj_cond_t* cond, opj_mutex_t* mutex)
362*3ac0a46fSAndroid Build Coastguard Worker {
363*3ac0a46fSAndroid Build Coastguard Worker     pthread_cond_wait(&(cond->cond), &(mutex->mutex));
364*3ac0a46fSAndroid Build Coastguard Worker }
365*3ac0a46fSAndroid Build Coastguard Worker 
opj_cond_signal(opj_cond_t * cond)366*3ac0a46fSAndroid Build Coastguard Worker void opj_cond_signal(opj_cond_t* cond)
367*3ac0a46fSAndroid Build Coastguard Worker {
368*3ac0a46fSAndroid Build Coastguard Worker     int ret = pthread_cond_signal(&(cond->cond));
369*3ac0a46fSAndroid Build Coastguard Worker     (void)ret;
370*3ac0a46fSAndroid Build Coastguard Worker     assert(ret == 0);
371*3ac0a46fSAndroid Build Coastguard Worker }
372*3ac0a46fSAndroid Build Coastguard Worker 
opj_cond_destroy(opj_cond_t * cond)373*3ac0a46fSAndroid Build Coastguard Worker void opj_cond_destroy(opj_cond_t* cond)
374*3ac0a46fSAndroid Build Coastguard Worker {
375*3ac0a46fSAndroid Build Coastguard Worker     if (!cond) {
376*3ac0a46fSAndroid Build Coastguard Worker         return;
377*3ac0a46fSAndroid Build Coastguard Worker     }
378*3ac0a46fSAndroid Build Coastguard Worker     pthread_cond_destroy(&(cond->cond));
379*3ac0a46fSAndroid Build Coastguard Worker     opj_free(cond);
380*3ac0a46fSAndroid Build Coastguard Worker }
381*3ac0a46fSAndroid Build Coastguard Worker 
382*3ac0a46fSAndroid Build Coastguard Worker 
383*3ac0a46fSAndroid Build Coastguard Worker struct opj_thread_t {
384*3ac0a46fSAndroid Build Coastguard Worker     opj_thread_fn thread_fn;
385*3ac0a46fSAndroid Build Coastguard Worker     void* user_data;
386*3ac0a46fSAndroid Build Coastguard Worker     pthread_t thread;
387*3ac0a46fSAndroid Build Coastguard Worker };
388*3ac0a46fSAndroid Build Coastguard Worker 
opj_thread_callback_adapter(void * info)389*3ac0a46fSAndroid Build Coastguard Worker static void* opj_thread_callback_adapter(void* info)
390*3ac0a46fSAndroid Build Coastguard Worker {
391*3ac0a46fSAndroid Build Coastguard Worker     opj_thread_t* thread = (opj_thread_t*) info;
392*3ac0a46fSAndroid Build Coastguard Worker     thread->thread_fn(thread->user_data);
393*3ac0a46fSAndroid Build Coastguard Worker     return NULL;
394*3ac0a46fSAndroid Build Coastguard Worker }
395*3ac0a46fSAndroid Build Coastguard Worker 
opj_thread_create(opj_thread_fn thread_fn,void * user_data)396*3ac0a46fSAndroid Build Coastguard Worker opj_thread_t* opj_thread_create(opj_thread_fn thread_fn, void* user_data)
397*3ac0a46fSAndroid Build Coastguard Worker {
398*3ac0a46fSAndroid Build Coastguard Worker     pthread_attr_t attr;
399*3ac0a46fSAndroid Build Coastguard Worker     opj_thread_t* thread;
400*3ac0a46fSAndroid Build Coastguard Worker 
401*3ac0a46fSAndroid Build Coastguard Worker     assert(thread_fn);
402*3ac0a46fSAndroid Build Coastguard Worker 
403*3ac0a46fSAndroid Build Coastguard Worker     thread = (opj_thread_t*) opj_malloc(sizeof(opj_thread_t));
404*3ac0a46fSAndroid Build Coastguard Worker     if (!thread) {
405*3ac0a46fSAndroid Build Coastguard Worker         return NULL;
406*3ac0a46fSAndroid Build Coastguard Worker     }
407*3ac0a46fSAndroid Build Coastguard Worker     thread->thread_fn = thread_fn;
408*3ac0a46fSAndroid Build Coastguard Worker     thread->user_data = user_data;
409*3ac0a46fSAndroid Build Coastguard Worker 
410*3ac0a46fSAndroid Build Coastguard Worker     pthread_attr_init(&attr);
411*3ac0a46fSAndroid Build Coastguard Worker     pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
412*3ac0a46fSAndroid Build Coastguard Worker     if (pthread_create(&(thread->thread), &attr,
413*3ac0a46fSAndroid Build Coastguard Worker                        opj_thread_callback_adapter, (void *) thread) != 0) {
414*3ac0a46fSAndroid Build Coastguard Worker         opj_free(thread);
415*3ac0a46fSAndroid Build Coastguard Worker         return NULL;
416*3ac0a46fSAndroid Build Coastguard Worker     }
417*3ac0a46fSAndroid Build Coastguard Worker     return thread;
418*3ac0a46fSAndroid Build Coastguard Worker }
419*3ac0a46fSAndroid Build Coastguard Worker 
opj_thread_join(opj_thread_t * thread)420*3ac0a46fSAndroid Build Coastguard Worker void opj_thread_join(opj_thread_t* thread)
421*3ac0a46fSAndroid Build Coastguard Worker {
422*3ac0a46fSAndroid Build Coastguard Worker     void* status;
423*3ac0a46fSAndroid Build Coastguard Worker     pthread_join(thread->thread, &status);
424*3ac0a46fSAndroid Build Coastguard Worker 
425*3ac0a46fSAndroid Build Coastguard Worker     opj_free(thread);
426*3ac0a46fSAndroid Build Coastguard Worker }
427*3ac0a46fSAndroid Build Coastguard Worker 
428*3ac0a46fSAndroid Build Coastguard Worker #else
429*3ac0a46fSAndroid Build Coastguard Worker /* Stub implementation */
430*3ac0a46fSAndroid Build Coastguard Worker 
431*3ac0a46fSAndroid Build Coastguard Worker #include "opj_includes.h"
432*3ac0a46fSAndroid Build Coastguard Worker 
opj_has_thread_support(void)433*3ac0a46fSAndroid Build Coastguard Worker OPJ_BOOL OPJ_CALLCONV opj_has_thread_support(void)
434*3ac0a46fSAndroid Build Coastguard Worker {
435*3ac0a46fSAndroid Build Coastguard Worker     return OPJ_FALSE;
436*3ac0a46fSAndroid Build Coastguard Worker }
437*3ac0a46fSAndroid Build Coastguard Worker 
opj_get_num_cpus(void)438*3ac0a46fSAndroid Build Coastguard Worker int OPJ_CALLCONV opj_get_num_cpus(void)
439*3ac0a46fSAndroid Build Coastguard Worker {
440*3ac0a46fSAndroid Build Coastguard Worker     return 1;
441*3ac0a46fSAndroid Build Coastguard Worker }
442*3ac0a46fSAndroid Build Coastguard Worker 
opj_mutex_create(void)443*3ac0a46fSAndroid Build Coastguard Worker opj_mutex_t* opj_mutex_create(void)
444*3ac0a46fSAndroid Build Coastguard Worker {
445*3ac0a46fSAndroid Build Coastguard Worker     return NULL;
446*3ac0a46fSAndroid Build Coastguard Worker }
447*3ac0a46fSAndroid Build Coastguard Worker 
opj_mutex_lock(opj_mutex_t * mutex)448*3ac0a46fSAndroid Build Coastguard Worker void opj_mutex_lock(opj_mutex_t* mutex)
449*3ac0a46fSAndroid Build Coastguard Worker {
450*3ac0a46fSAndroid Build Coastguard Worker     (void) mutex;
451*3ac0a46fSAndroid Build Coastguard Worker }
452*3ac0a46fSAndroid Build Coastguard Worker 
opj_mutex_unlock(opj_mutex_t * mutex)453*3ac0a46fSAndroid Build Coastguard Worker void opj_mutex_unlock(opj_mutex_t* mutex)
454*3ac0a46fSAndroid Build Coastguard Worker {
455*3ac0a46fSAndroid Build Coastguard Worker     (void) mutex;
456*3ac0a46fSAndroid Build Coastguard Worker }
457*3ac0a46fSAndroid Build Coastguard Worker 
opj_mutex_destroy(opj_mutex_t * mutex)458*3ac0a46fSAndroid Build Coastguard Worker void opj_mutex_destroy(opj_mutex_t* mutex)
459*3ac0a46fSAndroid Build Coastguard Worker {
460*3ac0a46fSAndroid Build Coastguard Worker     (void) mutex;
461*3ac0a46fSAndroid Build Coastguard Worker }
462*3ac0a46fSAndroid Build Coastguard Worker 
opj_cond_create(void)463*3ac0a46fSAndroid Build Coastguard Worker opj_cond_t* opj_cond_create(void)
464*3ac0a46fSAndroid Build Coastguard Worker {
465*3ac0a46fSAndroid Build Coastguard Worker     return NULL;
466*3ac0a46fSAndroid Build Coastguard Worker }
467*3ac0a46fSAndroid Build Coastguard Worker 
opj_cond_wait(opj_cond_t * cond,opj_mutex_t * mutex)468*3ac0a46fSAndroid Build Coastguard Worker void opj_cond_wait(opj_cond_t* cond, opj_mutex_t* mutex)
469*3ac0a46fSAndroid Build Coastguard Worker {
470*3ac0a46fSAndroid Build Coastguard Worker     (void) cond;
471*3ac0a46fSAndroid Build Coastguard Worker     (void) mutex;
472*3ac0a46fSAndroid Build Coastguard Worker }
473*3ac0a46fSAndroid Build Coastguard Worker 
opj_cond_signal(opj_cond_t * cond)474*3ac0a46fSAndroid Build Coastguard Worker void opj_cond_signal(opj_cond_t* cond)
475*3ac0a46fSAndroid Build Coastguard Worker {
476*3ac0a46fSAndroid Build Coastguard Worker     (void) cond;
477*3ac0a46fSAndroid Build Coastguard Worker }
478*3ac0a46fSAndroid Build Coastguard Worker 
opj_cond_destroy(opj_cond_t * cond)479*3ac0a46fSAndroid Build Coastguard Worker void opj_cond_destroy(opj_cond_t* cond)
480*3ac0a46fSAndroid Build Coastguard Worker {
481*3ac0a46fSAndroid Build Coastguard Worker     (void) cond;
482*3ac0a46fSAndroid Build Coastguard Worker }
483*3ac0a46fSAndroid Build Coastguard Worker 
opj_thread_create(opj_thread_fn thread_fn,void * user_data)484*3ac0a46fSAndroid Build Coastguard Worker opj_thread_t* opj_thread_create(opj_thread_fn thread_fn, void* user_data)
485*3ac0a46fSAndroid Build Coastguard Worker {
486*3ac0a46fSAndroid Build Coastguard Worker     (void) thread_fn;
487*3ac0a46fSAndroid Build Coastguard Worker     (void) user_data;
488*3ac0a46fSAndroid Build Coastguard Worker     return NULL;
489*3ac0a46fSAndroid Build Coastguard Worker }
490*3ac0a46fSAndroid Build Coastguard Worker 
opj_thread_join(opj_thread_t * thread)491*3ac0a46fSAndroid Build Coastguard Worker void opj_thread_join(opj_thread_t* thread)
492*3ac0a46fSAndroid Build Coastguard Worker {
493*3ac0a46fSAndroid Build Coastguard Worker     (void) thread;
494*3ac0a46fSAndroid Build Coastguard Worker }
495*3ac0a46fSAndroid Build Coastguard Worker 
496*3ac0a46fSAndroid Build Coastguard Worker #endif
497*3ac0a46fSAndroid Build Coastguard Worker 
498*3ac0a46fSAndroid Build Coastguard Worker typedef struct {
499*3ac0a46fSAndroid Build Coastguard Worker     int key;
500*3ac0a46fSAndroid Build Coastguard Worker     void* value;
501*3ac0a46fSAndroid Build Coastguard Worker     opj_tls_free_func opj_free_func;
502*3ac0a46fSAndroid Build Coastguard Worker } opj_tls_key_val_t;
503*3ac0a46fSAndroid Build Coastguard Worker 
504*3ac0a46fSAndroid Build Coastguard Worker struct opj_tls_t {
505*3ac0a46fSAndroid Build Coastguard Worker     opj_tls_key_val_t* key_val;
506*3ac0a46fSAndroid Build Coastguard Worker     int                key_val_count;
507*3ac0a46fSAndroid Build Coastguard Worker };
508*3ac0a46fSAndroid Build Coastguard Worker 
opj_tls_new(void)509*3ac0a46fSAndroid Build Coastguard Worker static opj_tls_t* opj_tls_new(void)
510*3ac0a46fSAndroid Build Coastguard Worker {
511*3ac0a46fSAndroid Build Coastguard Worker     return (opj_tls_t*) opj_calloc(1, sizeof(opj_tls_t));
512*3ac0a46fSAndroid Build Coastguard Worker }
513*3ac0a46fSAndroid Build Coastguard Worker 
opj_tls_destroy(opj_tls_t * tls)514*3ac0a46fSAndroid Build Coastguard Worker static void opj_tls_destroy(opj_tls_t* tls)
515*3ac0a46fSAndroid Build Coastguard Worker {
516*3ac0a46fSAndroid Build Coastguard Worker     int i;
517*3ac0a46fSAndroid Build Coastguard Worker     if (!tls) {
518*3ac0a46fSAndroid Build Coastguard Worker         return;
519*3ac0a46fSAndroid Build Coastguard Worker     }
520*3ac0a46fSAndroid Build Coastguard Worker     for (i = 0; i < tls->key_val_count; i++) {
521*3ac0a46fSAndroid Build Coastguard Worker         if (tls->key_val[i].opj_free_func) {
522*3ac0a46fSAndroid Build Coastguard Worker             tls->key_val[i].opj_free_func(tls->key_val[i].value);
523*3ac0a46fSAndroid Build Coastguard Worker         }
524*3ac0a46fSAndroid Build Coastguard Worker     }
525*3ac0a46fSAndroid Build Coastguard Worker     opj_free(tls->key_val);
526*3ac0a46fSAndroid Build Coastguard Worker     opj_free(tls);
527*3ac0a46fSAndroid Build Coastguard Worker }
528*3ac0a46fSAndroid Build Coastguard Worker 
opj_tls_get(opj_tls_t * tls,int key)529*3ac0a46fSAndroid Build Coastguard Worker void* opj_tls_get(opj_tls_t* tls, int key)
530*3ac0a46fSAndroid Build Coastguard Worker {
531*3ac0a46fSAndroid Build Coastguard Worker     int i;
532*3ac0a46fSAndroid Build Coastguard Worker     for (i = 0; i < tls->key_val_count; i++) {
533*3ac0a46fSAndroid Build Coastguard Worker         if (tls->key_val[i].key == key) {
534*3ac0a46fSAndroid Build Coastguard Worker             return tls->key_val[i].value;
535*3ac0a46fSAndroid Build Coastguard Worker         }
536*3ac0a46fSAndroid Build Coastguard Worker     }
537*3ac0a46fSAndroid Build Coastguard Worker     return NULL;
538*3ac0a46fSAndroid Build Coastguard Worker }
539*3ac0a46fSAndroid Build Coastguard Worker 
opj_tls_set(opj_tls_t * tls,int key,void * value,opj_tls_free_func opj_free_func)540*3ac0a46fSAndroid Build Coastguard Worker OPJ_BOOL opj_tls_set(opj_tls_t* tls, int key, void* value,
541*3ac0a46fSAndroid Build Coastguard Worker                      opj_tls_free_func opj_free_func)
542*3ac0a46fSAndroid Build Coastguard Worker {
543*3ac0a46fSAndroid Build Coastguard Worker     opj_tls_key_val_t* new_key_val;
544*3ac0a46fSAndroid Build Coastguard Worker     int i;
545*3ac0a46fSAndroid Build Coastguard Worker 
546*3ac0a46fSAndroid Build Coastguard Worker     if (tls->key_val_count == INT_MAX) {
547*3ac0a46fSAndroid Build Coastguard Worker         return OPJ_FALSE;
548*3ac0a46fSAndroid Build Coastguard Worker     }
549*3ac0a46fSAndroid Build Coastguard Worker     for (i = 0; i < tls->key_val_count; i++) {
550*3ac0a46fSAndroid Build Coastguard Worker         if (tls->key_val[i].key == key) {
551*3ac0a46fSAndroid Build Coastguard Worker             if (tls->key_val[i].opj_free_func) {
552*3ac0a46fSAndroid Build Coastguard Worker                 tls->key_val[i].opj_free_func(tls->key_val[i].value);
553*3ac0a46fSAndroid Build Coastguard Worker             }
554*3ac0a46fSAndroid Build Coastguard Worker             tls->key_val[i].value = value;
555*3ac0a46fSAndroid Build Coastguard Worker             tls->key_val[i].opj_free_func = opj_free_func;
556*3ac0a46fSAndroid Build Coastguard Worker             return OPJ_TRUE;
557*3ac0a46fSAndroid Build Coastguard Worker         }
558*3ac0a46fSAndroid Build Coastguard Worker     }
559*3ac0a46fSAndroid Build Coastguard Worker     new_key_val = (opj_tls_key_val_t*) opj_realloc(tls->key_val,
560*3ac0a46fSAndroid Build Coastguard Worker                   ((size_t)tls->key_val_count + 1U) * sizeof(opj_tls_key_val_t));
561*3ac0a46fSAndroid Build Coastguard Worker     if (!new_key_val) {
562*3ac0a46fSAndroid Build Coastguard Worker         return OPJ_FALSE;
563*3ac0a46fSAndroid Build Coastguard Worker     }
564*3ac0a46fSAndroid Build Coastguard Worker     tls->key_val = new_key_val;
565*3ac0a46fSAndroid Build Coastguard Worker     new_key_val[tls->key_val_count].key = key;
566*3ac0a46fSAndroid Build Coastguard Worker     new_key_val[tls->key_val_count].value = value;
567*3ac0a46fSAndroid Build Coastguard Worker     new_key_val[tls->key_val_count].opj_free_func = opj_free_func;
568*3ac0a46fSAndroid Build Coastguard Worker     tls->key_val_count ++;
569*3ac0a46fSAndroid Build Coastguard Worker     return OPJ_TRUE;
570*3ac0a46fSAndroid Build Coastguard Worker }
571*3ac0a46fSAndroid Build Coastguard Worker 
572*3ac0a46fSAndroid Build Coastguard Worker 
573*3ac0a46fSAndroid Build Coastguard Worker typedef struct {
574*3ac0a46fSAndroid Build Coastguard Worker     opj_job_fn          job_fn;
575*3ac0a46fSAndroid Build Coastguard Worker     void               *user_data;
576*3ac0a46fSAndroid Build Coastguard Worker } opj_worker_thread_job_t;
577*3ac0a46fSAndroid Build Coastguard Worker 
578*3ac0a46fSAndroid Build Coastguard Worker typedef struct {
579*3ac0a46fSAndroid Build Coastguard Worker     opj_thread_pool_t   *tp;
580*3ac0a46fSAndroid Build Coastguard Worker     opj_thread_t        *thread;
581*3ac0a46fSAndroid Build Coastguard Worker     int                  marked_as_waiting;
582*3ac0a46fSAndroid Build Coastguard Worker 
583*3ac0a46fSAndroid Build Coastguard Worker     opj_mutex_t         *mutex;
584*3ac0a46fSAndroid Build Coastguard Worker     opj_cond_t          *cond;
585*3ac0a46fSAndroid Build Coastguard Worker } opj_worker_thread_t;
586*3ac0a46fSAndroid Build Coastguard Worker 
587*3ac0a46fSAndroid Build Coastguard Worker typedef enum {
588*3ac0a46fSAndroid Build Coastguard Worker     OPJWTS_OK,
589*3ac0a46fSAndroid Build Coastguard Worker     OPJWTS_STOP,
590*3ac0a46fSAndroid Build Coastguard Worker     OPJWTS_ERROR
591*3ac0a46fSAndroid Build Coastguard Worker } opj_worker_thread_state;
592*3ac0a46fSAndroid Build Coastguard Worker 
593*3ac0a46fSAndroid Build Coastguard Worker struct opj_job_list_t {
594*3ac0a46fSAndroid Build Coastguard Worker     opj_worker_thread_job_t* job;
595*3ac0a46fSAndroid Build Coastguard Worker     struct opj_job_list_t* next;
596*3ac0a46fSAndroid Build Coastguard Worker };
597*3ac0a46fSAndroid Build Coastguard Worker typedef struct opj_job_list_t opj_job_list_t;
598*3ac0a46fSAndroid Build Coastguard Worker 
599*3ac0a46fSAndroid Build Coastguard Worker struct opj_worker_thread_list_t {
600*3ac0a46fSAndroid Build Coastguard Worker     opj_worker_thread_t* worker_thread;
601*3ac0a46fSAndroid Build Coastguard Worker     struct opj_worker_thread_list_t* next;
602*3ac0a46fSAndroid Build Coastguard Worker };
603*3ac0a46fSAndroid Build Coastguard Worker typedef struct opj_worker_thread_list_t opj_worker_thread_list_t;
604*3ac0a46fSAndroid Build Coastguard Worker 
605*3ac0a46fSAndroid Build Coastguard Worker struct opj_thread_pool_t {
606*3ac0a46fSAndroid Build Coastguard Worker     opj_worker_thread_t*             worker_threads;
607*3ac0a46fSAndroid Build Coastguard Worker     int                              worker_threads_count;
608*3ac0a46fSAndroid Build Coastguard Worker     opj_cond_t*                      cond;
609*3ac0a46fSAndroid Build Coastguard Worker     opj_mutex_t*                     mutex;
610*3ac0a46fSAndroid Build Coastguard Worker     volatile opj_worker_thread_state state;
611*3ac0a46fSAndroid Build Coastguard Worker     opj_job_list_t*                  job_queue;
612*3ac0a46fSAndroid Build Coastguard Worker     volatile int                     pending_jobs_count;
613*3ac0a46fSAndroid Build Coastguard Worker     opj_worker_thread_list_t*        waiting_worker_thread_list;
614*3ac0a46fSAndroid Build Coastguard Worker     int                              waiting_worker_thread_count;
615*3ac0a46fSAndroid Build Coastguard Worker     opj_tls_t*                       tls;
616*3ac0a46fSAndroid Build Coastguard Worker     int                              signaling_threshold;
617*3ac0a46fSAndroid Build Coastguard Worker };
618*3ac0a46fSAndroid Build Coastguard Worker 
619*3ac0a46fSAndroid Build Coastguard Worker static OPJ_BOOL opj_thread_pool_setup(opj_thread_pool_t* tp, int num_threads);
620*3ac0a46fSAndroid Build Coastguard Worker static opj_worker_thread_job_t* opj_thread_pool_get_next_job(
621*3ac0a46fSAndroid Build Coastguard Worker     opj_thread_pool_t* tp,
622*3ac0a46fSAndroid Build Coastguard Worker     opj_worker_thread_t* worker_thread,
623*3ac0a46fSAndroid Build Coastguard Worker     OPJ_BOOL signal_job_finished);
624*3ac0a46fSAndroid Build Coastguard Worker 
opj_thread_pool_create(int num_threads)625*3ac0a46fSAndroid Build Coastguard Worker opj_thread_pool_t* opj_thread_pool_create(int num_threads)
626*3ac0a46fSAndroid Build Coastguard Worker {
627*3ac0a46fSAndroid Build Coastguard Worker     opj_thread_pool_t* tp;
628*3ac0a46fSAndroid Build Coastguard Worker 
629*3ac0a46fSAndroid Build Coastguard Worker     tp = (opj_thread_pool_t*) opj_calloc(1, sizeof(opj_thread_pool_t));
630*3ac0a46fSAndroid Build Coastguard Worker     if (!tp) {
631*3ac0a46fSAndroid Build Coastguard Worker         return NULL;
632*3ac0a46fSAndroid Build Coastguard Worker     }
633*3ac0a46fSAndroid Build Coastguard Worker     tp->state = OPJWTS_OK;
634*3ac0a46fSAndroid Build Coastguard Worker 
635*3ac0a46fSAndroid Build Coastguard Worker     if (num_threads <= 0) {
636*3ac0a46fSAndroid Build Coastguard Worker         tp->tls = opj_tls_new();
637*3ac0a46fSAndroid Build Coastguard Worker         if (!tp->tls) {
638*3ac0a46fSAndroid Build Coastguard Worker             opj_free(tp);
639*3ac0a46fSAndroid Build Coastguard Worker             tp = NULL;
640*3ac0a46fSAndroid Build Coastguard Worker         }
641*3ac0a46fSAndroid Build Coastguard Worker         return tp;
642*3ac0a46fSAndroid Build Coastguard Worker     }
643*3ac0a46fSAndroid Build Coastguard Worker 
644*3ac0a46fSAndroid Build Coastguard Worker     tp->mutex = opj_mutex_create();
645*3ac0a46fSAndroid Build Coastguard Worker     if (!tp->mutex) {
646*3ac0a46fSAndroid Build Coastguard Worker         opj_free(tp);
647*3ac0a46fSAndroid Build Coastguard Worker         return NULL;
648*3ac0a46fSAndroid Build Coastguard Worker     }
649*3ac0a46fSAndroid Build Coastguard Worker     if (!opj_thread_pool_setup(tp, num_threads)) {
650*3ac0a46fSAndroid Build Coastguard Worker         opj_thread_pool_destroy(tp);
651*3ac0a46fSAndroid Build Coastguard Worker         return NULL;
652*3ac0a46fSAndroid Build Coastguard Worker     }
653*3ac0a46fSAndroid Build Coastguard Worker     return tp;
654*3ac0a46fSAndroid Build Coastguard Worker }
655*3ac0a46fSAndroid Build Coastguard Worker 
opj_worker_thread_function(void * user_data)656*3ac0a46fSAndroid Build Coastguard Worker static void opj_worker_thread_function(void* user_data)
657*3ac0a46fSAndroid Build Coastguard Worker {
658*3ac0a46fSAndroid Build Coastguard Worker     opj_worker_thread_t* worker_thread;
659*3ac0a46fSAndroid Build Coastguard Worker     opj_thread_pool_t* tp;
660*3ac0a46fSAndroid Build Coastguard Worker     opj_tls_t* tls;
661*3ac0a46fSAndroid Build Coastguard Worker     OPJ_BOOL job_finished = OPJ_FALSE;
662*3ac0a46fSAndroid Build Coastguard Worker 
663*3ac0a46fSAndroid Build Coastguard Worker     worker_thread = (opj_worker_thread_t*) user_data;
664*3ac0a46fSAndroid Build Coastguard Worker     tp = worker_thread->tp;
665*3ac0a46fSAndroid Build Coastguard Worker     tls = opj_tls_new();
666*3ac0a46fSAndroid Build Coastguard Worker 
667*3ac0a46fSAndroid Build Coastguard Worker     while (OPJ_TRUE) {
668*3ac0a46fSAndroid Build Coastguard Worker         opj_worker_thread_job_t* job = opj_thread_pool_get_next_job(tp, worker_thread,
669*3ac0a46fSAndroid Build Coastguard Worker                                        job_finished);
670*3ac0a46fSAndroid Build Coastguard Worker         if (job == NULL) {
671*3ac0a46fSAndroid Build Coastguard Worker             break;
672*3ac0a46fSAndroid Build Coastguard Worker         }
673*3ac0a46fSAndroid Build Coastguard Worker 
674*3ac0a46fSAndroid Build Coastguard Worker         if (job->job_fn) {
675*3ac0a46fSAndroid Build Coastguard Worker             job->job_fn(job->user_data, tls);
676*3ac0a46fSAndroid Build Coastguard Worker         }
677*3ac0a46fSAndroid Build Coastguard Worker         opj_free(job);
678*3ac0a46fSAndroid Build Coastguard Worker         job_finished = OPJ_TRUE;
679*3ac0a46fSAndroid Build Coastguard Worker     }
680*3ac0a46fSAndroid Build Coastguard Worker 
681*3ac0a46fSAndroid Build Coastguard Worker     opj_tls_destroy(tls);
682*3ac0a46fSAndroid Build Coastguard Worker }
683*3ac0a46fSAndroid Build Coastguard Worker 
opj_thread_pool_setup(opj_thread_pool_t * tp,int num_threads)684*3ac0a46fSAndroid Build Coastguard Worker static OPJ_BOOL opj_thread_pool_setup(opj_thread_pool_t* tp, int num_threads)
685*3ac0a46fSAndroid Build Coastguard Worker {
686*3ac0a46fSAndroid Build Coastguard Worker     int i;
687*3ac0a46fSAndroid Build Coastguard Worker     OPJ_BOOL bRet = OPJ_TRUE;
688*3ac0a46fSAndroid Build Coastguard Worker 
689*3ac0a46fSAndroid Build Coastguard Worker     assert(num_threads > 0);
690*3ac0a46fSAndroid Build Coastguard Worker 
691*3ac0a46fSAndroid Build Coastguard Worker     tp->cond = opj_cond_create();
692*3ac0a46fSAndroid Build Coastguard Worker     if (tp->cond == NULL) {
693*3ac0a46fSAndroid Build Coastguard Worker         return OPJ_FALSE;
694*3ac0a46fSAndroid Build Coastguard Worker     }
695*3ac0a46fSAndroid Build Coastguard Worker 
696*3ac0a46fSAndroid Build Coastguard Worker     tp->worker_threads = (opj_worker_thread_t*) opj_calloc((size_t)num_threads,
697*3ac0a46fSAndroid Build Coastguard Worker                          sizeof(opj_worker_thread_t));
698*3ac0a46fSAndroid Build Coastguard Worker     if (tp->worker_threads == NULL) {
699*3ac0a46fSAndroid Build Coastguard Worker         return OPJ_FALSE;
700*3ac0a46fSAndroid Build Coastguard Worker     }
701*3ac0a46fSAndroid Build Coastguard Worker     tp->worker_threads_count = num_threads;
702*3ac0a46fSAndroid Build Coastguard Worker 
703*3ac0a46fSAndroid Build Coastguard Worker     for (i = 0; i < num_threads; i++) {
704*3ac0a46fSAndroid Build Coastguard Worker         tp->worker_threads[i].tp = tp;
705*3ac0a46fSAndroid Build Coastguard Worker 
706*3ac0a46fSAndroid Build Coastguard Worker         tp->worker_threads[i].mutex = opj_mutex_create();
707*3ac0a46fSAndroid Build Coastguard Worker         if (tp->worker_threads[i].mutex == NULL) {
708*3ac0a46fSAndroid Build Coastguard Worker             tp->worker_threads_count = i;
709*3ac0a46fSAndroid Build Coastguard Worker             bRet = OPJ_FALSE;
710*3ac0a46fSAndroid Build Coastguard Worker             break;
711*3ac0a46fSAndroid Build Coastguard Worker         }
712*3ac0a46fSAndroid Build Coastguard Worker 
713*3ac0a46fSAndroid Build Coastguard Worker         tp->worker_threads[i].cond = opj_cond_create();
714*3ac0a46fSAndroid Build Coastguard Worker         if (tp->worker_threads[i].cond == NULL) {
715*3ac0a46fSAndroid Build Coastguard Worker             opj_mutex_destroy(tp->worker_threads[i].mutex);
716*3ac0a46fSAndroid Build Coastguard Worker             tp->worker_threads_count = i;
717*3ac0a46fSAndroid Build Coastguard Worker             bRet = OPJ_FALSE;
718*3ac0a46fSAndroid Build Coastguard Worker             break;
719*3ac0a46fSAndroid Build Coastguard Worker         }
720*3ac0a46fSAndroid Build Coastguard Worker 
721*3ac0a46fSAndroid Build Coastguard Worker         tp->worker_threads[i].marked_as_waiting = OPJ_FALSE;
722*3ac0a46fSAndroid Build Coastguard Worker 
723*3ac0a46fSAndroid Build Coastguard Worker         tp->worker_threads[i].thread = opj_thread_create(opj_worker_thread_function,
724*3ac0a46fSAndroid Build Coastguard Worker                                        &(tp->worker_threads[i]));
725*3ac0a46fSAndroid Build Coastguard Worker         if (tp->worker_threads[i].thread == NULL) {
726*3ac0a46fSAndroid Build Coastguard Worker             opj_mutex_destroy(tp->worker_threads[i].mutex);
727*3ac0a46fSAndroid Build Coastguard Worker             opj_cond_destroy(tp->worker_threads[i].cond);
728*3ac0a46fSAndroid Build Coastguard Worker             tp->worker_threads_count = i;
729*3ac0a46fSAndroid Build Coastguard Worker             bRet = OPJ_FALSE;
730*3ac0a46fSAndroid Build Coastguard Worker             break;
731*3ac0a46fSAndroid Build Coastguard Worker         }
732*3ac0a46fSAndroid Build Coastguard Worker     }
733*3ac0a46fSAndroid Build Coastguard Worker 
734*3ac0a46fSAndroid Build Coastguard Worker     /* Wait all threads to be started */
735*3ac0a46fSAndroid Build Coastguard Worker     /* printf("waiting for all threads to be started\n"); */
736*3ac0a46fSAndroid Build Coastguard Worker     opj_mutex_lock(tp->mutex);
737*3ac0a46fSAndroid Build Coastguard Worker     while (tp->waiting_worker_thread_count < tp->worker_threads_count) {
738*3ac0a46fSAndroid Build Coastguard Worker         opj_cond_wait(tp->cond, tp->mutex);
739*3ac0a46fSAndroid Build Coastguard Worker     }
740*3ac0a46fSAndroid Build Coastguard Worker     opj_mutex_unlock(tp->mutex);
741*3ac0a46fSAndroid Build Coastguard Worker     /* printf("all threads started\n"); */
742*3ac0a46fSAndroid Build Coastguard Worker 
743*3ac0a46fSAndroid Build Coastguard Worker     if (tp->state == OPJWTS_ERROR) {
744*3ac0a46fSAndroid Build Coastguard Worker         bRet = OPJ_FALSE;
745*3ac0a46fSAndroid Build Coastguard Worker     }
746*3ac0a46fSAndroid Build Coastguard Worker 
747*3ac0a46fSAndroid Build Coastguard Worker     return bRet;
748*3ac0a46fSAndroid Build Coastguard Worker }
749*3ac0a46fSAndroid Build Coastguard Worker 
750*3ac0a46fSAndroid Build Coastguard Worker /*
751*3ac0a46fSAndroid Build Coastguard Worker void opj_waiting()
752*3ac0a46fSAndroid Build Coastguard Worker {
753*3ac0a46fSAndroid Build Coastguard Worker     printf("waiting!\n");
754*3ac0a46fSAndroid Build Coastguard Worker }
755*3ac0a46fSAndroid Build Coastguard Worker */
756*3ac0a46fSAndroid Build Coastguard Worker 
opj_thread_pool_get_next_job(opj_thread_pool_t * tp,opj_worker_thread_t * worker_thread,OPJ_BOOL signal_job_finished)757*3ac0a46fSAndroid Build Coastguard Worker static opj_worker_thread_job_t* opj_thread_pool_get_next_job(
758*3ac0a46fSAndroid Build Coastguard Worker     opj_thread_pool_t* tp,
759*3ac0a46fSAndroid Build Coastguard Worker     opj_worker_thread_t* worker_thread,
760*3ac0a46fSAndroid Build Coastguard Worker     OPJ_BOOL signal_job_finished)
761*3ac0a46fSAndroid Build Coastguard Worker {
762*3ac0a46fSAndroid Build Coastguard Worker     while (OPJ_TRUE) {
763*3ac0a46fSAndroid Build Coastguard Worker         opj_job_list_t* top_job_iter;
764*3ac0a46fSAndroid Build Coastguard Worker 
765*3ac0a46fSAndroid Build Coastguard Worker         opj_mutex_lock(tp->mutex);
766*3ac0a46fSAndroid Build Coastguard Worker 
767*3ac0a46fSAndroid Build Coastguard Worker         if (signal_job_finished) {
768*3ac0a46fSAndroid Build Coastguard Worker             signal_job_finished = OPJ_FALSE;
769*3ac0a46fSAndroid Build Coastguard Worker             tp->pending_jobs_count --;
770*3ac0a46fSAndroid Build Coastguard Worker             /*printf("tp=%p, remaining jobs: %d\n", tp, tp->pending_jobs_count);*/
771*3ac0a46fSAndroid Build Coastguard Worker             if (tp->pending_jobs_count <= tp->signaling_threshold) {
772*3ac0a46fSAndroid Build Coastguard Worker                 opj_cond_signal(tp->cond);
773*3ac0a46fSAndroid Build Coastguard Worker             }
774*3ac0a46fSAndroid Build Coastguard Worker         }
775*3ac0a46fSAndroid Build Coastguard Worker 
776*3ac0a46fSAndroid Build Coastguard Worker         if (tp->state == OPJWTS_STOP) {
777*3ac0a46fSAndroid Build Coastguard Worker             opj_mutex_unlock(tp->mutex);
778*3ac0a46fSAndroid Build Coastguard Worker             return NULL;
779*3ac0a46fSAndroid Build Coastguard Worker         }
780*3ac0a46fSAndroid Build Coastguard Worker         top_job_iter = tp->job_queue;
781*3ac0a46fSAndroid Build Coastguard Worker         if (top_job_iter) {
782*3ac0a46fSAndroid Build Coastguard Worker             opj_worker_thread_job_t* job;
783*3ac0a46fSAndroid Build Coastguard Worker             tp->job_queue = top_job_iter->next;
784*3ac0a46fSAndroid Build Coastguard Worker 
785*3ac0a46fSAndroid Build Coastguard Worker             job = top_job_iter->job;
786*3ac0a46fSAndroid Build Coastguard Worker             opj_mutex_unlock(tp->mutex);
787*3ac0a46fSAndroid Build Coastguard Worker             opj_free(top_job_iter);
788*3ac0a46fSAndroid Build Coastguard Worker             return job;
789*3ac0a46fSAndroid Build Coastguard Worker         }
790*3ac0a46fSAndroid Build Coastguard Worker 
791*3ac0a46fSAndroid Build Coastguard Worker         /* opj_waiting(); */
792*3ac0a46fSAndroid Build Coastguard Worker         if (!worker_thread->marked_as_waiting) {
793*3ac0a46fSAndroid Build Coastguard Worker             opj_worker_thread_list_t* item;
794*3ac0a46fSAndroid Build Coastguard Worker 
795*3ac0a46fSAndroid Build Coastguard Worker             worker_thread->marked_as_waiting = OPJ_TRUE;
796*3ac0a46fSAndroid Build Coastguard Worker             tp->waiting_worker_thread_count ++;
797*3ac0a46fSAndroid Build Coastguard Worker             assert(tp->waiting_worker_thread_count <= tp->worker_threads_count);
798*3ac0a46fSAndroid Build Coastguard Worker 
799*3ac0a46fSAndroid Build Coastguard Worker             item = (opj_worker_thread_list_t*) opj_malloc(sizeof(opj_worker_thread_list_t));
800*3ac0a46fSAndroid Build Coastguard Worker             if (item == NULL) {
801*3ac0a46fSAndroid Build Coastguard Worker                 tp->state = OPJWTS_ERROR;
802*3ac0a46fSAndroid Build Coastguard Worker                 opj_cond_signal(tp->cond);
803*3ac0a46fSAndroid Build Coastguard Worker 
804*3ac0a46fSAndroid Build Coastguard Worker                 opj_mutex_unlock(tp->mutex);
805*3ac0a46fSAndroid Build Coastguard Worker                 return NULL;
806*3ac0a46fSAndroid Build Coastguard Worker             }
807*3ac0a46fSAndroid Build Coastguard Worker 
808*3ac0a46fSAndroid Build Coastguard Worker             item->worker_thread = worker_thread;
809*3ac0a46fSAndroid Build Coastguard Worker             item->next = tp->waiting_worker_thread_list;
810*3ac0a46fSAndroid Build Coastguard Worker             tp->waiting_worker_thread_list = item;
811*3ac0a46fSAndroid Build Coastguard Worker         }
812*3ac0a46fSAndroid Build Coastguard Worker 
813*3ac0a46fSAndroid Build Coastguard Worker         /* printf("signaling that worker thread is ready\n"); */
814*3ac0a46fSAndroid Build Coastguard Worker         opj_cond_signal(tp->cond);
815*3ac0a46fSAndroid Build Coastguard Worker 
816*3ac0a46fSAndroid Build Coastguard Worker         opj_mutex_lock(worker_thread->mutex);
817*3ac0a46fSAndroid Build Coastguard Worker         opj_mutex_unlock(tp->mutex);
818*3ac0a46fSAndroid Build Coastguard Worker 
819*3ac0a46fSAndroid Build Coastguard Worker         /* printf("waiting for job\n"); */
820*3ac0a46fSAndroid Build Coastguard Worker         opj_cond_wait(worker_thread->cond, worker_thread->mutex);
821*3ac0a46fSAndroid Build Coastguard Worker 
822*3ac0a46fSAndroid Build Coastguard Worker         opj_mutex_unlock(worker_thread->mutex);
823*3ac0a46fSAndroid Build Coastguard Worker         /* printf("got job\n"); */
824*3ac0a46fSAndroid Build Coastguard Worker     }
825*3ac0a46fSAndroid Build Coastguard Worker }
826*3ac0a46fSAndroid Build Coastguard Worker 
opj_thread_pool_submit_job(opj_thread_pool_t * tp,opj_job_fn job_fn,void * user_data)827*3ac0a46fSAndroid Build Coastguard Worker OPJ_BOOL opj_thread_pool_submit_job(opj_thread_pool_t* tp,
828*3ac0a46fSAndroid Build Coastguard Worker                                     opj_job_fn job_fn,
829*3ac0a46fSAndroid Build Coastguard Worker                                     void* user_data)
830*3ac0a46fSAndroid Build Coastguard Worker {
831*3ac0a46fSAndroid Build Coastguard Worker     opj_worker_thread_job_t* job;
832*3ac0a46fSAndroid Build Coastguard Worker     opj_job_list_t* item;
833*3ac0a46fSAndroid Build Coastguard Worker 
834*3ac0a46fSAndroid Build Coastguard Worker     if (tp->mutex == NULL) {
835*3ac0a46fSAndroid Build Coastguard Worker         job_fn(user_data, tp->tls);
836*3ac0a46fSAndroid Build Coastguard Worker         return OPJ_TRUE;
837*3ac0a46fSAndroid Build Coastguard Worker     }
838*3ac0a46fSAndroid Build Coastguard Worker 
839*3ac0a46fSAndroid Build Coastguard Worker     job = (opj_worker_thread_job_t*)opj_malloc(sizeof(opj_worker_thread_job_t));
840*3ac0a46fSAndroid Build Coastguard Worker     if (job == NULL) {
841*3ac0a46fSAndroid Build Coastguard Worker         return OPJ_FALSE;
842*3ac0a46fSAndroid Build Coastguard Worker     }
843*3ac0a46fSAndroid Build Coastguard Worker     job->job_fn = job_fn;
844*3ac0a46fSAndroid Build Coastguard Worker     job->user_data = user_data;
845*3ac0a46fSAndroid Build Coastguard Worker 
846*3ac0a46fSAndroid Build Coastguard Worker     item = (opj_job_list_t*) opj_malloc(sizeof(opj_job_list_t));
847*3ac0a46fSAndroid Build Coastguard Worker     if (item == NULL) {
848*3ac0a46fSAndroid Build Coastguard Worker         opj_free(job);
849*3ac0a46fSAndroid Build Coastguard Worker         return OPJ_FALSE;
850*3ac0a46fSAndroid Build Coastguard Worker     }
851*3ac0a46fSAndroid Build Coastguard Worker     item->job = job;
852*3ac0a46fSAndroid Build Coastguard Worker 
853*3ac0a46fSAndroid Build Coastguard Worker     opj_mutex_lock(tp->mutex);
854*3ac0a46fSAndroid Build Coastguard Worker 
855*3ac0a46fSAndroid Build Coastguard Worker     tp->signaling_threshold = 100 * tp->worker_threads_count;
856*3ac0a46fSAndroid Build Coastguard Worker     while (tp->pending_jobs_count > tp->signaling_threshold) {
857*3ac0a46fSAndroid Build Coastguard Worker         /* printf("%d jobs enqueued. Waiting\n", tp->pending_jobs_count); */
858*3ac0a46fSAndroid Build Coastguard Worker         opj_cond_wait(tp->cond, tp->mutex);
859*3ac0a46fSAndroid Build Coastguard Worker         /* printf("...%d jobs enqueued.\n", tp->pending_jobs_count); */
860*3ac0a46fSAndroid Build Coastguard Worker     }
861*3ac0a46fSAndroid Build Coastguard Worker 
862*3ac0a46fSAndroid Build Coastguard Worker     item->next = tp->job_queue;
863*3ac0a46fSAndroid Build Coastguard Worker     tp->job_queue = item;
864*3ac0a46fSAndroid Build Coastguard Worker     tp->pending_jobs_count ++;
865*3ac0a46fSAndroid Build Coastguard Worker 
866*3ac0a46fSAndroid Build Coastguard Worker     if (tp->waiting_worker_thread_list) {
867*3ac0a46fSAndroid Build Coastguard Worker         opj_worker_thread_t* worker_thread;
868*3ac0a46fSAndroid Build Coastguard Worker         opj_worker_thread_list_t* next;
869*3ac0a46fSAndroid Build Coastguard Worker         opj_worker_thread_list_t* to_opj_free;
870*3ac0a46fSAndroid Build Coastguard Worker 
871*3ac0a46fSAndroid Build Coastguard Worker         worker_thread = tp->waiting_worker_thread_list->worker_thread;
872*3ac0a46fSAndroid Build Coastguard Worker 
873*3ac0a46fSAndroid Build Coastguard Worker         assert(worker_thread->marked_as_waiting);
874*3ac0a46fSAndroid Build Coastguard Worker         worker_thread->marked_as_waiting = OPJ_FALSE;
875*3ac0a46fSAndroid Build Coastguard Worker 
876*3ac0a46fSAndroid Build Coastguard Worker         next = tp->waiting_worker_thread_list->next;
877*3ac0a46fSAndroid Build Coastguard Worker         to_opj_free = tp->waiting_worker_thread_list;
878*3ac0a46fSAndroid Build Coastguard Worker         tp->waiting_worker_thread_list = next;
879*3ac0a46fSAndroid Build Coastguard Worker         tp->waiting_worker_thread_count --;
880*3ac0a46fSAndroid Build Coastguard Worker 
881*3ac0a46fSAndroid Build Coastguard Worker         opj_mutex_lock(worker_thread->mutex);
882*3ac0a46fSAndroid Build Coastguard Worker         opj_mutex_unlock(tp->mutex);
883*3ac0a46fSAndroid Build Coastguard Worker         opj_cond_signal(worker_thread->cond);
884*3ac0a46fSAndroid Build Coastguard Worker         opj_mutex_unlock(worker_thread->mutex);
885*3ac0a46fSAndroid Build Coastguard Worker 
886*3ac0a46fSAndroid Build Coastguard Worker         opj_free(to_opj_free);
887*3ac0a46fSAndroid Build Coastguard Worker     } else {
888*3ac0a46fSAndroid Build Coastguard Worker         opj_mutex_unlock(tp->mutex);
889*3ac0a46fSAndroid Build Coastguard Worker     }
890*3ac0a46fSAndroid Build Coastguard Worker 
891*3ac0a46fSAndroid Build Coastguard Worker     return OPJ_TRUE;
892*3ac0a46fSAndroid Build Coastguard Worker }
893*3ac0a46fSAndroid Build Coastguard Worker 
opj_thread_pool_wait_completion(opj_thread_pool_t * tp,int max_remaining_jobs)894*3ac0a46fSAndroid Build Coastguard Worker void opj_thread_pool_wait_completion(opj_thread_pool_t* tp,
895*3ac0a46fSAndroid Build Coastguard Worker                                      int max_remaining_jobs)
896*3ac0a46fSAndroid Build Coastguard Worker {
897*3ac0a46fSAndroid Build Coastguard Worker     if (tp->mutex == NULL) {
898*3ac0a46fSAndroid Build Coastguard Worker         return;
899*3ac0a46fSAndroid Build Coastguard Worker     }
900*3ac0a46fSAndroid Build Coastguard Worker 
901*3ac0a46fSAndroid Build Coastguard Worker     if (max_remaining_jobs < 0) {
902*3ac0a46fSAndroid Build Coastguard Worker         max_remaining_jobs = 0;
903*3ac0a46fSAndroid Build Coastguard Worker     }
904*3ac0a46fSAndroid Build Coastguard Worker     opj_mutex_lock(tp->mutex);
905*3ac0a46fSAndroid Build Coastguard Worker     tp->signaling_threshold = max_remaining_jobs;
906*3ac0a46fSAndroid Build Coastguard Worker     while (tp->pending_jobs_count > max_remaining_jobs) {
907*3ac0a46fSAndroid Build Coastguard Worker         /*printf("tp=%p, jobs before wait = %d, max_remaining_jobs = %d\n", tp, tp->pending_jobs_count, max_remaining_jobs);*/
908*3ac0a46fSAndroid Build Coastguard Worker         opj_cond_wait(tp->cond, tp->mutex);
909*3ac0a46fSAndroid Build Coastguard Worker         /*printf("tp=%p, jobs after wait = %d\n", tp, tp->pending_jobs_count);*/
910*3ac0a46fSAndroid Build Coastguard Worker     }
911*3ac0a46fSAndroid Build Coastguard Worker     opj_mutex_unlock(tp->mutex);
912*3ac0a46fSAndroid Build Coastguard Worker }
913*3ac0a46fSAndroid Build Coastguard Worker 
opj_thread_pool_get_thread_count(opj_thread_pool_t * tp)914*3ac0a46fSAndroid Build Coastguard Worker int opj_thread_pool_get_thread_count(opj_thread_pool_t* tp)
915*3ac0a46fSAndroid Build Coastguard Worker {
916*3ac0a46fSAndroid Build Coastguard Worker     return tp->worker_threads_count;
917*3ac0a46fSAndroid Build Coastguard Worker }
918*3ac0a46fSAndroid Build Coastguard Worker 
opj_thread_pool_destroy(opj_thread_pool_t * tp)919*3ac0a46fSAndroid Build Coastguard Worker void opj_thread_pool_destroy(opj_thread_pool_t* tp)
920*3ac0a46fSAndroid Build Coastguard Worker {
921*3ac0a46fSAndroid Build Coastguard Worker     if (!tp) {
922*3ac0a46fSAndroid Build Coastguard Worker         return;
923*3ac0a46fSAndroid Build Coastguard Worker     }
924*3ac0a46fSAndroid Build Coastguard Worker     if (tp->cond) {
925*3ac0a46fSAndroid Build Coastguard Worker         int i;
926*3ac0a46fSAndroid Build Coastguard Worker         opj_thread_pool_wait_completion(tp, 0);
927*3ac0a46fSAndroid Build Coastguard Worker 
928*3ac0a46fSAndroid Build Coastguard Worker         opj_mutex_lock(tp->mutex);
929*3ac0a46fSAndroid Build Coastguard Worker         tp->state = OPJWTS_STOP;
930*3ac0a46fSAndroid Build Coastguard Worker         opj_mutex_unlock(tp->mutex);
931*3ac0a46fSAndroid Build Coastguard Worker 
932*3ac0a46fSAndroid Build Coastguard Worker         for (i = 0; i < tp->worker_threads_count; i++) {
933*3ac0a46fSAndroid Build Coastguard Worker             opj_mutex_lock(tp->worker_threads[i].mutex);
934*3ac0a46fSAndroid Build Coastguard Worker             opj_cond_signal(tp->worker_threads[i].cond);
935*3ac0a46fSAndroid Build Coastguard Worker             opj_mutex_unlock(tp->worker_threads[i].mutex);
936*3ac0a46fSAndroid Build Coastguard Worker             opj_thread_join(tp->worker_threads[i].thread);
937*3ac0a46fSAndroid Build Coastguard Worker             opj_cond_destroy(tp->worker_threads[i].cond);
938*3ac0a46fSAndroid Build Coastguard Worker             opj_mutex_destroy(tp->worker_threads[i].mutex);
939*3ac0a46fSAndroid Build Coastguard Worker         }
940*3ac0a46fSAndroid Build Coastguard Worker 
941*3ac0a46fSAndroid Build Coastguard Worker         opj_free(tp->worker_threads);
942*3ac0a46fSAndroid Build Coastguard Worker 
943*3ac0a46fSAndroid Build Coastguard Worker         while (tp->waiting_worker_thread_list != NULL) {
944*3ac0a46fSAndroid Build Coastguard Worker             opj_worker_thread_list_t* next = tp->waiting_worker_thread_list->next;
945*3ac0a46fSAndroid Build Coastguard Worker             opj_free(tp->waiting_worker_thread_list);
946*3ac0a46fSAndroid Build Coastguard Worker             tp->waiting_worker_thread_list = next;
947*3ac0a46fSAndroid Build Coastguard Worker         }
948*3ac0a46fSAndroid Build Coastguard Worker 
949*3ac0a46fSAndroid Build Coastguard Worker         opj_cond_destroy(tp->cond);
950*3ac0a46fSAndroid Build Coastguard Worker     }
951*3ac0a46fSAndroid Build Coastguard Worker     opj_mutex_destroy(tp->mutex);
952*3ac0a46fSAndroid Build Coastguard Worker     opj_tls_destroy(tp->tls);
953*3ac0a46fSAndroid Build Coastguard Worker     opj_free(tp);
954*3ac0a46fSAndroid Build Coastguard Worker }
955