Datenklo: Timers may only be scheduled or deleted in the main thread

Set flags to schedule timers in main thread.
Timers are: vtimer (datenklo.c), tx/rx timers (am791x.c)
This commit is contained in:
Andreas Eversberg
2024-01-12 18:57:53 +01:00
parent 3c2b5286c5
commit 26c348411c
4 changed files with 86 additions and 33 deletions

View File

@@ -587,7 +587,6 @@ static void set_flag(int *flag_p, int value, const char *name)
/*
* state machine according to datasheet
*/
static void go_main_channel_tx(am791x_t *am791x)
{
LOGP(DAM791X, LOGL_DEBUG, "Enable transmitter on main channel\n");
@@ -601,7 +600,8 @@ static void go_main_channel_tx(am791x_t *am791x)
/* activate TD now and set CTS timer (RCON) */
set_flag(&am791x->block_td, 0, "TD RELEASED");
set_flag(&am791x->tx_silence, 0, "RESET SILENCE");
osmo_timer_schedule(&am791x->tx_timer, FLOAT_TO_TIMEOUT(am791x->t_rcon));
/* Flag timer, because it must be added in main thread. */
am791x->tx_timer_f = am791x->t_rcon;
new_tx_state(am791x, AM791X_STATE_RCON);
set_filters(am791x);
/* check CD to be blocked */
@@ -652,7 +652,8 @@ static void tx_data_done(am791x_t *am791x)
if (!am791x->fullduplex) {
set_flag(&am791x->squelch, 1, "SET SQUELCH (ON)");
}
osmo_timer_schedule(&am791x->tx_timer, FLOAT_TO_TIMEOUT(am791x->t_rcoff));
/* Flag timer, because it must be added in main thread. */
am791x->tx_timer_f = am791x->t_rcoff;
}
static void rcoff_done(am791x_t *am791x)
@@ -667,11 +668,13 @@ static void rcoff_done(am791x_t *am791x)
return;
}
if (!am791x->sto) {
osmo_timer_schedule(&am791x->tx_timer, FLOAT_TO_TIMEOUT(am791x->t_sq - am791x->t_rcoff));
/* Flag timer, because it must be added in main thread. */
am791x->tx_timer_f = am791x->t_sq - am791x->t_rcoff;
new_tx_state(am791x, AM791X_STATE_SQ_OFF);
return;
}
osmo_timer_schedule(&am791x->tx_timer, FLOAT_TO_TIMEOUT(am791x->t_sto - am791x->t_rcoff));
/* Flag timer, because it must be added in main thread. */
am791x->tx_timer_f = am791x->t_sto - am791x->t_rcoff;
new_tx_state(am791x, AM791X_STATE_STO_OFF);
}
@@ -695,7 +698,8 @@ static void sto_done(am791x_t *am791x)
LOGP(DAM791X, LOGL_DEBUG, "STO over\n");
set_flag(&am791x->tx_sto, 0, "stop STO");
osmo_timer_schedule(&am791x->tx_timer, FLOAT_TO_TIMEOUT(am791x->t_sq - am791x->t_sto));
/* Flag timer, because it must be added in main thread. */
am791x->tx_timer_f = am791x->t_sq - am791x->t_sto;
new_tx_state(am791x, AM791X_STATE_SQ_OFF);
}
@@ -711,7 +715,8 @@ static void go_back_channel_tx(am791x_t *am791x)
/* activate BTD now and set BCTS timer (BRCON) */
set_flag(&am791x->block_btd, 0, "BTD RELEASED");
set_flag(&am791x->tx_silence, 0, "RESET SILENCE");
osmo_timer_schedule(&am791x->tx_timer, FLOAT_TO_TIMEOUT(am791x->t_brcon));
/* Flag timer, because it must be added in main thread. */
am791x->tx_timer_f = am791x->t_brcon;
new_tx_state(am791x, AM791X_STATE_BRCON);
set_filters(am791x);
/* check BCD to be blocked */
@@ -747,7 +752,8 @@ static void tx_bdata_done(am791x_t *am791x)
set_flag(&am791x->block_btd, 1, "BTD IGNORED");
set_flag(&am791x->tx_silence, 1, "SET SILENCE");
osmo_timer_schedule(&am791x->tx_timer, FLOAT_TO_TIMEOUT(am791x->t_brcoff));
/* Flag timer, because it must be added in main thread. */
am791x->tx_timer_f = am791x->t_brcoff;
}
static void brcoff_done(am791x_t *am791x)
@@ -793,7 +799,8 @@ static void handle_tx_state(am791x_t *am791x)
rcon_release_rts(am791x);
break;
}
if (!osmo_timer_pending(&am791x->tx_timer)) {
/* If timer is about to be switched off, of if it already has been switched off. */
if (am791x->tx_timer_f < 0.0 || (!osmo_timer_pending(&am791x->tx_timer) && am791x->tx_timer_f == 0.0)) {
rcon_done(am791x);
break;
}
@@ -805,19 +812,22 @@ static void handle_tx_state(am791x_t *am791x)
}
break;
case AM791X_STATE_RCOFF:
if (!osmo_timer_pending(&am791x->tx_timer)) {
/* If timer is about to be switched off, of if it already has been switched off. */
if (am791x->tx_timer_f < 0.0 || (!osmo_timer_pending(&am791x->tx_timer) && am791x->tx_timer_f == 0.0)) {
rcoff_done(am791x);
break;
}
break;
case AM791X_STATE_STO_OFF:
if (!osmo_timer_pending(&am791x->tx_timer)) {
/* If timer is about to be switched off, of if it already has been switched off. */
if (am791x->tx_timer_f < 0.0 || (!osmo_timer_pending(&am791x->tx_timer) && am791x->tx_timer_f == 0.0)) {
sto_done(am791x);
break;
}
break;
case AM791X_STATE_SQ_OFF:
if (!osmo_timer_pending(&am791x->tx_timer)) {
/* If timer is about to be switched off, of if it already has been switched off. */
if (am791x->tx_timer_f < 0.0 || (!osmo_timer_pending(&am791x->tx_timer) && am791x->tx_timer_f == 0.0)) {
sq_done(am791x);
break;
}
@@ -828,7 +838,8 @@ static void handle_tx_state(am791x_t *am791x)
brcon_release_brts(am791x);
break;
}
if (!osmo_timer_pending(&am791x->tx_timer)) {
/* If timer is about to be switched off, of if it already has been switched off. */
if (am791x->tx_timer_f < 0.0 || (!osmo_timer_pending(&am791x->tx_timer) && am791x->tx_timer_f == 0.0)) {
brcon_done(am791x);
break;
}
@@ -840,7 +851,8 @@ static void handle_tx_state(am791x_t *am791x)
}
break;
case AM791X_STATE_BRCOFF:
if (!osmo_timer_pending(&am791x->tx_timer)) {
/* If timer is about to be switched off, of if it already has been switched off. */
if (am791x->tx_timer_f < 0.0 || (!osmo_timer_pending(&am791x->tx_timer) && am791x->tx_timer_f == 0.0)) {
brcoff_done(am791x);
break;
}
@@ -854,7 +866,8 @@ static void go_main_channel_rx(am791x_t *am791x)
{
LOGP(DAM791X, LOGL_DEBUG, "Enable receiver on main channel\n");
osmo_timer_schedule(&am791x->rx_timer, FLOAT_TO_TIMEOUT(am791x->t_cdon));
/* Flag timer, because it must be added in main thread. */
am791x->rx_timer_f = am791x->t_cdon;
new_rx_state(am791x, AM791X_STATE_CDON);
}
@@ -876,7 +889,8 @@ static void cdon_no_cd(am791x_t *am791x)
{
LOGP(DAM791X, LOGL_DEBUG, "Carrier is gone\n");
osmo_timer_del(&am791x->rx_timer);
/* Flag timer, because it must be deleted in main thread. */
am791x->rx_timer_f = -1;
new_rx_state(am791x, AM791X_STATE_INIT);
}
@@ -884,7 +898,8 @@ static void rx_data_done(am791x_t *am791x)
{
LOGP(DAM791X, LOGL_DEBUG, "Carrier lost\n");
osmo_timer_schedule(&am791x->rx_timer, FLOAT_TO_TIMEOUT(am791x->t_cdoff));
/* Flag timer, because it must be added in main thread. */
am791x->rx_timer_f = am791x->t_cdoff;
new_rx_state(am791x, AM791X_STATE_CDOFF);
}
@@ -906,7 +921,8 @@ static void cdoff_cd(am791x_t *am791x)
{
LOGP(DAM791X, LOGL_DEBUG, "Carrier recovered\n");
osmo_timer_del(&am791x->rx_timer);
/* Flag timer, because it must be deleted in main thread. */
am791x->rx_timer_f = -1;
new_rx_state(am791x, AM791X_STATE_DATA);
}
@@ -914,7 +930,8 @@ static void go_back_channel_rx(am791x_t *am791x)
{
LOGP(DAM791X, LOGL_DEBUG, "Enable receiver on back channel\n");
osmo_timer_schedule(&am791x->rx_timer, FLOAT_TO_TIMEOUT(am791x->t_bcdon));
/* Flag timer, because it must be added in main thread. */
am791x->rx_timer_f = am791x->t_bcdon;
new_rx_state(am791x, AM791X_STATE_BCDON);
}
@@ -936,7 +953,8 @@ static void bcdon_no_cd(am791x_t *am791x)
{
LOGP(DAM791X, LOGL_DEBUG, "Carrier is gone\n");
osmo_timer_del(&am791x->rx_timer);
/* Flag timer, because it must be deleted in main thread. */
am791x->rx_timer_f = -1;
new_rx_state(am791x, AM791X_STATE_INIT);
}
@@ -944,7 +962,8 @@ static void rx_bdata_done(am791x_t *am791x)
{
LOGP(DAM791X, LOGL_DEBUG, "Carrier lost\n");
osmo_timer_schedule(&am791x->rx_timer, FLOAT_TO_TIMEOUT(am791x->t_bcdoff));
/* Flag timer, because it must be added in main thread. */
am791x->rx_timer_f = am791x->t_bcdoff;
new_rx_state(am791x, AM791X_STATE_BCDOFF);
}
@@ -967,7 +986,8 @@ static void bcdoff_cd(am791x_t *am791x)
{
LOGP(DAM791X, LOGL_DEBUG, "Carrier recovered\n");
osmo_timer_del(&am791x->rx_timer);
/* Flag timer, because it must be deleted in main thread. */
am791x->rx_timer_f = -1;
new_rx_state(am791x, AM791X_STATE_BDATA);
}
@@ -994,7 +1014,8 @@ static void handle_rx_state(am791x_t *am791x)
break;
/* all main channel states ... */
case AM791X_STATE_CDON:
if (!osmo_timer_pending(&am791x->rx_timer)) {
/* If timer is about to be switched off, of if it already has been switched off. */
if (am791x->rx_timer_f < 0.0 || (!osmo_timer_pending(&am791x->rx_timer) && am791x->rx_timer_f == 0.0)) {
cdon_done(am791x);
break;
}
@@ -1010,7 +1031,8 @@ static void handle_rx_state(am791x_t *am791x)
}
break;
case AM791X_STATE_CDOFF:
if (!osmo_timer_pending(&am791x->rx_timer)) {
/* If timer is about to be switched off, of if it already has been switched off. */
if (am791x->rx_timer_f < 0.0 || (!osmo_timer_pending(&am791x->rx_timer) && am791x->rx_timer_f == 0.0)) {
cdoff_done(am791x);
break;
}
@@ -1021,7 +1043,8 @@ static void handle_rx_state(am791x_t *am791x)
break;
/* all back channel states ... */
case AM791X_STATE_BCDON:
if (!osmo_timer_pending(&am791x->rx_timer)) {
/* If timer is about to be switched off, of if it already has been switched off. */
if (am791x->rx_timer_f < 0.0 || (!osmo_timer_pending(&am791x->rx_timer) && am791x->rx_timer_f == 0.0)) {
bcdon_done(am791x);
break;
}
@@ -1037,7 +1060,8 @@ static void handle_rx_state(am791x_t *am791x)
}
break;
case AM791X_STATE_BCDOFF:
if (!osmo_timer_pending(&am791x->rx_timer)) {
/* If timer is about to be switched off, of if it already has been switched off. */
if (am791x->rx_timer_f < 0.0 || (!osmo_timer_pending(&am791x->rx_timer) && am791x->rx_timer_f == 0.0)) {
bcdoff_done(am791x);
break;
}
@@ -1191,8 +1215,10 @@ void am791x_reset(am791x_t *am791x)
{
LOGP(DAM791X, LOGL_INFO, "Reset!\n");
osmo_timer_del(&am791x->tx_timer);
osmo_timer_del(&am791x->rx_timer);
/* Flag timer, because it must be deleted in main thread. */
am791x->tx_timer_f = -1.0;
/* Flag timer, because it must be deleted in main thread. */
am791x->rx_timer_f = -1.0;
if (am791x->f0_tx) {
fsk_mod_cleanup(&am791x->fsk_tx);
@@ -1266,3 +1292,19 @@ void am791x_ring(am791x_t *am791x, int ring)
handle_state(am791x);
}
void am791x_add_del_timers(am791x_t *am791x)
{
/* Timers may only be processed in main thread, because libosmocore has timer lists for individual threads. */
if (am791x->tx_timer_f < 0.0)
osmo_timer_del(&am791x->tx_timer);
if (am791x->tx_timer_f > 0.0)
osmo_timer_schedule(&am791x->tx_timer, FLOAT_TO_TIMEOUT(am791x->tx_timer_f));
am791x->tx_timer_f = 0.0;
if (am791x->rx_timer_f < 0.0)
osmo_timer_del(&am791x->rx_timer);
if (am791x->rx_timer_f > 0.0)
osmo_timer_schedule(&am791x->rx_timer, FLOAT_TO_TIMEOUT(am791x->rx_timer_f));
am791x->rx_timer_f = 0.0;
}

View File

@@ -68,6 +68,7 @@ typedef struct am791x {
/* timers */
struct osmo_timer_list tx_timer, rx_timer;
double tx_timer_f, rx_timer_f; /* time to stat / flag to stop */
double t_rcon;
double t_rcoff;
double t_brcon;
@@ -104,4 +105,5 @@ void am791x_dtr(am791x_t *am791x, int dtr);
void am791x_rts(am791x_t *am791x, int rts);
void am791x_brts(am791x_t *am791x, int brts);
void am791x_ring(am791x_t *am791x, int ring);
void am791x_add_del_timers(am791x_t *am791x);

View File

@@ -1093,7 +1093,7 @@ static ssize_t dk_read(void *inst, char *buf, size_t size, int flags)
if (vmin && vtime) {
/* first: start timer */
if (!datenklo->vtimeout)
osmo_timer_schedule(&datenklo->vtimer, vtime/10,(vtime % 10) * 100000);
datenklo->vtimer_us = vtime * 100000; /* start timer in main loop */
/* no data: block (in blocking IO) */
if (fill == 0) {
/* special value to tell device there is no data right now, we have to block */
@@ -1106,7 +1106,7 @@ static ssize_t dk_read(void *inst, char *buf, size_t size, int flags)
}
/* enough data or timeout or nonblocking IO: stop timer and return what we have */
datenklo->vtimeout = 0;
osmo_timer_del(&datenklo->vtimer);
datenklo->vtimer_us = -1; /* stop timer in main loop */
}
/* both MIN and TIME are zero */
if (!vmin && !vtime) {
@@ -1119,7 +1119,7 @@ static ssize_t dk_read(void *inst, char *buf, size_t size, int flags)
if (!vmin && vtime) {
/* first: start timer */
if (!datenklo->vtimeout)
osmo_timer_schedule(&datenklo->vtimer, vtime/10,(vtime % 10) * 100000);
datenklo->vtimer_us = vtime * 100000; /* start timer in main loop */
if (fill == 0) {
/* no data and no timeout: block (in blocking IO) */
if (!datenklo->vtimeout) {
@@ -1132,7 +1132,7 @@ static ssize_t dk_read(void *inst, char *buf, size_t size, int flags)
}
/* data: stop timer and return what we have */
datenklo->vtimeout = 0;
osmo_timer_del(&datenklo->vtimer);
datenklo->vtimer_us = -1; /* stop timer in main loop */
}
/* MIN is nonzero, TIME is zero */
if (vmin && !vtime) {
@@ -1522,7 +1522,15 @@ void datenklo_main(datenklo_t *datenklo, int loopback)
if (num_chan > 1)
process_auto_rts(datenklo->slave);
/* process timers */
/* Timers may only be processed in main thread, because libosmocore has timer lists for individual threads. */
if (datenklo->vtimer_us < 0)
osmo_timer_del(&datenklo->vtimer);
if (datenklo->vtimer_us > 0)
osmo_timer_schedule(&datenklo->vtimer, datenklo->vtimer_us / 1000000,datenklo->vtimer_us % 1000000);
datenklo->vtimer_us = 0;
am791x_add_del_timers(&datenklo->am791x);
osmo_select_main(1);
#ifdef HAVE_ALSA

View File

@@ -53,6 +53,7 @@ typedef struct datenklo {
int auto_rts_cd; /* CD was indicated */
int output_off; /* output stopped by flow control */
struct osmo_timer_list vtimer; /* VTIME timer */
int vtimer_us; /* time to stat / flag to stop */
int vtimeout; /* when timeout has fired */
/* data fifos */