Атомная работа в многопоточном встроенном программном обеспечении - PullRequest
0 голосов
/ 08 мая 2018

Я занимался разработкой встроенного программного обеспечения для ОС RTOS на C и столкнулся с проблемой доступа к общим ресурсам из нескольких потоков. У меня две проблемы. Первый - установка и получение значения переменной состояния в конечном автомате. Ниже приведен заголовочный файл для StateMachine «объект»:

typedef enum{
  STATE_01,
  STATE_02,
  STATE_03,
  STATE_04
}state_e;

// state machine instance
typedef struct{
  state_e currState;
}StateMachine;

extern state_e GetState(StateMachine*);
extern void SetState(StateMachine*, state_e);

Реализация методов доступа следующая:

state_e GetState(StateMachine *sm){
  return sm->currState;
}

void SetState(StateMachine *sm, state_e state){
  sm->currState = state;
}

Моя проблема в том, что я не уверен, должен ли я использовать мьютекс для управления доступом к переменной состояния. Я имел в виду, что чтение и запись 32-битной переменной на 32-битном MCU - это атомарная операция.

Вторая проблема касается чтения значения одного элемента массива, содержащего 32-разрядные целые числа без знака, где каждый бит хранит значение одной битовой переменной. И здесь я не уверен, нужно ли использовать мьютекс. По той же причине, что и выше, я думаю, что нет, но я хотел бы услышать мнение более опытного программиста. Связанный заголовочный файл для массива битов «объект»:

typedef struct{
  uint32_t BitsArray[NO_WORDS];
}BitsArray;

extern uint32_t GetWordValue(BitsArray*, uint8_t);

Реализация метода доступа:

uint32_t GetWordValue(BitsArray *ba, uint8_t word){
 return *(ba->BitsArray + word);
}

Спасибо за любые идеи.

1 Ответ

0 голосов
/ 08 мая 2018

Оба ваших вопроса - это действительно одна и та же проблема.

32-битный MCU ничего не значит, если вы не разберете код и не убедитесь, что операция действительно является одной инструкцией . Это часто не в случае с кодом C.

Часто у вас есть 2 или более инструкций, таких как: «загрузить значение из стека в регистр», «делать вещи с регистром», в этом случае не имеет значения, сколько битов получил ваш MCU. Вы можете получить прерывание или переключение контекста между двумя инструкциями.

И даже если вы можете проверить, что машинный код является атомарным, это не обязательно стабильное состояние дел. Внесите изменения в код, добавьте дополнительные переменные, снова свяжите и внезапно код, который был атомарным до того, как атомарный перестал быть, или наоборот.

C просто не имеет гарантии атомарности. Некоторые альтернативы, если вы не доверяете разборке:

  • C11 _Atomic.
  • Написать встроенный ассемблер.
  • Используйте мьютекс или аналогичный механизм синхронизации.
...