MISRA C 2023 consolidates guidelines for embedded developers

What’s new in MISRA C 2023 — the third edition and second revision of the MISRA C standard?

MISRA C 2023 has been released! As a member of the MISRA C working group, Parasoft contributes to the MISRA C standard. The MISRA organization had me in deep anticipation for this release after MISRA C 2012 Amendment 4 was published in March. 

MISRA C 2023 becomes the third edition and second revision of the MISRA C standard. It updates and incorporates MISRA C 2012 Amendments 2 – 4 and Technical Corrigendum 2. MISRA C 2012 was long-drawn and gave me flashbacks to being in a bunker, waiting for the world to come to an end. The long wait is over now, and my anticipation has shifted to the strong possibility of the MISRA organization releasing MISRA C++ 2023. But that’s a full story for another article.

The best news is that embedded industries and software teams developing in ISO/IEC 9899:2011 (C11) and ISO/IEC 9899:2018 (C18) versions of the C language have an updated C coding standard that continues to target safety and security vulnerabilities in the C language.

Another exciting fact is that Parasoft C/C++test fully supports MISRA C 2023 and MISRA C 2012 AMD 4. Teams can perform static code analysis on code with the newest MISRA C coding standards using our latest C/C++test 2023.1 product release.

So, what’s new in MISRA C 2012 Amendment 4—or should I say MISRA C 2023?

click for full size image

(Source: Parasoft)

Amendment 4 focuses on multi-threading and the use of atomic functions. Particularly the C11 built-in support for threads, atomic operations, mutual exclusion, condition variables, and thread-specific storages. Supported by the operating system, multithreading is the ability of a central processing unit to provide multiple threads of execution concurrently. Multithreaded applications can sometimes lead to unpredictable results because there are essentially multiple parts of a program that are running at the same time. For example, unpredictable issues will surface when threads are reading and writing to shared data. Therefore, synchronizing threads is very important when multi-threading.

Three new directives on concurrency considerations were created. New directive 5.1 states that there shall be no data races between threads. Thus, threads must be protected by a synchronization mechanism. It’s common to use a mutex or semaphore to prevent data race conditions like a read and write access on the same data at the same time. However, threads going about and locking data can pose its own issues, so new directive 5.2 states that there shall be no deadlocks between threads. This equates to having absolutely no cyclic dependencies between threads. And in addition, because of the uncertainty of knowing how many threads are running at a particular point in time, it justified new directive 5.3 where there shall be no dynamic thread creation. Creation of threads shall occur only at program start-up.

MISRA C 2012 AMD4 also created new rules in support of C11 language features, particularly for threading and by way of atomic functions . The C11 language adopted a set of atomic types and operations into the language, which makes it possible to write portable multi-threaded software that efficiently manipulates objects indivisibly and without data races. To get things properly set, new rule 9.7 states that atomic objects shall be appropriately initialized before being accessed. Here is one simple example using the atomic_init() function:

_Atomic int32_t ai3;   
atomic_init(&ai3, 333);    /* Compliant */

New rule 21.25 states that all memory synchronization operations shall be executed in sequentially consistent order. C11 provides a set of library functions that implicitly uses the strictest memory ordering variant “memory_order_seq_cst”.

  • atomic_store()
  • atomic_load()
  • atomic_exchange()
  • atomic_compare_exchange_strong()
  • atomic_compare_exchange_weak()
  • atomic_fetch_add()
  • atomic_fetch_sub()
  • atomic_fetch_or()
  • atomic_fetch_xor()
  • atomic_fetch_and()
  • atomic_flag_test_and_set()
  • atomic_flag_clear()
  • atomic_thread_fence()
  • atomic_signal_fence()

memory_order_seq_cst provides read and write ordering globally, and the sequentially consistent operations are visible in the same order across all threads.

Since a mutex is highly dependent on for synchronization, the MISRA C working group also took a good look at hardening the use of C11 mtx_timedlock(). The mtx_timedlock() function blocks the current thread until the mutex pointed to is locked or until a specified timeout expires. However, if the current thread has already locked the mutex and the mutex is not recursive or if the mutex does not support timeout, then the behavior is undefined. Therefor new rule 21.26 states that the standard library function mtx_timedlock() shall only be invoked on mutex objects of appropriate mutex type. The first argument of function mtx_timedlock() must be a mutex object of mutex type mtx_timed or (mtx_timed | mtx_recursive). But for this to properly work, the mutex object must be properly initialized.

New rule 22.14 states that thread synchronization objects shall be initialized before being accessed. Initializing all synchronization objects before creating the threads accessing them is a deterministic way to prevent threads from accessing synchronization objects with indeterminate state. C11 standard library function mtx_init() with different value of its type parameter than listed below is considered undefined behavior and non-compliant.

  • mtx_plain – a simple, non-recursive mutex.
  • mtx_timed – a non-recursive mutex, that supports timeout.
  • mtx_plain | mtx_recursive – a recursive mutex.
  • mtx_timed | mtx_recursive – a recursive mutex, that supports timeout.

Additional rules have been created to ensure that the use of concurrency or threads defined in C11 are safe as well as the synchronization, conditions, and thread-local storage. Below is a list of C11 functions that have required or mandatory categorization in MISRA C 2012 AMD4. New rules such as 22.11 – 22.20.

thrd_create() mtx_init() cnd_init() tss_create()
thrd_current() mtx_lock() cnd_signal() tss_get()
thrd_sleep() mtx_timedlock() cnd_broadcast() tss_set()
thrd_yield() mtx_trylock() cnd_wait() tss_delete()
thrd_exit() mtx_unlock() cnd_timedwait()  
thrd_detach() mtx_destroy() cnd_destroy()  

Of course, there are a few new rules that aren’t related to concurrency. Like mandatory rule 18.10, where pointers to variably modified array types shall not be used. In all, MISRA C 2012 AMD 4 has added 3 new directives and 19 new rules. Again, Parasoft C/C++test 2023.1 fully supports MISRA C 2012 AMD4 and MISRA C 2023. We have made it available to software development teams looking to ensure deployment of code that’s compliant with the latest MISRA coding standard.

Ricardo Camacho is Director of Regulatory Safety and Security Compliance for Parasoft’s embedded testing solutions. Ricardo has over 30 years expertise in Systems & Software engineering of embedded real-time, safety and security critical systems.

Related Contents: