diff --git a/src/dialogs/fl_digi.cxx b/src/dialogs/fl_digi.cxx index ea6d9b74..f954a3f6 100644 --- a/src/dialogs/fl_digi.cxx +++ b/src/dialogs/fl_digi.cxx @@ -585,17 +585,12 @@ void init_modem(trx_mode mode) void init_modem_sync(trx_mode m) { - if (trx_state != STATE_RX) - return; + ENSURE_THREAD(FLMAIN_TID); -#ifndef NDEBUG - if (GET_THREAD_ID() == TRX_TID) - LOG_ERROR("trx thread called init_modem_sync!"); -#endif + if (trx_state != STATE_RX) + TRX_WAIT(STATE_RX, abort_tx()); - wait_modem_ready_prep(); - init_modem(m); - wait_modem_ready_cmpl(); + TRX_WAIT(STATE_RX, init_modem(m)); REQ_FLUSH(TRX_TID); } diff --git a/src/globals/globals.cxx b/src/globals/globals.cxx index d7782596..a9641272 100644 --- a/src/globals/globals.cxx +++ b/src/globals/globals.cxx @@ -34,15 +34,6 @@ using namespace std; -const char *state_names[] = { - "PAUSED", - "RECEIVE", - "TRANSMIT", - "TUNING", - "ABORTED", - "FLUSHING" -}; - // Elements are in enum trx_mode order. Mode name video-id uses the // first string (sname), so its length should be a multiple of 2. const struct mode_info_t mode_info[NUM_MODES] = { diff --git a/src/include/globals.h b/src/include/globals.h index 1846675d..2684c828 100644 --- a/src/include/globals.h +++ b/src/include/globals.h @@ -44,7 +44,6 @@ enum state_t { STATE_IDLE, STATE_NEW_MODEM }; -extern const char *state_names[]; enum { MODE_PREV = -2, diff --git a/src/include/threads.h b/src/include/threads.h index f71cae9f..fa5b68a5 100644 --- a/src/include/threads.h +++ b/src/include/threads.h @@ -15,7 +15,7 @@ int sem_timedwait_rel(sem_t* sem, double rel_timeout); int pthread_cond_timedwait_rel(pthread_cond_t* cond, pthread_mutex_t* mutex, double rel_timeout); // 3 threads use qrunner -enum { UNKNOWN_TID = -1, TRX_TID, QRZ_TID, RIGCTL_TID, +enum { INVALID_TID = -1, TRX_TID, QRZ_TID, RIGCTL_TID, #if USE_XMLRPC XMLRPC_TID, #endif @@ -25,16 +25,39 @@ enum { UNKNOWN_TID = -1, TRX_TID, QRZ_TID, RIGCTL_TID, #if USE_TLS # define THREAD_ID_TYPE __thread int -# define CREATE_THREAD_ID() thread_id_ = UNKNOWN_TID +# define CREATE_THREAD_ID() thread_id_ = INVALID_TID # define SET_THREAD_ID(x) thread_id_ = (x) # define GET_THREAD_ID() thread_id_ #else # define THREAD_ID_TYPE pthread_key_t -# define CREATE_THREAD_ID() pthread_key_create(&thread_id_, 0); +# define CREATE_THREAD_ID() pthread_key_create(&thread_id_, 0) # define SET_THREAD_ID(x) pthread_setspecific(thread_id_, (void *)(x)) # define GET_THREAD_ID() (int)pthread_getspecific(thread_id_) #endif // USE_TLS + +#ifndef NDEBUG +# include "debug.h" +bool thread_in_list(int id, const int* list); +# define ENSURE_THREAD(...) \ + do { \ + int id_ = GET_THREAD_ID(); \ + int t_[] = { __VA_ARGS__, INVALID_TID }; \ + if (!thread_in_list(id_, t_)) \ + LOG_ERROR("bad thread context: %d", id_); \ + } while (0) +# define ENSURE_NOT_THREAD(...) \ + do { \ + int id_ = GET_THREAD_ID(); \ + int t_[] = { __VA_ARGS__, INVALID_TID }; \ + if (thread_in_list(id_, t_)) \ + LOG_ERROR("bad thread context: %d", id_); \ + } while (0) +#else +# define ENSURE_THREAD(...) ((void)0) +# define ENSURE_NOT_THREAD(...) ((void)0) +#endif // ! NDEBUG + extern THREAD_ID_TYPE thread_id_; #include "fl_lock.h" diff --git a/src/include/trx.h b/src/include/trx.h index 7dd00f1b..b5bd8e8b 100644 --- a/src/include/trx.h +++ b/src/include/trx.h @@ -48,9 +48,9 @@ extern void trx_receive(); extern void trx_reset(void); extern void trx_start_macro_timer(); -extern void wait_modem_ready_prep(void); -extern void wait_modem_ready_cmpl(void); -extern void signal_modem_ready(void); +extern void wait_trx_state_prep(void); +extern void wait_trx_state_wait(void); +extern void wait_trx_state_cmpl(void); extern void macro_timer(void *); @@ -62,4 +62,14 @@ extern SoundBase *scard; extern bool bHistory; +#define TRX_WAIT(s_, code_) \ + do { \ + ENSURE_NOT_THREAD(TRX_TID); \ + wait_trx_state_prep(); \ + code_; \ + while (trx_state != s_) \ + wait_trx_state_wait(); \ + wait_trx_state_cmpl(); \ + } while (0) + #endif diff --git a/src/misc/threads.cxx b/src/misc/threads.cxx index ccb81371..7304532c 100644 --- a/src/misc/threads.cxx +++ b/src/misc/threads.cxx @@ -54,3 +54,13 @@ int pthread_cond_timedwait_rel(pthread_cond_t* cond, pthread_mutex_t* mutex, dou return pthread_cond_timedwait(cond, mutex, &t); } + +#ifndef NDEBUG +bool thread_in_list(int id, const int* list) +{ + while (*list != INVALID_TID) + if (id == *list++) + return true; + return false; +} +#endif diff --git a/src/trx/trx.cxx b/src/trx/trx.cxx index 1fc91447..4742b170 100644 --- a/src/trx/trx.cxx +++ b/src/trx/trx.cxx @@ -52,6 +52,7 @@ void trx_start_modem_loop(); void trx_receive_loop(); void trx_transmit_loop(); void trx_tune_loop(); +static void signal_trx_state(void); //#define DEBUG @@ -321,7 +322,13 @@ void *trx_loop(void *args) { SET_THREAD_ID(TRX_TID); + state_t old_state = STATE_NOOP; + for (;;) { + if (unlikely(old_state != trx_state)) { + old_state = trx_state; + signal_trx_state(); + } switch (trx_state) { case STATE_ABORT: delete scard; @@ -351,32 +358,21 @@ void *trx_loop(void *args) } //============================================================================= -modem *trx_m; +modem* new_modem; void trx_start_modem_loop() { - if (trx_m == active_modem) { - trx_state = STATE_RX; + if (new_modem == active_modem) { active_modem->restart(); - signal_modem_ready(); + trx_state = STATE_RX; return; } modem* old_modem = active_modem; - if (old_modem == trx_m) { - trx_state = STATE_RX; - signal_modem_ready(); - return; - } - - if (old_modem) - old_modem->shutdown(); - - active_modem = trx_m; - active_modem->init(); + new_modem->init(); + active_modem = new_modem; trx_state = STATE_RX; - signal_modem_ready(); REQ(&waterfall::opmode, wf); if (old_modem) { @@ -388,7 +384,7 @@ void trx_start_modem_loop() //============================================================================= void trx_start_modem(modem *m) { - trx_m = m; + new_modem = m; trx_state = STATE_NEW_MODEM; } @@ -538,36 +534,24 @@ void trx_tune(void) { trx_state = STATE_TUNE; } void trx_receive(void) { trx_state = STATE_RX; } //============================================================================= -void wait_modem_ready_prep(void) -{ -#ifndef NDEBUG - if (GET_THREAD_ID() == TRX_TID) - LOG_ERROR("trx thread called wait_modem_ready_prep!"); -#endif +void wait_trx_state_prep(void) +{ pthread_mutex_lock(&trx_cond_mutex); } - -void wait_modem_ready_cmpl(void) +void wait_trx_state_wait(void) { -#ifndef NDEBUG - if (GET_THREAD_ID() == TRX_TID) - LOG_ERROR("trx thread called wait_modem_ready_cmpl!"); -#endif - pthread_cond_wait(&trx_cond, &trx_cond_mutex); +} +void wait_trx_state_cmpl(void) +{ pthread_mutex_unlock(&trx_cond_mutex); } -void signal_modem_ready(void) +static void signal_trx_state(void) { -#ifndef NDEBUG - if (GET_THREAD_ID() != TRX_TID) - LOG_ERROR("thread %d called signal_modem_ready!", GET_THREAD_ID()); -#endif - + ENSURE_THREAD(TRX_TID); pthread_mutex_lock(&trx_cond_mutex); pthread_cond_broadcast(&trx_cond); pthread_mutex_unlock(&trx_cond_mutex); } -