Clean exit of vrtsim client if server is stopped first
Force exit in case current sample is not modified by the server with 2s.
This commit is contained in:
@@ -223,12 +223,12 @@ void shm_td_iq_channel_produce_samples(ShmTDIQChannel *channel, size_t num_sampl
|
|||||||
mutexunlock(data->mutex);
|
mutexunlock(data->mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
void shm_td_iq_channel_wait(ShmTDIQChannel *channel, uint64_t timestamp, uint64_t timeout_uS)
|
int shm_td_iq_channel_wait(ShmTDIQChannel *channel, uint64_t timestamp, uint64_t timeout_uS)
|
||||||
{
|
{
|
||||||
ShmTDIQChannelData *data = channel->data;
|
ShmTDIQChannelData *data = channel->data;
|
||||||
size_t current_timestamp = data->timestamp;
|
size_t current_timestamp = data->timestamp;
|
||||||
if (current_timestamp >= timestamp) {
|
if (current_timestamp >= timestamp) {
|
||||||
return;
|
return 0;
|
||||||
}
|
}
|
||||||
if (timeout_uS == 0) {
|
if (timeout_uS == 0) {
|
||||||
mutexlock(data->mutex);
|
mutexlock(data->mutex);
|
||||||
@@ -241,8 +241,7 @@ void shm_td_iq_channel_wait(ShmTDIQChannel *channel, uint64_t timestamp, uint64_
|
|||||||
struct timespec ts = {.tv_sec = 0, .tv_nsec = 0};
|
struct timespec ts = {.tv_sec = 0, .tv_nsec = 0};
|
||||||
if (clock_gettime(CLOCK_REALTIME, &ts) != 0) {
|
if (clock_gettime(CLOCK_REALTIME, &ts) != 0) {
|
||||||
fprintf(stderr, "Error: clock_gettime failed: %s\n", strerror(errno));
|
fprintf(stderr, "Error: clock_gettime failed: %s\n", strerror(errno));
|
||||||
channel->abort = true;
|
return 1;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ts.tv_sec += timeout_uS / 1000000; // Convert microseconds to seconds
|
ts.tv_sec += timeout_uS / 1000000; // Convert microseconds to seconds
|
||||||
@@ -252,19 +251,20 @@ void shm_td_iq_channel_wait(ShmTDIQChannel *channel, uint64_t timestamp, uint64_
|
|||||||
while (current_timestamp < timestamp && !channel->abort) {
|
while (current_timestamp < timestamp && !channel->abort) {
|
||||||
int ret = pthread_cond_timedwait(&data->cond, &data->mutex, &ts);
|
int ret = pthread_cond_timedwait(&data->cond, &data->mutex, &ts);
|
||||||
if (ret == ETIMEDOUT) {
|
if (ret == ETIMEDOUT) {
|
||||||
channel->abort = true;
|
fprintf(stderr, "Error: Timed out waiting for samples.\n");
|
||||||
fprintf(stderr, "Error: Timed out waiting for samples. Aborting vrtsim\n");\
|
mutexunlock(data->mutex);
|
||||||
break;
|
return 1;
|
||||||
} else if (ret != 0) {
|
} else if (ret != 0) {
|
||||||
channel->abort = true;
|
|
||||||
fprintf(stderr, "Error: pthread_cond_timedwait failed: %s\n", strerror(ret));
|
fprintf(stderr, "Error: pthread_cond_timedwait failed: %s\n", strerror(ret));
|
||||||
break;
|
mutexunlock(data->mutex);
|
||||||
|
return 1;
|
||||||
} else {
|
} else {
|
||||||
current_timestamp = data->timestamp;
|
current_timestamp = data->timestamp;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mutexunlock(data->mutex);
|
mutexunlock(data->mutex);
|
||||||
}
|
}
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t shm_td_iq_channel_get_current_sample(const ShmTDIQChannel *channel)
|
uint64_t shm_td_iq_channel_get_current_sample(const ShmTDIQChannel *channel)
|
||||||
|
|||||||
@@ -120,8 +120,10 @@ void shm_td_iq_channel_produce_samples(ShmTDIQChannel *channel, uint64_t num_sam
|
|||||||
* @param channel The ShmTDIQChannel structure.
|
* @param channel The ShmTDIQChannel structure.
|
||||||
* @param timestamp The timestamp for which to wait.
|
* @param timestamp The timestamp for which to wait.
|
||||||
* @param timeout_uS The timeout in microseconds to wait for the sample. 0 means wait indefinitely.
|
* @param timeout_uS The timeout in microseconds to wait for the sample. 0 means wait indefinitely.
|
||||||
|
*
|
||||||
|
* @return 0 if the sample is available, 1 if timed out
|
||||||
*/
|
*/
|
||||||
void shm_td_iq_channel_wait(ShmTDIQChannel *channel, uint64_t timestamp, uint64_t timeout_uS);
|
int shm_td_iq_channel_wait(ShmTDIQChannel *channel, uint64_t timestamp, uint64_t timeout_uS);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Aborts the IQ channel causing the wait to return immediately
|
* @brief Aborts the IQ channel causing the wait to return immediately
|
||||||
|
|||||||
+29
-6
@@ -223,6 +223,7 @@ static void *vrtsim_timing_job(void *arg)
|
|||||||
samples_to_produce += 1;
|
samples_to_produce += 1;
|
||||||
leftover_samples -= 1;
|
leftover_samples -= 1;
|
||||||
}
|
}
|
||||||
|
AssertFatal(samples_to_produce >= 0, "Negative samples to produce: %f\n", samples_to_produce);
|
||||||
shm_td_iq_channel_produce_samples(vrtsim_state->channel, samples_to_produce);
|
shm_td_iq_channel_produce_samples(vrtsim_state->channel, samples_to_produce);
|
||||||
usleep(1);
|
usleep(1);
|
||||||
}
|
}
|
||||||
@@ -544,6 +545,12 @@ static int vrtsim_write_with_chanmod(vrtsim_state_t *vrtsim_state,
|
|||||||
|
|
||||||
static int vrtsim_write(openair0_device *device, openair0_timestamp timestamp, void **samplesVoid, int nsamps, int nbAnt, int flags)
|
static int vrtsim_write(openair0_device *device, openair0_timestamp timestamp, void **samplesVoid, int nsamps, int nbAnt, int flags)
|
||||||
{
|
{
|
||||||
|
AssertFatal(nsamps > 0, "Number of samples must be greater than 0\n");
|
||||||
|
AssertFatal(nbAnt > 0 && nbAnt <= MAX_NUM_ANTENNAS_TX,
|
||||||
|
"Number of antennas %d must be between 1 and %d\n",
|
||||||
|
nbAnt,
|
||||||
|
MAX_NUM_ANTENNAS_TX);
|
||||||
|
AssertFatal(timestamp >= 0, "Timestamp must be non-negative, got %ld\n", timestamp);
|
||||||
timestamp -= device->openair0_cfg->command_line_sample_advance;
|
timestamp -= device->openair0_cfg->command_line_sample_advance;
|
||||||
vrtsim_state_t *vrtsim_state = (vrtsim_state_t *)device->priv;
|
vrtsim_state_t *vrtsim_state = (vrtsim_state_t *)device->priv;
|
||||||
bool channel_modelling = vrtsim_state->chanmod || vrtsim_state->taps_socket;
|
bool channel_modelling = vrtsim_state->chanmod || vrtsim_state->taps_socket;
|
||||||
@@ -555,13 +562,29 @@ static int vrtsim_read(openair0_device *device, openair0_timestamp *ptimestamp,
|
|||||||
{
|
{
|
||||||
vrtsim_state_t *vrtsim_state = (vrtsim_state_t *)device->priv;
|
vrtsim_state_t *vrtsim_state = (vrtsim_state_t *)device->priv;
|
||||||
if (shm_td_iq_channel_is_aborted(vrtsim_state->channel)) {
|
if (shm_td_iq_channel_is_aborted(vrtsim_state->channel)) {
|
||||||
for (int i = 0; i < nbAnt; i++) {
|
return 0;
|
||||||
memset(samplesVoid[i], 0, sizeof(c16_t) * nsamps);
|
|
||||||
}
|
|
||||||
return nsamps;
|
|
||||||
}
|
}
|
||||||
uint64_t timeout_uS = 2 * 1000 * 1000 / vrtsim_state->timescale; // 2 seconds in uS
|
if (vrtsim_state->role == ROLE_SERVER) {
|
||||||
shm_td_iq_channel_wait(vrtsim_state->channel, vrtsim_state->last_received_sample + nsamps, timeout_uS);
|
uint64_t timeout_uS = 0; // 0 means no timeout
|
||||||
|
shm_td_iq_channel_wait(vrtsim_state->channel, vrtsim_state->last_received_sample + nsamps, timeout_uS);
|
||||||
|
} else {
|
||||||
|
uint64_t start_sample = shm_td_iq_channel_get_current_sample(vrtsim_state->channel);
|
||||||
|
uint64_t timeout_uS = 2 * 1000 * 1000; // 2 seconds timeout waiting for sample number to change
|
||||||
|
//
|
||||||
|
while (shm_td_iq_channel_wait(vrtsim_state->channel, vrtsim_state->last_received_sample + nsamps, timeout_uS) == 1) {
|
||||||
|
uint64_t sample = shm_td_iq_channel_get_current_sample(vrtsim_state->channel);
|
||||||
|
if (sample == start_sample) {
|
||||||
|
LOG_E(HW,
|
||||||
|
"VRTSIM: Read timeout waiting for sample %lu to change, aborting channel\n",
|
||||||
|
vrtsim_state->last_received_sample + nsamps);
|
||||||
|
shm_td_iq_channel_abort(vrtsim_state->channel);
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
start_sample = sample;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int ret = shm_td_iq_channel_rx(vrtsim_state->channel, vrtsim_state->last_received_sample, nsamps, 0, samplesVoid[0]);
|
int ret = shm_td_iq_channel_rx(vrtsim_state->channel, vrtsim_state->last_received_sample, nsamps, 0, samplesVoid[0]);
|
||||||
if (ret == CHANNEL_ERROR_TOO_LATE) {
|
if (ret == CHANNEL_ERROR_TOO_LATE) {
|
||||||
vrtsim_state->rx_samples_late += nsamps;
|
vrtsim_state->rx_samples_late += nsamps;
|
||||||
|
|||||||
Reference in New Issue
Block a user