2

I have been developing an RTOS based embedded software in C and I have encountered a problem regarding shared resource access from several threads. I have two problems. The first one is seting and getting a value of state variable in state machine. Below is the header file for StateMachine "object":

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);

The implementation of the access methods is following:

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

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

My problem is that I am not sure whether I should use a mutex for controlling the access to state variable. I meant that reading and writing of 32 bit variable on 32 bit MCU is atomic operation.

The second problem regards reading the value of one item of an array containing the unsigned 32 bits integers where each bit stores a value of one bit variable. Here again I am not sure whether it is necessary to use a mutex. From the same reason as above I think no but I would like to hear an opinion of some more experienced programmer. The associated header file for bits array "object":

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

extern uint32_t GetWordValue(BitsArray*, uint8_t);

The access method implementation:

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

Thank you for any ideas.

Steve
  • 805
  • 7
  • 27
  • 2
    You are sharing the current state of a state machine between multiple concurrent execution contexts? Then you have a bigger problem than the atomicity of the variable access. Do yourself a favor and go back and look very closely for alternative designs. – andy mango May 08 '18 at 14:47
  • 2
    ^^^ what @andymango says. If I need to operate a SM, I usually queue, (producer-consumer queue), events into one thread that has sole access to the state data. Anything else turns into an undebuggable mess very quickly. – Martin James May 08 '18 at 14:55
  • Also, the answer to your question depends in part on whether the target system has more than one CPU core. If it has more than one, then different threads running on different cores at the same time can have different opinions about what is out in memory. (Google for "Cache Coherence".) It is the responsibility of your RTOS to provide you with the tools you need to safely share data between different threads in that case. – Solomon Slow May 08 '18 at 16:20

1 Answers1

4

Both of your questions is the same problem really.

32 bit MCU means nothing unless you disassemble the code and verify that the operation is indeed a single instruction. This is often not the case with C code.

Often you have 2 or more instructions like: "load value from stack into register", "do stuff with register", in which case it doesn't matter how many bits your MCU got. You can get an interrupt or context switch in between the two instructions.

And even if you can verify that the machine code is atomic, that's not necessarily a stable state of affairs. Make changes to the code, add more variables, link again, and suddenly code that was atomic before is atomic no longer, or vice versa.

C simply has no guarantee of atomicity. Some alternatives if you don't trust the disassembly:

  • C11 _Atomic.
  • Write inline assembler.
  • Use a mutex or similar synchronization mechanism.
Lundin
  • 195,001
  • 40
  • 254
  • 396