Factor out sdr thread CPU monitoring
This commit is contained in:
parent
f82b7b7a8c
commit
8b21104d66
|
|
@ -382,6 +382,9 @@ static void backgroundTasks(void) {
|
||||||
interactiveShowData();
|
interactiveShowData();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// copy out reader CPU time and reset it
|
||||||
|
sdrUpdateCPUTime(&Modes.stats_current.reader_cpu);
|
||||||
|
|
||||||
// always update end time so it is current when requests arrive
|
// always update end time so it is current when requests arrive
|
||||||
Modes.stats_current.end = mstime();
|
Modes.stats_current.end = mstime();
|
||||||
|
|
||||||
|
|
@ -703,11 +706,6 @@ int main(int argc, char **argv) {
|
||||||
|
|
||||||
// Modes.data_mutex is locked, and possibly we have data.
|
// Modes.data_mutex is locked, and possibly we have data.
|
||||||
|
|
||||||
// copy out reader CPU time and reset it
|
|
||||||
add_timespecs(&Modes.reader_cpu_accumulator, &Modes.stats_current.reader_cpu, &Modes.stats_current.reader_cpu);
|
|
||||||
Modes.reader_cpu_accumulator.tv_sec = 0;
|
|
||||||
Modes.reader_cpu_accumulator.tv_nsec = 0;
|
|
||||||
|
|
||||||
if (Modes.first_free_buffer != Modes.first_filled_buffer) {
|
if (Modes.first_free_buffer != Modes.first_filled_buffer) {
|
||||||
// FIFO is not empty, process one buffer.
|
// FIFO is not empty, process one buffer.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -301,7 +301,9 @@ struct _Modes { // Internal state
|
||||||
struct mag_buf mag_buffers[MODES_MAG_BUFFERS]; // Converted magnitude buffers from RTL or file input
|
struct mag_buf mag_buffers[MODES_MAG_BUFFERS]; // Converted magnitude buffers from RTL or file input
|
||||||
unsigned first_free_buffer; // Entry in mag_buffers that will next be filled with input.
|
unsigned first_free_buffer; // Entry in mag_buffers that will next be filled with input.
|
||||||
unsigned first_filled_buffer; // Entry in mag_buffers that has valid data and will be demodulated next. If equal to next_free_buffer, there is no unprocessed data.
|
unsigned first_filled_buffer; // Entry in mag_buffers that has valid data and will be demodulated next. If equal to next_free_buffer, there is no unprocessed data.
|
||||||
struct timespec reader_cpu_accumulator; // CPU time used by the reader thread, copied out and reset by the main thread under the mutex
|
pthread_mutex_t reader_cpu_mutex; // mutex protecting reader_cpu_accumulator
|
||||||
|
struct timespec reader_cpu_accumulator; // accumulated CPU time used by the reader thread
|
||||||
|
struct timespec reader_cpu_start; // start time for the last reader thread CPU measurement
|
||||||
|
|
||||||
unsigned trailing_samples; // extra trailing samples in magnitude buffers
|
unsigned trailing_samples; // extra trailing samples in magnitude buffers
|
||||||
double sample_rate; // actual sample rate in use (in hz)
|
double sample_rate; // actual sample rate in use (in hz)
|
||||||
|
|
|
||||||
29
sdr.c
29
sdr.c
|
|
@ -168,16 +168,45 @@ static sdr_handler *current_handler()
|
||||||
|
|
||||||
bool sdrOpen()
|
bool sdrOpen()
|
||||||
{
|
{
|
||||||
|
pthread_mutex_init(&Modes.reader_cpu_mutex, NULL);
|
||||||
return current_handler()->open();
|
return current_handler()->open();
|
||||||
}
|
}
|
||||||
|
|
||||||
void sdrRun()
|
void sdrRun()
|
||||||
{
|
{
|
||||||
set_thread_name("dump1090-sdr");
|
set_thread_name("dump1090-sdr");
|
||||||
|
|
||||||
|
pthread_mutex_lock(&Modes.reader_cpu_mutex);
|
||||||
|
Modes.reader_cpu_accumulator.tv_sec = 0;
|
||||||
|
Modes.reader_cpu_accumulator.tv_nsec = 0;
|
||||||
|
start_cpu_timing(&Modes.reader_cpu_start);
|
||||||
|
pthread_mutex_unlock(&Modes.reader_cpu_mutex);
|
||||||
|
|
||||||
current_handler()->run();
|
current_handler()->run();
|
||||||
|
|
||||||
|
pthread_mutex_lock(&Modes.reader_cpu_mutex);
|
||||||
|
end_cpu_timing(&Modes.reader_cpu_start, &Modes.reader_cpu_accumulator);
|
||||||
|
pthread_mutex_unlock(&Modes.reader_cpu_mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
void sdrClose()
|
void sdrClose()
|
||||||
{
|
{
|
||||||
|
pthread_mutex_destroy(&Modes.reader_cpu_mutex);
|
||||||
current_handler()->close();
|
current_handler()->close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void sdrMonitor()
|
||||||
|
{
|
||||||
|
pthread_mutex_lock(&Modes.reader_cpu_mutex);
|
||||||
|
update_cpu_timing(&Modes.reader_cpu_start, &Modes.reader_cpu_accumulator);
|
||||||
|
pthread_mutex_unlock(&Modes.reader_cpu_mutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
void sdrUpdateCPUTime(struct timespec *addTo)
|
||||||
|
{
|
||||||
|
pthread_mutex_lock(&Modes.reader_cpu_mutex);
|
||||||
|
add_timespecs(&Modes.reader_cpu_accumulator, addTo, addTo);
|
||||||
|
Modes.reader_cpu_accumulator.tv_sec = 0;
|
||||||
|
Modes.reader_cpu_accumulator.tv_nsec = 0;
|
||||||
|
pthread_mutex_unlock(&Modes.reader_cpu_mutex);
|
||||||
|
}
|
||||||
|
|
|
||||||
5
sdr.h
5
sdr.h
|
|
@ -30,4 +30,9 @@ bool sdrOpen();
|
||||||
void sdrRun();
|
void sdrRun();
|
||||||
void sdrClose();
|
void sdrClose();
|
||||||
|
|
||||||
|
// Call periodically from the SDR read thread to update reader thread CPU stats:
|
||||||
|
void sdrMonitor();
|
||||||
|
// Retrieve CPU stats and add new CPU time to *addTo
|
||||||
|
void sdrUpdateCPUTime(struct timespec *addTo);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -300,7 +300,6 @@ bool bladeRFOpen()
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct timespec thread_cpu;
|
|
||||||
static unsigned timeouts = 0;
|
static unsigned timeouts = 0;
|
||||||
|
|
||||||
static void *handle_bladerf_samples(struct bladerf *dev,
|
static void *handle_bladerf_samples(struct bladerf *dev,
|
||||||
|
|
@ -322,6 +321,8 @@ static void *handle_bladerf_samples(struct bladerf *dev,
|
||||||
// record initial time for later sys timestamp calculation
|
// record initial time for later sys timestamp calculation
|
||||||
uint64_t entryTimestamp = mstime();
|
uint64_t entryTimestamp = mstime();
|
||||||
|
|
||||||
|
sdrMonitor();
|
||||||
|
|
||||||
pthread_mutex_lock(&Modes.data_mutex);
|
pthread_mutex_lock(&Modes.data_mutex);
|
||||||
if (Modes.exit) {
|
if (Modes.exit) {
|
||||||
pthread_mutex_unlock(&Modes.data_mutex);
|
pthread_mutex_unlock(&Modes.data_mutex);
|
||||||
|
|
@ -430,10 +431,6 @@ static void *handle_bladerf_samples(struct bladerf *dev,
|
||||||
// Push the new data to the demodulation thread
|
// Push the new data to the demodulation thread
|
||||||
pthread_mutex_lock(&Modes.data_mutex);
|
pthread_mutex_lock(&Modes.data_mutex);
|
||||||
|
|
||||||
// accumulate CPU while holding the mutex, and restart measurement
|
|
||||||
end_cpu_timing(&thread_cpu, &Modes.reader_cpu_accumulator);
|
|
||||||
start_cpu_timing(&thread_cpu);
|
|
||||||
|
|
||||||
Modes.mag_buffers[next_free_buffer].dropped = 0;
|
Modes.mag_buffers[next_free_buffer].dropped = 0;
|
||||||
Modes.mag_buffers[next_free_buffer].length = 0; // just in case
|
Modes.mag_buffers[next_free_buffer].length = 0; // just in case
|
||||||
Modes.first_free_buffer = next_free_buffer;
|
Modes.first_free_buffer = next_free_buffer;
|
||||||
|
|
@ -482,8 +479,6 @@ void bladeRFRun()
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
start_cpu_timing(&thread_cpu);
|
|
||||||
|
|
||||||
timeouts = 0; // reset to zero when we get a callback with some data
|
timeouts = 0; // reset to zero when we get a callback with some data
|
||||||
retry:
|
retry:
|
||||||
if ((status = bladerf_stream(stream, BLADERF_MODULE_RX)) < 0) {
|
if ((status = bladerf_stream(stream, BLADERF_MODULE_RX)) < 0) {
|
||||||
|
|
|
||||||
10
sdr_hackrf.c
10
sdr_hackrf.c
|
|
@ -195,8 +195,6 @@ bool hackRFOpen()
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct timespec thread_cpu;
|
|
||||||
|
|
||||||
static int handle_hackrf_samples(hackrf_transfer *transfer)
|
static int handle_hackrf_samples(hackrf_transfer *transfer)
|
||||||
{
|
{
|
||||||
struct mag_buf *outbuf;
|
struct mag_buf *outbuf;
|
||||||
|
|
@ -211,6 +209,8 @@ static int handle_hackrf_samples(hackrf_transfer *transfer)
|
||||||
static int dropping = 0;
|
static int dropping = 0;
|
||||||
static uint64_t sampleCounter = 0;
|
static uint64_t sampleCounter = 0;
|
||||||
|
|
||||||
|
sdrMonitor();
|
||||||
|
|
||||||
// Lock the data buffer variables before accessing them
|
// Lock the data buffer variables before accessing them
|
||||||
pthread_mutex_lock(&Modes.data_mutex);
|
pthread_mutex_lock(&Modes.data_mutex);
|
||||||
if (Modes.exit) {
|
if (Modes.exit) {
|
||||||
|
|
@ -271,10 +271,6 @@ static int handle_hackrf_samples(hackrf_transfer *transfer)
|
||||||
Modes.mag_buffers[next_free_buffer].length = 0; // just in case
|
Modes.mag_buffers[next_free_buffer].length = 0; // just in case
|
||||||
Modes.first_free_buffer = next_free_buffer;
|
Modes.first_free_buffer = next_free_buffer;
|
||||||
|
|
||||||
// accumulate CPU while holding the mutex, and restart measurement
|
|
||||||
end_cpu_timing(&thread_cpu, &Modes.reader_cpu_accumulator);
|
|
||||||
start_cpu_timing(&thread_cpu);
|
|
||||||
|
|
||||||
pthread_cond_signal(&Modes.data_cond);
|
pthread_cond_signal(&Modes.data_cond);
|
||||||
pthread_mutex_unlock(&Modes.data_mutex);
|
pthread_mutex_unlock(&Modes.data_mutex);
|
||||||
|
|
||||||
|
|
@ -289,8 +285,6 @@ void hackRFRun()
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
start_cpu_timing(&thread_cpu);
|
|
||||||
|
|
||||||
int status = hackrf_start_rx(HackRF.device, &handle_hackrf_samples, NULL);
|
int status = hackrf_start_rx(HackRF.device, &handle_hackrf_samples, NULL);
|
||||||
|
|
||||||
if (status != 0) {
|
if (status != 0) {
|
||||||
|
|
|
||||||
|
|
@ -179,9 +179,6 @@ void ifileRun()
|
||||||
int eof = 0;
|
int eof = 0;
|
||||||
struct timespec next_buffer_delivery;
|
struct timespec next_buffer_delivery;
|
||||||
|
|
||||||
struct timespec thread_cpu;
|
|
||||||
start_cpu_timing(&thread_cpu);
|
|
||||||
|
|
||||||
uint64_t sampleCounter = 0;
|
uint64_t sampleCounter = 0;
|
||||||
|
|
||||||
clock_gettime(CLOCK_MONOTONIC, &next_buffer_delivery);
|
clock_gettime(CLOCK_MONOTONIC, &next_buffer_delivery);
|
||||||
|
|
@ -205,6 +202,8 @@ void ifileRun()
|
||||||
lastbuf = &Modes.mag_buffers[(Modes.first_free_buffer + MODES_MAG_BUFFERS - 1) % MODES_MAG_BUFFERS];
|
lastbuf = &Modes.mag_buffers[(Modes.first_free_buffer + MODES_MAG_BUFFERS - 1) % MODES_MAG_BUFFERS];
|
||||||
pthread_mutex_unlock(&Modes.data_mutex);
|
pthread_mutex_unlock(&Modes.data_mutex);
|
||||||
|
|
||||||
|
sdrMonitor();
|
||||||
|
|
||||||
// Compute the sample timestamp for the start of the block
|
// Compute the sample timestamp for the start of the block
|
||||||
outbuf->sampleTimestamp = sampleCounter * 12e6 / Modes.sample_rate;
|
outbuf->sampleTimestamp = sampleCounter * 12e6 / Modes.sample_rate;
|
||||||
sampleCounter += MODES_MAG_BUF_SAMPLES;
|
sampleCounter += MODES_MAG_BUF_SAMPLES;
|
||||||
|
|
@ -253,9 +252,6 @@ void ifileRun()
|
||||||
// Push the new data to the main thread
|
// Push the new data to the main thread
|
||||||
pthread_mutex_lock(&Modes.data_mutex);
|
pthread_mutex_lock(&Modes.data_mutex);
|
||||||
Modes.first_free_buffer = next_free_buffer;
|
Modes.first_free_buffer = next_free_buffer;
|
||||||
// accumulate CPU while holding the mutex, and restart measurement
|
|
||||||
end_cpu_timing(&thread_cpu, &Modes.reader_cpu_accumulator);
|
|
||||||
start_cpu_timing(&thread_cpu);
|
|
||||||
pthread_cond_signal(&Modes.data_cond);
|
pthread_cond_signal(&Modes.data_cond);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -315,8 +315,6 @@ bool limesdrOpen(void)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct timespec limesdr_thread_cpu;
|
|
||||||
|
|
||||||
static void limesdrCallback(unsigned char *buf, uint32_t len, void *ctx)
|
static void limesdrCallback(unsigned char *buf, uint32_t len, void *ctx)
|
||||||
{
|
{
|
||||||
struct mag_buf *outbuf;
|
struct mag_buf *outbuf;
|
||||||
|
|
@ -331,6 +329,8 @@ static void limesdrCallback(unsigned char *buf, uint32_t len, void *ctx)
|
||||||
|
|
||||||
MODES_NOTUSED(ctx);
|
MODES_NOTUSED(ctx);
|
||||||
|
|
||||||
|
sdrMonitor();
|
||||||
|
|
||||||
// Lock the data buffer variables before accessing them
|
// Lock the data buffer variables before accessing them
|
||||||
pthread_mutex_lock(&Modes.data_mutex);
|
pthread_mutex_lock(&Modes.data_mutex);
|
||||||
if (Modes.exit) {
|
if (Modes.exit) {
|
||||||
|
|
@ -396,10 +396,6 @@ static void limesdrCallback(unsigned char *buf, uint32_t len, void *ctx)
|
||||||
Modes.mag_buffers[next_free_buffer].length = 0; // just in case
|
Modes.mag_buffers[next_free_buffer].length = 0; // just in case
|
||||||
Modes.first_free_buffer = next_free_buffer;
|
Modes.first_free_buffer = next_free_buffer;
|
||||||
|
|
||||||
// accumulate CPU while holding the mutex, and restart measurement
|
|
||||||
end_cpu_timing(&limesdr_thread_cpu, &Modes.reader_cpu_accumulator);
|
|
||||||
start_cpu_timing(&limesdr_thread_cpu);
|
|
||||||
|
|
||||||
pthread_cond_signal(&Modes.data_cond);
|
pthread_cond_signal(&Modes.data_cond);
|
||||||
pthread_mutex_unlock(&Modes.data_mutex);
|
pthread_mutex_unlock(&Modes.data_mutex);
|
||||||
}
|
}
|
||||||
|
|
@ -414,8 +410,6 @@ void limesdrRun()
|
||||||
|
|
||||||
LMS_StartStream(&LimeSDR.stream);
|
LMS_StartStream(&LimeSDR.stream);
|
||||||
|
|
||||||
start_cpu_timing(&limesdr_thread_cpu);
|
|
||||||
|
|
||||||
while (!LimeSDR.is_stop) {
|
while (!LimeSDR.is_stop) {
|
||||||
int sampleCnt = LMS_RecvStream(&LimeSDR.stream, buffer, MODES_RTL_BUF_SIZE / LimeSDR.bytes_in_sample, NULL, 1000);
|
int sampleCnt = LMS_RecvStream(&LimeSDR.stream, buffer, MODES_RTL_BUF_SIZE / LimeSDR.bytes_in_sample, NULL, 1000);
|
||||||
if (sampleCnt) {
|
if (sampleCnt) {
|
||||||
|
|
|
||||||
10
sdr_rtlsdr.c
10
sdr_rtlsdr.c
|
|
@ -265,8 +265,6 @@ bool rtlsdrOpen(void) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct timespec rtlsdr_thread_cpu;
|
|
||||||
|
|
||||||
static void rtlsdrCallback(unsigned char *buf, uint32_t len, void *ctx) {
|
static void rtlsdrCallback(unsigned char *buf, uint32_t len, void *ctx) {
|
||||||
struct mag_buf *outbuf;
|
struct mag_buf *outbuf;
|
||||||
struct mag_buf *lastbuf;
|
struct mag_buf *lastbuf;
|
||||||
|
|
@ -280,6 +278,8 @@ static void rtlsdrCallback(unsigned char *buf, uint32_t len, void *ctx) {
|
||||||
|
|
||||||
MODES_NOTUSED(ctx);
|
MODES_NOTUSED(ctx);
|
||||||
|
|
||||||
|
sdrMonitor();
|
||||||
|
|
||||||
// Lock the data buffer variables before accessing them
|
// Lock the data buffer variables before accessing them
|
||||||
pthread_mutex_lock(&Modes.data_mutex);
|
pthread_mutex_lock(&Modes.data_mutex);
|
||||||
if (Modes.exit) {
|
if (Modes.exit) {
|
||||||
|
|
@ -346,10 +346,6 @@ static void rtlsdrCallback(unsigned char *buf, uint32_t len, void *ctx) {
|
||||||
Modes.mag_buffers[next_free_buffer].length = 0; // just in case
|
Modes.mag_buffers[next_free_buffer].length = 0; // just in case
|
||||||
Modes.first_free_buffer = next_free_buffer;
|
Modes.first_free_buffer = next_free_buffer;
|
||||||
|
|
||||||
// accumulate CPU while holding the mutex, and restart measurement
|
|
||||||
end_cpu_timing(&rtlsdr_thread_cpu, &Modes.reader_cpu_accumulator);
|
|
||||||
start_cpu_timing(&rtlsdr_thread_cpu);
|
|
||||||
|
|
||||||
pthread_cond_signal(&Modes.data_cond);
|
pthread_cond_signal(&Modes.data_cond);
|
||||||
pthread_mutex_unlock(&Modes.data_mutex);
|
pthread_mutex_unlock(&Modes.data_mutex);
|
||||||
}
|
}
|
||||||
|
|
@ -360,8 +356,6 @@ void rtlsdrRun()
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
start_cpu_timing(&rtlsdr_thread_cpu);
|
|
||||||
|
|
||||||
rtlsdr_read_async(RTLSDR.dev, rtlsdrCallback, NULL,
|
rtlsdr_read_async(RTLSDR.dev, rtlsdrCallback, NULL,
|
||||||
/* MODES_RTL_BUFFERS */ 4,
|
/* MODES_RTL_BUFFERS */ 4,
|
||||||
MODES_RTL_BUF_SIZE);
|
MODES_RTL_BUF_SIZE);
|
||||||
|
|
|
||||||
11
util.c
11
util.c
|
|
@ -106,6 +106,17 @@ void end_cpu_timing(const struct timespec *start_time, struct timespec *add_to)
|
||||||
normalize_timespec(add_to);
|
normalize_timespec(add_to);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* add difference between start_time and the current CPU time to add_to; then store the current CPU time in start_time */
|
||||||
|
void update_cpu_timing(struct timespec *start_time, struct timespec *add_to)
|
||||||
|
{
|
||||||
|
struct timespec end_time;
|
||||||
|
clock_gettime(CLOCK_THREAD_CPUTIME_ID, &end_time);
|
||||||
|
add_to->tv_sec += end_time.tv_sec - start_time->tv_sec;
|
||||||
|
add_to->tv_nsec += end_time.tv_nsec - start_time->tv_nsec;
|
||||||
|
normalize_timespec(add_to);
|
||||||
|
*start_time = end_time;
|
||||||
|
}
|
||||||
|
|
||||||
void set_thread_name(const char *name)
|
void set_thread_name(const char *name)
|
||||||
{
|
{
|
||||||
#if (__GLIBC__ > 2) || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 12)
|
#if (__GLIBC__ > 2) || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 12)
|
||||||
|
|
|
||||||
3
util.h
3
util.h
|
|
@ -51,6 +51,9 @@ void start_cpu_timing(struct timespec *start_time);
|
||||||
/* add difference between start_time and the current CPU time to add_to */
|
/* add difference between start_time and the current CPU time to add_to */
|
||||||
void end_cpu_timing(const struct timespec *start_time, struct timespec *add_to);
|
void end_cpu_timing(const struct timespec *start_time, struct timespec *add_to);
|
||||||
|
|
||||||
|
/* like end_cpu_timing followed by start_cpu_timing, but without a gap */
|
||||||
|
void update_cpu_timing(struct timespec *start_time, struct timespec *add_to);
|
||||||
|
|
||||||
/* set current thread name, if supported */
|
/* set current thread name, if supported */
|
||||||
void set_thread_name(const char *name);
|
void set_thread_name(const char *name);
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue