Gabriel Staples
Gabriel Staples

Reputation: 52401

Mutexes/Locks in C: C11 `mtx_lock()` vs `pthread_mutex_lock()`

Mutexes were not introduced to the C standard until C11, right? Now that they exist, which should one use or prefer, and when? Why? What are the differences?

C11's mtx_lock() vs pthread_mutex_lock():

  1. C11's mtx_lock()
    1. From <threads.h>:
      1. https://en.cppreference.com/w/c/thread
      2. https://www.gnu.org/software/libc/manual/html_node/ISO-C-Mutexes.html
  2. pthread_mutex_lock()
    1. From <pthread.h>:
      1. https://pubs.opengroup.org/onlinepubs/7908799/xsh/pthread_mutex_lock.html
      2. https://man7.org/linux/man-pages/man3/pthread_mutex_lock.3p.html
    2. Stack Overflow: Mutex lock threads

It looks like <threads.h> is part of the C11 and later C standard, whereas <pthread.h> is a Posix standard provided by Linux directly? I don't have a good understanding of the history or ecosystem, or when to choose what, and why. It also makes me wonder: is <threads.h> part of any microcontroller compiler yet--ex: AVR, SAMD, or STM32? Ideally, whatever system I go with, I'd like it to work on Linux and microcontrollers, or even better: all operating systems, and microcontrollers.

Up to now I've done most locking on a computer in C++ using C++11's std::mutex, or on a microcontroller in C using FreeRTOS semaphores, or on a bare-metal microcontroller by turning interrupts and global interrupts on and off to protect volatile variables shared between ISRs and the main loop. Ex: on 8-bit AVR microcontrollers I use the ATOMIC_BLOCK() macros, which do just that. But, now I'm writing a fast_malloc() implementation in C and realized I don't even know how to use a mutex in C on a computer, so I began the above research and found the above links, and realized I don't know anything about pthread locks vs this new C11 mtx_lock().

Upvotes: 5

Views: 1942

Answers (1)

James Henstridge
James Henstridge

Reputation: 43879

The main benefit of the C11 mtx_t API is that it is part of the C standard, so is potentially more portable. However, that portability only extends as far as C11 support on the platforms you care about. For example, Microsoft only implemented C11 threads in 2023.

As you mention, the pthread API originates from POSIX. So it is mostly found on UNIX-like systems, but there are implementations for a number of other platforms. The specification dates to the 90s, so implementations are generally mature and stable on platforms where they're available.

Outside of portability, one difference is that the pthread_mutex_init function takes a pthread_mutexattr_t argument that can be used to customise the behaviour of the mutex. Some of the specified attributes include:

  • Setting the mutex type, such as creating a recursive mutex (allow a thread to lock the mutex multiple times) or an error checking mutex (return an error if a thread tries to lock the mutex multiple times).
  • Setting a priority ceiling and the protocol for handling threads with different priority. These are mostly of interest to realtime systems.
  • Allowing the mutex to be shared between processes that share memory. This opens up the possibility that a process that owns the mutex could terminate while other processes continue. So there is also a robust attribute to let you attempt to recover from this kind of error.

If none of that is of interest to you, then you could use either API. On most UNIX-like systems, the standard C mutexes are likely use the same implementation as the non-esoteric pthread mutexes.

Upvotes: 1

Related Questions