diff options
author | Bhalchandra Gajare <gajare@codeaurora.org> | 2016-02-04 15:14:57 -0800 |
---|---|---|
committer | David Keitel <dkeitel@codeaurora.org> | 2016-03-23 21:20:37 -0700 |
commit | 72f0f4b937bd8a4ae15a6dd3b8a7a92b39ec6567 (patch) | |
tree | e8107e30b7dd1dfa5dbfd0ddd89d093d7ba902fd /sound/soc/codecs | |
parent | 90c2030c5bdc3013b2b02eda8bdc7cf93c5eb141 (diff) |
ASoC: wcd_cpe_services: Make the worker thread standalone
The worker thread can either be stopped through kthread_stop or could
return from the function on some conditions. Since thread has two exit
points, this is causing a race condition where kthread_stop indefinitely
waits for the thread to exit. Make the thread standalone and always call
do_exit itself to exit instead of stopping it through kthread_stop.
CRs-fixed: 972943
Change-Id: If95cbd6ee895d566887453e98421d1514147441b
Signed-off-by: Bhalchandra Gajare <gajare@codeaurora.org>
Diffstat (limited to 'sound/soc/codecs')
-rw-r--r-- | sound/soc/codecs/wcd_cpe_services.c | 23 |
1 files changed, 15 insertions, 8 deletions
diff --git a/sound/soc/codecs/wcd_cpe_services.c b/sound/soc/codecs/wcd_cpe_services.c index d4dbf02d15d1..5a82c8e5382b 100644 --- a/sound/soc/codecs/wcd_cpe_services.c +++ b/sound/soc/codecs/wcd_cpe_services.c @@ -161,6 +161,7 @@ struct cpe_command_node { struct cpe_info { struct list_head main_queue; struct completion cmd_complete; + struct completion thread_comp; void *thread_handler; bool stop_thread; struct mutex msg_lock; @@ -392,31 +393,34 @@ static int cpe_worker_thread(void *context) { struct cpe_info *t_info = (struct cpe_info *)context; - while (!kthread_should_stop()) { + /* + * Thread will run until requested to stop explicitly + * by setting the t_info->stop_thread flag + */ + while (1) { + /* Wait for command to be processed */ wait_for_completion(&t_info->cmd_complete); CPE_SVC_GRAB_LOCK(&t_info->msg_lock, "msg_lock"); cpe_cmd_received(t_info); reinit_completion(&t_info->cmd_complete); + /* Check if thread needs to be stopped */ if (t_info->stop_thread) goto unlock_and_exit; CPE_SVC_REL_LOCK(&t_info->msg_lock, "msg_lock"); }; - pr_debug("%s: thread exited\n", __func__); - return 0; - unlock_and_exit: pr_debug("%s: thread stopped\n", __func__); CPE_SVC_REL_LOCK(&t_info->msg_lock, "msg_lock"); - - return 0; + complete_and_exit(&t_info->thread_comp, 0); } static void cpe_create_worker_thread(struct cpe_info *t_info) { INIT_LIST_HEAD(&t_info->main_queue); init_completion(&t_info->cmd_complete); + init_completion(&t_info->thread_comp); t_info->stop_thread = false; t_info->thread_handler = kthread_run(cpe_worker_thread, (void *)t_info, "cpe-worker-thread"); @@ -440,9 +444,12 @@ static void cpe_cleanup_worker_thread(struct cpe_info *t_info) complete(&t_info->cmd_complete); CPE_SVC_REL_LOCK(&t_info->msg_lock, "msg_lock"); - kthread_stop(t_info->thread_handler); - + /* Wait for the thread to exit */ + wait_for_completion(&t_info->thread_comp); t_info->thread_handler = NULL; + + pr_debug("%s: Thread cleaned up successfully\n", + __func__); } static enum cpe_svc_result |