mirror of
https://gitee.com/mirrors_PX4/PX4-Autopilot.git
synced 2026-07-16 05:20:36 +08:00
output modules simplify locking for mixer reset and load
- fixes the deadlock in px4io ioctl mixer reset - px4io Run() locks (CDev semaphore) - mixer load goes through px4io ioctl MIXERIOCRESET which calls MixingOutput::resetMixerThreadSafe() - MixingOutput::resetMixerThreadSafe() stores a Command::Type::resetMixer command in an atomic variable, schedules a work queue cycle, then sleep spins until the command is cleared - the execution of the cycle eventually calls back into PX4IO::updateOutputs(), which tries to lock (and waits forever)
This commit is contained in:
@@ -331,7 +331,6 @@ bool MixingOutput::updateSubscriptionsStaticMixer(bool allow_wq_switch, bool lim
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void MixingOutput::cleanupFunctions()
|
||||
{
|
||||
if (_subscription_callback) {
|
||||
@@ -645,7 +644,6 @@ bool MixingOutput::update()
|
||||
bool MixingOutput::updateStaticMixer()
|
||||
{
|
||||
if (!_mixers) {
|
||||
handleCommands();
|
||||
// do nothing until we have a valid mixer
|
||||
return false;
|
||||
}
|
||||
@@ -707,7 +705,6 @@ bool MixingOutput::updateStaticMixer()
|
||||
setAndPublishActuatorOutputs(num_motor_test, actuator_outputs);
|
||||
}
|
||||
|
||||
handleCommands();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -749,8 +746,6 @@ bool MixingOutput::updateStaticMixer()
|
||||
updateLatencyPerfCounter(actuator_outputs);
|
||||
}
|
||||
|
||||
handleCommands();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1248,88 +1243,3 @@ int MixingOutput::loadMixer(const char *buf, unsigned len)
|
||||
_interface.mixerChanged();
|
||||
return ret;
|
||||
}
|
||||
|
||||
void MixingOutput::handleCommands()
|
||||
{
|
||||
if ((Command::Type)_command.command.load() == Command::Type::None) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch ((Command::Type)_command.command.load()) {
|
||||
case Command::Type::loadMixer:
|
||||
_command.result = loadMixer(_command.mixer_buf, _command.mixer_buf_length);
|
||||
break;
|
||||
|
||||
case Command::Type::resetMixer:
|
||||
resetMixer();
|
||||
_command.result = 0;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// mark as done
|
||||
_command.command.store((int)Command::Type::None);
|
||||
}
|
||||
|
||||
void MixingOutput::resetMixerThreadSafe()
|
||||
{
|
||||
if (_use_dynamic_mixing) {
|
||||
PX4_ERR("mixer reset unavailable, not using static mixers");
|
||||
return;
|
||||
}
|
||||
|
||||
if ((Command::Type)_command.command.load() != Command::Type::None) {
|
||||
// Cannot happen, because we expect only one other thread to call this.
|
||||
// But as a safety precaution we return here.
|
||||
PX4_ERR("Command not None");
|
||||
return;
|
||||
}
|
||||
|
||||
lock();
|
||||
|
||||
_command.command.store((int)Command::Type::resetMixer);
|
||||
|
||||
_interface.ScheduleNow();
|
||||
|
||||
unlock();
|
||||
|
||||
// wait until processed
|
||||
while ((Command::Type)_command.command.load() != Command::Type::None) {
|
||||
usleep(1000);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
int MixingOutput::loadMixerThreadSafe(const char *buf, unsigned len)
|
||||
{
|
||||
if (_use_dynamic_mixing) {
|
||||
PX4_ERR("mixer load unavailable, not using static mixers");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((Command::Type)_command.command.load() != Command::Type::None) {
|
||||
// Cannot happen, because we expect only one other thread to call this.
|
||||
// But as a safety precaution we return here.
|
||||
PX4_ERR("Command not None");
|
||||
return -1;
|
||||
}
|
||||
|
||||
lock();
|
||||
|
||||
_command.mixer_buf = buf;
|
||||
_command.mixer_buf_length = len;
|
||||
_command.command.store((int)Command::Type::loadMixer);
|
||||
|
||||
_interface.ScheduleNow();
|
||||
|
||||
unlock();
|
||||
|
||||
// wait until processed
|
||||
while ((Command::Type)_command.command.load() != Command::Type::None) {
|
||||
usleep(1000);
|
||||
}
|
||||
|
||||
return _command.result;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user