SDR: Fixed stack overflow by allocating memory instead of local buffers

This commit is contained in:
Andreas Eversberg
2017-08-27 10:49:19 +02:00
parent eb0c123433
commit 05c516ca16

View File

@@ -59,6 +59,11 @@ typedef struct sdr {
wave_rec_t wave_tx_rec; wave_rec_t wave_tx_rec;
wave_play_t wave_rx_play; wave_play_t wave_rx_play;
wave_play_t wave_tx_play; wave_play_t wave_tx_play;
float *modbuff; /* buffer for FM transmodulation */
sample_t *modbuff_I;
sample_t *modbuff_Q;
sample_t *wavespl0; /* sample buffer for wave generation */
sample_t *wavespl1;
} sdr_t; } sdr_t;
typedef struct sdr_thread { typedef struct sdr_thread {
@@ -66,6 +71,7 @@ typedef struct sdr_thread {
volatile int running, exit; /* flags to control exit of threads */ volatile int running, exit; /* flags to control exit of threads */
int buffer_size; int buffer_size;
volatile float *buffer; volatile float *buffer;
float *buffer2;
volatile int in, out; /* in and out pointers (atomic, so no locking required) */ volatile int in, out; /* in and out pointers (atomic, so no locking required) */
int max_fill; /* measure maximum buffer fill */ int max_fill; /* measure maximum buffer fill */
double max_fill_timer; /* timer to display/reset maximum fill */ double max_fill_timer; /* timer to display/reset maximum fill */
@@ -140,6 +146,7 @@ void *sdr_open(const char __attribute__((__unused__)) *audiodev, double *tx_freq
sdr_oversample = sdr_samplerate / samplerate; sdr_oversample = sdr_samplerate / samplerate;
sdr_threads = 1; sdr_threads = 1;
} }
if (sdr_threads) { if (sdr_threads) {
memset(&sdr_thread_read, 0, sizeof(sdr_thread_read)); memset(&sdr_thread_read, 0, sizeof(sdr_thread_read));
sdr_thread_read.buffer_size = sdr_latspl * 2 * sdr_oversample + 2; sdr_thread_read.buffer_size = sdr_latspl * 2 * sdr_oversample + 2;
@@ -148,6 +155,11 @@ void *sdr_open(const char __attribute__((__unused__)) *audiodev, double *tx_freq
PDEBUG(DSDR, DEBUG_ERROR, "No mem!\n"); PDEBUG(DSDR, DEBUG_ERROR, "No mem!\n");
return NULL; return NULL;
} }
sdr_thread_read.buffer2 = calloc(sdr_thread_read.buffer_size, sizeof(*sdr_thread_read.buffer2));
if (!sdr_thread_read.buffer2) {
PDEBUG(DSDR, DEBUG_ERROR, "No mem!\n");
return NULL;
}
sdr_thread_read.in = sdr_thread_read.out = 0; sdr_thread_read.in = sdr_thread_read.out = 0;
memset(&sdr_thread_write, 0, sizeof(sdr_thread_write)); memset(&sdr_thread_write, 0, sizeof(sdr_thread_write));
sdr_thread_write.buffer_size = sdr_latspl * 2 + 2; sdr_thread_write.buffer_size = sdr_latspl * 2 + 2;
@@ -156,6 +168,11 @@ void *sdr_open(const char __attribute__((__unused__)) *audiodev, double *tx_freq
PDEBUG(DSDR, DEBUG_ERROR, "No mem!\n"); PDEBUG(DSDR, DEBUG_ERROR, "No mem!\n");
return NULL; return NULL;
} }
sdr_thread_write.buffer2 = calloc(sdr_thread_write.buffer_size * sdr_oversample, sizeof(*sdr_thread_write.buffer2));
if (!sdr_thread_write.buffer2) {
PDEBUG(DSDR, DEBUG_ERROR, "No mem!\n");
return NULL;
}
sdr_thread_write.in = sdr_thread_write.out = 0; sdr_thread_write.in = sdr_thread_write.out = 0;
} }
@@ -179,6 +196,33 @@ void *sdr_open(const char __attribute__((__unused__)) *audiodev, double *tx_freq
sdr->amplitude = 1.0 / (double)channels; sdr->amplitude = 1.0 / (double)channels;
sdr->samplerate = samplerate; sdr->samplerate = samplerate;
/* alloc fm modulation buffers */
sdr->modbuff = calloc(sdr_latspl * 2, sizeof(*sdr->modbuff));
if (!sdr->modbuff) {
PDEBUG(DSDR, DEBUG_ERROR, "NO MEM!\n");
goto error;
}
sdr->modbuff_I = calloc(sdr_latspl, sizeof(*sdr->modbuff_I));
if (!sdr->modbuff_I) {
PDEBUG(DSDR, DEBUG_ERROR, "NO MEM!\n");
goto error;
}
sdr->modbuff_Q = calloc(sdr_latspl, sizeof(*sdr->modbuff_Q));
if (!sdr->modbuff_Q) {
PDEBUG(DSDR, DEBUG_ERROR, "NO MEM!\n");
goto error;
}
sdr->wavespl0 = calloc(sdr_latspl, sizeof(*sdr->wavespl0));
if (!sdr->wavespl0) {
PDEBUG(DSDR, DEBUG_ERROR, "NO MEM!\n");
goto error;
}
sdr->wavespl1 = calloc(sdr_latspl, sizeof(*sdr->wavespl1));
if (!sdr->wavespl1) {
PDEBUG(DSDR, DEBUG_ERROR, "NO MEM!\n");
goto error;
}
/* special case where we use a paging frequency */ /* special case where we use a paging frequency */
if (paging_frequency) { if (paging_frequency) {
/* add extra paging channel */ /* add extra paging channel */
@@ -372,25 +416,24 @@ static void *sdr_write_child(void __attribute__((__unused__)) *arg)
} }
num = fill / 2; num = fill / 2;
if (num) { if (num) {
float buff[num * 2 * sdr_oversample];
#ifdef DEBUG_BUFFER #ifdef DEBUG_BUFFER
printf("Thread found %d samples in write buffer and forwards them to SDR.\n", num); printf("Thread found %d samples in write buffer and forwards them to SDR.\n", num);
#endif #endif
out = sdr_thread_write.out; out = sdr_thread_write.out;
for (s = 0, ss = 0; s < num; s++) { for (s = 0, ss = 0; s < num; s++) {
for (o = 0; o < sdr_oversample; o++) { for (o = 0; o < sdr_oversample; o++) {
buff[ss++] = sdr_thread_write.buffer[out]; sdr_thread_write.buffer2[ss++] = sdr_thread_write.buffer[out];
buff[ss++] = sdr_thread_write.buffer[out + 1]; sdr_thread_write.buffer2[ss++] = sdr_thread_write.buffer[out + 1];
} }
out = (out + 2) % sdr_thread_write.buffer_size; out = (out + 2) % sdr_thread_write.buffer_size;
} }
#ifdef HAVE_UHD #ifdef HAVE_UHD
if (sdr_use_uhd) if (sdr_use_uhd)
uhd_send(buff, num * sdr_oversample); uhd_send(sdr_thread_write.buffer2, num * sdr_oversample);
#endif #endif
#ifdef HAVE_SOAPY #ifdef HAVE_SOAPY
if (sdr_use_soapy) if (sdr_use_soapy)
soapy_send(buff, num * sdr_oversample); soapy_send(sdr_thread_write.buffer2, num * sdr_oversample);
#endif #endif
sdr_thread_write.out = out; sdr_thread_write.out = out;
} }
@@ -416,14 +459,13 @@ static void *sdr_read_child(void __attribute__((__unused__)) *arg)
space = (sdr_thread_read.out - sdr_thread_read.in - 2 + sdr_thread_read.buffer_size) % sdr_thread_read.buffer_size; space = (sdr_thread_read.out - sdr_thread_read.in - 2 + sdr_thread_read.buffer_size) % sdr_thread_read.buffer_size;
num = space / 2; num = space / 2;
if (num) { if (num) {
float buff[num * 2];
#ifdef HAVE_UHD #ifdef HAVE_UHD
if (sdr_use_uhd) if (sdr_use_uhd)
count = uhd_receive(buff, num); count = uhd_receive(sdr_thread_read.buffer2, num);
#endif #endif
#ifdef HAVE_SOAPY #ifdef HAVE_SOAPY
if (sdr_use_soapy) if (sdr_use_soapy)
count = soapy_receive(buff, num); count = soapy_receive(sdr_thread_read.buffer2, num);
#endif #endif
if (count > 0) { if (count > 0) {
#ifdef DEBUG_BUFFER #ifdef DEBUG_BUFFER
@@ -431,8 +473,8 @@ static void *sdr_read_child(void __attribute__((__unused__)) *arg)
#endif #endif
in = sdr_thread_read.in; in = sdr_thread_read.in;
for (s = 0, ss = 0; s < count; s++) { for (s = 0, ss = 0; s < count; s++) {
sdr_thread_read.buffer[in++] = buff[ss++]; sdr_thread_read.buffer[in++] = sdr_thread_read.buffer2[ss++];
sdr_thread_read.buffer[in++] = buff[ss++]; sdr_thread_read.buffer[in++] = sdr_thread_read.buffer2[ss++];
in %= sdr_thread_read.buffer_size; in %= sdr_thread_read.buffer_size;
} }
sdr_thread_read.in = in; sdr_thread_read.in = in;
@@ -523,8 +565,12 @@ void sdr_close(void *inst)
if (sdr_thread_read.buffer) if (sdr_thread_read.buffer)
free((void *)sdr_thread_read.buffer); free((void *)sdr_thread_read.buffer);
if (sdr_thread_read.buffer2)
free((void *)sdr_thread_read.buffer2);
if (sdr_thread_write.buffer) if (sdr_thread_write.buffer)
free((void *)sdr_thread_write.buffer); free((void *)sdr_thread_write.buffer);
if (sdr_thread_write.buffer2)
free((void *)sdr_thread_write.buffer2);
#ifdef HAVE_UHD #ifdef HAVE_UHD
if (sdr_use_uhd) if (sdr_use_uhd)
@@ -537,6 +583,11 @@ void sdr_close(void *inst)
#endif #endif
if (sdr) { if (sdr) {
free(sdr->modbuff);
free(sdr->modbuff_I);
free(sdr->modbuff_Q);
free(sdr->wavespl0);
free(sdr->wavespl1);
wave_destroy_record(&sdr->wave_rx_rec); wave_destroy_record(&sdr->wave_rx_rec);
wave_destroy_record(&sdr->wave_tx_rec); wave_destroy_record(&sdr->wave_tx_rec);
wave_destroy_playback(&sdr->wave_rx_play); wave_destroy_playback(&sdr->wave_rx_play);
@@ -560,10 +611,14 @@ void sdr_close(void *inst)
int sdr_write(void *inst, sample_t **samples, uint8_t **power, int num, enum paging_signal __attribute__((unused)) *paging_signal, int *on, int channels) int sdr_write(void *inst, sample_t **samples, uint8_t **power, int num, enum paging_signal __attribute__((unused)) *paging_signal, int *on, int channels)
{ {
sdr_t *sdr = (sdr_t *)inst; sdr_t *sdr = (sdr_t *)inst;
float buffer[num * 2], *buff = NULL; float *buff = NULL;
int c, s, ss; int c, s, ss;
int sent = 0; int sent = 0;
if (num > sdr_latspl) {
fprintf(stderr, "exceeding maximum size given by sdr_latspl, please fix!\n");
abort();
}
if (channels != sdr->channels && channels != 0) { if (channels != sdr->channels && channels != 0) {
PDEBUG(DSDR, DEBUG_ERROR, "Invalid number of channels, please fix!\n"); PDEBUG(DSDR, DEBUG_ERROR, "Invalid number of channels, please fix!\n");
abort(); abort();
@@ -571,8 +626,8 @@ int sdr_write(void *inst, sample_t **samples, uint8_t **power, int num, enum pag
/* process all channels */ /* process all channels */
if (channels) { if (channels) {
memset(buffer, 0, sizeof(buffer)); buff = sdr->modbuff;
buff = buffer; memset(buff, 0, sizeof(*buff) * num * 2);
for (c = 0; c < channels; c++) { for (c = 0; c < channels; c++) {
/* switch to paging channel, if requested */ /* switch to paging channel, if requested */
if (on[c] && sdr->paging_channel) if (on[c] && sdr->paging_channel)
@@ -585,19 +640,19 @@ int sdr_write(void *inst, sample_t **samples, uint8_t **power, int num, enum pag
} }
if (sdr->wave_tx_rec.fp) { if (sdr->wave_tx_rec.fp) {
sample_t spl[2][num], *spl_list[2] = { spl[0], spl[1] }; sample_t *spl_list[2] = { sdr->wavespl0, sdr->wavespl1 };
for (s = 0, ss = 0; s < num; s++) { for (s = 0, ss = 0; s < num; s++) {
spl[0][s] = buff[ss++]; spl_list[0][s] = buff[ss++];
spl[1][s] = buff[ss++]; spl_list[1][s] = buff[ss++];
} }
wave_write(&sdr->wave_tx_rec, spl_list, num); wave_write(&sdr->wave_tx_rec, spl_list, num);
} }
if (sdr->wave_tx_play.fp) { if (sdr->wave_tx_play.fp) {
sample_t spl[2][num], *spl_list[2] = { spl[0], spl[1] }; sample_t *spl_list[2] = { sdr->wavespl0, sdr->wavespl1 };
wave_read(&sdr->wave_tx_play, spl_list, num); wave_read(&sdr->wave_tx_play, spl_list, num);
for (s = 0, ss = 0; s < num; s++) { for (s = 0, ss = 0; s < num; s++) {
buff[ss++] = spl[0][s]; buff[ss++] = spl_list[0][s];
buff[ss++] = spl[1][s]; buff[ss++] = spl_list[1][s];
} }
} }
@@ -640,13 +695,17 @@ int sdr_write(void *inst, sample_t **samples, uint8_t **power, int num, enum pag
int sdr_read(void *inst, sample_t **samples, int num, int channels) int sdr_read(void *inst, sample_t **samples, int num, int channels)
{ {
sdr_t *sdr = (sdr_t *)inst; sdr_t *sdr = (sdr_t *)inst;
float buffer[num * 2], *buff = NULL; float *buff = NULL;
sample_t I[num], Q[num];
int count = 0; int count = 0;
int c, s, ss; int c, s, ss;
if (num > sdr_latspl) {
fprintf(stderr, "exceeding maximum size given by sdr_latspl, please fix!\n");
abort();
}
if (channels) { if (channels) {
buff = buffer; buff = sdr->modbuff;
} else { } else {
buff = (float *)samples; buff = (float *)samples;
} }
@@ -694,19 +753,19 @@ int sdr_read(void *inst, sample_t **samples, int num, int channels)
} }
if (sdr->wave_rx_rec.fp) { if (sdr->wave_rx_rec.fp) {
sample_t spl[2][count], *spl_list[2] = { spl[0], spl[1] }; sample_t *spl_list[2] = { sdr->wavespl0, sdr->wavespl1 };
for (s = 0, ss = 0; s < count; s++) { for (s = 0, ss = 0; s < count; s++) {
spl[0][s] = buff[ss++]; spl_list[0][s] = buff[ss++];
spl[1][s] = buff[ss++]; spl_list[1][s] = buff[ss++];
} }
wave_write(&sdr->wave_rx_rec, spl_list, count); wave_write(&sdr->wave_rx_rec, spl_list, count);
} }
if (sdr->wave_rx_play.fp) { if (sdr->wave_rx_play.fp) {
sample_t spl[2][count], *spl_list[2] = { spl[0], spl[1] }; sample_t *spl_list[2] = { sdr->wavespl0, sdr->wavespl1 };
wave_read(&sdr->wave_rx_play, spl_list, count); wave_read(&sdr->wave_rx_play, spl_list, count);
for (s = 0, ss = 0; s < count; s++) { for (s = 0, ss = 0; s < count; s++) {
buff[ss++] = spl[0][s]; buff[ss++] = spl_list[0][s];
buff[ss++] = spl[1][s]; buff[ss++] = spl_list[1][s];
} }
} }
display_iq(buff, count); display_iq(buff, count);
@@ -714,7 +773,7 @@ int sdr_read(void *inst, sample_t **samples, int num, int channels)
if (channels) { if (channels) {
for (c = 0; c < channels; c++) for (c = 0; c < channels; c++)
fm_demodulate_complex(&sdr->chan[c].demod, samples[c], count, buff, I, Q); fm_demodulate_complex(&sdr->chan[c].demod, samples[c], count, buff, sdr->modbuff_I, sdr->modbuff_Q);
} }
return count; return count;