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