loc_eng_dmn_conn_thread_helper.c revision f77c85bb51137f5ba854184e5e9194197027438a
1/* Copyright (c) 2011, Code Aurora Forum. All rights reserved.
2 *
3 * Redistribution and use in source and binary forms, with or without
4 * modification, are permitted provided that the following conditions are
5 * met:
6 *     * Redistributions of source code must retain the above copyright
7 *       notice, this list of conditions and the following disclaimer.
8 *     * Redistributions in binary form must reproduce the above
9 *       copyright notice, this list of conditions and the following
10 *       disclaimer in the documentation and/or other materials provided
11 *       with the distribution.
12 *     * Neither the name of Code Aurora Forum, Inc. nor the names of its
13 *       contributors may be used to endorse or promote products derived
14 *       from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
19 * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
23 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
24 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
25 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
26 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 *
28 */
29#include <stdio.h>
30
31#include "log_util.h"
32#include "loc_eng_dmn_conn_thread_helper.h"
33
34/*===========================================================================
35FUNCTION    thelper_signal_init
36
37DESCRIPTION
38   This function will initialize the conditional variable resources.
39
40   thelper - thelper instance
41
42DEPENDENCIES
43   None
44
45RETURN VALUE
46   0: success or negative value for failure
47
48SIDE EFFECTS
49   N/A
50
51===========================================================================*/
52int thelper_signal_init(struct loc_eng_dmn_conn_thelper * thelper)
53{
54    int result;
55    thelper->thread_exit  = 0;
56    thelper->thread_ready = 0;
57    result = pthread_cond_init( &thelper->thread_cond, NULL);
58    if (result) {
59        return result;
60    }
61
62    result = pthread_mutex_init(&thelper->thread_mutex, NULL);
63    if (result) {
64        pthread_cond_destroy(&thelper->thread_cond);
65    }
66    return result;
67}
68
69/*===========================================================================
70FUNCTION
71
72DESCRIPTION
73   This function will destroy the conditional variable resources
74
75    thelper - pointer to thelper instance
76
77DEPENDENCIES
78   None
79
80RETURN VALUE
81   0: success or negative value for failure
82
83SIDE EFFECTS
84   N/A
85
86===========================================================================*/
87int thelper_signal_destroy(struct loc_eng_dmn_conn_thelper * thelper)
88{
89    int result, ret_result = 0;
90    result = pthread_cond_destroy( &thelper->thread_cond);
91    if (result) {
92        ret_result = result;
93    }
94
95    result = pthread_mutex_destroy(&thelper->thread_mutex);
96    if (result) {
97        ret_result = result;
98    }
99
100    return ret_result;
101}
102
103/*===========================================================================
104FUNCTION    thelper_signal_wait
105
106DESCRIPTION
107   This function will be blocked on the conditional variable until thelper_signal_ready
108   is called
109
110    thelper - pointer to thelper instance
111
112DEPENDENCIES
113   None
114
115RETURN VALUE
116   0: success or negative value for failure
117
118SIDE EFFECTS
119   N/A
120
121===========================================================================*/
122int thelper_signal_wait(struct loc_eng_dmn_conn_thelper * thelper)
123{
124    int result = 0;
125
126    pthread_mutex_lock(&thelper->thread_mutex);
127    if (!thelper->thread_ready && !thelper->thread_exit) {
128        result = pthread_cond_wait(&thelper->thread_cond, &thelper->thread_mutex);
129    }
130
131    if (thelper->thread_exit) {
132        result = -1;
133    }
134    pthread_mutex_unlock(&thelper->thread_mutex);
135
136    return result;
137}
138
139/*===========================================================================
140FUNCTION     thelper_signal_ready
141
142DESCRIPTION
143   This function will wake up the conditional variable
144
145    thelper - pointer to thelper instance
146
147DEPENDENCIES
148   None
149
150RETURN VALUE
151   0: success or negative value for failure
152
153SIDE EFFECTS
154   N/A
155
156===========================================================================*/
157int thelper_signal_ready(struct loc_eng_dmn_conn_thelper * thelper)
158{
159    int result;
160
161    LOC_LOGD("%s:%d] 0x%lx\n", __func__, __LINE__, (long) thelper);
162
163    pthread_mutex_lock(&thelper->thread_mutex);
164    thelper->thread_ready = 1;
165    result = pthread_cond_signal(&thelper->thread_cond);
166    pthread_mutex_unlock(&thelper->thread_mutex);
167
168    return result;
169}
170
171/*===========================================================================
172FUNCTION     thelper_signal_block
173
174DESCRIPTION
175   This function will set the thread ready to 0 to block the thelper_signal_wait
176
177    thelper - pointer to thelper instance
178
179DEPENDENCIES
180   None
181
182RETURN VALUE
183   if thread_ready is set
184
185SIDE EFFECTS
186   N/A
187
188===========================================================================*/
189int thelper_signal_block(struct loc_eng_dmn_conn_thelper * thelper)
190{
191    int result = thelper->thread_ready;
192
193    LOC_LOGD("%s:%d] 0x%lx\n", __func__, __LINE__, (long) thelper);
194
195    pthread_mutex_lock(&thelper->thread_mutex);
196    thelper->thread_ready = 0;
197    pthread_mutex_unlock(&thelper->thread_mutex);
198
199    return result;
200}
201
202/*===========================================================================
203FUNCTION    thelper_main
204
205DESCRIPTION
206   This function is the main thread. It will be launched as a child thread
207
208    data - pointer to the instance
209
210DEPENDENCIES
211   None
212
213RETURN VALUE
214   NULL
215
216SIDE EFFECTS
217   N/A
218
219===========================================================================*/
220static void * thelper_main(void *data)
221{
222    int result = 0;
223    struct loc_eng_dmn_conn_thelper * thelper = (struct loc_eng_dmn_conn_thelper *) data;
224
225    if (thelper->thread_proc_init) {
226        result = thelper->thread_proc_init(thelper->thread_context);
227        if (result < 0) {
228            thelper->thread_exit = 1;
229            thelper_signal_ready(thelper);
230            LOC_LOGE("%s:%d] error: 0x%lx\n", __func__, __LINE__, (long) thelper);
231            return NULL;
232        }
233    }
234
235    thelper_signal_ready(thelper);
236
237    if (thelper->thread_proc_pre) {
238        result = thelper->thread_proc_pre(thelper->thread_context);
239        if (result < 0) {
240            thelper->thread_exit = 1;
241            LOC_LOGE("%s:%d] error: 0x%lx\n", __func__, __LINE__, (long) thelper);
242            return NULL;
243        }
244    }
245
246    do {
247        if (thelper->thread_proc) {
248            result = thelper->thread_proc(thelper->thread_context);
249            if (result < 0) {
250                thelper->thread_exit = 1;
251                LOC_LOGE("%s:%d] error: 0x%lx\n", __func__, __LINE__, (long) thelper);
252            }
253        }
254    } while (thelper->thread_exit == 0);
255
256    if (thelper->thread_proc_post) {
257        result = thelper->thread_proc_post(thelper->thread_context);
258    }
259
260    if (result != 0) {
261        LOC_LOGE("%s:%d] error: 0x%lx\n", __func__, __LINE__, (long) thelper);
262    }
263    return NULL;
264}
265
266static void thelper_main_2(void *data)
267{
268    thelper_main(data);
269    return;
270}
271
272
273/*===========================================================================
274FUNCTION    loc_eng_dmn_conn_launch_thelper
275
276DESCRIPTION
277   This function will initialize the thread context and launch the thelper_main
278
279    thelper - pointer to thelper instance
280    thread_proc_init - The initialization function pointer
281    thread_proc_pre  - The function to call before task loop and after initialization
282    thread_proc      - The task loop
283    thread_proc_post - The function to call after the task loop
284    context          - the context for the above four functions
285
286DEPENDENCIES
287   None
288
289RETURN VALUE
290   0: success or negative value for failure
291
292SIDE EFFECTS
293   N/A
294
295===========================================================================*/
296int loc_eng_dmn_conn_launch_thelper(struct loc_eng_dmn_conn_thelper * thelper,
297    int (*thread_proc_init) (void * context),
298    int (*thread_proc_pre) (void * context),
299    int (*thread_proc) (void * context),
300    int (*thread_proc_post) (void * context),
301    thelper_create_thread   create_thread_cb,
302    void * context)
303{
304    int result;
305
306    thelper_signal_init(thelper);
307
308    if (context) {
309        thelper->thread_context    = context;
310    }
311
312    thelper->thread_proc_init  = thread_proc_init;
313    thelper->thread_proc_pre   = thread_proc_pre;
314    thelper->thread_proc       = thread_proc;
315    thelper->thread_proc_post  = thread_proc_post;
316
317    LOC_LOGD("%s:%d] 0x%lx call pthread_create\n", __func__, __LINE__, (long) thelper);
318    if (create_thread_cb) {
319        result = 0;
320        thelper->thread_id = create_thread_cb("loc_eng_dmn_conn",
321            thelper_main_2, (void *)thelper);
322    } else {
323        result = pthread_create(&thelper->thread_id, NULL,
324            thelper_main, (void *)thelper);
325    }
326
327    if (result != 0) {
328        LOC_LOGE("%s:%d] 0x%lx\n", __func__, __LINE__, (long) thelper);
329        return -1;
330    }
331
332    LOC_LOGD("%s:%d] 0x%lx pthread_create done\n", __func__, __LINE__, (long) thelper);
333
334    thelper_signal_wait(thelper);
335
336    LOC_LOGD("%s:%d] 0x%lx pthread ready\n", __func__, __LINE__, (long) thelper);
337    return thelper->thread_exit;
338}
339
340/*===========================================================================
341FUNCTION    loc_eng_dmn_conn_unblock_thelper
342
343DESCRIPTION
344   This function unblocks thelper_main to release the thread
345
346    thelper - pointer to thelper instance
347
348DEPENDENCIES
349   None
350
351RETURN VALUE
352   0: success
353
354SIDE EFFECTS
355   N/A
356
357===========================================================================*/
358int loc_eng_dmn_conn_unblock_thelper(struct loc_eng_dmn_conn_thelper * thelper)
359{
360    LOC_LOGD("%s:%d] 0x%lx\n", __func__, __LINE__, (long) thelper);
361    thelper->thread_exit = 1;
362    return 0;
363}
364
365/*===========================================================================
366FUNCTION    loc_eng_dmn_conn_join_thelper
367
368    thelper - pointer to thelper instance
369
370DESCRIPTION
371   This function will wait for the thread of thelper_main to finish
372
373DEPENDENCIES
374   None
375
376RETURN VALUE
377   0: success or negative value for failure
378
379SIDE EFFECTS
380   N/A
381
382===========================================================================*/
383int loc_eng_dmn_conn_join_thelper(struct loc_eng_dmn_conn_thelper * thelper)
384{
385    int result;
386
387    LOC_LOGD("%s:%d] 0x%lx\n", __func__, __LINE__, (long) thelper);
388    result = pthread_join(thelper->thread_id, NULL);
389    if (result != 0) {
390        LOC_LOGE("%s:%d] 0x%lx\n", __func__, __LINE__, (long) thelper);
391    }
392    LOC_LOGD("%s:%d] 0x%lx\n", __func__, __LINE__, (long) thelper);
393
394    thelper_signal_destroy(thelper);
395
396    return result;
397}
398
399