/* Copyright (c) 2011, The Linux Foundation. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following * disclaimer in the documentation and/or other materials provided * with the distribution. * * Neither the name of The Linux Foundation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include #include "log_util.h" #include "platform_lib_includes.h" #include "loc_eng_dmn_conn_thread_helper.h" /*=========================================================================== FUNCTION thelper_signal_init DESCRIPTION This function will initialize the conditional variable resources. thelper - thelper instance DEPENDENCIES None RETURN VALUE 0: success or negative value for failure SIDE EFFECTS N/A ===========================================================================*/ int thelper_signal_init(struct loc_eng_dmn_conn_thelper * thelper) { int result; thelper->thread_exit = 0; thelper->thread_ready = 0; result = pthread_cond_init( &thelper->thread_cond, NULL); if (result) { return result; } result = pthread_mutex_init(&thelper->thread_mutex, NULL); if (result) { pthread_cond_destroy(&thelper->thread_cond); } return result; } /*=========================================================================== FUNCTION DESCRIPTION This function will destroy the conditional variable resources thelper - pointer to thelper instance DEPENDENCIES None RETURN VALUE 0: success or negative value for failure SIDE EFFECTS N/A ===========================================================================*/ int thelper_signal_destroy(struct loc_eng_dmn_conn_thelper * thelper) { int result, ret_result = 0; result = pthread_cond_destroy( &thelper->thread_cond); if (result) { ret_result = result; } result = pthread_mutex_destroy(&thelper->thread_mutex); if (result) { ret_result = result; } return ret_result; } /*=========================================================================== FUNCTION thelper_signal_wait DESCRIPTION This function will be blocked on the conditional variable until thelper_signal_ready is called thelper - pointer to thelper instance DEPENDENCIES None RETURN VALUE 0: success or negative value for failure SIDE EFFECTS N/A ===========================================================================*/ int thelper_signal_wait(struct loc_eng_dmn_conn_thelper * thelper) { int result = 0; pthread_mutex_lock(&thelper->thread_mutex); if (!thelper->thread_ready && !thelper->thread_exit) { result = pthread_cond_wait(&thelper->thread_cond, &thelper->thread_mutex); } if (thelper->thread_exit) { result = -1; } pthread_mutex_unlock(&thelper->thread_mutex); return result; } /*=========================================================================== FUNCTION thelper_signal_ready DESCRIPTION This function will wake up the conditional variable thelper - pointer to thelper instance DEPENDENCIES None RETURN VALUE 0: success or negative value for failure SIDE EFFECTS N/A ===========================================================================*/ int thelper_signal_ready(struct loc_eng_dmn_conn_thelper * thelper) { int result; LOC_LOGD("%s:%d] 0x%lx\n", __func__, __LINE__, (long) thelper); pthread_mutex_lock(&thelper->thread_mutex); thelper->thread_ready = 1; result = pthread_cond_signal(&thelper->thread_cond); pthread_mutex_unlock(&thelper->thread_mutex); return result; } /*=========================================================================== FUNCTION thelper_signal_block DESCRIPTION This function will set the thread ready to 0 to block the thelper_signal_wait thelper - pointer to thelper instance DEPENDENCIES None RETURN VALUE if thread_ready is set SIDE EFFECTS N/A ===========================================================================*/ int thelper_signal_block(struct loc_eng_dmn_conn_thelper * thelper) { int result = thelper->thread_ready; LOC_LOGD("%s:%d] 0x%lx\n", __func__, __LINE__, (long) thelper); pthread_mutex_lock(&thelper->thread_mutex); thelper->thread_ready = 0; pthread_mutex_unlock(&thelper->thread_mutex); return result; } /*=========================================================================== FUNCTION thelper_main DESCRIPTION This function is the main thread. It will be launched as a child thread data - pointer to the instance DEPENDENCIES None RETURN VALUE NULL SIDE EFFECTS N/A ===========================================================================*/ static void * thelper_main(void *data) { int result = 0; struct loc_eng_dmn_conn_thelper * thelper = (struct loc_eng_dmn_conn_thelper *) data; if (thelper->thread_proc_init) { result = thelper->thread_proc_init(thelper->thread_context); if (result < 0) { thelper->thread_exit = 1; thelper_signal_ready(thelper); LOC_LOGE("%s:%d] error: 0x%lx\n", __func__, __LINE__, (long) thelper); return NULL; } } thelper_signal_ready(thelper); if (thelper->thread_proc_pre) { result = thelper->thread_proc_pre(thelper->thread_context); if (result < 0) { thelper->thread_exit = 1; LOC_LOGE("%s:%d] error: 0x%lx\n", __func__, __LINE__, (long) thelper); return NULL; } } do { if (thelper->thread_proc) { result = thelper->thread_proc(thelper->thread_context); if (result < 0) { thelper->thread_exit = 1; LOC_LOGE("%s:%d] error: 0x%lx\n", __func__, __LINE__, (long) thelper); } } } while (thelper->thread_exit == 0); if (thelper->thread_proc_post) { result = thelper->thread_proc_post(thelper->thread_context); } if (result != 0) { LOC_LOGE("%s:%d] error: 0x%lx\n", __func__, __LINE__, (long) thelper); } return NULL; } static void thelper_main_2(void *data) { thelper_main(data); return; } /*=========================================================================== FUNCTION loc_eng_dmn_conn_launch_thelper DESCRIPTION This function will initialize the thread context and launch the thelper_main thelper - pointer to thelper instance thread_proc_init - The initialization function pointer thread_proc_pre - The function to call before task loop and after initialization thread_proc - The task loop thread_proc_post - The function to call after the task loop context - the context for the above four functions DEPENDENCIES None RETURN VALUE 0: success or negative value for failure SIDE EFFECTS N/A ===========================================================================*/ int loc_eng_dmn_conn_launch_thelper(struct loc_eng_dmn_conn_thelper * thelper, int (*thread_proc_init) (void * context), int (*thread_proc_pre) (void * context), int (*thread_proc) (void * context), int (*thread_proc_post) (void * context), thelper_create_thread create_thread_cb, void * context) { int result; thelper_signal_init(thelper); if (context) { thelper->thread_context = context; } thelper->thread_proc_init = thread_proc_init; thelper->thread_proc_pre = thread_proc_pre; thelper->thread_proc = thread_proc; thelper->thread_proc_post = thread_proc_post; LOC_LOGD("%s:%d] 0x%lx call pthread_create\n", __func__, __LINE__, (long) thelper); if (create_thread_cb) { result = 0; thelper->thread_id = create_thread_cb("loc_eng_dmn_conn", thelper_main_2, (void *)thelper); } else { result = pthread_create(&thelper->thread_id, NULL, thelper_main, (void *)thelper); } if (result != 0) { LOC_LOGE("%s:%d] 0x%lx\n", __func__, __LINE__, (long) thelper); return -1; } LOC_LOGD("%s:%d] 0x%lx pthread_create done\n", __func__, __LINE__, (long) thelper); thelper_signal_wait(thelper); LOC_LOGD("%s:%d] 0x%lx pthread ready\n", __func__, __LINE__, (long) thelper); return thelper->thread_exit; } /*=========================================================================== FUNCTION loc_eng_dmn_conn_unblock_thelper DESCRIPTION This function unblocks thelper_main to release the thread thelper - pointer to thelper instance DEPENDENCIES None RETURN VALUE 0: success SIDE EFFECTS N/A ===========================================================================*/ int loc_eng_dmn_conn_unblock_thelper(struct loc_eng_dmn_conn_thelper * thelper) { LOC_LOGD("%s:%d] 0x%lx\n", __func__, __LINE__, (long) thelper); thelper->thread_exit = 1; return 0; } /*=========================================================================== FUNCTION loc_eng_dmn_conn_join_thelper thelper - pointer to thelper instance DESCRIPTION This function will wait for the thread of thelper_main to finish DEPENDENCIES None RETURN VALUE 0: success or negative value for failure SIDE EFFECTS N/A ===========================================================================*/ int loc_eng_dmn_conn_join_thelper(struct loc_eng_dmn_conn_thelper * thelper) { int result; LOC_LOGD("%s:%d] 0x%lx\n", __func__, __LINE__, (long) thelper); result = pthread_join(thelper->thread_id, NULL); if (result != 0) { LOC_LOGE("%s:%d] 0x%lx\n", __func__, __LINE__, (long) thelper); } LOC_LOGD("%s:%d] 0x%lx\n", __func__, __LINE__, (long) thelper); thelper_signal_destroy(thelper); return result; }