Add mutex for rig_send_morse and when locked use cache

for rig_get_freq, rig_get_mode, rig_get_vfo, and rig_get_split_vfo
Might need to add more down the road
https://github.com/Hamlib/Hamlib/issues/1514
pull/1522/head
Mike Black W9MDB 2024-02-28 23:04:47 -06:00
rodzic 25ee5d65d5
commit c68ef118e9
1 zmienionych plików z 72 dodań i 20 usunięć

Wyświetl plik

@ -174,16 +174,33 @@ const char hamlib_copyright[231] = /* hamlib 1.2 ABI specifies 231 bytes */
#define LOCK(n) if (rig->state.depth == 1) { rig_debug(RIG_DEBUG_CACHE, "%s: %s\n", n?"lock":"unlock", __func__); rig_lock(rig,n); } #define LOCK(n) if (rig->state.depth == 1) { rig_debug(RIG_DEBUG_CACHE, "%s: %s\n", n?"lock":"unlock", __func__); rig_lock(rig,n); }
#ifdef PTHREAD #ifdef HAVE_PTHREAD
#define MUTEX(var) static pthread_mutex_t var = PTHREAD_MUTEX_INITIALIZER #define MUTEX(var) static pthread_mutex_t var = PTHREAD_MUTEX_INITIALIZER
#define MUTEX_LOCK(var) pthread_mutex_lock(var) #define MUTEX_LOCK(var) pthread_mutex_lock(&var)
#define MUTEX_UNLOCK(var) pthread_mutex_unlock(var) #define MUTEX_UNLOCK(var) pthread_mutex_unlock(&var)
#else #else
#warning NOT PTHREAD
#define MUTEX(var) #define MUTEX(var)
#define MUTEX_LOCK(var) #define MUTEX_LOCK(var)
#define MUTEX_UNLOCK(var) #define MUTEX_UNLOCK(var)
#endif #endif
MUTEX(morse_mutex);
// returns true if mutex is busy
int MUTEX_CHECK(pthread_mutex_t *m)
{
int trylock = pthread_mutex_trylock(m);
if (trylock != EBUSY)
{
pthread_mutex_unlock(m);
}
return trylock == EBUSY;
}
/* /*
* Data structure to track the opened rig (by rig_open) * Data structure to track the opened rig (by rig_open)
*/ */
@ -358,7 +375,7 @@ char debugmsgsave[DEBUGMSGSAVE_SIZE] = "";
char debugmsgsave2[DEBUGMSGSAVE_SIZE] = ""; // deprecated char debugmsgsave2[DEBUGMSGSAVE_SIZE] = ""; // deprecated
char debugmsgsave3[DEBUGMSGSAVE_SIZE] = ""; // deprecated char debugmsgsave3[DEBUGMSGSAVE_SIZE] = ""; // deprecated
MUTEX(debugmsgsave); MUTEX(mutex_debugmsgsave);
void add2debugmsgsave(const char *s) void add2debugmsgsave(const char *s)
{ {
@ -366,7 +383,7 @@ void add2debugmsgsave(const char *s)
char stmp[DEBUGMSGSAVE_SIZE]; char stmp[DEBUGMSGSAVE_SIZE];
int i, nlines; int i, nlines;
int maxmsg = DEBUGMSGSAVE_SIZE / 2; int maxmsg = DEBUGMSGSAVE_SIZE / 2;
MUTEX_LOCK(debugmsgsave); MUTEX_LOCK(mutex_debugmsgsave);
memset(stmp, 0, sizeof(stmp)); memset(stmp, 0, sizeof(stmp));
// we'll keep 20 lines including this one // we'll keep 20 lines including this one
@ -409,7 +426,7 @@ void add2debugmsgsave(const char *s)
(int)strlen(debugmsgsave), (int)strlen(s)); (int)strlen(debugmsgsave), (int)strlen(s));
} }
MUTEX_UNLOCK(debugmsgsave); MUTEX_UNLOCK(mutex_debugmsgsave);
} }
/** /**
@ -2322,6 +2339,7 @@ int HAMLIB_API rig_get_freq(RIG *rig, vfo_t vfo, freq_t *freq)
rmode_t mode; rmode_t mode;
pbwidth_t width; pbwidth_t width;
int curr_band; int curr_band;
int use_cache = 0;
static int last_band = -1; static int last_band = -1;
if (CHECK_RIG_ARG(rig)) if (CHECK_RIG_ARG(rig))
@ -2360,12 +2378,18 @@ int HAMLIB_API rig_get_freq(RIG *rig, vfo_t vfo, freq_t *freq)
rig_debug(RIG_DEBUG_VERBOSE, "%s(%d) vfo=%s, curr_vfo=%s\n", __FILE__, __LINE__, rig_debug(RIG_DEBUG_VERBOSE, "%s(%d) vfo=%s, curr_vfo=%s\n", __FILE__, __LINE__,
rig_strvfo(vfo), rig_strvfo(curr_vfo)); rig_strvfo(vfo), rig_strvfo(curr_vfo));
if (MUTEX_CHECK(&morse_mutex))
{
use_cache = 1;
}
if (vfo == RIG_VFO_CURR) { vfo = curr_vfo; } if (vfo == RIG_VFO_CURR) { vfo = curr_vfo; }
// we ignore get_freq for the uplink VFO for gpredict to behave better // we ignore get_freq for the uplink VFO for gpredict to behave better
if ((rig->state.uplink == 1 && vfo == RIG_VFO_SUB) if ((rig->state.uplink == 1 && vfo == RIG_VFO_SUB)
|| (rig->state.uplink == 2 && vfo == RIG_VFO_MAIN) || (rig->state.uplink == 2 && vfo == RIG_VFO_MAIN)
|| (vfo == RIG_VFO_TX && cachep->ptt == 0)) || (vfo == RIG_VFO_TX && cachep->ptt == 0)
|| use_cache)
{ {
rig_debug(RIG_DEBUG_TRACE, "%s: uplink=%d, ignoring get_freq\n", __func__, rig_debug(RIG_DEBUG_TRACE, "%s: uplink=%d, ignoring get_freq\n", __func__,
rig->state.uplink); rig->state.uplink);
@ -2717,7 +2741,8 @@ int HAMLIB_API rig_set_mode(RIG *rig, vfo_t vfo, rmode_t mode, pbwidth_t width)
retcode = caps->get_mode(rig, vfo, &mode_curr, &width_curr); retcode = caps->get_mode(rig, vfo, &mode_curr, &width_curr);
// For Icom rigs we may need to force the filter so we always set mode // For Icom rigs we may need to force the filter so we always set mode
if (retcode == RIG_OK && mode == mode_curr && RIG_ICOM != RIG_BACKEND_NUM(rig->caps->rig_model)) if (retcode == RIG_OK && mode == mode_curr
&& RIG_ICOM != RIG_BACKEND_NUM(rig->caps->rig_model))
{ {
rig_debug(RIG_DEBUG_VERBOSE, rig_debug(RIG_DEBUG_VERBOSE,
"%s: mode already %s and bw change not requested\n", __func__, "%s: mode already %s and bw change not requested\n", __func__,
@ -2842,6 +2867,7 @@ int HAMLIB_API rig_get_mode(RIG *rig,
{ {
const struct rig_caps *caps; const struct rig_caps *caps;
int retcode; int retcode;
int use_cache = 0;
freq_t freq; freq_t freq;
vfo_t curr_vfo; vfo_t curr_vfo;
struct rig_cache *cachep = CACHE(rig); struct rig_cache *cachep = CACHE(rig);
@ -2871,6 +2897,7 @@ int HAMLIB_API rig_get_mode(RIG *rig,
curr_vfo = rig->state.current_vfo; curr_vfo = rig->state.current_vfo;
vfo = vfo_fixup(rig, vfo, cachep->split); vfo = vfo_fixup(rig, vfo, cachep->split);
if (vfo == RIG_VFO_CURR) { vfo = curr_vfo; } if (vfo == RIG_VFO_CURR) { vfo = curr_vfo; }
*mode = RIG_MODE_NONE; *mode = RIG_MODE_NONE;
@ -2883,8 +2910,13 @@ int HAMLIB_API rig_get_mode(RIG *rig,
rig_cache_show(rig, __func__, __LINE__); rig_cache_show(rig, __func__, __LINE__);
if (MUTEX_CHECK(&morse_mutex))
{
use_cache = 1;
}
if (cachep->timeout_ms == HAMLIB_CACHE_ALWAYS if (cachep->timeout_ms == HAMLIB_CACHE_ALWAYS
|| rig->state.use_cached_mode) || rig->state.use_cached_mode || use_cache)
{ {
rig_debug(RIG_DEBUG_TRACE, "%s: cache hit age mode=%dms, width=%dms\n", rig_debug(RIG_DEBUG_TRACE, "%s: cache hit age mode=%dms, width=%dms\n",
__func__, cache_ms_mode, cache_ms_width); __func__, cache_ms_mode, cache_ms_width);
@ -3305,6 +3337,7 @@ int HAMLIB_API rig_get_vfo(RIG *rig, vfo_t *vfo)
struct rig_cache *cachep = CACHE(rig); struct rig_cache *cachep = CACHE(rig);
int retcode = -RIG_EINTERNAL; int retcode = -RIG_EINTERNAL;
int cache_ms; int cache_ms;
int use_cache = 0;
if (CHECK_RIG_ARG(rig) || !vfo) if (CHECK_RIG_ARG(rig) || !vfo)
{ {
@ -3328,7 +3361,12 @@ int HAMLIB_API rig_get_vfo(RIG *rig, vfo_t *vfo)
cache_ms = elapsed_ms(&cachep->time_vfo, HAMLIB_ELAPSED_GET); cache_ms = elapsed_ms(&cachep->time_vfo, HAMLIB_ELAPSED_GET);
//rig_debug(RIG_DEBUG_TRACE, "%s: cache check age=%dms\n", __func__, cache_ms); //rig_debug(RIG_DEBUG_TRACE, "%s: cache check age=%dms\n", __func__, cache_ms);
if (cache_ms < cachep->timeout_ms) if (MUTEX_CHECK(&morse_mutex))
{
use_cache = 1;
}
if (cache_ms < cachep->timeout_ms || use_cache)
{ {
*vfo = cachep->vfo; *vfo = cachep->vfo;
rig_debug(RIG_DEBUG_TRACE, "%s: cache hit age=%dms, vfo=%s\n", __func__, rig_debug(RIG_DEBUG_TRACE, "%s: cache hit age=%dms, vfo=%s\n", __func__,
@ -4529,7 +4567,8 @@ int HAMLIB_API rig_set_split_freq(RIG *rig, vfo_t vfo, freq_t tx_freq)
// Always use the previously selected TX VFO for split. The targeted VFO will have no effect. // Always use the previously selected TX VFO for split. The targeted VFO will have no effect.
tx_vfo = rs->tx_vfo; tx_vfo = rs->tx_vfo;
if (cachep->split == RIG_SPLIT_OFF || tx_vfo == RIG_VFO_NONE || tx_vfo == RIG_VFO_CURR) if (cachep->split == RIG_SPLIT_OFF || tx_vfo == RIG_VFO_NONE
|| tx_vfo == RIG_VFO_CURR)
{ {
// Turn split on if not enabled already // Turn split on if not enabled already
retcode = rig_set_split_vfo(rig, rs->current_vfo, RIG_SPLIT_ON, vfo_fixup(rig, retcode = rig_set_split_vfo(rig, rs->current_vfo, RIG_SPLIT_ON, vfo_fixup(rig,
@ -4718,7 +4757,8 @@ int HAMLIB_API rig_get_split_freq(RIG *rig, vfo_t vfo, freq_t *tx_freq)
// Always use the previously selected TX VFO for split. The targeted VFO will have no effect. // Always use the previously selected TX VFO for split. The targeted VFO will have no effect.
tx_vfo = rs->tx_vfo; tx_vfo = rs->tx_vfo;
if (cachep->split == RIG_SPLIT_OFF || tx_vfo == RIG_VFO_NONE || tx_vfo == RIG_VFO_CURR) if (cachep->split == RIG_SPLIT_OFF || tx_vfo == RIG_VFO_NONE
|| tx_vfo == RIG_VFO_CURR)
{ {
// Split frequency not available if split is off // Split frequency not available if split is off
*tx_freq = 0; *tx_freq = 0;
@ -4894,7 +4934,8 @@ int HAMLIB_API rig_set_split_mode(RIG *rig,
// Always use the previously selected TX VFO for split. The targeted VFO will have no effect. // Always use the previously selected TX VFO for split. The targeted VFO will have no effect.
tx_vfo = rs->tx_vfo; tx_vfo = rs->tx_vfo;
if (cachep->split == RIG_SPLIT_OFF || tx_vfo == RIG_VFO_NONE || tx_vfo == RIG_VFO_CURR) if (cachep->split == RIG_SPLIT_OFF || tx_vfo == RIG_VFO_NONE
|| tx_vfo == RIG_VFO_CURR)
{ {
// Turn split on if not enabled already // Turn split on if not enabled already
retcode = rig_set_split_vfo(rig, rs->current_vfo, RIG_SPLIT_ON, vfo_fixup(rig, retcode = rig_set_split_vfo(rig, rs->current_vfo, RIG_SPLIT_ON, vfo_fixup(rig,
@ -5130,7 +5171,8 @@ int HAMLIB_API rig_get_split_mode(RIG *rig, vfo_t vfo, rmode_t *tx_mode,
// Always use the previously selected TX VFO for split. The targeted VFO will have no effect. // Always use the previously selected TX VFO for split. The targeted VFO will have no effect.
tx_vfo = rs->tx_vfo; tx_vfo = rs->tx_vfo;
if (cachep->split == RIG_SPLIT_OFF || tx_vfo == RIG_VFO_NONE || tx_vfo == RIG_VFO_CURR) if (cachep->split == RIG_SPLIT_OFF || tx_vfo == RIG_VFO_NONE
|| tx_vfo == RIG_VFO_CURR)
{ {
// Split mode and filter width are not available if split is off // Split mode and filter width are not available if split is off
*tx_mode = RIG_MODE_NONE; *tx_mode = RIG_MODE_NONE;
@ -5289,7 +5331,8 @@ int HAMLIB_API rig_set_split_freq_mode(RIG *rig,
// Always use the previously selected TX VFO for split. The targeted VFO will have no effect. // Always use the previously selected TX VFO for split. The targeted VFO will have no effect.
tx_vfo = rs->tx_vfo; tx_vfo = rs->tx_vfo;
if (cachep->split == RIG_SPLIT_OFF || tx_vfo == RIG_VFO_NONE || tx_vfo == RIG_VFO_CURR) if (cachep->split == RIG_SPLIT_OFF || tx_vfo == RIG_VFO_NONE
|| tx_vfo == RIG_VFO_CURR)
{ {
// Turn split on if not enabled already // Turn split on if not enabled already
retcode = rig_set_split_vfo(rig, rs->current_vfo, RIG_SPLIT_ON, vfo_fixup(rig, retcode = rig_set_split_vfo(rig, rs->current_vfo, RIG_SPLIT_ON, vfo_fixup(rig,
@ -5435,7 +5478,8 @@ int HAMLIB_API rig_get_split_freq_mode(RIG *rig,
// Always use the previously selected TX VFO for split. The targeted VFO will have no effect. // Always use the previously selected TX VFO for split. The targeted VFO will have no effect.
tx_vfo = rs->tx_vfo; tx_vfo = rs->tx_vfo;
if (cachep->split == RIG_SPLIT_OFF || tx_vfo == RIG_VFO_NONE || tx_vfo == RIG_VFO_CURR) if (cachep->split == RIG_SPLIT_OFF || tx_vfo == RIG_VFO_NONE
|| tx_vfo == RIG_VFO_CURR)
{ {
// Split frequency, mode and filter width are not available if split is off // Split frequency, mode and filter width are not available if split is off
*tx_freq = 0; *tx_freq = 0;
@ -5634,6 +5678,7 @@ int HAMLIB_API rig_set_split_vfo(RIG *rig,
// Only update cache on success // Only update cache on success
rs->rx_vfo = rs->current_vfo; rs->rx_vfo = rs->current_vfo;
cachep->split = split; cachep->split = split;
if (split == RIG_SPLIT_OFF) if (split == RIG_SPLIT_OFF)
{ {
rs->tx_vfo = rs->current_vfo; rs->tx_vfo = rs->current_vfo;
@ -5692,6 +5737,7 @@ int HAMLIB_API rig_set_split_vfo(RIG *rig,
{ {
// Only update cache on success // Only update cache on success
cachep->split = split; cachep->split = split;
if (split == RIG_SPLIT_OFF) if (split == RIG_SPLIT_OFF)
{ {
if (caps->targetable_vfo & RIG_TARGETABLE_FREQ) if (caps->targetable_vfo & RIG_TARGETABLE_FREQ)
@ -5746,6 +5792,7 @@ int HAMLIB_API rig_get_split_vfo(RIG *rig,
struct rig_cache *cachep = CACHE(rig); struct rig_cache *cachep = CACHE(rig);
int retcode; int retcode;
int cache_ms; int cache_ms;
int use_cache;
if (CHECK_RIG_ARG(rig)) if (CHECK_RIG_ARG(rig))
{ {
@ -5767,14 +5814,16 @@ int HAMLIB_API rig_get_split_vfo(RIG *rig,
caps = rig->caps; caps = rig->caps;
rs = &rig->state; rs = &rig->state;
if (caps->get_split_vfo == NULL) if (MUTEX_CHECK(&morse_mutex))
{
use_cache = 1;
}
if (caps->get_split_vfo == NULL || use_cache)
{ {
// if we can't get the vfo we will return whatever we have cached // if we can't get the vfo we will return whatever we have cached
*split = cachep->split; *split = cachep->split;
*tx_vfo = cachep->split_vfo; *tx_vfo = cachep->split_vfo;
rig_debug(RIG_DEBUG_VERBOSE,
"%s: no get_split_vfo so returning split=%d, tx_vfo=%s\n", __func__, *split,
rig_strvfo(*tx_vfo));
ELAPSED2; ELAPSED2;
RETURNFUNC(RIG_OK); RETURNFUNC(RIG_OK);
} }
@ -8560,6 +8609,7 @@ void *morse_data_handler(void *arg)
if (strlen(c) > 0) if (strlen(c) > 0)
{ {
int nloops = 10; int nloops = 10;
MUTEX_LOCK(morse_mutex);
do do
{ {
@ -8585,6 +8635,8 @@ void *morse_data_handler(void *arg)
} }
while (result != RIG_OK && rig->state.fifo_morse->flush == 0 && --nloops > 0); while (result != RIG_OK && rig->state.fifo_morse->flush == 0 && --nloops > 0);
MUTEX_UNLOCK(morse_mutex);
if (nloops == 0) if (nloops == 0)
{ {
rig_debug(RIG_DEBUG_ERR, "%s: send_morse failed\n", __func__); rig_debug(RIG_DEBUG_ERR, "%s: send_morse failed\n", __func__);