This documents some of the design decisions made when implementing the C11 threading primitives on Windows

tss_t

Note: see C11 defect report: tss_t destruction unspecified for issues with the standard specification of tss_t. The PDCLib implementation at present follows that report.

Windows provides a thread local storage implementation which mostly implements the requirements of the standard. However, it doesn't implement destructors. To solve that, PDCLib uses two approaches

There are three cases to consider:

Our implementation strategy:

mtx_t

Our implementation doesn't use Win32 CRITICAL_SECTIONs; primarily because this would involve exposing <windows.h> to all people who include <threads.h>, or duplicating the definition of CRITICAL_SECTION (messy). Instead, we implement a locking primitive on top of Windows' event handles

  1. Every mutex has two members, _WaitEvHandle, which is a automatic reset Win32 event handle used for blocking, and _ThreadId, the ID of the current thread
  2. _ThreadId is initialized to 0
  3. To lock, mtx_lock calls InterlockedCompareExchange on _ThreadId. If the return value is 0, we successfully locked the mutex. If it is not 0, then we must block, so go ahead and block on the event handle
  4. To unlock, mtx_unlock sets _ThreadId to 0 and invokes SetEvent to unblock a thread