Search code examples
cstorefreertos

Create thread safe global store in C


I'm writing an application running on FreeRTOS where I have different threads that all have to access (read and some write) the same data structures. So I thought I could implement a global data store holding all the data in some grouped structs. I also thought about using something like SQLite but I think that's an overkill for my application.

Nevertheless there are some open questions

  1. To guarantee thread safety I assume I need to add a semaphore for my read and write access but...
  2. If a thread only has to update certain elements of a struct I'd need to hand it a pointer to that struct, but as soon as I start using pointer references I can no longer protect my access with a semaphore. So how can I allow a thread to modify single struct elements without violating thread safety?
  3. Is there a better way to have something like a global store than the one I planned to use? Google didn't give much hints.

Solution

  • Let me share with you the most common C-way to handle this type of scenarios.

    In order to avoid exposing a lot of global data, use opaque pointers and have a list of APIs that take the opaque pointer as a parameter. In this way you can have a clean set of APIs to access all of your structures leaving the implementation specifics just in the .c file. The good thing about using opaque pointers is that no one knows how to deal with the type pointed-to-data except for the APIs that takes in opaque pointer as a parameter. This provides protection & encapsulation to your structures, so that they are ever accessed or mutated with the APIs that you provide.

    In each of the structure definitions identified by the opaque pointers, have a mutex (FreeRTOS has mutex implemented in-terms of semaphores) to access the structure members in a thread-safe manner. You have to use xSemaphoreCreateMutex when creating the mutex. In all your APIs use xSemaphoreGive & xSemaphoreTake when you want to access the member data that are potentially accessed by multiple tasks.