Skip to content

Commit 633fdff

Browse files
committed
ballle98#8: replace busy polling with pthread_cond_wait
1 parent 42586e5 commit 633fdff

File tree

4 files changed

+68
-40
lines changed

4 files changed

+68
-40
lines changed

aq_programmer.c

+62-39
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,9 @@ unsigned char _pgm_command = NUL;
9696

9797
bool _last_sent_was_cmd = false;
9898

99+
static pthread_mutex_t _pgm_command_mutex = PTHREAD_MUTEX_INITIALIZER;
100+
static pthread_cond_t _pgm_command_sent_cond = PTHREAD_COND_INITIALIZER;
101+
99102
// External view of adding to queue
100103
void aq_send_cmd(unsigned char cmd) {
101104
push_aq_cmd(cmd);
@@ -146,9 +149,12 @@ unsigned char pop_aq_cmd(struct aqualinkdata *aq_data)
146149
if (in_programming_mode(aq_data) && ( in_ot_programming_mode(aq_data) == false && in_iaqt_programming_mode(aq_data) == false )) {
147150
//if (aq_data->active_thread.thread_id != 0) {
148151
if ( _pgm_command != NUL && aq_data->last_packet_type == CMD_STATUS) {
152+
pthread_mutex_lock(&_pgm_command_mutex);
149153
cmd = _pgm_command;
150154
_pgm_command = NUL;
151155
LOG(PROG_LOG, LOG_DEBUG_SERIAL, "RS SEND cmd '0x%02hhx' (programming)\n", cmd);
156+
pthread_cond_signal(&_pgm_command_sent_cond);
157+
pthread_mutex_unlock(&_pgm_command_mutex);
152158
} else if (_pgm_command != NUL) {
153159
LOG(PROG_LOG, LOG_DEBUG_SERIAL, "RS Waiting to send cmd '0x%02hhx' (programming)\n", _pgm_command);
154160
} else {
@@ -900,39 +906,33 @@ void aq_programmer(program_type r_type, char *args, struct aqualinkdata *aq_data
900906

901907
void waitForSingleThreadOrTerminate(struct programmingThreadCtrl *threadCtrl, program_type type)
902908
{
903-
//static int tries = 120;
904-
int tries = 120;
905-
static int waitTime = 1;
906-
int i=0;
907-
908-
i = 0;
909-
while (get_aq_cmd_length() > 0 && ( i++ <= tries) ) {
910-
LOG(PROG_LOG, LOG_DEBUG, "Thread %p (%s) sleeping, waiting command queue to empty\n", &threadCtrl->thread_id, ptypeName(type));
911-
sleep(waitTime);
912-
}
913-
if (i >= tries) {
914-
LOG(PROG_LOG, LOG_ERR, "Thread %p (%s) timeout waiting, ending\n",&threadCtrl->thread_id,ptypeName(type));
915-
free(threadCtrl);
916-
pthread_exit(0);
917-
}
909+
int ret = 0;
910+
struct timespec max_wait;
911+
clock_gettime(CLOCK_REALTIME, &max_wait);
912+
max_wait.tv_sec += 30;
918913

919-
while ( (threadCtrl->aq_data->active_thread.thread_id != 0) && ( i++ <= tries) ) {
920-
//LOG(PROG_LOG, LOG_DEBUG, "Thread %d sleeping, waiting for thread %d to finish\n", threadCtrl->thread_id, threadCtrl->aq_data->active_thread.thread_id);
921-
LOG(PROG_LOG, LOG_DEBUG, "Thread %p (%s) sleeping, waiting for thread %p (%s) to finish\n",
922-
&threadCtrl->thread_id, ptypeName(type),
923-
threadCtrl->aq_data->active_thread.thread_id, ptypeName(threadCtrl->aq_data->active_thread.ptype));
924-
sleep(waitTime);
925-
}
926-
927-
if (i >= tries) {
928-
//LOG(PROG_LOG, LOG_ERR, "Thread %d timeout waiting, ending\n",threadCtrl->thread_id);
929-
LOG(PROG_LOG, LOG_ERR, "Thread %d,%p timeout waiting for thread %d,%p to finish\n",
930-
type, &threadCtrl->thread_id, threadCtrl->aq_data->active_thread.ptype,
931-
threadCtrl->aq_data->active_thread.thread_id);
932-
free(threadCtrl);
933-
pthread_exit(0);
934-
}
935-
914+
pthread_mutex_lock(&threadCtrl->aq_data->mutex);
915+
while (threadCtrl->aq_data->active_thread.thread_id != 0)
916+
{
917+
LOG(PROG_LOG, LOG_DEBUG, "Thread %d,%p (%s) sleeping, waiting for thread %d,%p (%s) to finish\n",
918+
type, &threadCtrl->thread_id, ptypeName(type),
919+
threadCtrl->aq_data->active_thread.ptype, threadCtrl->aq_data->active_thread.thread_id, ptypeName(threadCtrl->aq_data->active_thread.ptype));
920+
if ((ret = pthread_cond_timedwait(&threadCtrl->aq_data->thread_finished_cond,
921+
&threadCtrl->aq_data->mutex, &max_wait)))
922+
{
923+
LOG(PROG_LOG, LOG_ERR, "Thread %d,%p err %s waiting for thread %d,%p to finish\n",
924+
type, &threadCtrl->thread_id, strerror(ret),
925+
threadCtrl->aq_data->active_thread.ptype,
926+
threadCtrl->aq_data->active_thread.thread_id);
927+
928+
if ((ret = pthread_mutex_unlock(&threadCtrl->aq_data->mutex)))
929+
{
930+
LOG(PROG_LOG, LOG_ERR, "waitForSingleThreadOrTerminate mutex unlock ret %s\n", strerror(ret));
931+
}
932+
free(threadCtrl);
933+
pthread_exit(0);
934+
}
935+
}
936936
// Clear out any messages to the UI.
937937
threadCtrl->aq_data->last_display_message[0] = '\0';
938938
threadCtrl->aq_data->active_thread.thread_id = &threadCtrl->thread_id;
@@ -948,10 +948,12 @@ void waitForSingleThreadOrTerminate(struct programmingThreadCtrl *threadCtrl, pr
948948
threadCtrl->aq_data->active_thread.ptype,
949949
threadCtrl->aq_data->active_thread.thread_id,
950950
ptypeName(threadCtrl->aq_data->active_thread.ptype));
951+
pthread_mutex_unlock(&threadCtrl->aq_data->mutex);
951952
}
952953

953954
void cleanAndTerminateThread(struct programmingThreadCtrl *threadCtrl)
954955
{
956+
pthread_mutex_lock(&threadCtrl->aq_data->mutex);
955957
#ifndef AQ_DEBUG
956958
LOG(PROG_LOG, LOG_DEBUG, "Thread %d,%p (%s) finished\n",threadCtrl->aq_data->active_thread.ptype, threadCtrl->thread_id,ptypeName(threadCtrl->aq_data->active_thread.ptype));
957959
#else
@@ -965,10 +967,11 @@ void cleanAndTerminateThread(struct programmingThreadCtrl *threadCtrl)
965967
elapsed.tv_sec, elapsed.tv_nsec / 1000000L);
966968
#endif
967969

968-
// Quick delay to allow for last message to be sent.
969-
delay(500);
970970
threadCtrl->aq_data->active_thread.thread_id = 0;
971971
threadCtrl->aq_data->active_thread.ptype = AQP_NULL;
972+
pthread_cond_signal(&threadCtrl->aq_data->thread_finished_cond);
973+
pthread_mutex_unlock(&threadCtrl->aq_data->mutex);
974+
972975
threadCtrl->thread_id = 0;
973976
// Force update, change display message
974977
threadCtrl->aq_data->updated = true;
@@ -1996,14 +1999,34 @@ void longwaitfor_queue2empty()
19961999
_waitfor_queue2empty(true);
19972000
}
19982001

1999-
void send_cmd(unsigned char cmd)
2002+
bool send_cmd(unsigned char cmd)
20002003
{
2001-
waitfor_queue2empty();
2002-
2003-
_pgm_command = cmd;
2004-
//delay(200);
2004+
bool ret=true;
2005+
int pret = 0;
2006+
struct timespec max_wait;
2007+
2008+
clock_gettime(CLOCK_REALTIME, &max_wait);
2009+
max_wait.tv_sec += 5;
20052010

2011+
pthread_mutex_lock(&_pgm_command_mutex);
2012+
_pgm_command = cmd;
20062013
LOG(PROG_LOG, LOG_INFO, "Queue send '0x%02hhx' to controller (programming)\n", _pgm_command);
2014+
while (_pgm_command != NUL)
2015+
{
2016+
if ((pret = pthread_cond_timedwait(&_pgm_command_sent_cond,
2017+
&_pgm_command_mutex, &max_wait)))
2018+
{
2019+
LOG(PROG_LOG, LOG_ERR, "send_cmd 0x%02hhx err %s\n",
2020+
cmd, strerror(pret));
2021+
ret = false;
2022+
break;
2023+
}
2024+
}
2025+
if (ret) {
2026+
LOG(PROG_LOG, LOG_INFO, "sent '0x%02hhx' to controller\n", _pgm_command);
2027+
}
2028+
pthread_mutex_unlock(&_pgm_command_mutex);
2029+
return ret;
20072030
}
20082031

20092032
/*

aq_programmer.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,7 @@ const char *ptypeName(program_type type);
129129
const char *programtypeDisplayName(program_type type);
130130

131131
// These shouldn't be here, but just for the PDA AQ PROGRAMMER
132-
void send_cmd(unsigned char cmd);
132+
bool send_cmd(unsigned char cmd);
133133
bool push_aq_cmd(unsigned char cmd);
134134
void waitForSingleThreadOrTerminate(struct programmingThreadCtrl *threadCtrl, program_type type);
135135
void cleanAndTerminateThread(struct programmingThreadCtrl *threadCtrl);

aqualink.h

+2
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,8 @@ struct aqualinkdata
208208
struct timespec last_active_time;
209209
struct timespec start_active_time;
210210
#endif
211+
pthread_mutex_t mutex;
212+
pthread_cond_t thread_finished_cond;
211213
};
212214

213215

aqualinkd.c

+3
Original file line numberDiff line numberDiff line change
@@ -1461,6 +1461,9 @@ void main_loop()
14611461
_aqualink_data.swg_ppm = 0;
14621462
}
14631463

1464+
pthread_mutex_init(&_aqualink_data.mutex, NULL);
1465+
pthread_cond_init(&_aqualink_data.thread_finished_cond, NULL);
1466+
14641467
if (!start_net_services(&mgr, &_aqualink_data))
14651468
{
14661469
LOG(AQUA_LOG,LOG_ERR, "Can not start webserver on port %s.\n", _aqconfig_.socket_port);

0 commit comments

Comments
 (0)