Set thread names for additional threads in system. (#1103)

* Set thread names for additional threads in system.

* Fix linting errors.

* Add additional thread names for Mac and Windows.

* Use const reference for SetThreadName.

* Fix more linting errors.

* Fix PortAudio compiler error.

* Add missed thread names.

* VOX tone atomic doesn't need seq_cst.

* Only wake up non-RT playback thread if FIFO is less than half full.

* Only wake up the TX/RX threads after all audio received.

* Optimized RADE is only for radio integrations.

* Add missed changes.

* Need to build integ in order for lint to work.

* remove invalid target.

* Fix additional Linux compiler failures from previous changes.

* Additional compiler fixes.

* Exclude duplicate tests.

* Fix macOS CI failure.
pull/1094/head
Mooneer Salem 2025-11-24 14:55:13 -08:00 committed by GitHub
parent e5705cc77e
commit 539bd55969
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
48 changed files with 316 additions and 55 deletions

View File

@ -42,7 +42,7 @@ jobs:
cd build_linux
cmake -DCMAKE_EXPORT_COMPILE_COMMANDS=1 ..
# Partially build so we have all required .h and .c/.cpp files
make -j$(nproc) build_mimalloc build_rade build_codec2
make -j$(nproc) build_mimalloc build_rade build_codec2 build_rade_integ
- name: Run clang-tidy on codebase
working-directory: ${{github.workspace}}/build_linux
@ -340,6 +340,22 @@ jobs:
native-audio: USE_NATIVE_AUDIO=0
- sanitizer: WITH_UBSAN=1
native-audio: USE_NATIVE_AUDIO=0
- os: ubuntu-22.04
sanitizer: WITH_RTSAN=1
- os: ubuntu-22.04
sanitizer: WITH_TSAN=1
- os: ubuntu-22.04
sanitizer: WITH_ASAN=1
- os: ubuntu-22.04
sanitizer: WITH_UBSAN=1
- os: ubuntu-22.04-arm
sanitizer: WITH_RTSAN=1
- os: ubuntu-22.04-arm
sanitizer: WITH_TSAN=1
- os: ubuntu-22.04-arm
sanitizer: WITH_ASAN=1
- os: ubuntu-22.04-arm
sanitizer: WITH_UBSAN=1
runs-on: ${{ matrix.os }}
needs: lint

View File

@ -37,7 +37,7 @@ jobs:
cd build_osx
CC=clang CXX=clang++ cmake -DCMAKE_EXPORT_COMPILE_COMMANDS=1 ..
# Partially build so we have all required .h and .c/.cpp files
make -j$(nproc) build_mimalloc build_rade build_codec2
make -j$(nproc) build_mimalloc build_rade build_codec2 build_rade_integ
- name: Run clang-tidy on codebase
working-directory: ${{github.workspace}}/build_osx

View File

@ -370,6 +370,7 @@ message(STATUS "Threads library flags: ${CMAKE_THREAD_LIBS_INIT}")
# Build RADE.
# (TBD - allow override with own build, similar to Codec2)
include(cmake/BuildRADE.cmake)
include(cmake/BuildRADEForIntegrations.cmake)
#
# Build codec2

View File

@ -6,14 +6,17 @@ if [[ "${TARGET}" == "all" ]]; then
export APPNAME="FreeDV"
export APPEXEC=../build_linux/src/freedv
export APPRUN="AppRun.sh"
export RADE_SRC="rade_src"
elif [[ "${TARGET}" == "freedv-flex" ]]; then
export APPNAME="FreeDV-FlexRadio"
export APPEXEC=../build_linux/src/integrations/flex/freedv-flex
export APPRUN="AppRun-FlexRadio.sh"
export RADE_SRC="rade_integ_src"
elif [[ "${TARGET}" == "freedv-ka9q" ]]; then
export APPNAME="FreeDV-KA9Q"
export APPEXEC=../build_linux/src/integrations/ka9q/freedv-ka9q
export APPRUN="AppRun-KA9Q.sh"
export RADE_SRC="rade_integ_src"
fi
DESKTOP_FILE="$APPNAME.desktop"
@ -81,9 +84,9 @@ cd -
echo "Copying rade_src..."
# ls freedv-rade/freedv-gui/build_linux/rade_src/model
# model05/ model17/ model18/ model19/ model19_check3/ model_bbfm_01/
cp -r "$BUILDDIR/build_linux/rade_src" "$APPDIR/."
cp -r "$BUILDDIR/build_linux/$RADE_SRC" "$APPDIR/."
cd "$APPDIR/usr/bin"
ln -s "../../rade_src/model19_check3" "model19_check3"
ln -s "../../$RADE_SRC/model19_check3" "model19_check3"
cd -
# Create the output

View File

@ -15,7 +15,7 @@ ExternalProject_Add(build_rade
SOURCE_DIR rade_src
BINARY_DIR rade_build
GIT_REPOSITORY https://github.com/drowe67/radae.git
GIT_TAG ms-disable-python-gc
GIT_TAG main
CMAKE_ARGS ${RADE_CMAKE_ARGS}
#CMAKE_CACHE_ARGS -DCMAKE_OSX_DEPLOYMENT_TARGET:STRING=${CMAKE_OSX_DEPLOYMENT_TARGET}
INSTALL_COMMAND ""

View File

@ -0,0 +1,71 @@
if(CMAKE_CROSSCOMPILING)
set(RADE_CMAKE_ARGS ${RADE_CMAKE_ARGS} -DPython3_ROOT_DIR=${Python3_ROOT_DIR} -DCMAKE_TOOLCHAIN_FILE=${CMAKE_TOOLCHAIN_FILE})
elseif(APPLE)
set(RADE_CMAKE_ARGS ${RADE_CMAKE_ARGS} -DPython3_ROOT_DIR=${Python3_ROOT_DIR})
endif()
if(BUILD_OSX_UNIVERSAL)
set(RADE_CMAKE_ARGS ${RADE_CMAKE_ARGS} -DBUILD_OSX_UNIVERSAL=1)
endif(BUILD_OSX_UNIVERSAL)
set(RADE_CMAKE_ARGS ${RADE_CMAKE_ARGS} -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} -DOPUS_URL=https://github.com/xiph/opus/archive/940d4e5af64351ca8ba8390df3f555484c567fbb.zip)
include(ExternalProject)
ExternalProject_Add(build_rade_integ
SOURCE_DIR rade_integ_src
BINARY_DIR rade_integ_build
GIT_REPOSITORY https://github.com/drowe67/radae.git
GIT_TAG ms-disable-python-gc
CMAKE_ARGS ${RADE_CMAKE_ARGS}
#CMAKE_CACHE_ARGS -DCMAKE_OSX_DEPLOYMENT_TARGET:STRING=${CMAKE_OSX_DEPLOYMENT_TARGET}
INSTALL_COMMAND ""
EXCLUDE_FROM_ALL TRUE
)
ExternalProject_Get_Property(build_rade_integ BINARY_DIR)
ExternalProject_Get_Property(build_rade_integ SOURCE_DIR)
add_library(rade_integ SHARED IMPORTED)
add_dependencies(rade_integ build_rade_integ)
include_directories(${SOURCE_DIR}/src)
set_target_properties(rade_integ PROPERTIES
IMPORTED_LOCATION "${BINARY_DIR}/src/librade${CMAKE_SHARED_LIBRARY_SUFFIX}"
IMPORTED_IMPLIB "${BINARY_DIR}/src/librade${CMAKE_IMPORT_LIBRARY_SUFFIX}"
)
list(APPEND FREEDV_PACKAGE_SEARCH_PATHS ${BINARY_DIR}/src)
set(rade_integ_BINARY_DIR ${BINARY_DIR})
add_library(opus_integ STATIC IMPORTED)
add_dependencies(opus_integ build_rade_integ)
set(FARGAN_INTEG_ARM_CONFIG_H_FILE "${BINARY_DIR}/build_opus_arm-prefix/src/build_opus_arm/config.h")
set(FARGAN_INTEG_X86_CONFIG_H_FILE "${BINARY_DIR}/build_opus_x86-prefix/src/build_opus_x86/config.h")
if(APPLE AND BUILD_OSX_UNIVERSAL)
include_directories(
${BINARY_DIR}/build_opus_arm-prefix/src/build_opus_arm
${BINARY_DIR}/build_opus_arm-prefix/src/build_opus_arm/dnn
${BINARY_DIR}/build_opus_arm-prefix/src/build_opus_arm/celt
${BINARY_DIR}/build_opus_arm-prefix/src/build_opus_arm/silk
${BINARY_DIR}/build_opus_arm-prefix/src/build_opus_arm/include)
set_target_properties(opus_integ PROPERTIES
IMPORTED_LOCATION "${BINARY_DIR}/libopus${CMAKE_STATIC_LIBRARY_SUFFIX}"
)
set(FARGAN_INTEG_CONFIG_H_FILE "${BINARY_DIR}/build_opus_arm-prefix/src/build_opus_arm/config.h")
else(APPLE AND BUILD_OSX_UNIVERSAL)
include_directories(
${BINARY_DIR}/build_opus-prefix/src/build_opus
${BINARY_DIR}/build_opus-prefix/src/build_opus/dnn
${BINARY_DIR}/build_opus-prefix/src/build_opus/celt
${BINARY_DIR}/build_opus-prefix/src/build_opus/silk
${BINARY_DIR}/build_opus-prefix/src/build_opus/include)
set_target_properties(opus_integ PROPERTIES
IMPORTED_LOCATION "${BINARY_DIR}/build_opus-prefix/src/build_opus/.libs/libopus${CMAKE_STATIC_LIBRARY_SUFFIX}"
)
set(FARGAN_INTEG_CONFIG_H_FILE "${BINARY_DIR}/build_opus-prefix/src/build_opus/config.h")
set(FARGAN_INTEG_ARM_CONFIG_H_FILE "${FARGAN_CONFIG_H_FILE}")
set(FARGAN_INTEG_X86_CONFIG_H_FILE "${FARGAN_CONFIG_H_FILE}")
endif(APPLE AND BUILD_OSX_UNIVERSAL)
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/fargan_config_integ.h.in" "${CMAKE_CURRENT_BINARY_DIR}/fargan_config_integ.h")

View File

@ -0,0 +1,15 @@
#ifndef FARGAN_CONFIG_H
#define FARGAN_CONFIG_H
// Include Opus config.h to suppress warnings
#ifdef __APPLE__
#ifdef __aarch64__
#include "@FARGAN_INTEG_ARM_CONFIG_H_FILE@"
#else
#include "@FARGAN_INTEG_X86_CONFIG_H_FILE@"
#endif // __aarch64__
#else
#include "@FARGAN_INTEG_CONFIG_H_FILE@"
#endif // __APPLE__
#endif // FARGAN_CONFIG_H

View File

@ -114,7 +114,8 @@ static OSStatus SetCurrentIOBufferFrameSize(AudioObjectID inDeviceID,
}
MacAudioDevice::MacAudioDevice(MacAudioEngine* parent, std::string deviceName, int coreAudioId, IAudioEngine::AudioDirection direction, int numChannels, int sampleRate)
: coreAudioId_(coreAudioId)
: ThreadedObject("MacDevice")
, coreAudioId_(coreAudioId)
, direction_(direction)
, numChannels_(numChannels)
, sampleRate_(sampleRate)

View File

@ -30,7 +30,8 @@
class PortAudioInterface : public ThreadedObject
{
public:
PortAudioInterface() = default;
PortAudioInterface()
: ThreadedObject("PortAudio") {}
virtual ~PortAudioInterface() = default;
std::future<PaError> Initialize();
@ -55,4 +56,4 @@ public:
std::future<const PaStreamInfo*> GetStreamInfo(PaStream* stream);
};
#endif // PORT_AUDIO_INTERFACE_H
#endif // PORT_AUDIO_INTERFACE_H

View File

@ -365,16 +365,16 @@ void PulseAudioDevice::StreamReadCallback_(pa_stream *s, size_t length, void *us
pa_stream_peek(s, &data, &length);
if (!data || length == 0)
{
return; //break;
return;
}
if (thisObj->onAudioDataFunction)
{
thisObj->onAudioDataFunction(*thisObj, const_cast<void*>(data), length / thisObj->getNumChannels() / sizeof(short), thisObj->onAudioDataState);
}
sem_post(&thisObj->sem_);
pa_stream_drop(s);
} while (pa_stream_readable_size(s) > 0);
sem_post(&thisObj->sem_);
}
void PulseAudioDevice::StreamWriteCallback_(pa_stream *s, size_t length, void *userdata)

View File

@ -26,6 +26,10 @@
#include <map>
#include "../util/logging/ulog.h"
#if defined(USE_RTKIT)
#include "rtkit.h"
#endif // defined(USE_RTKIT)
PulseAudioEngine::PulseAudioEngine()
: initialized_(false)
{
@ -73,6 +77,51 @@ void PulseAudioEngine::start()
pa_context_set_state_callback(context_, [](pa_context*, void* mainloop) {
pa_threaded_mainloop *threadedML = static_cast<pa_threaded_mainloop *>(mainloop);
#if defined(USE_RTKIT)
if (pa_threaded_mainloop_in_thread(threadedML))
{
DBusError error;
DBusConnection* bus = nullptr;
int result = 0;
dbus_error_init(&error);
if (!(bus = dbus_bus_get(DBUS_BUS_SYSTEM, &error)))
{
log_warn("Could not connect to system bus: %s", error.message);
}
else
{
int minNiceLevel = 0;
constexpr int ERROR_BUFFER_SIZE = 1024;
char tmpBuf[ERROR_BUFFER_SIZE];
if ((result = rtkit_get_min_nice_level(bus, &minNiceLevel)) < 0)
{
#if (_POSIX_C_SOURCE >= 200112L) && !_GNU_SOURCE
strerror_r(-result, tmpBuf, ERROR_BUFFER_SIZE);
log_warn("rtkit could not get minimum nice level: %s", tmpBuf);
#else
log_warn("rtkit could not get minimum nice level: %s", strerror_r(-result, tmpBuf, ERROR_BUFFER_SIZE));
#endif // (_POSIX_C_SOURCE >= 200112L) && !_GNU_SOURCE
}
else if ((result = rtkit_make_high_priority(bus, 0, minNiceLevel)) < 0)
{
#if (_POSIX_C_SOURCE >= 200112L) && !_GNU_SOURCE
strerror_r(-result, tmpBuf, ERROR_BUFFER_SIZE);
log_warn("rtkit could not make high priority: %s", tmpBuf);
#else
log_warn("rtkit could not make high priority: %s", strerror_r(-result, tmpBuf, ERROR_BUFFER_SIZE));
#endif // (_POSIX_C_SOURCE >= 200112L) && !_GNU_SOURCE
}
}
if (bus != nullptr)
{
dbus_connection_unref(bus);
}
}
#endif // defined(USE_RTKIT)
pa_threaded_mainloop_signal(threadedML, 0);
}, mainloop_);

View File

@ -37,7 +37,8 @@
thread_local HANDLE WASAPIAudioDevice::HelperTask_ = nullptr;
WASAPIAudioDevice::WASAPIAudioDevice(ComPtr<IAudioClient> client, ComPtr<IMMDevice> device, IAudioEngine::AudioDirection direction, int sampleRate, int numChannels)
: client_(client)
: Win32COMObject("WASAPIDev")
, client_(client)
, device_(device)
, renderClient_(nullptr)
, captureClient_(nullptr)

View File

@ -34,7 +34,8 @@
#include "../util/logging/ulog.h"
WASAPIAudioEngine::WASAPIAudioEngine()
: devEnumerator_(nullptr)
: Win32COMObject("WASAPIEng")
, devEnumerator_(nullptr)
, inputDeviceList_(nullptr)
, outputDeviceList_(nullptr)
{

View File

@ -1,7 +1,7 @@
set(PIPELINE_SUBSET
../../pipeline/AgcStep.cpp
../../pipeline/AudioPipeline.cpp
../../pipeline/BandwidthExpandStep.cpp
#../../pipeline/BandwidthExpandStep.cpp
../../pipeline/IPipelineStep.cpp
../../pipeline/LevelAdjustStep.cpp
../../pipeline/RADEReceiveStep.cpp
@ -25,8 +25,8 @@ add_library(fdv_integ_audio_pipeline STATIC
${PIPELINE_SUBSET})
target_compile_options(fdv_integ_audio_pipeline PRIVATE ${WARNINGS_AS_ERRORS_FLAGS})
target_compile_definitions(fdv_integ_audio_pipeline PRIVATE -DDISABLE_UNIT_TEST)
target_link_libraries(fdv_integ_audio_pipeline PRIVATE fdv_os_wrapper rade opus codec2 samplerate agc ebur128 ${SPEEXDSP_LIBRARY})
target_compile_definitions(fdv_integ_audio_pipeline PRIVATE -DDISABLE_UNIT_TEST -DFREEDV_INTEGRATION)
target_link_libraries(fdv_integ_audio_pipeline PRIVATE fdv_os_wrapper rade_integ opus_integ codec2 samplerate agc ebur128 ${SPEEXDSP_LIBRARY})
if(STATIC_SPEEXDSP_BUILT)
add_dependencies(fdv_integ_audio_pipeline speex)
endif(STATIC_SPEEXDSP_BUILT)

View File

@ -39,9 +39,13 @@
#include "../pipeline/RADETransmitStep.h"
// TBD - need to wrap in "extern C" to avoid linker errors
extern "C"
extern "C"
{
#if defined(FREEDV_INTEGRATION)
#include "fargan_config_integ.h"
#else
#include "fargan_config.h"
#endif // defined(FREEDV_INTEGRATION)
#include "fargan.h"
#include "lpcnet.h"
}

View File

@ -39,7 +39,8 @@ std::string ReportingController::getVersionString_()
#define PSKREPORTER_REPORT_INTERVAL_MS (5*60*1000)
ReportingController::ReportingController(std::string softwareName, bool rxOnly)
: softwareName_(std::move(softwareName))
: ThreadedObject("Reporting")
, softwareName_(std::move(softwareName))
, pskReporterSendTimer_(PSKREPORTER_REPORT_INTERVAL_MS, [&](ThreadedTimer&) {
enqueue_([&]() {
if (pskReporterConnection_ != nullptr)

View File

@ -13,4 +13,5 @@ add_executable(freedv-flex
${MIMALLOC_SOURCE_FILE})
target_compile_options(freedv-flex PRIVATE ${WARNINGS_AS_ERRORS_FLAGS} -Wno-missing-field-initializers)
target_compile_definitions(freedv-flex PRIVATE -DFREEDV_INTEGRATION)
target_link_libraries(freedv-flex PRIVATE fdv_integ_audio_pipeline fdv_reporting fdv_util)

View File

@ -33,7 +33,8 @@ constexpr short FLOAT_TO_SHORT_MULTIPLIER = 32767;
using namespace std::placeholders;
FlexVitaTask::FlexVitaTask(std::shared_ptr<IRealtimeHelper> helper, bool randomUdpPort)
: socket_(-1)
: ThreadedObject("FlexVita")
, socket_(-1)
, rxStreamId_(0)
, txStreamId_(0)
, audioSeqNum_(0)

View File

@ -47,7 +47,7 @@
extern "C"
{
#include "fargan_config.h"
#include "fargan_config_integ.h"
#include "fargan.h"
#include "lpcnet.h"
}

View File

@ -9,4 +9,5 @@ add_executable(freedv-ka9q
${MIMALLOC_SOURCE_FILE})
target_compile_options(freedv-ka9q PRIVATE ${WARNINGS_AS_ERRORS_FLAGS})
target_compile_definitions(freedv-ka9q PRIVATE -DFREEDV_INTEGRATION)
target_link_libraries(freedv-ka9q PRIVATE git_version fdv_integ_audio_pipeline fdv_reporting fdv_util fdv_os_wrapper)

View File

@ -59,7 +59,7 @@
extern "C"
{
#include "fargan_config.h"
#include "fargan_config_integ.h"
#include "fargan.h"
#include "lpcnet.h"
}

View File

@ -259,6 +259,8 @@ void MainFrame::handleAudioDeviceChange_(std::string const& newDeviceName)
void MainApp::UnitTest_()
{
SetThreadName("UnitTest");
// List audio devices
auto engine = AudioEngineFactory::GetAudioEngine();
engine->start();
@ -1009,9 +1011,7 @@ MainFrame::MainFrame(wxWindow *parent) : TopFrame(parent, wxID_ANY, _("FreeDV ")
VAR_FMT("Var: %4.1f"),
CLK_OFF_FMT("ClkOff: %+-d")
{
#if defined(__linux__)
pthread_setname_np(pthread_self(), "FreeDV GUI");
#endif // defined(__linux__)
SetThreadName("GUI");
terminating_ = false;
realigned_ = false;
@ -2657,9 +2657,7 @@ void MainFrame::OnTogBtnOnOff(wxCommandEvent&)
{
std::thread onOffExec([this]()
{
#if defined(__linux__)
pthread_setname_np(pthread_self(), "FreeDV TurningOn");
#endif // defined(__linux__)
SetThreadName("TurningOn");
performFreeDVOn_();
@ -2701,9 +2699,7 @@ void MainFrame::OnTogBtnOnOff(wxCommandEvent&)
{
std::thread onOffExec([this]()
{
#if defined(__linux__)
pthread_setname_np(pthread_self(), "FreeDV TurningOff");
#endif // defined(__linux__)
SetThreadName("TurningOff");
performFreeDVOff_();
@ -3669,7 +3665,7 @@ void MainFrame::OnTxOutAudioData_(IAudioDevice& dev, void* data, size_t size, vo
// If VOX tone is enabled, go back through and add the VOX tone
// on the left channel.
if (cbData->leftChannelVoxTone)
if (cbData->leftChannelVoxTone.load(std::memory_order_acquire))
{
cbData->voxTonePhase += 2.0*M_PI*VOX_TONE_FREQ/dev.getSampleRate();
cbData->voxTonePhase -= 2.0*M_PI*floor(cbData->voxTonePhase/(2.0*M_PI));

View File

@ -50,4 +50,7 @@ void StartLowLatencyActivity();
// Tells the operating system that we no longer need low latency.
void StopLowLatencyActivity();
// Sets the name of the current thread in the OS.
void SetThreadName(std::string const& name);
#endif // __OS_INTERFACE__

View File

@ -23,6 +23,9 @@
#import <Foundation/Foundation.h>
#import <AVFoundation/AVFoundation.h>
#import <AppKit/AppKit.h>
#include <pthread.h>
#include "os_interface.h"
static id<NSObject> Activity = nil;
@ -117,3 +120,10 @@ std::string GetOperatingSystemString()
{
return "macos";
}
void SetThreadName(std::string const& name)
{
std::string fullName = "FDV ";
fullName += name;
pthread_setname_np(fullName.c_str());
}

View File

@ -50,3 +50,13 @@ std::string GetOperatingSystemString()
return "other";
#endif // __linux__
}
void SetThreadName(std::string const& name)
{
std::string fullName = "FDV ";
fullName += name;
#ifdef __linux__
pthread_setname_np(pthread_self(), fullName.c_str());
#endif // __linux__
}

View File

@ -63,3 +63,13 @@ std::string GetOperatingSystemString()
{
return "windows";
}
void SetThreadName(std::string const& name)
{
// XXX - assumes ASCII. This is probably fine, though, since
// this is debug code.
std::string fullName = "FDV ";
fullName += name;
std::wstring stemp = std::wstring(fullName.begin(), fullName.end());
SetThreadDescription(GetCurrentThread(), stemp.c_str());
}

View File

@ -26,7 +26,7 @@ add_library(fdv_audio_pipeline STATIC
)
target_compile_options(fdv_audio_pipeline PRIVATE ${WARNINGS_AS_ERRORS_FLAGS})
target_link_libraries(fdv_audio_pipeline PRIVATE ebur128 agc)
target_link_libraries(fdv_audio_pipeline PRIVATE ebur128 agc fdv_os_wrapper)
target_include_directories(fdv_audio_pipeline PRIVATE ${CODEC2_INCLUDE_DIRS} ${CMAKE_CURRENT_SOURCE_DIR}/.. ${CMAKE_CURRENT_BINARY_DIR}/..)
add_dependencies(fdv_audio_pipeline rade opus codec2)

View File

@ -32,6 +32,8 @@
#include <pthread.h>
#endif // defined(__APPLE__)
#include "../os/os_interface.h"
extern wxMutex g_mutexProtectingCallbackData;
using namespace std::chrono_literals;
@ -86,8 +88,11 @@ short* PlaybackStep::execute(short*, int numInputSamples, int* numOutputSamples)
{
outputFifo_.read(outputSamples_.get(), *numOutputSamples);
}
fileIoThreadSem_.signal();
if (outputFifo_.numUsed() < (outputFifo_.capacity() / 2))
{
fileIoThreadSem_.signal();
}
return outputSamples_.get();
}
@ -101,6 +106,8 @@ void PlaybackStep::nonRtThreadEntry_()
pthread_set_qos_class_self_np(QOS_CLASS_UTILITY, 0);
#endif // defined(__APPLE__)
SetThreadName("PlayStep");
while (!nonRtThreadEnding_)
{
g_mutexProtectingCallbackData.Lock();

View File

@ -33,6 +33,8 @@
#include "pipeline_defines.h"
#include "../os/os_interface.h"
using namespace std::chrono_literals;
#if !defined(DISABLE_UNIT_TEST)
@ -236,6 +238,8 @@ void RADEReceiveStep::utFeatureThreadEntry_()
setiopolicy_np(IOPOL_TYPE_DISK, IOPOL_SCOPE_THREAD, IOPOL_THROTTLE);
#endif // defined(__APPLE__)
SetThreadName("RADERx");
float* featureBuf = new float[utFeatures_->capacity()];
assert(featureBuf != nullptr);

View File

@ -29,7 +29,6 @@
#include <functional>
#include "IPipelineStep.h"
#include "../freedv_interface.h"
#include "rade_api.h"
#include "rade_text.h"
#include "../util/GenericFIFO.h"
@ -42,9 +41,15 @@
#define NUM_FEATURES_TO_STORE (256 * 1024)
// TBD - need to wrap in "extern C" to avoid linker errors
extern "C"
extern "C"
{
#if defined(FREEDV_INTEGRATION)
#include "fargan_config_integ.h"
#else
#include "fargan_config.h"
#endif // defined(FREEDV_INTEGRATION)
#include "fargan.h"
#include "lpcnet.h"
}
class RADEReceiveStep : public IPipelineStep

View File

@ -33,6 +33,8 @@
#include <sys/resource.h>
#endif // defined(__APPLE__)
#include "../os/os_interface.h"
using namespace std::chrono_literals;
#define FEATURE_FIFO_SIZE ((RADE_SPEECH_SAMPLE_RATE / LPCNET_FRAME_SIZE) * rade_n_features_in_out(dv_))
@ -246,6 +248,8 @@ void RADETransmitStep::utFeatureThreadEntry_()
setiopolicy_np(IOPOL_TYPE_DISK, IOPOL_SCOPE_THREAD, IOPOL_THROTTLE);
#endif // defined(__APPLE__)
SetThreadName("RADETx");
float* featureBuf = new float[utFeatures_->capacity()];
assert(featureBuf != nullptr);

View File

@ -28,12 +28,22 @@
#include <atomic>
#include "IPipelineStep.h"
#include "../freedv_interface.h"
#include "rade_api.h"
#include "lpcnet.h"
#include "../util/GenericFIFO.h"
#include "../util/Semaphore.h"
// TBD - need to wrap in "extern C" to avoid linker errors
extern "C"
{
#if defined(FREEDV_INTEGRATION)
#include "fargan_config_integ.h"
#else
#include "fargan_config.h"
#endif // defined(FREEDV_INTEGRATION)
#include "fargan.h"
#include "lpcnet.h"
}
// Number of features to store. This is set to be close to the
// typical size for RX/TX features for the rade_loss ctest to
// avoid contention with normal RADE operation.

View File

@ -29,6 +29,8 @@
#include <pthread.h>
#endif // defined(__APPLE__)
#include "../os/os_interface.h"
extern wxMutex g_mutexProtectingCallbackData;
using namespace std::chrono_literals;
@ -97,6 +99,8 @@ void RecordStep::fileIoThreadEntry_()
pthread_set_qos_class_self_np(QOS_CLASS_UTILITY, 0);
#endif // defined(__APPLE__)
SetThreadName("RecordStep");
while (!fileIoThreadEnding_)
{
g_mutexProtectingCallbackData.Lock();

View File

@ -30,6 +30,8 @@
#include <pthread.h>
#endif // defined(__APPLE__)
#include "../os/os_interface.h"
using namespace std::chrono_literals;
TapStep::TapStep(int sampleRate, IPipelineStep* tapStep)
@ -43,6 +45,8 @@ TapStep::TapStep(int sampleRate, IPipelineStep* tapStep)
short* fifoInput = new short[SAMPLE_RATE_AT_10MS];
assert(fifoInput != nullptr);
SetThreadName("TapStep");
#if defined(__APPLE__)
// Downgrade thread QoS to Utility to avoid thread contention issues.
pthread_set_qos_class_self_np(QOS_CLASS_UTILITY, 0);

View File

@ -531,12 +531,11 @@ void* TxRxThread::Entry() noexcept
resetStats_();
#endif // defined(ENABLE_PROCESSING_STATS)
#if defined(__linux__)
// Set thread name for debugging
const char* threadName = nullptr;
if (m_tx) threadName = "FreeDV txThread";
else threadName = "FreeDV rxThread";
pthread_setname_np(pthread_self(), threadName);
#endif // defined(__linux__)
if (m_tx) threadName = "txThread";
else threadName = "rxThread";
SetThreadName(threadName);
// Make sure we don't start processing until
// the main thread is ready.

View File

@ -49,6 +49,7 @@
#endif // defined(WIN32) || defined(__MINGW32__)
#include "pskreporter.h"
#include "../os/os_interface.h"
//#define PSK_REPORTER_TEST
#if defined(PSK_REPORTER_TEST)
@ -270,6 +271,8 @@ bool PskReporter::reportCommon_()
{
std::unique_lock<std::mutex> lock(recordListMutex_);
SetThreadName("PSKReport");
// Header (2) + length (2) + time (4) + sequence # (4) + random identifier (4) +
// RX format block + TX format block + RX data + TX data
int dgSize = 16 + sizeof(rxFormatHeader) + sizeof(txFormatHeader) + getRxDataSize_() + getTxDataSize_();

View File

@ -69,7 +69,8 @@ bool HamlibRigController::RigCompare_(const struct rig_caps *rig1, const struct
}
HamlibRigController::HamlibRigController(std::string rigName, std::string serialPort, const int serialRate, const int civHex, const PttType pttType, std::string pttSerialPort, bool restoreFreqModeOnDisconnect, bool freqOnly)
: rigName_(std::move(rigName))
: ThreadedObject("hamlib")
, rigName_(std::move(rigName))
, serialPort_(std::move(serialPort))
, serialRate_(serialRate)
, civHex_(civHex)
@ -92,7 +93,8 @@ HamlibRigController::HamlibRigController(std::string rigName, std::string serial
}
HamlibRigController::HamlibRigController(int rigIndex, std::string serialPort, const int serialRate, const int civHex, const PttType pttType, std::string pttSerialPort, bool restoreFreqModeOnDisconnect, bool freqOnly)
: rigName_(RigIndexToName(rigIndex))
: ThreadedObject("hamlib")
, rigName_(RigIndexToName(rigIndex))
, serialPort_(std::move(serialPort))
, serialRate_(serialRate)
, civHex_(civHex)

View File

@ -21,6 +21,7 @@
//=========================================================================
#include "SerialPortInRigController.h"
#include "../os/os_interface.h"
#define PTT_INPUT_MONITORING_TIME_MS 10
@ -80,6 +81,8 @@ bool SerialPortInRigController::getCTS_()
void SerialPortInRigController::pollThreadEntry_()
{
SetThreadName("SerialIn");
while (!threadExiting_)
{
enqueue_(std::bind(&SerialPortInRigController::pollSerialPort_, this));

View File

@ -27,7 +27,8 @@
#include "../util/logging/ulog.h"
SerialPortRigController::SerialPortRigController(std::string serialPort)
: serialPortHandle_(COM_HANDLE_INVALID)
: ThreadedObject("SerialController")
, serialPortHandle_(COM_HANDLE_INVALID)
, serialPort_(std::move(serialPort))
{
// empty

View File

@ -34,7 +34,8 @@ using namespace std::chrono_literals;
#define OMNI_RIG_WAIT_TIME (200ms)
OmniRigController::OmniRigController(int rigId, bool restoreOnDisconnect, bool freqOnly)
: rigId_(rigId)
: ThreadedObject("OmniRig")
, rigId_(rigId)
, omniRig_(nullptr)
, rig_(nullptr)
, origFreq_(0)

View File

@ -24,7 +24,7 @@ add_library(fdv_util STATIC
)
target_compile_options(fdv_util PRIVATE ${WARNINGS_AS_ERRORS_FLAGS})
target_link_libraries(fdv_util yyjson)
target_link_libraries(fdv_util yyjson fdv_os_wrapper)
if(UNITTEST)
macro(DefineUnitTest utName)

View File

@ -47,6 +47,7 @@
#include "TcpConnectionHandler.h"
#include "logging/ulog.h"
#include "../os/os_interface.h"
using namespace std::chrono_literals;
@ -59,7 +60,8 @@ using namespace std::chrono_literals;
#endif // INVALID_SOCKET
TcpConnectionHandler::TcpConnectionHandler()
: enableReconnect_(false)
: ThreadedObject("TcpConn")
, enableReconnect_(false)
, reconnectTimer_(RECONNECT_INTERVAL_MS, [&](ThreadedTimer&) {
enqueue_(std::bind(&TcpConnectionHandler::connectImpl_, this));
}, false)
@ -178,6 +180,8 @@ void TcpConnectionHandler::connectImpl_()
std::string portStr = portStream.str();
std::thread ipv6ResolveThread([&, portStr, ipv6ResultPromise]() {
SetThreadName("ipv6");
struct addrinfo *result = nullptr;
resolveAddresses_(AF_INET6, host_.c_str(), portStr.c_str(), &result);
ipv6ResultPromise->set_value(result);
@ -185,6 +189,8 @@ void TcpConnectionHandler::connectImpl_()
});
std::thread ipv4ResolveThread([&, portStr, ipv4ResultPromise]() {
SetThreadName("ipv4");
struct addrinfo *result = nullptr;
resolveAddresses_(AF_INET, host_.c_str(), portStr.c_str(), &result);
ipv4ResultPromise->set_value(result);
@ -579,9 +585,10 @@ void TcpConnectionHandler::sendImpl_(const char* buf, int length)
void TcpConnectionHandler::receiveImpl_()
{
constexpr int READ_SIZE_BYTES = 1024;
char buf[READ_SIZE_BYTES];
SetThreadName("TCPRx");
while (socket_.load(std::memory_order_acquire) != INVALID_SOCKET)
{
struct timeval tv = {0, 250000}; // 250ms

View File

@ -21,12 +21,14 @@
//=========================================================================
#include <chrono>
#include "../os/os_interface.h"
#include "ThreadedObject.h"
using namespace std::chrono_literals;
ThreadedObject::ThreadedObject(ThreadedObject* parent)
ThreadedObject::ThreadedObject(std::string name, ThreadedObject* parent)
: parent_(parent)
, name_(std::move(name))
, isDestroying_(false)
{
// Instantiate thread here rather than the initializer since otherwise
@ -107,6 +109,8 @@ void ThreadedObject::eventLoop_()
pthread_set_qos_class_self_np(QOS_CLASS_UTILITY,0);
#endif // defined(__APPLE__)
SetThreadName(name_);
while (!isDestroying_.load(std::memory_order_acquire))
{
std::function<void()> fn;

View File

@ -33,6 +33,7 @@
#include <deque>
#include <functional>
#include <atomic>
#include <string>
class ThreadedObject
{
@ -40,7 +41,7 @@ public:
virtual ~ThreadedObject();
protected:
ThreadedObject(ThreadedObject* parent = nullptr);
ThreadedObject(std::string name, ThreadedObject* parent = nullptr);
// Enqueues some code to run on a different thread.
// @param timeoutMilliseconds Timeout to wait for lock. Note: if we can't get a lock within the timeout, the function doesn't run!
@ -48,7 +49,8 @@ protected:
private:
ThreadedObject* parent_;
std::string name_;
#if defined(__APPLE__)
dispatch_queue_t queue_;
#else

View File

@ -24,8 +24,9 @@
#include "ThreadedObject.h"
ThreadedObject::ThreadedObject(ThreadedObject* parent)
ThreadedObject::ThreadedObject(std::string name, ThreadedObject* parent)
: parent_(parent)
, name_(std::move(name))
{
dispatch_queue_t parentQueue;

View File

@ -21,6 +21,7 @@
//=========================================================================
#include "ThreadedTimer.h"
#include "../os/os_interface.h"
#include <cinttypes>
@ -85,6 +86,8 @@ void ThreadedTimer::TimerServer::unregisterTimer(ThreadedTimer* timer)
void ThreadedTimer::TimerServer::eventLoop_()
{
SetThreadName("Timer");
std::unique_lock<std::mutex> lk(mutex_);
std::chrono::time_point<std::chrono::steady_clock> nextFireTime;
while (!isDestroying_.load(std::memory_order_acquire))

View File

@ -27,7 +27,8 @@
#include <future>
Win32COMObject::Win32COMObject()
Win32COMObject::Win32COMObject(std::string name)
: ThreadedObject(name)
{
enqueue_([&]() {
HRESULT res = CoInitializeEx(nullptr, COINIT_MULTITHREADED | COINIT_DISABLE_OLE1DDE);

View File

@ -32,7 +32,7 @@ public:
virtual ~Win32COMObject();
protected:
Win32COMObject();
Win32COMObject(std::string name);
private:
};