refactor(simu): use C++ native threads (#6449)
Co-authored-by: raphaelcoeffic <1050031+raphaelcoeffic@users.noreply.github.com> Co-authored-by: Malte Langermann <malte@langermann.net>
This commit is contained in:
co-authored by
raphaelcoeffic
Malte Langermann
parent
4eddda034d
commit
7d91cdd428
@@ -74,7 +74,6 @@ if(WIN32)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mno-ms-bitfields")
|
||||
endif()
|
||||
else()
|
||||
set(PTHREAD_LIBRARY pthread)
|
||||
link_directories(/usr/local/lib)
|
||||
endif()
|
||||
|
||||
@@ -192,7 +191,6 @@ target_link_libraries(common
|
||||
Qt5::Xml
|
||||
Qt5::Widgets
|
||||
Qt5::SerialPort
|
||||
${PTHREAD_LIBRARY}
|
||||
${SDL2_LIBRARIES}
|
||||
${WIN_LINK_LIBRARIES}
|
||||
)
|
||||
@@ -656,4 +654,4 @@ if (CMAKE_SYSTEM_NAME STREQUAL "Linux")
|
||||
set(CPACK_EXTERNAL_PACKAGE_SCRIPT "${CMAKE_BINARY_DIR}/CPackExternal.cmake")
|
||||
endif()
|
||||
|
||||
include(CPack)
|
||||
include(CPack)
|
||||
|
||||
@@ -203,7 +203,6 @@ Section "un.EdgeTX Companion @VERSION_FAMILY@"
|
||||
Delete "$INSTDIR\libgcc_s_dw2-1.dll"
|
||||
Delete "$INSTDIR\libgcc_s_seh-1.dll"
|
||||
Delete "$INSTDIR\libstdc++-6.dll"
|
||||
Delete "$INSTDIR\libwinpthread-1.dll"
|
||||
|
||||
Delete "$INSTDIR\Uninstall.exe"
|
||||
|
||||
|
||||
@@ -492,15 +492,15 @@ if(NATIVE_BUILD)
|
||||
${RADIOLIB_NATIVE_SRC}
|
||||
)
|
||||
|
||||
# Add SIMU and POSIX_THREAD here PUBLIC, so it can be imported by other targets
|
||||
# Add SIMU and NATIVE_THREAD here PUBLIC, so it can be imported by other targets
|
||||
# via INTERFACE_COMPILE_OPTIONS
|
||||
target_compile_options(radiolib_native PUBLIC -DSIMU -DPOSIX_THREADS)
|
||||
target_compile_options(radiolib_native PUBLIC -DSIMU -DNATIVE_THREADS)
|
||||
target_sources(radiolib_native PUBLIC
|
||||
os/async_native.cpp
|
||||
os/sleep_native.cpp
|
||||
os/task_pthread.cpp
|
||||
os/task_native.cpp
|
||||
os/time_native.cpp
|
||||
os/timer_pthread.cpp
|
||||
os/timer_native.cpp
|
||||
)
|
||||
add_dependencies(radiolib_native ${RADIO_DEPENDENCIES})
|
||||
set_property(TARGET radiolib_native PROPERTY POSITION_INDEPENDENT_CODE ON)
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
*/
|
||||
|
||||
#include "async.h"
|
||||
#include "timer_pthread_impl.h"
|
||||
#include "timer_native_impl.h"
|
||||
|
||||
bool async_call(async_func_t func, volatile bool* excl_flag, void* param1,
|
||||
uint32_t param2)
|
||||
|
||||
+2
-3
@@ -21,12 +21,11 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
// OS specific implementation
|
||||
#if defined(POSIX_THREADS)
|
||||
#include "task_pthread.h"
|
||||
#if defined(NATIVE_THREADS)
|
||||
#include "task_native.h"
|
||||
#elif defined(FREE_RTOS)
|
||||
#include "task_freertos.h"
|
||||
#endif
|
||||
|
||||
@@ -21,10 +21,10 @@
|
||||
|
||||
#include "task.h"
|
||||
#include "debug.h"
|
||||
#include "timer_pthread_impl.h"
|
||||
#include "timer_native_impl.h"
|
||||
|
||||
#include <pthread.h>
|
||||
#include <chrono>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
#include <mutex>
|
||||
#include <string>
|
||||
@@ -33,7 +33,7 @@ static std::condition_variable _stop_cv;
|
||||
static std::mutex _stop_m;
|
||||
|
||||
static std::mutex _tasks_m;
|
||||
static std::vector<pthread_t> _tasks;
|
||||
static std::vector<task_handle_t*> _tasks;
|
||||
static bool _stop_tasks = false;
|
||||
|
||||
void task_sleep_ms(uint32_t ms)
|
||||
@@ -56,7 +56,7 @@ static void stop_tasks()
|
||||
_stop_tasks = true;
|
||||
}
|
||||
|
||||
static bool next_task_to_stop(pthread_t& task)
|
||||
static bool next_task_to_stop(task_handle_t*& task)
|
||||
{
|
||||
std::lock_guard lock(_tasks_m);
|
||||
|
||||
@@ -75,9 +75,10 @@ void task_shutdown_all()
|
||||
stop_tasks();
|
||||
_stop_cv.notify_all();
|
||||
|
||||
pthread_t task;
|
||||
task_handle_t* task = nullptr;
|
||||
while (next_task_to_stop(task)) {
|
||||
pthread_join(task, nullptr);
|
||||
task->_thread_handle->join();
|
||||
task->_thread_handle = {};
|
||||
}
|
||||
|
||||
timer_queue::destroy();
|
||||
@@ -89,7 +90,7 @@ struct run_context {
|
||||
std::string name;
|
||||
};
|
||||
|
||||
static void* _task_stub(void* p)
|
||||
static void* _task_stub(run_context* p)
|
||||
{
|
||||
std::unique_ptr<run_context> ctx{(run_context*)p};
|
||||
auto name = ctx->name.c_str();
|
||||
@@ -109,9 +110,8 @@ void task_create(task_handle_t* h, task_func_t func, const char* name,
|
||||
|
||||
h->_stack_size = stack_size;
|
||||
run_context* ctx = new run_context{func, name};
|
||||
if (pthread_create(&h->_thread_handle, nullptr, _task_stub, (void*)ctx) == 0) {
|
||||
_tasks.emplace_back(h->_thread_handle);
|
||||
}
|
||||
h->_thread_handle = std::make_unique<std::thread>([=]() { _task_stub(ctx); });
|
||||
if (h->_thread_handle) _tasks.emplace_back(h);
|
||||
}
|
||||
|
||||
bool task_running()
|
||||
@@ -132,22 +132,26 @@ unsigned task_get_stack_size(task_handle_t* h)
|
||||
|
||||
void mutex_create(mutex_handle_t* h)
|
||||
{
|
||||
pthread_mutex_init(h, nullptr);
|
||||
(void)h;
|
||||
}
|
||||
|
||||
bool mutex_lock(mutex_handle_t* h)
|
||||
{
|
||||
return pthread_mutex_lock(h) == 0;
|
||||
if (!h) return false;
|
||||
h->lock();
|
||||
return true;
|
||||
}
|
||||
|
||||
void mutex_unlock(mutex_handle_t* h)
|
||||
{
|
||||
pthread_mutex_unlock(h);
|
||||
if (!h) return;
|
||||
h->unlock();
|
||||
}
|
||||
|
||||
bool mutex_trylock(mutex_handle_t* h)
|
||||
{
|
||||
return pthread_mutex_trylock(h) == 0;
|
||||
if (!h) return false;
|
||||
return h->try_lock();
|
||||
}
|
||||
|
||||
|
||||
@@ -21,19 +21,22 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "time.h"
|
||||
#include "time_native.h"
|
||||
|
||||
#include <pthread.h>
|
||||
#include <semaphore.h>
|
||||
#include <thread>
|
||||
#include <mutex>
|
||||
#include <memory>
|
||||
|
||||
#define TASK_DEFINE_STACK(name, size) void* name
|
||||
|
||||
using _thread_ptr_t = std::unique_ptr<std::thread>;
|
||||
|
||||
struct task_handle_t {
|
||||
pthread_t _thread_handle;
|
||||
uint32_t _stack_size;
|
||||
_thread_ptr_t _thread_handle;
|
||||
uint32_t _stack_size;
|
||||
};
|
||||
|
||||
typedef pthread_mutex_t mutex_handle_t;
|
||||
typedef std::mutex mutex_handle_t;
|
||||
|
||||
bool task_running();
|
||||
|
||||
+1
-1
@@ -24,7 +24,7 @@
|
||||
#include <stdint.h>
|
||||
|
||||
// OS specific implementation
|
||||
#if defined(POSIX_THREADS)
|
||||
#if defined(NATIVE_THREADS)
|
||||
#include "time_native.h"
|
||||
#elif defined(FREE_RTOS)
|
||||
#include "time_freertos.h"
|
||||
|
||||
@@ -21,12 +21,11 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
// OS specific implementation
|
||||
#if defined(POSIX_THREADS)
|
||||
#include "timer_pthread.h"
|
||||
#if defined(NATIVE_THREADS)
|
||||
#include "timer_native.h"
|
||||
#elif defined(FREE_RTOS)
|
||||
#include "timer_freertos.h"
|
||||
#endif
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#include "timer.h"
|
||||
#include "debug.h"
|
||||
#include "timer_pthread_impl.h"
|
||||
#include "timer_native_impl.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#include "timer_pthread.h"
|
||||
#include "timer_native.h"
|
||||
|
||||
#include <condition_variable>
|
||||
#include <deque>
|
||||
+1
-8
@@ -21,20 +21,13 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C++" {
|
||||
#endif
|
||||
|
||||
#if defined(SIMU)
|
||||
#include <pthread.h>
|
||||
#include <semaphore.h>
|
||||
|
||||
static inline void RTOS_START()
|
||||
{
|
||||
}
|
||||
static inline void RTOS_START() {}
|
||||
|
||||
#elif defined(FREE_RTOS)
|
||||
|
||||
|
||||
@@ -201,9 +201,8 @@ set(STB_DIR ${RADIO_SRC_DIR}/thirdparty/stb)
|
||||
target_include_directories(simu PUBLIC ${STB_DIR})
|
||||
target_link_libraries(simu PUBLIC imgui)
|
||||
|
||||
target_link_libraries(simu PUBLIC
|
||||
pthread
|
||||
${SDL2_LIBRARIES}
|
||||
)
|
||||
target_link_libraries(simu PUBLIC
|
||||
${SDL2_LIBRARIES}
|
||||
)
|
||||
|
||||
PrintTargetReport("simu/libsimulator")
|
||||
|
||||
@@ -36,7 +36,7 @@
|
||||
|
||||
#include "os/sleep.h"
|
||||
#include "os/task.h"
|
||||
#include "os/timer_pthread_impl.h"
|
||||
#include "os/timer_native_impl.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
@@ -1,178 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) EdgeTX
|
||||
*
|
||||
* Based on code named
|
||||
* opentx - https://github.com/opentx/opentx
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#include "edgetx.h"
|
||||
|
||||
const char * eepromFile = nullptr;
|
||||
FILE * fp = nullptr;
|
||||
uint32_t eeprom_pointer;
|
||||
uint8_t * eeprom_buffer_data;
|
||||
volatile int32_t eeprom_buffer_size;
|
||||
bool eeprom_read_operation;
|
||||
bool eeprom_thread_running = false;
|
||||
uint8_t * eeprom = nullptr;
|
||||
sem_t * eeprom_write_sem;
|
||||
|
||||
void eepromReadBlock (uint8_t * buffer, size_t address, size_t size)
|
||||
{
|
||||
assert(size);
|
||||
|
||||
if (fp) {
|
||||
// TRACE("EEPROM read (pos=%d, size=%d)", pointer_eeprom, size);
|
||||
if (fseek(fp, address, SEEK_SET) < 0)
|
||||
perror("error in fseek");
|
||||
if (fread(buffer, size, 1, fp) <= 0)
|
||||
perror("error in fread");
|
||||
}
|
||||
else if (eeprom) {
|
||||
memcpy(buffer, &eeprom[address], size);
|
||||
}
|
||||
}
|
||||
|
||||
void eepromSimuWriteBlock(uint8_t * buffer, size_t address, size_t size)
|
||||
{
|
||||
assert(size);
|
||||
|
||||
if (fp) {
|
||||
// TRACE("EEPROM write (pos=%d, size=%d)", pointer_eeprom, size);
|
||||
if (fseek(fp, address, SEEK_SET) < 0)
|
||||
perror("error in fseek");
|
||||
if (fwrite(buffer, size, 1, fp) <= 0)
|
||||
perror("error in fwrite");
|
||||
}
|
||||
else if (eeprom) {
|
||||
memcpy(&eeprom[address], buffer, size);
|
||||
}
|
||||
}
|
||||
|
||||
volatile uint8_t eepromTransferComplete = 1;
|
||||
void * eeprom_thread_function(void *)
|
||||
{
|
||||
eeprom_thread_running = true;
|
||||
|
||||
while (!sem_wait(eeprom_write_sem)) {
|
||||
if (!eeprom_thread_running)
|
||||
return nullptr;
|
||||
assert(eeprom_buffer_size);
|
||||
if (eeprom_read_operation) {
|
||||
eepromReadBlock(eeprom_buffer_data, eeprom_pointer, eeprom_buffer_size);
|
||||
}
|
||||
else {
|
||||
eepromSimuWriteBlock(eeprom_buffer_data, eeprom_pointer, eeprom_buffer_size);
|
||||
}
|
||||
eepromTransferComplete = 1;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
uint8_t eepromReadStatus()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
uint8_t eepromIsTransferComplete()
|
||||
{
|
||||
return eepromTransferComplete;
|
||||
}
|
||||
|
||||
void eepromTransmitData(uint32_t address, uint8_t * buffer, uint32_t size, bool read)
|
||||
{
|
||||
eeprom_pointer = address;
|
||||
eeprom_buffer_data = buffer;
|
||||
eeprom_buffer_size = size;
|
||||
eeprom_read_operation = read;
|
||||
eepromTransferComplete = 0;
|
||||
sem_post(eeprom_write_sem);
|
||||
}
|
||||
|
||||
#if defined(EEPROM_BLOCK_SIZE)
|
||||
void eepromBlockErase(uint32_t address)
|
||||
{
|
||||
static uint8_t erasedBlock[EEPROM_BLOCK_SIZE]; // can't be on the stack!
|
||||
memset(erasedBlock, 0xff, sizeof(erasedBlock));
|
||||
eepromTransmitData(address, erasedBlock, EEPROM_BLOCK_SIZE, false);
|
||||
}
|
||||
#endif
|
||||
|
||||
void eepromStartRead(uint8_t * buffer, size_t address, size_t size)
|
||||
{
|
||||
assert(size);
|
||||
eepromTransmitData(address, buffer, size, true);
|
||||
}
|
||||
|
||||
void eepromStartWrite(uint8_t * buffer, size_t address, size_t size)
|
||||
{
|
||||
assert(size);
|
||||
eepromTransmitData(address, buffer, size, false);
|
||||
}
|
||||
|
||||
bool _eeprom_write_simu_delay = true;
|
||||
|
||||
void eepromWriteBlock(uint8_t * buffer, size_t address, size_t size)
|
||||
{
|
||||
eepromStartWrite(buffer, address, size);
|
||||
|
||||
while (!eepromIsTransferComplete()) {
|
||||
if (_eeprom_write_simu_delay)
|
||||
sleep(1/*ms*/);
|
||||
}
|
||||
}
|
||||
|
||||
pthread_t eeprom_thread_pid;
|
||||
|
||||
void startEepromThread(const char * filename)
|
||||
{
|
||||
eepromFile = filename;
|
||||
if (eepromFile) {
|
||||
fp = fopen(eepromFile, "rb+");
|
||||
if (!fp)
|
||||
fp = fopen(eepromFile, "wb+");
|
||||
if (!fp)
|
||||
perror("error in fopen");
|
||||
}
|
||||
|
||||
#ifdef __APPLE__
|
||||
eeprom_write_sem = sem_open("eepromsem", O_CREAT, S_IRUSR | S_IWUSR, 0);
|
||||
#else
|
||||
eeprom_write_sem = (sem_t *)malloc(sizeof(sem_t));
|
||||
sem_init(eeprom_write_sem, 0, 0);
|
||||
#endif
|
||||
|
||||
RTOS_CREATE_TASK(eeprom_thread_pid, eeprom_thread_function, "eeprom");
|
||||
}
|
||||
|
||||
void stopEepromThread()
|
||||
{
|
||||
eeprom_thread_running = false;
|
||||
sem_post(eeprom_write_sem);
|
||||
pthread_join(eeprom_thread_pid, nullptr);
|
||||
|
||||
#ifdef __APPLE__
|
||||
sem_close(eeprom_write_sem);
|
||||
#else
|
||||
sem_destroy(eeprom_write_sem);
|
||||
free(eeprom_write_sem);
|
||||
#endif
|
||||
|
||||
if (fp)
|
||||
fclose(fp);
|
||||
}
|
||||
@@ -39,6 +39,7 @@
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/stat.h>
|
||||
#include <time.h>
|
||||
|
||||
#if MSVC_BUILD
|
||||
#include <direct.h>
|
||||
|
||||
@@ -45,6 +45,6 @@ if(Qt5Widgets_FOUND)
|
||||
target_compile_options(gtests-radio PRIVATE ${SIMU_SRC_OPTIONS})
|
||||
|
||||
add_dependencies(gtests-radio gtests-radio-lib)
|
||||
target_link_libraries(gtests-radio gtests-radio-lib pthread Qt5::Core Qt5::Widgets)
|
||||
target_link_libraries(gtests-radio gtests-radio-lib Qt5::Core Qt5::Widgets)
|
||||
message(STATUS "Added optional gtests target")
|
||||
endif()
|
||||
|
||||
Reference in New Issue
Block a user