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/*=========================================================================== 36FUNCTION thelper_signal_init 37 38DESCRIPTION 39 This function will initialize the conditional variable resources. 40 41 thelper - thelper instance 42 43DEPENDENCIES 44 None 45 46RETURN VALUE 47 0: success or negative value for failure 48 49SIDE EFFECTS 50 N/A 51 52===========================================================================*/ 53int 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/*=========================================================================== 71FUNCTION 72 73DESCRIPTION 74 This function will destroy the conditional variable resources 75 76 thelper - pointer to thelper instance 77 78DEPENDENCIES 79 None 80 81RETURN VALUE 82 0: success or negative value for failure 83 84SIDE EFFECTS 85 N/A 86 87===========================================================================*/ 88int 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/*=========================================================================== 105FUNCTION thelper_signal_wait 106 107DESCRIPTION 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 113DEPENDENCIES 114 None 115 116RETURN VALUE 117 0: success or negative value for failure 118 119SIDE EFFECTS 120 N/A 121 122===========================================================================*/ 123int 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/*=========================================================================== 141FUNCTION thelper_signal_ready 142 143DESCRIPTION 144 This function will wake up the conditional variable 145 146 thelper - pointer to thelper instance 147 148DEPENDENCIES 149 None 150 151RETURN VALUE 152 0: success or negative value for failure 153 154SIDE EFFECTS 155 N/A 156 157===========================================================================*/ 158int 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/*=========================================================================== 173FUNCTION thelper_signal_block 174 175DESCRIPTION 176 This function will set the thread ready to 0 to block the thelper_signal_wait 177 178 thelper - pointer to thelper instance 179 180DEPENDENCIES 181 None 182 183RETURN VALUE 184 if thread_ready is set 185 186SIDE EFFECTS 187 N/A 188 189===========================================================================*/ 190int 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/*=========================================================================== 204FUNCTION thelper_main 205 206DESCRIPTION 207 This function is the main thread. It will be launched as a child thread 208 209 data - pointer to the instance 210 211DEPENDENCIES 212 None 213 214RETURN VALUE 215 NULL 216 217SIDE EFFECTS 218 N/A 219 220===========================================================================*/ 221static 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 267static void thelper_main_2(void *data) 268{ 269 thelper_main(data); 270 return; 271} 272 273 274/*=========================================================================== 275FUNCTION loc_eng_dmn_conn_launch_thelper 276 277DESCRIPTION 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 287DEPENDENCIES 288 None 289 290RETURN VALUE 291 0: success or negative value for failure 292 293SIDE EFFECTS 294 N/A 295 296===========================================================================*/ 297int 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/*=========================================================================== 342FUNCTION loc_eng_dmn_conn_unblock_thelper 343 344DESCRIPTION 345 This function unblocks thelper_main to release the thread 346 347 thelper - pointer to thelper instance 348 349DEPENDENCIES 350 None 351 352RETURN VALUE 353 0: success 354 355SIDE EFFECTS 356 N/A 357 358===========================================================================*/ 359int 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/*=========================================================================== 367FUNCTION loc_eng_dmn_conn_join_thelper 368 369 thelper - pointer to thelper instance 370 371DESCRIPTION 372 This function will wait for the thread of thelper_main to finish 373 374DEPENDENCIES 375 None 376 377RETURN VALUE 378 0: success or negative value for failure 379 380SIDE EFFECTS 381 N/A 382 383===========================================================================*/ 384int 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