Skip to content

Commit

Permalink
Thread Calculation : fix data race.
Browse files Browse the repository at this point in the history
  • Loading branch information
brunotl committed Nov 22, 2024
1 parent a19f593 commit e423c6b
Show file tree
Hide file tree
Showing 4 changed files with 81 additions and 80 deletions.
1 change: 0 additions & 1 deletion Common/Header/Globals.h
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,6 @@ struct Radio_t {
};

GEXTERN bool MenuActive GEXTFALSE;
GEXTERN Poco::Event dataTriggerEvent;

GEXTERN unsigned short HaveSystemInfo GEXTZERO; // Normally only on linux
GEXTERN bool HaveBatteryInfo GEXTFALSE;
Expand Down
153 changes: 79 additions & 74 deletions Common/Source/Thread_Calculation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,7 @@ extern bool OnFastPanning;
// PulseEvent is unreliable. But it does not matter anymore, since we should
// change approach for compatibility with unix.

void TriggerRedraws(NMEA_INFO *nmea_info, DERIVED_INFO *derived_info) {
(void) nmea_info;
(void) derived_info;
void TriggerRedraws() {

#ifndef ENABLE_OPENGL
if (MapWindow::IsDisplayRunning()) {
Expand All @@ -42,119 +40,122 @@ void TriggerRedraws(NMEA_INFO *nmea_info, DERIVED_INFO *derived_info) {
#endif
}

// System boot specific flags
// Give me a go/no-go
static bool goCalculationThread = false;

class CalculationThread : public Thread {
public:
CalculationThread() : Thread("Calculation") {}

void Run() override {
bool needcalculationsslow = false;

// let's not create a deadlock here, setting the go after another race condition
goCalculationThread = true; // 091119 CHECK
// wait for proper startup signal
while (!MapWindow::IsDisplayRunning()) {
Sleep(100);
}

Sleep(1000); // 091213 BUGFIX need to syncronize !!! TOFIX02 TODO

while (!MapWindow::CLOSETHREAD) {
Sleep(1000); // 091213 BUGFIX need to synchronize !!! TOFIX02 TODO

if (dataTriggerEvent.tryWait(5000)) dataTriggerEvent.reset();
if (MapWindow::CLOSETHREAD) break; // drop out on exit
while (Wait()) {

#ifdef HAVE_CPU_FREQUENCY
const ScopeLockCPU cpu;
#endif
// make local copy before editing...
LockFlightData();
FLARM_RefreshSlots(&GPS_INFO);
Fanet_RefreshSlots(&GPS_INFO); //refresh slots of FANET
memcpy(&tmpGPS, &GPS_INFO, sizeof (NMEA_INFO));
memcpy(&tmpCALCULATED, &CALCULATED_INFO, sizeof (DERIVED_INFO));
UnlockFlightData();

DoCalculationsVario(&tmpGPS, &tmpCALCULATED);
if (!VarioAvailable(tmpGPS)) {
UpdateLocalFlightData();

DoCalculationsVario(&Local_NMEA, &Local_DERIVED);
if (!VarioAvailable(Local_NMEA)) {
TriggerVarioUpdate(); // emulate vario update
}

if (DoCalculations(&tmpGPS, &tmpCALCULATED)) {
#if (WINDOWSPC>0) && !TESTBENCH
#else
if (!INPAN)
#endif
{
bool needcalculationsslow = false;

if (DoCalculations(&Local_NMEA, &Local_DERIVED)) {
if (!INPAN) {
MapWindow::MapDirty = true;
}
needcalculationsslow = true;

if (tmpCALCULATED.Circling)
if (Local_DERIVED.Circling) {
MapWindow::mode.Fly(MapWindow::Mode::MODE_FLY_CIRCLING);
else if (tmpCALCULATED.FinalGlide)
}
else if (Local_DERIVED.FinalGlide) {
MapWindow::mode.Fly(MapWindow::Mode::MODE_FLY_FINAL_GLIDE);
else
}
else {
MapWindow::mode.Fly(MapWindow::Mode::MODE_FLY_CRUISE);
}
}

if (MapWindow::CLOSETHREAD) break; // drop out on exit

// values changed, so copy them back now: ONLY CALCULATED INFO
// should be changed in DoCalculations, so we only need to write
// that one back (otherwise we may write over new data)
// Need to be Done before TriggerRedraw
LockFlightData();
memcpy(&CALCULATED_INFO, &tmpCALCULATED, sizeof (DERIVED_INFO));
UnlockFlightData();
// Need to be Done before TriggerRedraw
UpdateCalculatedFlightData();

// This is activating another run for Thread Draw
TriggerRedraws(&tmpGPS, &tmpCALCULATED);
TriggerRedraws();

if (MapWindow::CLOSETHREAD) break; // drop out on exit
if (needcalculationsslow || (SIMMODE && ReplayLogger::IsEnabled())) {
DoCalculationsSlow(&Local_NMEA, &Local_DERIVED);
needcalculationsslow = false;

bool need_update = false;
if (SIMMODE) {
if (needcalculationsslow || (ReplayLogger::IsEnabled())) {
DoCalculationsSlow(&tmpGPS, &tmpCALCULATED);
needcalculationsslow = false;
need_update = true;
}
} else {
if (needcalculationsslow) {
DoCalculationsSlow(&tmpGPS, &tmpCALCULATED);
needcalculationsslow = false;
need_update = true;
}
}

if(need_update) {
// CALCULATED_INFO need to copy back second time if data are updated by DoCalculationsSlow;
LockFlightData();
memcpy(&CALCULATED_INFO, &tmpCALCULATED, sizeof (DERIVED_INFO));
UnlockFlightData();
}

if (MapWindow::CLOSETHREAD) break; // drop out on exit
UpdateCalculatedFlightData();
}

// update live tracker with new values
// this is a nonblocking call, live tracker runs on different thread
tracking::Update(tmpGPS, tmpCALCULATED);
tracking::Update(Local_NMEA, Local_DERIVED);

UpdateFlightDataRecorder(tmpGPS, tmpCALCULATED);
CheckAltitudeAlarms(tmpGPS, tmpCALCULATED);
UpdateFlightDataRecorder(Local_NMEA, Local_DERIVED);
CheckAltitudeAlarms(Local_NMEA, Local_DERIVED);

ExternalDeviceSendTarget();
SendDataToExternalDevice(tmpGPS, tmpCALCULATED);
SendDataToExternalDevice(Local_NMEA, Local_DERIVED);
}
}

void SignalNewData() {
ScopeLock lock(mtx);
new_data = true;
cond.Signal();
}

void RequestStop() {
ScopeLock lock(mtx);
run = false;
cond.Signal();
}

private:
NMEA_INFO tmpGPS;
DERIVED_INFO tmpCALCULATED;

void UpdateLocalFlightData() {
ScopeLock lock(CritSec_FlightData);
FLARM_RefreshSlots(&GPS_INFO);
Fanet_RefreshSlots(&GPS_INFO); //refresh slots of FANET
Local_NMEA = GPS_INFO;
Local_DERIVED = CALCULATED_INFO;
}

void UpdateCalculatedFlightData() {
ScopeLock lock(CritSec_FlightData);
CALCULATED_INFO = Local_DERIVED;
}

bool Wait() {
ScopeLock lock(mtx);
while (run && !new_data) {
cond.Wait(mtx);
}
new_data = false;
return run;
}

NMEA_INFO Local_NMEA;
DERIVED_INFO Local_DERIVED;

Mutex mtx;
Cond cond;
bool run = true;
bool new_data = false;
};

CalculationThread _CalculationThread;
Expand All @@ -165,12 +166,16 @@ CalculationThread _CalculationThread;
void CreateCalculationThread() {
// Create a read thread for performing calculations
_CalculationThread.Start();

while(!(goCalculationThread)) {
Sleep(50);
}
}

void WaitThreadCalculation() {
_CalculationThread.Join();
}

void StopThreadCalculation() {
_CalculationThread.RequestStop();
}

void TriggerGPSUpdate() {
_CalculationThread.SignalNewData();
}
4 changes: 0 additions & 4 deletions Common/Source/Utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,6 @@ int GetUTCOffset() {
return UTCOffset;
}

void TriggerGPSUpdate() {
dataTriggerEvent.set();
}

// This is currently doing nothing.

void TriggerVarioUpdate() {
Expand Down
3 changes: 2 additions & 1 deletion Common/Source/Window/WndMain.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ WndMain::~WndMain() {
}

extern void WaitThreadCalculation();
extern void StopThreadCalculation();

void BeforeShutdown(void) {

Expand Down Expand Up @@ -110,7 +111,7 @@ void BeforeShutdown(void) {
MapWindow::CloseDrawingThread();

// Stop calculating too (wake up)
dataTriggerEvent.set();
StopThreadCalculation();

// Clear data
// LKTOKEN _@M1222_ "Shutdown, saving task..."
Expand Down

0 comments on commit e423c6b

Please sign in to comment.