xref: /aosp_15_r20/external/libopenapv/src/oapv_tpool.c (revision abb65b4b03b69e1d508d4d9a44dcf199df16e7c3)
1*abb65b4bSAndroid Build Coastguard Worker /*
2*abb65b4bSAndroid Build Coastguard Worker  * Copyright (c) 2022 Samsung Electronics Co., Ltd.
3*abb65b4bSAndroid Build Coastguard Worker  * All Rights Reserved.
4*abb65b4bSAndroid Build Coastguard Worker  *
5*abb65b4bSAndroid Build Coastguard Worker  * Redistribution and use in source and binary forms, with or without
6*abb65b4bSAndroid Build Coastguard Worker  * modification, are permitted provided that the following conditions are met:
7*abb65b4bSAndroid Build Coastguard Worker  *
8*abb65b4bSAndroid Build Coastguard Worker  * - Redistributions of source code must retain the above copyright notice,
9*abb65b4bSAndroid Build Coastguard Worker  *   this list of conditions and the following disclaimer.
10*abb65b4bSAndroid Build Coastguard Worker  *
11*abb65b4bSAndroid Build Coastguard Worker  * - Redistributions in binary form must reproduce the above copyright notice,
12*abb65b4bSAndroid Build Coastguard Worker  *   this list of conditions and the following disclaimer in the documentation
13*abb65b4bSAndroid Build Coastguard Worker  *   and/or other materials provided with the distribution.
14*abb65b4bSAndroid Build Coastguard Worker  *
15*abb65b4bSAndroid Build Coastguard Worker  * - Neither the name of the copyright owner, nor the names of its contributors
16*abb65b4bSAndroid Build Coastguard Worker  *   may be used to endorse or promote products derived from this software
17*abb65b4bSAndroid Build Coastguard Worker  *   without specific prior written permission.
18*abb65b4bSAndroid Build Coastguard Worker  *
19*abb65b4bSAndroid Build Coastguard Worker  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20*abb65b4bSAndroid Build Coastguard Worker  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21*abb65b4bSAndroid Build Coastguard Worker  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22*abb65b4bSAndroid Build Coastguard Worker  * ARE DISCLAIMED.IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
23*abb65b4bSAndroid Build Coastguard Worker  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24*abb65b4bSAndroid Build Coastguard Worker  * CONSEQUENTIAL DAMAGES(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25*abb65b4bSAndroid Build Coastguard Worker  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26*abb65b4bSAndroid Build Coastguard Worker  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27*abb65b4bSAndroid Build Coastguard Worker  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28*abb65b4bSAndroid Build Coastguard Worker  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29*abb65b4bSAndroid Build Coastguard Worker  * POSSIBILITY OF SUCH DAMAGE.
30*abb65b4bSAndroid Build Coastguard Worker  */
31*abb65b4bSAndroid Build Coastguard Worker 
32*abb65b4bSAndroid Build Coastguard Worker #include <stdio.h>
33*abb65b4bSAndroid Build Coastguard Worker #include <stdlib.h>
34*abb65b4bSAndroid Build Coastguard Worker #include "oapv_tpool.h"
35*abb65b4bSAndroid Build Coastguard Worker #if defined(WIN32) || defined(WIN64)
36*abb65b4bSAndroid Build Coastguard Worker #include <windows.h>
37*abb65b4bSAndroid Build Coastguard Worker #include <process.h>
38*abb65b4bSAndroid Build Coastguard Worker #else
39*abb65b4bSAndroid Build Coastguard Worker #include <pthread.h>
40*abb65b4bSAndroid Build Coastguard Worker #endif
41*abb65b4bSAndroid Build Coastguard Worker 
42*abb65b4bSAndroid Build Coastguard Worker #define WINDOWS_MUTEX_SYNC 0
43*abb65b4bSAndroid Build Coastguard Worker 
44*abb65b4bSAndroid Build Coastguard Worker #if !defined(WIN32) && !defined(WIN64)
45*abb65b4bSAndroid Build Coastguard Worker 
46*abb65b4bSAndroid Build Coastguard Worker typedef struct thread_ctx {
47*abb65b4bSAndroid Build Coastguard Worker     // synchronization members
48*abb65b4bSAndroid Build Coastguard Worker     pthread_t              t_handle;   // worker thread handle
49*abb65b4bSAndroid Build Coastguard Worker     pthread_attr_t         tAttribute; // worker thread attribute
50*abb65b4bSAndroid Build Coastguard Worker     pthread_cond_t         w_event;    // wait event for worker thread
51*abb65b4bSAndroid Build Coastguard Worker     pthread_cond_t         r_event;    // wait event for main thread
52*abb65b4bSAndroid Build Coastguard Worker     pthread_mutex_t        c_section;  // for synchronization
53*abb65b4bSAndroid Build Coastguard Worker 
54*abb65b4bSAndroid Build Coastguard Worker     // member field to run  a task
55*abb65b4bSAndroid Build Coastguard Worker     oapv_fn_thread_entry_t task;
56*abb65b4bSAndroid Build Coastguard Worker     void                  *t_arg;
57*abb65b4bSAndroid Build Coastguard Worker     tpool_status_t         t_status;
58*abb65b4bSAndroid Build Coastguard Worker     tpool_result_t         t_result;
59*abb65b4bSAndroid Build Coastguard Worker     int                    thread_id;
60*abb65b4bSAndroid Build Coastguard Worker     int                    task_ret; // return value of task function
61*abb65b4bSAndroid Build Coastguard Worker } thread_ctx_t;
62*abb65b4bSAndroid Build Coastguard Worker 
63*abb65b4bSAndroid Build Coastguard Worker typedef struct thread_mutex {
64*abb65b4bSAndroid Build Coastguard Worker     pthread_mutex_t lmutex;
65*abb65b4bSAndroid Build Coastguard Worker } thread_mutex_t;
66*abb65b4bSAndroid Build Coastguard Worker 
tpool_worker_thread(void * arg)67*abb65b4bSAndroid Build Coastguard Worker static void *tpool_worker_thread(void *arg)
68*abb65b4bSAndroid Build Coastguard Worker {
69*abb65b4bSAndroid Build Coastguard Worker     /********************* main routine for thread pool worker thread *************************
70*abb65b4bSAndroid Build Coastguard Worker     ********************** worker thread can remain in suspended or running state *************
71*abb65b4bSAndroid Build Coastguard Worker     ********************* control the synchronization with help of thread context members *****/
72*abb65b4bSAndroid Build Coastguard Worker 
73*abb65b4bSAndroid Build Coastguard Worker     // member Initialization section
74*abb65b4bSAndroid Build Coastguard Worker     thread_ctx_t *t_context = (thread_ctx_t *)arg;
75*abb65b4bSAndroid Build Coastguard Worker     int           ret;
76*abb65b4bSAndroid Build Coastguard Worker 
77*abb65b4bSAndroid Build Coastguard Worker     if(!t_context) {
78*abb65b4bSAndroid Build Coastguard Worker         return 0; // error handling, more like a fail safe mechanism
79*abb65b4bSAndroid Build Coastguard Worker     }
80*abb65b4bSAndroid Build Coastguard Worker 
81*abb65b4bSAndroid Build Coastguard Worker     while(1) {
82*abb65b4bSAndroid Build Coastguard Worker         // worker thread loop
83*abb65b4bSAndroid Build Coastguard Worker         // remains suspended/sleep waiting for an event
84*abb65b4bSAndroid Build Coastguard Worker 
85*abb65b4bSAndroid Build Coastguard Worker         // get the mutex and check the state
86*abb65b4bSAndroid Build Coastguard Worker         pthread_mutex_lock(&t_context->c_section);
87*abb65b4bSAndroid Build Coastguard Worker         while(t_context->t_status == TPOOL_SUSPENDED) {
88*abb65b4bSAndroid Build Coastguard Worker             // wait for the event
89*abb65b4bSAndroid Build Coastguard Worker             pthread_cond_wait(&t_context->w_event, &t_context->c_section);
90*abb65b4bSAndroid Build Coastguard Worker         }
91*abb65b4bSAndroid Build Coastguard Worker 
92*abb65b4bSAndroid Build Coastguard Worker         if(t_context->t_status == TPOOL_TERMINATED) {
93*abb65b4bSAndroid Build Coastguard Worker             t_context->t_result = TPOOL_SUCCESS;
94*abb65b4bSAndroid Build Coastguard Worker             pthread_mutex_unlock(&t_context->c_section);
95*abb65b4bSAndroid Build Coastguard Worker             break; // exit the routine
96*abb65b4bSAndroid Build Coastguard Worker         }
97*abb65b4bSAndroid Build Coastguard Worker 
98*abb65b4bSAndroid Build Coastguard Worker         t_context->t_status = TPOOL_RUNNING;
99*abb65b4bSAndroid Build Coastguard Worker         pthread_mutex_unlock(&t_context->c_section);
100*abb65b4bSAndroid Build Coastguard Worker 
101*abb65b4bSAndroid Build Coastguard Worker         // run the routine
102*abb65b4bSAndroid Build Coastguard Worker         // worker thread state is running with entry function and arg set
103*abb65b4bSAndroid Build Coastguard Worker         ret = t_context->task(t_context->t_arg);
104*abb65b4bSAndroid Build Coastguard Worker 
105*abb65b4bSAndroid Build Coastguard Worker         // signal the thread waiting on the result
106*abb65b4bSAndroid Build Coastguard Worker         pthread_mutex_lock(&t_context->c_section);
107*abb65b4bSAndroid Build Coastguard Worker         t_context->t_status = TPOOL_SUSPENDED;
108*abb65b4bSAndroid Build Coastguard Worker         t_context->t_result = TPOOL_SUCCESS;
109*abb65b4bSAndroid Build Coastguard Worker         t_context->task_ret = ret;
110*abb65b4bSAndroid Build Coastguard Worker         pthread_cond_signal(&t_context->r_event);
111*abb65b4bSAndroid Build Coastguard Worker         pthread_mutex_unlock(&t_context->c_section);
112*abb65b4bSAndroid Build Coastguard Worker     }
113*abb65b4bSAndroid Build Coastguard Worker 
114*abb65b4bSAndroid Build Coastguard Worker     return 0;
115*abb65b4bSAndroid Build Coastguard Worker }
116*abb65b4bSAndroid Build Coastguard Worker 
tpool_create_thread(oapv_tpool_t * tp,int thread_id)117*abb65b4bSAndroid Build Coastguard Worker static oapv_thread_t tpool_create_thread(oapv_tpool_t *tp, int thread_id)
118*abb65b4bSAndroid Build Coastguard Worker {
119*abb65b4bSAndroid Build Coastguard Worker     if(!tp) {
120*abb65b4bSAndroid Build Coastguard Worker         return NULL; // error management
121*abb65b4bSAndroid Build Coastguard Worker     }
122*abb65b4bSAndroid Build Coastguard Worker 
123*abb65b4bSAndroid Build Coastguard Worker     thread_ctx_t *tctx = NULL;
124*abb65b4bSAndroid Build Coastguard Worker 
125*abb65b4bSAndroid Build Coastguard Worker     tctx = (thread_ctx_t *)malloc(sizeof(thread_ctx_t));
126*abb65b4bSAndroid Build Coastguard Worker 
127*abb65b4bSAndroid Build Coastguard Worker     if(!tctx) {
128*abb65b4bSAndroid Build Coastguard Worker         return NULL; // error management, bad alloc
129*abb65b4bSAndroid Build Coastguard Worker     }
130*abb65b4bSAndroid Build Coastguard Worker 
131*abb65b4bSAndroid Build Coastguard Worker     int result = 1;
132*abb65b4bSAndroid Build Coastguard Worker 
133*abb65b4bSAndroid Build Coastguard Worker     // intialize conditional variable and mutexes
134*abb65b4bSAndroid Build Coastguard Worker     result = pthread_mutex_init(&tctx->c_section, NULL);
135*abb65b4bSAndroid Build Coastguard Worker     if(result) {
136*abb65b4bSAndroid Build Coastguard Worker         goto TERROR; // error handling
137*abb65b4bSAndroid Build Coastguard Worker     }
138*abb65b4bSAndroid Build Coastguard Worker     result = pthread_cond_init(&tctx->w_event, NULL);
139*abb65b4bSAndroid Build Coastguard Worker     if(result) {
140*abb65b4bSAndroid Build Coastguard Worker         goto TERROR;
141*abb65b4bSAndroid Build Coastguard Worker     }
142*abb65b4bSAndroid Build Coastguard Worker     result = pthread_cond_init(&tctx->r_event, NULL);
143*abb65b4bSAndroid Build Coastguard Worker     if(result) {
144*abb65b4bSAndroid Build Coastguard Worker         goto TERROR;
145*abb65b4bSAndroid Build Coastguard Worker     }
146*abb65b4bSAndroid Build Coastguard Worker 
147*abb65b4bSAndroid Build Coastguard Worker     // initialize the worker thread attribute and set the type to joinable
148*abb65b4bSAndroid Build Coastguard Worker     result = pthread_attr_init(&tctx->tAttribute);
149*abb65b4bSAndroid Build Coastguard Worker     if(result) {
150*abb65b4bSAndroid Build Coastguard Worker         goto TERROR;
151*abb65b4bSAndroid Build Coastguard Worker     }
152*abb65b4bSAndroid Build Coastguard Worker 
153*abb65b4bSAndroid Build Coastguard Worker     result = pthread_attr_setdetachstate(&tctx->tAttribute, PTHREAD_CREATE_JOINABLE);
154*abb65b4bSAndroid Build Coastguard Worker     if(result) {
155*abb65b4bSAndroid Build Coastguard Worker         goto TERROR;
156*abb65b4bSAndroid Build Coastguard Worker     }
157*abb65b4bSAndroid Build Coastguard Worker 
158*abb65b4bSAndroid Build Coastguard Worker     tctx->task = NULL;
159*abb65b4bSAndroid Build Coastguard Worker     tctx->t_arg = NULL;
160*abb65b4bSAndroid Build Coastguard Worker     tctx->t_status = TPOOL_SUSPENDED;
161*abb65b4bSAndroid Build Coastguard Worker     tctx->t_result = TPOOL_INVALID_STATE;
162*abb65b4bSAndroid Build Coastguard Worker     tctx->thread_id = thread_id;
163*abb65b4bSAndroid Build Coastguard Worker 
164*abb65b4bSAndroid Build Coastguard Worker     // create the worker thread
165*abb65b4bSAndroid Build Coastguard Worker     result = pthread_create(&tctx->t_handle, &tctx->tAttribute, tpool_worker_thread, (void *)(tctx));
166*abb65b4bSAndroid Build Coastguard Worker     if(result) {
167*abb65b4bSAndroid Build Coastguard Worker         goto TERROR;
168*abb65b4bSAndroid Build Coastguard Worker     }
169*abb65b4bSAndroid Build Coastguard Worker 
170*abb65b4bSAndroid Build Coastguard Worker     // deinit the attribue
171*abb65b4bSAndroid Build Coastguard Worker     pthread_attr_destroy(&tctx->tAttribute);
172*abb65b4bSAndroid Build Coastguard Worker     return (oapv_thread_t)tctx;
173*abb65b4bSAndroid Build Coastguard Worker 
174*abb65b4bSAndroid Build Coastguard Worker TERROR:
175*abb65b4bSAndroid Build Coastguard Worker     pthread_mutex_destroy(&tctx->c_section);
176*abb65b4bSAndroid Build Coastguard Worker     pthread_cond_destroy(&tctx->w_event);
177*abb65b4bSAndroid Build Coastguard Worker     pthread_cond_destroy(&tctx->r_event);
178*abb65b4bSAndroid Build Coastguard Worker     pthread_attr_destroy(&tctx->tAttribute);
179*abb65b4bSAndroid Build Coastguard Worker     free(tctx);
180*abb65b4bSAndroid Build Coastguard Worker 
181*abb65b4bSAndroid Build Coastguard Worker     return NULL; // error handling, can't create a worker thread with proper initialization
182*abb65b4bSAndroid Build Coastguard Worker }
183*abb65b4bSAndroid Build Coastguard Worker 
tpool_assign_task(oapv_thread_t thread_id,oapv_fn_thread_entry_t entry,void * arg)184*abb65b4bSAndroid Build Coastguard Worker static tpool_result_t tpool_assign_task(oapv_thread_t thread_id, oapv_fn_thread_entry_t entry, void *arg)
185*abb65b4bSAndroid Build Coastguard Worker {
186*abb65b4bSAndroid Build Coastguard Worker     // assign the task function and argument
187*abb65b4bSAndroid Build Coastguard Worker     // worker thread may be in running state or suspended state
188*abb65b4bSAndroid Build Coastguard Worker     // if worker thread is in suspended state, it can be waiting for first run or it has finished one task and is waiting again
189*abb65b4bSAndroid Build Coastguard Worker     // if worker thread is in running state, it will come to waiting state
190*abb65b4bSAndroid Build Coastguard Worker     // in any case, waiting on read event will always work
191*abb65b4bSAndroid Build Coastguard Worker 
192*abb65b4bSAndroid Build Coastguard Worker     thread_ctx_t *tctx = (thread_ctx_t *)(thread_id);
193*abb65b4bSAndroid Build Coastguard Worker     if(!tctx) {
194*abb65b4bSAndroid Build Coastguard Worker         return TPOOL_INVALID_ARG;
195*abb65b4bSAndroid Build Coastguard Worker     }
196*abb65b4bSAndroid Build Coastguard Worker 
197*abb65b4bSAndroid Build Coastguard Worker     // lock the mutex and wait on read event
198*abb65b4bSAndroid Build Coastguard Worker     pthread_mutex_lock(&tctx->c_section);
199*abb65b4bSAndroid Build Coastguard Worker     while(tctx->t_status == TPOOL_RUNNING) {
200*abb65b4bSAndroid Build Coastguard Worker         pthread_cond_wait(&tctx->r_event, &tctx->c_section);
201*abb65b4bSAndroid Build Coastguard Worker     }
202*abb65b4bSAndroid Build Coastguard Worker 
203*abb65b4bSAndroid Build Coastguard Worker     // thread is in suspended state
204*abb65b4bSAndroid Build Coastguard Worker     tctx->t_status = TPOOL_RUNNING;
205*abb65b4bSAndroid Build Coastguard Worker     tctx->task = entry;
206*abb65b4bSAndroid Build Coastguard Worker     tctx->t_arg = arg;
207*abb65b4bSAndroid Build Coastguard Worker     // signal the worker thread to wake up and run the task
208*abb65b4bSAndroid Build Coastguard Worker     pthread_cond_signal(&tctx->w_event);
209*abb65b4bSAndroid Build Coastguard Worker     pthread_mutex_unlock(&tctx->c_section); // release the lock
210*abb65b4bSAndroid Build Coastguard Worker 
211*abb65b4bSAndroid Build Coastguard Worker     return TPOOL_SUCCESS;
212*abb65b4bSAndroid Build Coastguard Worker }
213*abb65b4bSAndroid Build Coastguard Worker 
tpool_retrieve_result(oapv_thread_t thread_id,int * ret)214*abb65b4bSAndroid Build Coastguard Worker static tpool_result_t tpool_retrieve_result(oapv_thread_t thread_id, int *ret)
215*abb65b4bSAndroid Build Coastguard Worker {
216*abb65b4bSAndroid Build Coastguard Worker     // whatever task has been assigned to worker thread
217*abb65b4bSAndroid Build Coastguard Worker     // wait for it to finish get the result
218*abb65b4bSAndroid Build Coastguard Worker 
219*abb65b4bSAndroid Build Coastguard Worker     thread_ctx_t *t_context = (thread_ctx_t *)(thread_id);
220*abb65b4bSAndroid Build Coastguard Worker     if(!t_context) {
221*abb65b4bSAndroid Build Coastguard Worker         return TPOOL_INVALID_ARG;
222*abb65b4bSAndroid Build Coastguard Worker     }
223*abb65b4bSAndroid Build Coastguard Worker 
224*abb65b4bSAndroid Build Coastguard Worker     tpool_result_t result = TPOOL_SUCCESS;
225*abb65b4bSAndroid Build Coastguard Worker 
226*abb65b4bSAndroid Build Coastguard Worker     pthread_mutex_lock(&t_context->c_section);
227*abb65b4bSAndroid Build Coastguard Worker     while(TPOOL_RUNNING == t_context->t_status) {
228*abb65b4bSAndroid Build Coastguard Worker         pthread_cond_wait(&t_context->r_event, &t_context->c_section);
229*abb65b4bSAndroid Build Coastguard Worker     }
230*abb65b4bSAndroid Build Coastguard Worker     result = t_context->t_result;
231*abb65b4bSAndroid Build Coastguard Worker     if(ret != NULL)
232*abb65b4bSAndroid Build Coastguard Worker         *ret = t_context->task_ret;
233*abb65b4bSAndroid Build Coastguard Worker     pthread_mutex_unlock(&t_context->c_section);
234*abb65b4bSAndroid Build Coastguard Worker     return result;
235*abb65b4bSAndroid Build Coastguard Worker }
236*abb65b4bSAndroid Build Coastguard Worker 
tpool_terminate_thread(oapv_thread_t * thread_id)237*abb65b4bSAndroid Build Coastguard Worker static tpool_result_t tpool_terminate_thread(oapv_thread_t *thread_id)
238*abb65b4bSAndroid Build Coastguard Worker {
239*abb65b4bSAndroid Build Coastguard Worker     // handler to close the thread
240*abb65b4bSAndroid Build Coastguard Worker     // close the thread handle
241*abb65b4bSAndroid Build Coastguard Worker     // release all the resource
242*abb65b4bSAndroid Build Coastguard Worker     //  delete the thread context object
243*abb65b4bSAndroid Build Coastguard Worker 
244*abb65b4bSAndroid Build Coastguard Worker     thread_ctx_t *t_context = (thread_ctx_t *)(*thread_id);
245*abb65b4bSAndroid Build Coastguard Worker     if(!t_context) {
246*abb65b4bSAndroid Build Coastguard Worker         return TPOOL_INVALID_ARG;
247*abb65b4bSAndroid Build Coastguard Worker     }
248*abb65b4bSAndroid Build Coastguard Worker 
249*abb65b4bSAndroid Build Coastguard Worker     // The worker thread might be in suspended state or may be processing a task
250*abb65b4bSAndroid Build Coastguard Worker     pthread_mutex_lock(&t_context->c_section);
251*abb65b4bSAndroid Build Coastguard Worker     while(TPOOL_RUNNING == t_context->t_status) {
252*abb65b4bSAndroid Build Coastguard Worker         pthread_cond_wait(&t_context->r_event, &t_context->c_section);
253*abb65b4bSAndroid Build Coastguard Worker     }
254*abb65b4bSAndroid Build Coastguard Worker 
255*abb65b4bSAndroid Build Coastguard Worker     t_context->t_status = TPOOL_TERMINATED;
256*abb65b4bSAndroid Build Coastguard Worker     pthread_cond_signal(&t_context->w_event);
257*abb65b4bSAndroid Build Coastguard Worker 
258*abb65b4bSAndroid Build Coastguard Worker     pthread_mutex_unlock(&t_context->c_section);
259*abb65b4bSAndroid Build Coastguard Worker 
260*abb65b4bSAndroid Build Coastguard Worker     // join the worker thread
261*abb65b4bSAndroid Build Coastguard Worker     pthread_join(t_context->t_handle, NULL);
262*abb65b4bSAndroid Build Coastguard Worker 
263*abb65b4bSAndroid Build Coastguard Worker     // clean all the synchronization memebers
264*abb65b4bSAndroid Build Coastguard Worker     pthread_mutex_destroy(&t_context->c_section);
265*abb65b4bSAndroid Build Coastguard Worker     pthread_cond_destroy(&t_context->w_event);
266*abb65b4bSAndroid Build Coastguard Worker     pthread_cond_destroy(&t_context->r_event);
267*abb65b4bSAndroid Build Coastguard Worker 
268*abb65b4bSAndroid Build Coastguard Worker     // delete the thread context memory
269*abb65b4bSAndroid Build Coastguard Worker     free(t_context);
270*abb65b4bSAndroid Build Coastguard Worker     (*thread_id) = NULL;
271*abb65b4bSAndroid Build Coastguard Worker     return TPOOL_SUCCESS;
272*abb65b4bSAndroid Build Coastguard Worker }
273*abb65b4bSAndroid Build Coastguard Worker 
tpool_threadsafe_decrement(oapv_sync_obj_t sobj,volatile int * pcnt)274*abb65b4bSAndroid Build Coastguard Worker static int tpool_threadsafe_decrement(oapv_sync_obj_t sobj, volatile int *pcnt)
275*abb65b4bSAndroid Build Coastguard Worker {
276*abb65b4bSAndroid Build Coastguard Worker     thread_mutex_t *imutex = (thread_mutex_t *)(sobj);
277*abb65b4bSAndroid Build Coastguard Worker     int             temp = 0;
278*abb65b4bSAndroid Build Coastguard Worker 
279*abb65b4bSAndroid Build Coastguard Worker     // lock the mutex, decrement the count and release the mutex
280*abb65b4bSAndroid Build Coastguard Worker     pthread_mutex_lock(&imutex->lmutex);
281*abb65b4bSAndroid Build Coastguard Worker     temp = *pcnt;
282*abb65b4bSAndroid Build Coastguard Worker     *pcnt = --temp;
283*abb65b4bSAndroid Build Coastguard Worker     pthread_mutex_unlock(&imutex->lmutex);
284*abb65b4bSAndroid Build Coastguard Worker 
285*abb65b4bSAndroid Build Coastguard Worker     return temp;
286*abb65b4bSAndroid Build Coastguard Worker }
287*abb65b4bSAndroid Build Coastguard Worker 
oapv_tpool_sync_obj_create()288*abb65b4bSAndroid Build Coastguard Worker oapv_sync_obj_t oapv_tpool_sync_obj_create()
289*abb65b4bSAndroid Build Coastguard Worker {
290*abb65b4bSAndroid Build Coastguard Worker     thread_mutex_t *imutex = (thread_mutex_t *)malloc(sizeof(thread_mutex_t));
291*abb65b4bSAndroid Build Coastguard Worker     if(0 == imutex) {
292*abb65b4bSAndroid Build Coastguard Worker         return 0; // failure case
293*abb65b4bSAndroid Build Coastguard Worker     }
294*abb65b4bSAndroid Build Coastguard Worker 
295*abb65b4bSAndroid Build Coastguard Worker     // intialize the mutex
296*abb65b4bSAndroid Build Coastguard Worker     int result = pthread_mutex_init(&imutex->lmutex, NULL);
297*abb65b4bSAndroid Build Coastguard Worker     if(result) {
298*abb65b4bSAndroid Build Coastguard Worker         if(imutex) {
299*abb65b4bSAndroid Build Coastguard Worker             free(imutex);
300*abb65b4bSAndroid Build Coastguard Worker         }
301*abb65b4bSAndroid Build Coastguard Worker         imutex = 0;
302*abb65b4bSAndroid Build Coastguard Worker     }
303*abb65b4bSAndroid Build Coastguard Worker 
304*abb65b4bSAndroid Build Coastguard Worker     return imutex;
305*abb65b4bSAndroid Build Coastguard Worker }
306*abb65b4bSAndroid Build Coastguard Worker 
oapv_tpool_sync_obj_delete(oapv_sync_obj_t * sobj)307*abb65b4bSAndroid Build Coastguard Worker tpool_result_t oapv_tpool_sync_obj_delete(oapv_sync_obj_t *sobj)
308*abb65b4bSAndroid Build Coastguard Worker {
309*abb65b4bSAndroid Build Coastguard Worker 
310*abb65b4bSAndroid Build Coastguard Worker     thread_mutex_t *imutex = (thread_mutex_t *)(*sobj);
311*abb65b4bSAndroid Build Coastguard Worker 
312*abb65b4bSAndroid Build Coastguard Worker     // delete the mutex
313*abb65b4bSAndroid Build Coastguard Worker     pthread_mutex_destroy(&imutex->lmutex);
314*abb65b4bSAndroid Build Coastguard Worker 
315*abb65b4bSAndroid Build Coastguard Worker     // free the memory
316*abb65b4bSAndroid Build Coastguard Worker     free(imutex);
317*abb65b4bSAndroid Build Coastguard Worker     *sobj = NULL;
318*abb65b4bSAndroid Build Coastguard Worker 
319*abb65b4bSAndroid Build Coastguard Worker     return TPOOL_SUCCESS;
320*abb65b4bSAndroid Build Coastguard Worker }
321*abb65b4bSAndroid Build Coastguard Worker 
oapv_tpool_enter_cs(oapv_sync_obj_t sobj)322*abb65b4bSAndroid Build Coastguard Worker void oapv_tpool_enter_cs(oapv_sync_obj_t sobj)
323*abb65b4bSAndroid Build Coastguard Worker {
324*abb65b4bSAndroid Build Coastguard Worker     thread_mutex_t *imutex = (thread_mutex_t *)(sobj);
325*abb65b4bSAndroid Build Coastguard Worker     pthread_mutex_lock(&imutex->lmutex);
326*abb65b4bSAndroid Build Coastguard Worker }
327*abb65b4bSAndroid Build Coastguard Worker 
oapv_tpool_leave_cs(oapv_sync_obj_t sobj)328*abb65b4bSAndroid Build Coastguard Worker void oapv_tpool_leave_cs(oapv_sync_obj_t sobj)
329*abb65b4bSAndroid Build Coastguard Worker {
330*abb65b4bSAndroid Build Coastguard Worker     thread_mutex_t *imutex = (thread_mutex_t *)(sobj);
331*abb65b4bSAndroid Build Coastguard Worker     pthread_mutex_unlock(&imutex->lmutex);
332*abb65b4bSAndroid Build Coastguard Worker }
333*abb65b4bSAndroid Build Coastguard Worker 
334*abb65b4bSAndroid Build Coastguard Worker #else
335*abb65b4bSAndroid Build Coastguard Worker typedef struct thread_ctx {
336*abb65b4bSAndroid Build Coastguard Worker     // synchronization members
337*abb65b4bSAndroid Build Coastguard Worker     HANDLE                 t_handle;  // worker thread handle
338*abb65b4bSAndroid Build Coastguard Worker     HANDLE                 w_event;   // worker thread waiting event handle
339*abb65b4bSAndroid Build Coastguard Worker     HANDLE                 r_event;   // signalling thread read event handle
340*abb65b4bSAndroid Build Coastguard Worker     CRITICAL_SECTION       c_section; // critical section for fast synchronization
341*abb65b4bSAndroid Build Coastguard Worker 
342*abb65b4bSAndroid Build Coastguard Worker     // member field to run  a task
343*abb65b4bSAndroid Build Coastguard Worker     oapv_fn_thread_entry_t task;
344*abb65b4bSAndroid Build Coastguard Worker     void                  *t_arg;
345*abb65b4bSAndroid Build Coastguard Worker     tpool_status_t         t_status;
346*abb65b4bSAndroid Build Coastguard Worker     tpool_result_t         t_result;
347*abb65b4bSAndroid Build Coastguard Worker     int                    task_ret;
348*abb65b4bSAndroid Build Coastguard Worker     int                    thread_id;
349*abb65b4bSAndroid Build Coastguard Worker 
350*abb65b4bSAndroid Build Coastguard Worker } thread_ctx_t;
351*abb65b4bSAndroid Build Coastguard Worker 
352*abb65b4bSAndroid Build Coastguard Worker typedef struct thread_mutex {
353*abb65b4bSAndroid Build Coastguard Worker #if WINDOWS_MUTEX_SYNC
354*abb65b4bSAndroid Build Coastguard Worker     HANDLE lmutex;
355*abb65b4bSAndroid Build Coastguard Worker #else
356*abb65b4bSAndroid Build Coastguard Worker     CRITICAL_SECTION c_section; // critical section for fast synchronization
357*abb65b4bSAndroid Build Coastguard Worker #endif
358*abb65b4bSAndroid Build Coastguard Worker 
359*abb65b4bSAndroid Build Coastguard Worker } thread_mutex_t;
360*abb65b4bSAndroid Build Coastguard Worker 
tpool_worker_thread(void * arg)361*abb65b4bSAndroid Build Coastguard Worker static unsigned int __stdcall tpool_worker_thread(void *arg)
362*abb65b4bSAndroid Build Coastguard Worker {
363*abb65b4bSAndroid Build Coastguard Worker     /********************* main routine for thread pool worker thread *************************
364*abb65b4bSAndroid Build Coastguard Worker     ********************** worker thread can remain in suspended or running state *************
365*abb65b4bSAndroid Build Coastguard Worker     ********************* control the synchronization with help of thread context members *****/
366*abb65b4bSAndroid Build Coastguard Worker 
367*abb65b4bSAndroid Build Coastguard Worker     // member Initialization section
368*abb65b4bSAndroid Build Coastguard Worker     thread_ctx_t *t_context = (thread_ctx_t *)arg;
369*abb65b4bSAndroid Build Coastguard Worker     if(!t_context) {
370*abb65b4bSAndroid Build Coastguard Worker         return 0; // error handling, more like a fail safe mechanism
371*abb65b4bSAndroid Build Coastguard Worker     }
372*abb65b4bSAndroid Build Coastguard Worker 
373*abb65b4bSAndroid Build Coastguard Worker     while(1) {
374*abb65b4bSAndroid Build Coastguard Worker         // worker thread loop
375*abb65b4bSAndroid Build Coastguard Worker         // remains suspended/sleep waiting for an event
376*abb65b4bSAndroid Build Coastguard Worker         WaitForSingleObject(t_context->w_event, INFINITE);
377*abb65b4bSAndroid Build Coastguard Worker 
378*abb65b4bSAndroid Build Coastguard Worker         // worker thread has received the event to wake up and perform operation
379*abb65b4bSAndroid Build Coastguard Worker         EnterCriticalSection(&t_context->c_section);
380*abb65b4bSAndroid Build Coastguard Worker         if(t_context->t_status == TPOOL_TERMINATED) {
381*abb65b4bSAndroid Build Coastguard Worker             // received signal to terminate
382*abb65b4bSAndroid Build Coastguard Worker             t_context->t_result = TPOOL_SUCCESS;
383*abb65b4bSAndroid Build Coastguard Worker             LeaveCriticalSection(&t_context->c_section);
384*abb65b4bSAndroid Build Coastguard Worker             break;
385*abb65b4bSAndroid Build Coastguard Worker         }
386*abb65b4bSAndroid Build Coastguard Worker         LeaveCriticalSection(&t_context->c_section);
387*abb65b4bSAndroid Build Coastguard Worker 
388*abb65b4bSAndroid Build Coastguard Worker         // worker thread state is running with entry function and arg set
389*abb65b4bSAndroid Build Coastguard Worker         t_context->task_ret = t_context->task(t_context->t_arg);
390*abb65b4bSAndroid Build Coastguard Worker 
391*abb65b4bSAndroid Build Coastguard Worker         // change the state to suspended/waiting
392*abb65b4bSAndroid Build Coastguard Worker         EnterCriticalSection(&t_context->c_section);
393*abb65b4bSAndroid Build Coastguard Worker         t_context->t_status = TPOOL_SUSPENDED;
394*abb65b4bSAndroid Build Coastguard Worker         t_context->t_result = TPOOL_SUCCESS;
395*abb65b4bSAndroid Build Coastguard Worker         LeaveCriticalSection(&t_context->c_section);
396*abb65b4bSAndroid Build Coastguard Worker 
397*abb65b4bSAndroid Build Coastguard Worker         // send an event to thread, waiting for it to finish it's task
398*abb65b4bSAndroid Build Coastguard Worker         SetEvent(t_context->r_event);
399*abb65b4bSAndroid Build Coastguard Worker     }
400*abb65b4bSAndroid Build Coastguard Worker 
401*abb65b4bSAndroid Build Coastguard Worker     return 0;
402*abb65b4bSAndroid Build Coastguard Worker }
403*abb65b4bSAndroid Build Coastguard Worker 
tpool_create_thread(oapv_tpool_t * tp,int thread_id)404*abb65b4bSAndroid Build Coastguard Worker static oapv_thread_t tpool_create_thread(oapv_tpool_t *tp, int thread_id)
405*abb65b4bSAndroid Build Coastguard Worker {
406*abb65b4bSAndroid Build Coastguard Worker     if(!tp) {
407*abb65b4bSAndroid Build Coastguard Worker         return NULL; // error management
408*abb65b4bSAndroid Build Coastguard Worker     }
409*abb65b4bSAndroid Build Coastguard Worker 
410*abb65b4bSAndroid Build Coastguard Worker     thread_ctx_t *thread_context = NULL;
411*abb65b4bSAndroid Build Coastguard Worker     thread_context = (thread_ctx_t *)malloc(sizeof(thread_ctx_t));
412*abb65b4bSAndroid Build Coastguard Worker 
413*abb65b4bSAndroid Build Coastguard Worker     if(!thread_context) {
414*abb65b4bSAndroid Build Coastguard Worker         return NULL; // error management, bad alloc
415*abb65b4bSAndroid Build Coastguard Worker     }
416*abb65b4bSAndroid Build Coastguard Worker 
417*abb65b4bSAndroid Build Coastguard Worker     // create waiting event
418*abb65b4bSAndroid Build Coastguard Worker     // create waiting event as automatic reset, only one thread can come out of waiting state
419*abb65b4bSAndroid Build Coastguard Worker     // done intentionally ... signally happens from different thread and only worker thread should be able to respond
420*abb65b4bSAndroid Build Coastguard Worker     thread_context->w_event = CreateEvent(NULL, FALSE, FALSE, NULL);
421*abb65b4bSAndroid Build Coastguard Worker     if(!thread_context->w_event) {
422*abb65b4bSAndroid Build Coastguard Worker         goto TERROR; // error handling, can't create event handler
423*abb65b4bSAndroid Build Coastguard Worker     }
424*abb65b4bSAndroid Build Coastguard Worker 
425*abb65b4bSAndroid Build Coastguard Worker     thread_context->r_event = CreateEvent(NULL, TRUE, TRUE, NULL); // read event is enabled by default
426*abb65b4bSAndroid Build Coastguard Worker     if(!thread_context->r_event) {
427*abb65b4bSAndroid Build Coastguard Worker         goto TERROR;
428*abb65b4bSAndroid Build Coastguard Worker     }
429*abb65b4bSAndroid Build Coastguard Worker 
430*abb65b4bSAndroid Build Coastguard Worker     InitializeCriticalSection(&(thread_context->c_section)); // This section for fast data retrieval
431*abb65b4bSAndroid Build Coastguard Worker 
432*abb65b4bSAndroid Build Coastguard Worker     // intialize the state variables for the thread context object
433*abb65b4bSAndroid Build Coastguard Worker     thread_context->task = NULL;
434*abb65b4bSAndroid Build Coastguard Worker     thread_context->t_arg = NULL;
435*abb65b4bSAndroid Build Coastguard Worker     thread_context->t_status = TPOOL_SUSPENDED;
436*abb65b4bSAndroid Build Coastguard Worker     thread_context->t_result = TPOOL_INVALID_STATE;
437*abb65b4bSAndroid Build Coastguard Worker     thread_context->thread_id = thread_id;
438*abb65b4bSAndroid Build Coastguard Worker 
439*abb65b4bSAndroid Build Coastguard Worker     thread_context->t_handle = (HANDLE)_beginthreadex(NULL, 0, tpool_worker_thread, (void *)thread_context, 0, NULL); // create a thread store the handle and pass the handle to context
440*abb65b4bSAndroid Build Coastguard Worker     if(!thread_context->t_handle) {
441*abb65b4bSAndroid Build Coastguard Worker         goto TERROR;
442*abb65b4bSAndroid Build Coastguard Worker     }
443*abb65b4bSAndroid Build Coastguard Worker 
444*abb65b4bSAndroid Build Coastguard Worker     // Everything created and intialized properly
445*abb65b4bSAndroid Build Coastguard Worker     // return the created thread_context;
446*abb65b4bSAndroid Build Coastguard Worker     return (oapv_thread_t)thread_context;
447*abb65b4bSAndroid Build Coastguard Worker 
448*abb65b4bSAndroid Build Coastguard Worker TERROR:
449*abb65b4bSAndroid Build Coastguard Worker     if(thread_context->w_event) {
450*abb65b4bSAndroid Build Coastguard Worker         CloseHandle(thread_context->w_event);
451*abb65b4bSAndroid Build Coastguard Worker     }
452*abb65b4bSAndroid Build Coastguard Worker     if(thread_context->r_event) {
453*abb65b4bSAndroid Build Coastguard Worker         CloseHandle(thread_context->r_event);
454*abb65b4bSAndroid Build Coastguard Worker     }
455*abb65b4bSAndroid Build Coastguard Worker     DeleteCriticalSection(&thread_context->c_section);
456*abb65b4bSAndroid Build Coastguard Worker     if(thread_context) {
457*abb65b4bSAndroid Build Coastguard Worker         free(thread_context);
458*abb65b4bSAndroid Build Coastguard Worker     }
459*abb65b4bSAndroid Build Coastguard Worker 
460*abb65b4bSAndroid Build Coastguard Worker     return NULL; // error handling, can't create a worker thread with proper initialization
461*abb65b4bSAndroid Build Coastguard Worker }
462*abb65b4bSAndroid Build Coastguard Worker 
tpool_assign_task(oapv_thread_t thread_id,oapv_fn_thread_entry_t entry,void * arg)463*abb65b4bSAndroid Build Coastguard Worker static tpool_result_t tpool_assign_task(oapv_thread_t thread_id, oapv_fn_thread_entry_t entry, void *arg)
464*abb65b4bSAndroid Build Coastguard Worker {
465*abb65b4bSAndroid Build Coastguard Worker     // assign the task function and argument
466*abb65b4bSAndroid Build Coastguard Worker     // worker thread may be in running state or suspended state
467*abb65b4bSAndroid Build Coastguard Worker     // if worker thread is in suspended state, it can be waiting for first run or it has finished one task and is waiting again
468*abb65b4bSAndroid Build Coastguard Worker     // if worker thread is in running state, it will come to waiting state
469*abb65b4bSAndroid Build Coastguard Worker     // in any case, waiting on read event will always work
470*abb65b4bSAndroid Build Coastguard Worker 
471*abb65b4bSAndroid Build Coastguard Worker     thread_ctx_t *t_context = (thread_ctx_t *)(thread_id);
472*abb65b4bSAndroid Build Coastguard Worker     if(!t_context) {
473*abb65b4bSAndroid Build Coastguard Worker         return TPOOL_INVALID_ARG;
474*abb65b4bSAndroid Build Coastguard Worker     }
475*abb65b4bSAndroid Build Coastguard Worker 
476*abb65b4bSAndroid Build Coastguard Worker     WaitForSingleObject(t_context->r_event, INFINITE);
477*abb65b4bSAndroid Build Coastguard Worker 
478*abb65b4bSAndroid Build Coastguard Worker     // worker thread is in waiting state
479*abb65b4bSAndroid Build Coastguard Worker     EnterCriticalSection(&t_context->c_section);
480*abb65b4bSAndroid Build Coastguard Worker     t_context->t_status = TPOOL_RUNNING;
481*abb65b4bSAndroid Build Coastguard Worker     t_context->task = entry;
482*abb65b4bSAndroid Build Coastguard Worker     t_context->t_arg = arg;
483*abb65b4bSAndroid Build Coastguard Worker     // signal the worker thread to wake up and run the task
484*abb65b4bSAndroid Build Coastguard Worker     ResetEvent(t_context->r_event);
485*abb65b4bSAndroid Build Coastguard Worker     SetEvent(t_context->w_event);
486*abb65b4bSAndroid Build Coastguard Worker     LeaveCriticalSection(&t_context->c_section);
487*abb65b4bSAndroid Build Coastguard Worker 
488*abb65b4bSAndroid Build Coastguard Worker     return TPOOL_SUCCESS;
489*abb65b4bSAndroid Build Coastguard Worker }
490*abb65b4bSAndroid Build Coastguard Worker 
tpool_retrieve_result(oapv_thread_t thread_id,int * ret)491*abb65b4bSAndroid Build Coastguard Worker static tpool_result_t tpool_retrieve_result(oapv_thread_t thread_id, int *ret)
492*abb65b4bSAndroid Build Coastguard Worker {
493*abb65b4bSAndroid Build Coastguard Worker     // whatever task has been assigned to worker thread
494*abb65b4bSAndroid Build Coastguard Worker     // wait for it to finish get the result
495*abb65b4bSAndroid Build Coastguard Worker     thread_ctx_t *t_context = (thread_ctx_t *)(thread_id);
496*abb65b4bSAndroid Build Coastguard Worker     if(!t_context) {
497*abb65b4bSAndroid Build Coastguard Worker         return TPOOL_INVALID_ARG;
498*abb65b4bSAndroid Build Coastguard Worker     }
499*abb65b4bSAndroid Build Coastguard Worker 
500*abb65b4bSAndroid Build Coastguard Worker     tpool_result_t result = TPOOL_SUCCESS;
501*abb65b4bSAndroid Build Coastguard Worker 
502*abb65b4bSAndroid Build Coastguard Worker     WaitForSingleObject(t_context->r_event, INFINITE);
503*abb65b4bSAndroid Build Coastguard Worker 
504*abb65b4bSAndroid Build Coastguard Worker     // worker thread has finished it's job and now it is in waiting state
505*abb65b4bSAndroid Build Coastguard Worker     EnterCriticalSection(&t_context->c_section);
506*abb65b4bSAndroid Build Coastguard Worker     result = t_context->t_result;
507*abb65b4bSAndroid Build Coastguard Worker     if(ret != NULL)
508*abb65b4bSAndroid Build Coastguard Worker         *ret = t_context->task_ret;
509*abb65b4bSAndroid Build Coastguard Worker     LeaveCriticalSection(&t_context->c_section);
510*abb65b4bSAndroid Build Coastguard Worker 
511*abb65b4bSAndroid Build Coastguard Worker     return result;
512*abb65b4bSAndroid Build Coastguard Worker }
513*abb65b4bSAndroid Build Coastguard Worker 
tpool_terminate_thread(oapv_thread_t * thread_id)514*abb65b4bSAndroid Build Coastguard Worker tpool_result_t tpool_terminate_thread(oapv_thread_t *thread_id)
515*abb65b4bSAndroid Build Coastguard Worker {
516*abb65b4bSAndroid Build Coastguard Worker     // handler to close the thread
517*abb65b4bSAndroid Build Coastguard Worker     // close the thread handle
518*abb65b4bSAndroid Build Coastguard Worker     // release all the resource
519*abb65b4bSAndroid Build Coastguard Worker     //  delete the thread context object
520*abb65b4bSAndroid Build Coastguard Worker 
521*abb65b4bSAndroid Build Coastguard Worker     // the thread may be running or it is in suspended state
522*abb65b4bSAndroid Build Coastguard Worker     // if it is in suspended state, read event will be active
523*abb65b4bSAndroid Build Coastguard Worker     // if it is in running state, read event will be active after sometime
524*abb65b4bSAndroid Build Coastguard Worker 
525*abb65b4bSAndroid Build Coastguard Worker     thread_ctx_t *t_context = (thread_ctx_t *)(*thread_id);
526*abb65b4bSAndroid Build Coastguard Worker     if(!t_context) {
527*abb65b4bSAndroid Build Coastguard Worker         return TPOOL_INVALID_ARG;
528*abb65b4bSAndroid Build Coastguard Worker     }
529*abb65b4bSAndroid Build Coastguard Worker 
530*abb65b4bSAndroid Build Coastguard Worker     WaitForSingleObject(t_context->r_event, INFINITE);
531*abb65b4bSAndroid Build Coastguard Worker 
532*abb65b4bSAndroid Build Coastguard Worker     // worker thread is in waiting state
533*abb65b4bSAndroid Build Coastguard Worker     EnterCriticalSection(&t_context->c_section);
534*abb65b4bSAndroid Build Coastguard Worker     t_context->t_status = TPOOL_TERMINATED;
535*abb65b4bSAndroid Build Coastguard Worker     LeaveCriticalSection(&t_context->c_section);
536*abb65b4bSAndroid Build Coastguard Worker 
537*abb65b4bSAndroid Build Coastguard Worker     // signal the worker thread to wake up and run the task
538*abb65b4bSAndroid Build Coastguard Worker     SetEvent(t_context->w_event);
539*abb65b4bSAndroid Build Coastguard Worker 
540*abb65b4bSAndroid Build Coastguard Worker     // wait for worker thread to finish it's routine
541*abb65b4bSAndroid Build Coastguard Worker     WaitForSingleObject(t_context->t_handle, INFINITE);
542*abb65b4bSAndroid Build Coastguard Worker     CloseHandle(t_context->t_handle); // freed all the resources for the thread
543*abb65b4bSAndroid Build Coastguard Worker 
544*abb65b4bSAndroid Build Coastguard Worker     CloseHandle(t_context->w_event);
545*abb65b4bSAndroid Build Coastguard Worker     CloseHandle(t_context->r_event);
546*abb65b4bSAndroid Build Coastguard Worker     DeleteCriticalSection(&t_context->c_section);
547*abb65b4bSAndroid Build Coastguard Worker 
548*abb65b4bSAndroid Build Coastguard Worker     // delete the thread context memory
549*abb65b4bSAndroid Build Coastguard Worker     free(t_context);
550*abb65b4bSAndroid Build Coastguard Worker     (*thread_id) = NULL;
551*abb65b4bSAndroid Build Coastguard Worker 
552*abb65b4bSAndroid Build Coastguard Worker     return TPOOL_SUCCESS;
553*abb65b4bSAndroid Build Coastguard Worker }
554*abb65b4bSAndroid Build Coastguard Worker 
tpool_threadsafe_decrement(oapv_sync_obj_t sobj,volatile int * pcnt)555*abb65b4bSAndroid Build Coastguard Worker static int tpool_threadsafe_decrement(oapv_sync_obj_t sobj, volatile int *pcnt)
556*abb65b4bSAndroid Build Coastguard Worker {
557*abb65b4bSAndroid Build Coastguard Worker     thread_mutex_t *imutex = (thread_mutex_t *)(sobj);
558*abb65b4bSAndroid Build Coastguard Worker     int             temp = 0;
559*abb65b4bSAndroid Build Coastguard Worker 
560*abb65b4bSAndroid Build Coastguard Worker #if WINDOWS_MUTEX_SYNC
561*abb65b4bSAndroid Build Coastguard Worker     // let's lock the mutex
562*abb65b4bSAndroid Build Coastguard Worker     DWORD dw_wait_result = WaitForSingleObject(imutex->lmutex, INFINITE); // wait for infinite time
563*abb65b4bSAndroid Build Coastguard Worker 
564*abb65b4bSAndroid Build Coastguard Worker     switch(dw_wait_result) {
565*abb65b4bSAndroid Build Coastguard Worker         // The thread got ownership of the mutex
566*abb65b4bSAndroid Build Coastguard Worker     case WAIT_OBJECT_0:
567*abb65b4bSAndroid Build Coastguard Worker         temp = *pcnt;
568*abb65b4bSAndroid Build Coastguard Worker         *pcnt = --temp;
569*abb65b4bSAndroid Build Coastguard Worker         // Release ownership of the mutex object
570*abb65b4bSAndroid Build Coastguard Worker         ReleaseMutex(imutex->lmutex);
571*abb65b4bSAndroid Build Coastguard Worker         break;
572*abb65b4bSAndroid Build Coastguard Worker         // The thread got ownership of an abandoned mutex
573*abb65b4bSAndroid Build Coastguard Worker         // The database is in an indeterminate state
574*abb65b4bSAndroid Build Coastguard Worker     case WAIT_ABANDONED:
575*abb65b4bSAndroid Build Coastguard Worker         temp = *pcnt;
576*abb65b4bSAndroid Build Coastguard Worker         temp--;
577*abb65b4bSAndroid Build Coastguard Worker         *pcnt = temp;
578*abb65b4bSAndroid Build Coastguard Worker         break;
579*abb65b4bSAndroid Build Coastguard Worker     }
580*abb65b4bSAndroid Build Coastguard Worker #else
581*abb65b4bSAndroid Build Coastguard Worker     EnterCriticalSection(&imutex->c_section);
582*abb65b4bSAndroid Build Coastguard Worker     temp = *pcnt;
583*abb65b4bSAndroid Build Coastguard Worker     *pcnt = --temp;
584*abb65b4bSAndroid Build Coastguard Worker     LeaveCriticalSection(&imutex->c_section);
585*abb65b4bSAndroid Build Coastguard Worker #endif
586*abb65b4bSAndroid Build Coastguard Worker     return temp;
587*abb65b4bSAndroid Build Coastguard Worker }
588*abb65b4bSAndroid Build Coastguard Worker 
oapv_tpool_sync_obj_create()589*abb65b4bSAndroid Build Coastguard Worker oapv_sync_obj_t oapv_tpool_sync_obj_create()
590*abb65b4bSAndroid Build Coastguard Worker {
591*abb65b4bSAndroid Build Coastguard Worker     thread_mutex_t *imutex = (thread_mutex_t *)malloc(sizeof(thread_mutex_t));
592*abb65b4bSAndroid Build Coastguard Worker     if(0 == imutex) {
593*abb65b4bSAndroid Build Coastguard Worker         return 0; // failure case
594*abb65b4bSAndroid Build Coastguard Worker     }
595*abb65b4bSAndroid Build Coastguard Worker 
596*abb65b4bSAndroid Build Coastguard Worker #if WINDOWS_MUTEX_SYNC
597*abb65b4bSAndroid Build Coastguard Worker     // initialize the created mutex instance
598*abb65b4bSAndroid Build Coastguard Worker     imutex->lmutex = CreateMutex(NULL, FALSE, NULL);
599*abb65b4bSAndroid Build Coastguard Worker     if(0 == imutex->lmutex) {
600*abb65b4bSAndroid Build Coastguard Worker         if(imutex) {
601*abb65b4bSAndroid Build Coastguard Worker             free(imutex);
602*abb65b4bSAndroid Build Coastguard Worker         }
603*abb65b4bSAndroid Build Coastguard Worker         return 0;
604*abb65b4bSAndroid Build Coastguard Worker     }
605*abb65b4bSAndroid Build Coastguard Worker #else
606*abb65b4bSAndroid Build Coastguard Worker     // initialize the critical section
607*abb65b4bSAndroid Build Coastguard Worker     InitializeCriticalSection(&(imutex->c_section));
608*abb65b4bSAndroid Build Coastguard Worker #endif
609*abb65b4bSAndroid Build Coastguard Worker     return imutex;
610*abb65b4bSAndroid Build Coastguard Worker }
611*abb65b4bSAndroid Build Coastguard Worker 
oapv_tpool_sync_obj_delete(oapv_sync_obj_t * sobj)612*abb65b4bSAndroid Build Coastguard Worker tpool_result_t oapv_tpool_sync_obj_delete(oapv_sync_obj_t *sobj)
613*abb65b4bSAndroid Build Coastguard Worker {
614*abb65b4bSAndroid Build Coastguard Worker     thread_mutex_t *imutex = (thread_mutex_t *)(*sobj);
615*abb65b4bSAndroid Build Coastguard Worker #if WINDOWS_MUTEX_SYNC
616*abb65b4bSAndroid Build Coastguard Worker     // release the mutex
617*abb65b4bSAndroid Build Coastguard Worker     CloseHandle(imutex->lmutex);
618*abb65b4bSAndroid Build Coastguard Worker #else
619*abb65b4bSAndroid Build Coastguard Worker     // delete critical section
620*abb65b4bSAndroid Build Coastguard Worker     DeleteCriticalSection(&imutex->c_section);
621*abb65b4bSAndroid Build Coastguard Worker #endif
622*abb65b4bSAndroid Build Coastguard Worker 
623*abb65b4bSAndroid Build Coastguard Worker     // free the memory
624*abb65b4bSAndroid Build Coastguard Worker     free(imutex);
625*abb65b4bSAndroid Build Coastguard Worker     *sobj = NULL;
626*abb65b4bSAndroid Build Coastguard Worker 
627*abb65b4bSAndroid Build Coastguard Worker     return TPOOL_SUCCESS;
628*abb65b4bSAndroid Build Coastguard Worker }
629*abb65b4bSAndroid Build Coastguard Worker 
oapv_tpool_enter_cs(oapv_sync_obj_t sobj)630*abb65b4bSAndroid Build Coastguard Worker void oapv_tpool_enter_cs(oapv_sync_obj_t sobj)
631*abb65b4bSAndroid Build Coastguard Worker {
632*abb65b4bSAndroid Build Coastguard Worker     thread_mutex_t *imutex = (thread_mutex_t *)(sobj);
633*abb65b4bSAndroid Build Coastguard Worker     EnterCriticalSection(&imutex->c_section);
634*abb65b4bSAndroid Build Coastguard Worker }
oapv_tpool_leave_cs(oapv_sync_obj_t sobj)635*abb65b4bSAndroid Build Coastguard Worker void oapv_tpool_leave_cs(oapv_sync_obj_t sobj)
636*abb65b4bSAndroid Build Coastguard Worker {
637*abb65b4bSAndroid Build Coastguard Worker     thread_mutex_t *imutex = (thread_mutex_t *)(sobj);
638*abb65b4bSAndroid Build Coastguard Worker     LeaveCriticalSection(&imutex->c_section);
639*abb65b4bSAndroid Build Coastguard Worker }
640*abb65b4bSAndroid Build Coastguard Worker 
641*abb65b4bSAndroid Build Coastguard Worker #endif
642*abb65b4bSAndroid Build Coastguard Worker 
oapv_tpool_init(oapv_tpool_t * tp,int maxtask)643*abb65b4bSAndroid Build Coastguard Worker tpool_result_t oapv_tpool_init(oapv_tpool_t *tp, int maxtask)
644*abb65b4bSAndroid Build Coastguard Worker {
645*abb65b4bSAndroid Build Coastguard Worker     // assign handles to threadcontroller object
646*abb65b4bSAndroid Build Coastguard Worker     // handles for create, run, join and terminate will be given to controller  object
647*abb65b4bSAndroid Build Coastguard Worker 
648*abb65b4bSAndroid Build Coastguard Worker     tp->create = tpool_create_thread;
649*abb65b4bSAndroid Build Coastguard Worker     tp->run = tpool_assign_task;
650*abb65b4bSAndroid Build Coastguard Worker     tp->join = tpool_retrieve_result;
651*abb65b4bSAndroid Build Coastguard Worker     tp->release = tpool_terminate_thread;
652*abb65b4bSAndroid Build Coastguard Worker     tp->max_task_cnt = maxtask;
653*abb65b4bSAndroid Build Coastguard Worker 
654*abb65b4bSAndroid Build Coastguard Worker     return TPOOL_SUCCESS;
655*abb65b4bSAndroid Build Coastguard Worker }
656*abb65b4bSAndroid Build Coastguard Worker 
oapv_tpool_deinit(oapv_tpool_t * tp)657*abb65b4bSAndroid Build Coastguard Worker tpool_result_t oapv_tpool_deinit(oapv_tpool_t *tp)
658*abb65b4bSAndroid Build Coastguard Worker {
659*abb65b4bSAndroid Build Coastguard Worker     // reset all the handler to NULL
660*abb65b4bSAndroid Build Coastguard Worker     tp->create = NULL;
661*abb65b4bSAndroid Build Coastguard Worker     tp->run = NULL;
662*abb65b4bSAndroid Build Coastguard Worker     tp->join = NULL;
663*abb65b4bSAndroid Build Coastguard Worker     tp->release = NULL;
664*abb65b4bSAndroid Build Coastguard Worker     tp->max_task_cnt = 0;
665*abb65b4bSAndroid Build Coastguard Worker 
666*abb65b4bSAndroid Build Coastguard Worker     return TPOOL_SUCCESS;
667*abb65b4bSAndroid Build Coastguard Worker }
668*abb65b4bSAndroid Build Coastguard Worker 
oapv_tpool_spinlock_wait(volatile int * addr,int val)669*abb65b4bSAndroid Build Coastguard Worker int oapv_tpool_spinlock_wait(volatile int *addr, int val)
670*abb65b4bSAndroid Build Coastguard Worker {
671*abb65b4bSAndroid Build Coastguard Worker     int temp;
672*abb65b4bSAndroid Build Coastguard Worker 
673*abb65b4bSAndroid Build Coastguard Worker     while(1) {
674*abb65b4bSAndroid Build Coastguard Worker         temp = *addr; // thread safe volatile read
675*abb65b4bSAndroid Build Coastguard Worker         if(temp == val || temp == -1) {
676*abb65b4bSAndroid Build Coastguard Worker             break;
677*abb65b4bSAndroid Build Coastguard Worker         }
678*abb65b4bSAndroid Build Coastguard Worker     }
679*abb65b4bSAndroid Build Coastguard Worker     return temp;
680*abb65b4bSAndroid Build Coastguard Worker }
681*abb65b4bSAndroid Build Coastguard Worker 
threadsafe_assign(volatile int * addr,int val)682*abb65b4bSAndroid Build Coastguard Worker void threadsafe_assign(volatile int *addr, int val)
683*abb65b4bSAndroid Build Coastguard Worker {
684*abb65b4bSAndroid Build Coastguard Worker     // thread safe volatile assign
685*abb65b4bSAndroid Build Coastguard Worker     *addr = val;
686*abb65b4bSAndroid Build Coastguard Worker }
687