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