Home | History | Annotate | Download | only in libloc_api_50001
      1 /* Copyright (c) 2011, The Linux Foundation. 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 The Linux Foundation 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 "platform_lib_includes.h"
     33 #include "loc_eng_dmn_conn_thread_helper.h"
     34 
     35 /*===========================================================================
     36 FUNCTION    thelper_signal_init
     37 
     38 DESCRIPTION
     39    This function will initialize the conditional variable resources.
     40 
     41    thelper - thelper instance
     42 
     43 DEPENDENCIES
     44    None
     45 
     46 RETURN VALUE
     47    0: success or negative value for failure
     48 
     49 SIDE EFFECTS
     50    N/A
     51 
     52 ===========================================================================*/
     53 int thelper_signal_init(struct loc_eng_dmn_conn_thelper * thelper)
     54 {
     55     int result;
     56     thelper->thread_exit  = 0;
     57     thelper->thread_ready = 0;
     58     result = pthread_cond_init( &thelper->thread_cond, NULL);
     59     if (result) {
     60         return result;
     61     }
     62 
     63     result = pthread_mutex_init(&thelper->thread_mutex, NULL);
     64     if (result) {
     65         pthread_cond_destroy(&thelper->thread_cond);
     66     }
     67     return result;
     68 }
     69 
     70 /*===========================================================================
     71 FUNCTION
     72 
     73 DESCRIPTION
     74    This function will destroy the conditional variable resources
     75 
     76     thelper - pointer to thelper instance
     77 
     78 DEPENDENCIES
     79    None
     80 
     81 RETURN VALUE
     82    0: success or negative value for failure
     83 
     84 SIDE EFFECTS
     85    N/A
     86 
     87 ===========================================================================*/
     88 int thelper_signal_destroy(struct loc_eng_dmn_conn_thelper * thelper)
     89 {
     90     int result, ret_result = 0;
     91     result = pthread_cond_destroy( &thelper->thread_cond);
     92     if (result) {
     93         ret_result = result;
     94     }
     95 
     96     result = pthread_mutex_destroy(&thelper->thread_mutex);
     97     if (result) {
     98         ret_result = result;
     99     }
    100 
    101     return ret_result;
    102 }
    103 
    104 /*===========================================================================
    105 FUNCTION    thelper_signal_wait
    106 
    107 DESCRIPTION
    108    This function will be blocked on the conditional variable until thelper_signal_ready
    109    is called
    110 
    111     thelper - pointer to thelper instance
    112 
    113 DEPENDENCIES
    114    None
    115 
    116 RETURN VALUE
    117    0: success or negative value for failure
    118 
    119 SIDE EFFECTS
    120    N/A
    121 
    122 ===========================================================================*/
    123 int thelper_signal_wait(struct loc_eng_dmn_conn_thelper * thelper)
    124 {
    125     int result = 0;
    126 
    127     pthread_mutex_lock(&thelper->thread_mutex);
    128     if (!thelper->thread_ready && !thelper->thread_exit) {
    129         result = pthread_cond_wait(&thelper->thread_cond, &thelper->thread_mutex);
    130     }
    131 
    132     if (thelper->thread_exit) {
    133         result = -1;
    134     }
    135     pthread_mutex_unlock(&thelper->thread_mutex);
    136 
    137     return result;
    138 }
    139 
    140 /*===========================================================================
    141 FUNCTION     thelper_signal_ready
    142 
    143 DESCRIPTION
    144    This function will wake up the conditional variable
    145 
    146     thelper - pointer to thelper instance
    147 
    148 DEPENDENCIES
    149    None
    150 
    151 RETURN VALUE
    152    0: success or negative value for failure
    153 
    154 SIDE EFFECTS
    155    N/A
    156 
    157 ===========================================================================*/
    158 int thelper_signal_ready(struct loc_eng_dmn_conn_thelper * thelper)
    159 {
    160     int result;
    161 
    162     LOC_LOGD("%s:%d] 0x%lx\n", __func__, __LINE__, (long) thelper);
    163 
    164     pthread_mutex_lock(&thelper->thread_mutex);
    165     thelper->thread_ready = 1;
    166     result = pthread_cond_signal(&thelper->thread_cond);
    167     pthread_mutex_unlock(&thelper->thread_mutex);
    168 
    169     return result;
    170 }
    171 
    172 /*===========================================================================
    173 FUNCTION     thelper_signal_block
    174 
    175 DESCRIPTION
    176    This function will set the thread ready to 0 to block the thelper_signal_wait
    177 
    178     thelper - pointer to thelper instance
    179 
    180 DEPENDENCIES
    181    None
    182 
    183 RETURN VALUE
    184    if thread_ready is set
    185 
    186 SIDE EFFECTS
    187    N/A
    188 
    189 ===========================================================================*/
    190 int thelper_signal_block(struct loc_eng_dmn_conn_thelper * thelper)
    191 {
    192     int result = thelper->thread_ready;
    193 
    194     LOC_LOGD("%s:%d] 0x%lx\n", __func__, __LINE__, (long) thelper);
    195 
    196     pthread_mutex_lock(&thelper->thread_mutex);
    197     thelper->thread_ready = 0;
    198     pthread_mutex_unlock(&thelper->thread_mutex);
    199 
    200     return result;
    201 }
    202 
    203 /*===========================================================================
    204 FUNCTION    thelper_main
    205 
    206 DESCRIPTION
    207    This function is the main thread. It will be launched as a child thread
    208 
    209     data - pointer to the instance
    210 
    211 DEPENDENCIES
    212    None
    213 
    214 RETURN VALUE
    215    NULL
    216 
    217 SIDE EFFECTS
    218    N/A
    219 
    220 ===========================================================================*/
    221 static void * thelper_main(void *data)
    222 {
    223     int result = 0;
    224     struct loc_eng_dmn_conn_thelper * thelper = (struct loc_eng_dmn_conn_thelper *) data;
    225 
    226     if (thelper->thread_proc_init) {
    227         result = thelper->thread_proc_init(thelper->thread_context);
    228         if (result < 0) {
    229             thelper->thread_exit = 1;
    230             thelper_signal_ready(thelper);
    231             LOC_LOGE("%s:%d] error: 0x%lx\n", __func__, __LINE__, (long) thelper);
    232             return NULL;
    233         }
    234     }
    235 
    236     thelper_signal_ready(thelper);
    237 
    238     if (thelper->thread_proc_pre) {
    239         result = thelper->thread_proc_pre(thelper->thread_context);
    240         if (result < 0) {
    241             thelper->thread_exit = 1;
    242             LOC_LOGE("%s:%d] error: 0x%lx\n", __func__, __LINE__, (long) thelper);
    243             return NULL;
    244         }
    245     }
    246 
    247     do {
    248         if (thelper->thread_proc) {
    249             result = thelper->thread_proc(thelper->thread_context);
    250             if (result < 0) {
    251                 thelper->thread_exit = 1;
    252                 LOC_LOGE("%s:%d] error: 0x%lx\n", __func__, __LINE__, (long) thelper);
    253             }
    254         }
    255     } while (thelper->thread_exit == 0);
    256 
    257     if (thelper->thread_proc_post) {
    258         result = thelper->thread_proc_post(thelper->thread_context);
    259     }
    260 
    261     if (result != 0) {
    262         LOC_LOGE("%s:%d] error: 0x%lx\n", __func__, __LINE__, (long) thelper);
    263     }
    264     return NULL;
    265 }
    266 
    267 static void thelper_main_2(void *data)
    268 {
    269     thelper_main(data);
    270     return;
    271 }
    272 
    273 
    274 /*===========================================================================
    275 FUNCTION    loc_eng_dmn_conn_launch_thelper
    276 
    277 DESCRIPTION
    278    This function will initialize the thread context and launch the thelper_main
    279 
    280     thelper - pointer to thelper instance
    281     thread_proc_init - The initialization function pointer
    282     thread_proc_pre  - The function to call before task loop and after initialization
    283     thread_proc      - The task loop
    284     thread_proc_post - The function to call after the task loop
    285     context          - the context for the above four functions
    286 
    287 DEPENDENCIES
    288    None
    289 
    290 RETURN VALUE
    291    0: success or negative value for failure
    292 
    293 SIDE EFFECTS
    294    N/A
    295 
    296 ===========================================================================*/
    297 int loc_eng_dmn_conn_launch_thelper(struct loc_eng_dmn_conn_thelper * thelper,
    298     int (*thread_proc_init) (void * context),
    299     int (*thread_proc_pre) (void * context),
    300     int (*thread_proc) (void * context),
    301     int (*thread_proc_post) (void * context),
    302     thelper_create_thread   create_thread_cb,
    303     void * context)
    304 {
    305     int result;
    306 
    307     thelper_signal_init(thelper);
    308 
    309     if (context) {
    310         thelper->thread_context    = context;
    311     }
    312 
    313     thelper->thread_proc_init  = thread_proc_init;
    314     thelper->thread_proc_pre   = thread_proc_pre;
    315     thelper->thread_proc       = thread_proc;
    316     thelper->thread_proc_post  = thread_proc_post;
    317 
    318     LOC_LOGD("%s:%d] 0x%lx call pthread_create\n", __func__, __LINE__, (long) thelper);
    319     if (create_thread_cb) {
    320         result = 0;
    321         thelper->thread_id = create_thread_cb("loc_eng_dmn_conn",
    322             thelper_main_2, (void *)thelper);
    323     } else {
    324         result = pthread_create(&thelper->thread_id, NULL,
    325             thelper_main, (void *)thelper);
    326     }
    327 
    328     if (result != 0) {
    329         LOC_LOGE("%s:%d] 0x%lx\n", __func__, __LINE__, (long) thelper);
    330         return -1;
    331     }
    332 
    333     LOC_LOGD("%s:%d] 0x%lx pthread_create done\n", __func__, __LINE__, (long) thelper);
    334 
    335     thelper_signal_wait(thelper);
    336 
    337     LOC_LOGD("%s:%d] 0x%lx pthread ready\n", __func__, __LINE__, (long) thelper);
    338     return thelper->thread_exit;
    339 }
    340 
    341 /*===========================================================================
    342 FUNCTION    loc_eng_dmn_conn_unblock_thelper
    343 
    344 DESCRIPTION
    345    This function unblocks thelper_main to release the thread
    346 
    347     thelper - pointer to thelper instance
    348 
    349 DEPENDENCIES
    350    None
    351 
    352 RETURN VALUE
    353    0: success
    354 
    355 SIDE EFFECTS
    356    N/A
    357 
    358 ===========================================================================*/
    359 int loc_eng_dmn_conn_unblock_thelper(struct loc_eng_dmn_conn_thelper * thelper)
    360 {
    361     LOC_LOGD("%s:%d] 0x%lx\n", __func__, __LINE__, (long) thelper);
    362     thelper->thread_exit = 1;
    363     return 0;
    364 }
    365 
    366 /*===========================================================================
    367 FUNCTION    loc_eng_dmn_conn_join_thelper
    368 
    369     thelper - pointer to thelper instance
    370 
    371 DESCRIPTION
    372    This function will wait for the thread of thelper_main to finish
    373 
    374 DEPENDENCIES
    375    None
    376 
    377 RETURN VALUE
    378    0: success or negative value for failure
    379 
    380 SIDE EFFECTS
    381    N/A
    382 
    383 ===========================================================================*/
    384 int loc_eng_dmn_conn_join_thelper(struct loc_eng_dmn_conn_thelper * thelper)
    385 {
    386     int result;
    387 
    388     LOC_LOGD("%s:%d] 0x%lx\n", __func__, __LINE__, (long) thelper);
    389     result = pthread_join(thelper->thread_id, NULL);
    390     if (result != 0) {
    391         LOC_LOGE("%s:%d] 0x%lx\n", __func__, __LINE__, (long) thelper);
    392     }
    393     LOC_LOGD("%s:%d] 0x%lx\n", __func__, __LINE__, (long) thelper);
    394 
    395     thelper_signal_destroy(thelper);
    396 
    397     return result;
    398 }
    399 
    400