From c4f5756c82d7bbb5a5e70d9aad0d2c497d956a17 Mon Sep 17 00:00:00 2001 From: Lee Ballard Date: Mon, 11 Feb 2019 12:23:29 -0600 Subject: [PATCH] #8: replace busy polling with pthread_cond_wait --- aq_programmer.c | 51 ++++++++++++++++++++++++++++++++----------------- aqualink.h | 4 ++++ aqualinkd.c | 4 ++++ 3 files changed, 42 insertions(+), 17 deletions(-) diff --git a/aq_programmer.c b/aq_programmer.c index db31647..52c196c 100644 --- a/aq_programmer.c +++ b/aq_programmer.c @@ -393,24 +393,35 @@ void waitForSingleThreadOrTerminate(struct programmingThreadCtrl *threadCtrl, pr pthread_exit(0); } - - - // :TODO: use a mutex or semaphore instead of polling - while ( (threadCtrl->aq_data->active_thread.thread_id != 0) && ( i++ <= tries) ) { - logMessage (LOG_DEBUG, "Thread %d,%p (%s) sleeping, waiting for thread %d,%p (%s) to finish\n", - type, &threadCtrl->thread_id, ptypeName(type), - threadCtrl->aq_data->active_thread.ptype, threadCtrl->aq_data->active_thread.thread_id, ptypeName(threadCtrl->aq_data->active_thread.ptype)); - sleep(waitTime); - } - if (i >= tries) { - logMessage (LOG_ERR, "Thread %d,%p timeout waiting for thread %d,%p to finish\n", - type, &threadCtrl->thread_id, threadCtrl->aq_data->active_thread.ptype, - threadCtrl->aq_data->active_thread.thread_id); - free(threadCtrl); - pthread_exit(0); - } - + int ret; + struct timespec max_wait; + clock_gettime(CLOCK_REALTIME, &max_wait); + max_wait.tv_sec += 30; + + pthread_mutex_lock(&threadCtrl->aq_data->mutex); + while (threadCtrl->aq_data->active_thread.thread_id != 0) + { + logMessage (LOG_DEBUG, "Thread %d,%p (%s) sleeping, waiting for thread %d,%p (%s) to finish\n", + type, &threadCtrl->thread_id, ptypeName(type), + threadCtrl->aq_data->active_thread.ptype, threadCtrl->aq_data->active_thread.thread_id, ptypeName(threadCtrl->aq_data->active_thread.ptype)); + if ((ret = pthread_cond_timedwait(&threadCtrl->aq_data->thread_finished_cond, + &threadCtrl->aq_data->mutex, &max_wait))) + { + logMessage (LOG_ERR, "Thread %d,%p err %s waiting for thread %d,%p to finish\n", + type, &threadCtrl->thread_id, strerror(ret), + threadCtrl->aq_data->active_thread.ptype, + threadCtrl->aq_data->active_thread.thread_id); + + if ((ret = pthread_mutex_unlock(&threadCtrl->aq_data->mutex))) + { + logMessage (LOG_ERR, "waitForSingleThreadOrTerminate mutex unlock ret %s\n", strerror(ret)); + } + free(threadCtrl); + pthread_exit(0); + } + } + threadCtrl->aq_data->active_thread.thread_id = &threadCtrl->thread_id; threadCtrl->aq_data->active_thread.ptype = type; @@ -420,11 +431,14 @@ void waitForSingleThreadOrTerminate(struct programmingThreadCtrl *threadCtrl, pr threadCtrl->aq_data->active_thread.ptype, threadCtrl->aq_data->active_thread.thread_id, ptypeName(threadCtrl->aq_data->active_thread.ptype)); + pthread_mutex_unlock(&threadCtrl->aq_data->mutex); } void cleanAndTerminateThread(struct programmingThreadCtrl *threadCtrl) { struct timespec elapsed; + + pthread_mutex_lock(&threadCtrl->aq_data->mutex); clock_gettime(CLOCK_REALTIME, &threadCtrl->aq_data->last_active_time); timespec_subtract(&elapsed, &threadCtrl->aq_data->last_active_time, &threadCtrl->aq_data->start_active_time); logMessage(LOG_DEBUG, "Thread %d,%p (%s) finished in %d.%03ld sec\n", @@ -437,6 +451,9 @@ void cleanAndTerminateThread(struct programmingThreadCtrl *threadCtrl) // delay(500); threadCtrl->aq_data->active_thread.thread_id = 0; threadCtrl->aq_data->active_thread.ptype = AQP_NULL; + pthread_cond_signal(&threadCtrl->aq_data->thread_finished_cond); + pthread_mutex_unlock(&threadCtrl->aq_data->mutex); + threadCtrl->thread_id = 0; free(threadCtrl); pthread_exit(0); diff --git a/aqualink.h b/aqualink.h index 9a074b8..fec108e 100644 --- a/aqualink.h +++ b/aqualink.h @@ -4,6 +4,8 @@ #include #include +#include + #include "aq_serial.h" #include "aq_programmer.h" @@ -117,6 +119,8 @@ struct aqualinkdata //bool ar_swg_connected; struct timespec last_active_time; struct timespec start_active_time; + pthread_mutex_t mutex; + pthread_cond_t thread_finished_cond; }; diff --git a/aqualinkd.c b/aqualinkd.c index 4737f8e..e53f848 100644 --- a/aqualinkd.c +++ b/aqualinkd.c @@ -1029,6 +1029,7 @@ void main_loop() int i; //int delayAckCnt = 0; + // NSF need to find a better place to init this. //_aqualink_data.aq_command = 0x00; _aqualink_data.simulate_panel = false; @@ -1066,6 +1067,9 @@ void main_loop() clock_gettime(CLOCK_REALTIME, &_aqualink_data.last_active_time); + pthread_mutex_init(&_aqualink_data.mutex, NULL); + pthread_cond_init(&_aqualink_data.thread_finished_cond, NULL); + if (!start_net_services(&mgr, &_aqualink_data, &_config_parameters)) { logMessage(LOG_ERR, "Can not start webserver on port %s.\n", _config_parameters.socket_port);