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