mirror of https://github.com/PentHertz/srsLTE.git
Fix concurrency bug in ZMQ during srate change (#954)
The bug was manifesting as buffer overflow in 20 MHz 2x2 CA
This commit is contained in:
parent
d8d10daebe
commit
be82e1f368
|
@ -64,6 +64,7 @@ typedef struct {
|
||||||
|
|
||||||
pthread_mutex_t tx_config_mutex;
|
pthread_mutex_t tx_config_mutex;
|
||||||
pthread_mutex_t rx_config_mutex;
|
pthread_mutex_t rx_config_mutex;
|
||||||
|
pthread_mutex_t decim_mutex;
|
||||||
} rf_zmq_handler_t;
|
} rf_zmq_handler_t;
|
||||||
|
|
||||||
void update_rates(rf_zmq_handler_t* handler, double srate);
|
void update_rates(rf_zmq_handler_t* handler, double srate);
|
||||||
|
@ -242,6 +243,9 @@ int rf_zmq_open_multi(char* args, void** h, uint32_t nof_channels)
|
||||||
if (pthread_mutex_init(&handler->rx_config_mutex, NULL)) {
|
if (pthread_mutex_init(&handler->rx_config_mutex, NULL)) {
|
||||||
perror("Mutex init");
|
perror("Mutex init");
|
||||||
}
|
}
|
||||||
|
if (pthread_mutex_init(&handler->decim_mutex, NULL)) {
|
||||||
|
perror("Mutex init");
|
||||||
|
}
|
||||||
|
|
||||||
// parse args
|
// parse args
|
||||||
if (args && strlen(args)) {
|
if (args && strlen(args)) {
|
||||||
|
@ -524,6 +528,7 @@ int rf_zmq_close(void* h)
|
||||||
|
|
||||||
pthread_mutex_destroy(&handler->tx_config_mutex);
|
pthread_mutex_destroy(&handler->tx_config_mutex);
|
||||||
pthread_mutex_destroy(&handler->rx_config_mutex);
|
pthread_mutex_destroy(&handler->rx_config_mutex);
|
||||||
|
pthread_mutex_destroy(&handler->decim_mutex);
|
||||||
|
|
||||||
// Free all
|
// Free all
|
||||||
free(handler);
|
free(handler);
|
||||||
|
@ -533,6 +538,7 @@ int rf_zmq_close(void* h)
|
||||||
|
|
||||||
void update_rates(rf_zmq_handler_t* handler, double srate)
|
void update_rates(rf_zmq_handler_t* handler, double srate)
|
||||||
{
|
{
|
||||||
|
pthread_mutex_lock(&handler->decim_mutex);
|
||||||
if (handler) {
|
if (handler) {
|
||||||
// Decimation must be full integer
|
// Decimation must be full integer
|
||||||
if (((uint64_t)handler->base_srate % (uint64_t)srate) == 0) {
|
if (((uint64_t)handler->base_srate % (uint64_t)srate) == 0) {
|
||||||
|
@ -549,6 +555,7 @@ void update_rates(rf_zmq_handler_t* handler, double srate)
|
||||||
handler->base_srate / 1e6,
|
handler->base_srate / 1e6,
|
||||||
handler->decim_factor);
|
handler->decim_factor);
|
||||||
}
|
}
|
||||||
|
pthread_mutex_unlock(&handler->decim_mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
double rf_zmq_set_rx_srate(void* h, double srate)
|
double rf_zmq_set_rx_srate(void* h, double srate)
|
||||||
|
@ -715,11 +722,6 @@ int rf_zmq_recv_with_time_multi(void* h,
|
||||||
if (h) {
|
if (h) {
|
||||||
rf_zmq_handler_t* handler = (rf_zmq_handler_t*)h;
|
rf_zmq_handler_t* handler = (rf_zmq_handler_t*)h;
|
||||||
|
|
||||||
uint32_t nbytes = NSAMPLES2NBYTES(nsamples * handler->decim_factor);
|
|
||||||
uint32_t nsamples_baserate = nsamples * handler->decim_factor;
|
|
||||||
|
|
||||||
rf_zmq_info(handler->id, "Rx %d samples (%d B)\n", nsamples, nbytes);
|
|
||||||
|
|
||||||
// Map ports to data buffers according to the selected frequencies
|
// Map ports to data buffers according to the selected frequencies
|
||||||
pthread_mutex_lock(&handler->rx_config_mutex);
|
pthread_mutex_lock(&handler->rx_config_mutex);
|
||||||
cf_t* buffers[SRSLTE_MAX_PORTS] = {}; // Buffer pointers, NULL if unmatched
|
cf_t* buffers[SRSLTE_MAX_PORTS] = {}; // Buffer pointers, NULL if unmatched
|
||||||
|
@ -743,6 +745,16 @@ int rf_zmq_recv_with_time_multi(void* h,
|
||||||
}
|
}
|
||||||
pthread_mutex_unlock(&handler->rx_config_mutex);
|
pthread_mutex_unlock(&handler->rx_config_mutex);
|
||||||
|
|
||||||
|
// Protect the access to decim_factor since is a shared variable
|
||||||
|
pthread_mutex_lock(&handler->decim_mutex);
|
||||||
|
uint32_t decim_factor = handler->decim_factor;
|
||||||
|
pthread_mutex_unlock(&handler->decim_mutex);
|
||||||
|
|
||||||
|
uint32_t nbytes = NSAMPLES2NBYTES(nsamples * decim_factor);
|
||||||
|
uint32_t nsamples_baserate = nsamples * decim_factor;
|
||||||
|
|
||||||
|
rf_zmq_info(handler->id, "Rx %d samples (%d B)\n", nsamples, nbytes);
|
||||||
|
|
||||||
// set timestamp for this reception
|
// set timestamp for this reception
|
||||||
if (secs != NULL && frac_secs != NULL) {
|
if (secs != NULL && frac_secs != NULL) {
|
||||||
srslte_timestamp_t ts = {};
|
srslte_timestamp_t ts = {};
|
||||||
|
@ -792,7 +804,7 @@ int rf_zmq_recv_with_time_multi(void* h,
|
||||||
|
|
||||||
// Iterate channels
|
// Iterate channels
|
||||||
for (uint32_t i = 0; i < handler->nof_channels; i++) {
|
for (uint32_t i = 0; i < handler->nof_channels; i++) {
|
||||||
cf_t* ptr = (handler->decim_factor != 1 || buffers[i] == NULL) ? handler->buffer_decimation[i] : buffers[i];
|
cf_t* ptr = (decim_factor != 1 || buffers[i] == NULL) ? handler->buffer_decimation[i] : buffers[i];
|
||||||
|
|
||||||
// Completed condition
|
// Completed condition
|
||||||
if (count[i] < nsamples_baserate && handler->receiver[i].running) {
|
if (count[i] < nsamples_baserate && handler->receiver[i].running) {
|
||||||
|
@ -843,7 +855,7 @@ int rf_zmq_recv_with_time_multi(void* h,
|
||||||
NBYTES2NSAMPLES(srslte_ringbuffer_status(&handler->receiver[0].ringbuffer)));
|
NBYTES2NSAMPLES(srslte_ringbuffer_status(&handler->receiver[0].ringbuffer)));
|
||||||
|
|
||||||
// decimate if needed
|
// decimate if needed
|
||||||
if (handler->decim_factor != 1) {
|
if (decim_factor != 1) {
|
||||||
for (uint32_t c = 0; c < handler->nof_channels; c++) {
|
for (uint32_t c = 0; c < handler->nof_channels; c++) {
|
||||||
// skip if buffer is not available
|
// skip if buffer is not available
|
||||||
if (buffers[c]) {
|
if (buffers[c]) {
|
||||||
|
@ -853,7 +865,7 @@ int rf_zmq_recv_with_time_multi(void* h,
|
||||||
for (uint32_t i = 0, n = 0; i < nsamples; i++) {
|
for (uint32_t i = 0, n = 0; i < nsamples; i++) {
|
||||||
// Averaging decimation
|
// Averaging decimation
|
||||||
cf_t avg = 0.0f;
|
cf_t avg = 0.0f;
|
||||||
for (int j = 0; j < handler->decim_factor; j++, n++) {
|
for (int j = 0; j < decim_factor; j++, n++) {
|
||||||
avg += ptr[n];
|
avg += ptr[n];
|
||||||
}
|
}
|
||||||
dst[i] = avg;
|
dst[i] = avg;
|
||||||
|
@ -861,7 +873,7 @@ int rf_zmq_recv_with_time_multi(void* h,
|
||||||
|
|
||||||
rf_zmq_info(handler->id,
|
rf_zmq_info(handler->id,
|
||||||
" - re-adjust bytes due to %dx decimation %d --> %d samples)\n",
|
" - re-adjust bytes due to %dx decimation %d --> %d samples)\n",
|
||||||
handler->decim_factor,
|
decim_factor,
|
||||||
nsamples_baserate,
|
nsamples_baserate,
|
||||||
nsamples);
|
nsamples);
|
||||||
}
|
}
|
||||||
|
@ -918,14 +930,6 @@ int rf_zmq_send_timed_multi(void* h,
|
||||||
|
|
||||||
if (h && data && nsamples > 0) {
|
if (h && data && nsamples > 0) {
|
||||||
rf_zmq_handler_t* handler = (rf_zmq_handler_t*)h;
|
rf_zmq_handler_t* handler = (rf_zmq_handler_t*)h;
|
||||||
uint32_t nbytes = NSAMPLES2NBYTES(nsamples);
|
|
||||||
uint32_t nsamples_baseband = nsamples * handler->decim_factor;
|
|
||||||
uint32_t nbytes_baseband = NSAMPLES2NBYTES(nsamples_baseband);
|
|
||||||
|
|
||||||
if (nbytes_baseband > ZMQ_MAX_BUFFER_SIZE) {
|
|
||||||
fprintf(stderr, "Error: trying to transmit too many samples (%d > %zu).\n", nbytes, ZMQ_MAX_BUFFER_SIZE);
|
|
||||||
goto clean_exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Map ports to data buffers according to the selected frequencies
|
// Map ports to data buffers according to the selected frequencies
|
||||||
pthread_mutex_lock(&handler->tx_config_mutex);
|
pthread_mutex_lock(&handler->tx_config_mutex);
|
||||||
|
@ -945,6 +949,19 @@ int rf_zmq_send_timed_multi(void* h,
|
||||||
}
|
}
|
||||||
pthread_mutex_unlock(&handler->tx_config_mutex);
|
pthread_mutex_unlock(&handler->tx_config_mutex);
|
||||||
|
|
||||||
|
// Protect the access to decim_factor since is a shared variable
|
||||||
|
pthread_mutex_lock(&handler->decim_mutex);
|
||||||
|
uint32_t decim_factor = handler->decim_factor;
|
||||||
|
pthread_mutex_unlock(&handler->decim_mutex);
|
||||||
|
|
||||||
|
uint32_t nbytes = NSAMPLES2NBYTES(nsamples);
|
||||||
|
uint32_t nsamples_baseband = nsamples * decim_factor;
|
||||||
|
uint32_t nbytes_baseband = NSAMPLES2NBYTES(nsamples_baseband);
|
||||||
|
if (nbytes_baseband > ZMQ_MAX_BUFFER_SIZE) {
|
||||||
|
fprintf(stderr, "Error: trying to transmit too many samples (%d > %zu).\n", nbytes, ZMQ_MAX_BUFFER_SIZE);
|
||||||
|
goto clean_exit;
|
||||||
|
}
|
||||||
|
|
||||||
rf_zmq_info(handler->id, "Tx %d samples (%d B)\n", nsamples, nbytes);
|
rf_zmq_info(handler->id, "Tx %d samples (%d B)\n", nsamples, nbytes);
|
||||||
|
|
||||||
// return if transmitter is switched off
|
// return if transmitter is switched off
|
||||||
|
@ -981,13 +998,13 @@ int rf_zmq_send_timed_multi(void* h,
|
||||||
for (int i = 0; i < handler->nof_channels; i++) {
|
for (int i = 0; i < handler->nof_channels; i++) {
|
||||||
if (buffers[i] != NULL) {
|
if (buffers[i] != NULL) {
|
||||||
// Select buffer pointer depending on interpolation
|
// Select buffer pointer depending on interpolation
|
||||||
cf_t* buf = (handler->decim_factor != 1) ? handler->buffer_tx : buffers[i];
|
cf_t* buf = (decim_factor != 1) ? handler->buffer_tx : buffers[i];
|
||||||
|
|
||||||
// Interpolate if required
|
// Interpolate if required
|
||||||
if (handler->decim_factor != 1) {
|
if (decim_factor != 1) {
|
||||||
rf_zmq_info(handler->id,
|
rf_zmq_info(handler->id,
|
||||||
" - re-adjust bytes due to %dx interpolation %d --> %d samples)\n",
|
" - re-adjust bytes due to %dx interpolation %d --> %d samples)\n",
|
||||||
handler->decim_factor,
|
decim_factor,
|
||||||
nsamples,
|
nsamples,
|
||||||
nsamples_baseband);
|
nsamples_baseband);
|
||||||
|
|
||||||
|
@ -995,7 +1012,7 @@ int rf_zmq_send_timed_multi(void* h,
|
||||||
cf_t* src = data[i];
|
cf_t* src = data[i];
|
||||||
for (int k = 0; k < nsamples; k++) {
|
for (int k = 0; k < nsamples; k++) {
|
||||||
// perform zero order hold
|
// perform zero order hold
|
||||||
for (int j = 0; j < handler->decim_factor; j++, n++) {
|
for (int j = 0; j < decim_factor; j++, n++) {
|
||||||
buf[n] = src[k];
|
buf[n] = src[k];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -374,8 +374,12 @@ void sync::run_thread()
|
||||||
|
|
||||||
cf_t* dummy_buffer[SRSLTE_MAX_PORTS];
|
cf_t* dummy_buffer[SRSLTE_MAX_PORTS];
|
||||||
uint32_t nof_rf_channels = worker_com->args->nof_rf_channels * worker_com->args->nof_rx_ant;
|
uint32_t nof_rf_channels = worker_com->args->nof_rf_channels * worker_com->args->nof_rx_ant;
|
||||||
|
if (nof_rf_channels > SRSLTE_MAX_PORTS) {
|
||||||
|
fprintf(stderr, "Fatal error: nof_rf_channels x nof_rx_ant must be lower than %d\n", SRSLTE_MAX_PORTS);
|
||||||
|
return;
|
||||||
|
}
|
||||||
for (uint32_t i = 0; i < nof_rf_channels; i++) {
|
for (uint32_t i = 0; i < nof_rf_channels; i++) {
|
||||||
dummy_buffer[i] = (cf_t*)malloc(sizeof(cf_t) * SRSLTE_SF_LEN_PRB(100));
|
dummy_buffer[i] = (cf_t*)srslte_vec_cf_malloc(3 * SRSLTE_SF_LEN_PRB(100));
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t prach_nof_sf = 0;
|
uint32_t prach_nof_sf = 0;
|
||||||
|
|
Loading…
Reference in New Issue