*/ } ul /* Whole unordered list */ { } ul li /* Unordered list item */ { } ol /* Whole ordered list */ { } ol li /* Ordered list item */ { } hr {} /* ---- Some span elements --- */ sub /* Subscripts. Pandoc: H~2~O */ { } sup /* Superscripts. Pandoc: The 2^nd^ try. */ { } em /* Emphasis. Markdown: *emphasis* or _emphasis_ */ { } em > em /* Emphasis within emphasis: *This is all *emphasized* except that* */ { font-style: normal; } blockquote > p > em /* Emphasis within emphasis: *This is all *emphasized* except that* */ { font-style: normal; } blockquote > * > p > em /* Emphasis within emphasis: *This is all *emphasized* except that* */ { font-style: normal; } blockquote > p > ins > em /* Emphasis within emphasis: *This is all *emphasized* except that* */ { font-style: normal; } blockquote > * > p > ins > em /* Emphasis within emphasis: *This is all *emphasized* except that* */ { font-style: normal; } /* ---- Links (anchors) ---- */ a /* All links */ { /* Keep links clean. On screen, they are colored; in print, they do nothing anyway. */ text-decoration: none; } @media screen { a:hover { /* On hover, we indicate a bit more that it is a link. */ text-decoration: underline; } } @media print { a { /* In print, a colored link is useless, so un-style it. */ color: black; background: transparent; } a[href^="http://"]:after, a[href^="https://"]:after { /* However, links that go somewhere else, might be useful to the reader, so for http and https links, print the URL after what was the link text in parens */ content: " (" attr(href) ") "; font-size: 90%; } } /* ---- Images ---- */ img { /* Let it be inline left/right where it wants to be, but verticality make it in the middle to look nicer, but opinions differ, and if in a multi-line paragraph, it might not be so great. */ vertical-align: middle; } div.figure /* Pandoc figure-style image */ { /* Center the image and caption */ margin-left: auto; margin-right: auto; text-align: center; font-style: italic; } p.caption /* Pandoc figure-style caption within div.figure */ { /* Inherits div.figure props by default */ } /* ---- Code blocks and spans ---- */ pre, code { background-color: #fdf7ee; /* BEGIN word wrap */ /* Need all the following to word wrap instead of scroll box */ /* This will override the overflow:auto if present */ white-space: pre-wrap; /* css-3 */ white-space: -moz-pre-wrap !important; /* Mozilla, since 1999 */ white-space: -pre-wrap; /* Opera 4-6 */ white-space: -o-pre-wrap; /* Opera 7 */ word-wrap: break-word; /* Internet Explorer 5.5+ */ /* END word wrap */ } pre /* Code blocks */ { /* Distinguish pre blocks from other text by more than the font with a background tint. */ padding: 0.5em; /* Since we have a background color */ border-radius: 5px; /* Softens it */ /* Give it a some definition */ border: 1px solid #aaa; /* Set it off left and right, seems to look a bit nicer when we have a background */ margin-left: 0.5em; margin-right: 0.5em; } pre.yacc, code.yacc { background-color: #f0f0f0; } pre.yacc /* Code blocks */ { /* Distinguish pre blocks from other text by more than the font with a background tint. */ padding: 0.0em; /* Since we have a background color */ border-radius: 5px; /* Softens it */ /* Give it a some definition */ border: 0px solid #aaa; /* Set it off left and right, seems to look a bit nicer when we have a background */ margin-left: 0.0em; margin-right: 0.0em; } @media screen { pre { white-space: pre; /* Dotted looks better on screen and solid seems to print better. */ border: 1px dotted #777; } } code /* All inline code spans */ { } p > code, li > code /* Code spans in paragraphs and tight lists */ { /* Pad a little from adjacent text */ padding-left: 2px; padding-right: 2px; } li > p code /* Code span in a loose list */ { /* We have room for some more background color above and below */ padding: 2px; } span.option { color: blue; text-decoration: underline; } /* ---- Math ---- */ span.math /* Pandoc inline math default and --jsmath inline math */ { /* Tried font-style:italic here, and it messed up MathJax rendering in some browsers. Maybe don't mess with at all. */ } div.math /* Pandoc --jsmath display math */ { } span.LaTeX /* Pandoc --latexmathml math */ { } eq /* Pandoc --gladtex math */ { } /* ---- Tables ---- */ /* A clean textbook-like style with horizontal lines above and below and under the header. Rows highlight on hover to help scanning the table on screen. */ table { border-collapse: collapse; border-spacing: 0; /* IE 6 */ border-bottom: 2pt solid #000; border-top: 2pt solid #000; /* The caption on top will not have a bottom-border */ /* Center */ margin-left: auto; margin-right: auto; } thead /* Entire table header */ { border-bottom: 1pt solid #000; background-color: #eee; /* Does this BG print well? */ } tr.header /* Each header row */ { } tbody /* Entire table body */ { } /* Table body rows */ tr { } tr.odd:hover, tr.even:hover /* Use .odd and .even classes to avoid styling rows in other tables */ { background-color: #eee; } /* Odd and even rows */ tr.odd {} tr.even {} td, th /* Table cells and table header cells */ { vertical-align: top; /* Word */ vertical-align: baseline; /* Others */ padding-left: 0.5em; padding-right: 0.5em; padding-top: 0.2em; padding-bottom: 0.2em; } /* Removes padding on left and right of table for a tight look. Good if thead has no background color*/ /* tr td:last-child, tr th:last-child { padding-right: 0; } tr td:first-child, tr th:first-child { padding-left: 0; } */ th /* Table header cells */ { font-weight: bold; } tfoot /* Table footer (what appears here if caption is on top?) */ { } caption /* This is for a table caption tag, not the p.caption Pandoc uses in a div.figure */ { caption-side: top; border: none; font-size: 0.9em; font-style: italic; text-align: center; margin-bottom: 0.3em; /* Good for when on top */ padding-bottom: 0.2em; } /* ---- Definition lists ---- */ dl /* The whole list */ { border-top: 2pt solid black; padding-top: 0.5em; border-bottom: 2pt solid black; } dt /* Definition term */ { font-weight: bold; } dd+dt /* 2nd or greater term in the list */ { border-top: 1pt solid black; padding-top: 0.5em; } dd /* A definition */ { margin-bottom: 0.5em; } dd+dd /* 2nd or greater definition of a term */ { border-top: 1px solid black; /* To separate multiple definitions */ } /* ---- Footnotes ---- */ a.footnote, a.footnoteRef { /* Pandoc, MultiMarkdown footnote links */ font-size: small; vertical-align: text-top; } a[href^="#fnref"], a.reversefootnote /* Pandoc, MultiMarkdown, ?? footnote back links */ { } @media print { a[href^="#fnref"], a.reversefootnote /* Pandoc, MultiMarkdown */ { /* Don't display these at all in print since the arrow is only something to click on */ display: none; } } div.footnotes /* Pandoc footnotes div at end of the document */ { } div.footnotes li[id^="fn"] /* A footnote item within that div */ { } table tr td,th { border-right: 1px solid; border-left: 1px solid; } /* You can class stuff as "noprint" to not print. Useful since you can't set this media conditional inside an HTML element's style attribute (I think), and you don't want to make another stylesheet that imports this one and adds a class just to do this. */ @media print { .noprint { display:none; } }
2025-10-07
integration into IS ISO/IEC 9899:202y
C document ID: C4242
document number | date | comment |
---|---|---|
n3672 | 202507 | Original proposal |
n3708 | 202510 | better single out the different atomic operations |
integrate feedback from the reflector |
CC BY, see https://creativecommons.org/licenses/by/4.0
This paper draws part of its motivation from n3655
‘’Make implicit undefined behaviour in
mtx_destroy()
explicit’’,
and could either replace the solutions proposed there or be constructed on top of it. When discussing that paper on the reflector it became quickly apparent, that not only the undefined behavior is currently poorly described, but that the description also lacks a proper integration into C11’s model of inter-thread time.
For example, the “General” section unspecifically indicate that lock and unlock “behave as atomic operation” and “in some particular order” without properly relating to the terminology that is developed for atomic objects. In particular a simple mapping of a lock operation as one single atomic operation is not sensible: because a thread that enters a lock operation can be blocked for an indeterminate amount of time, the entry into a call and the return from the call have to represent two separate events in the modification order of the mutex:
The only sensible way to provide this integration is to add mutexes
to the set of atomic types, but much as atomic_flag
that
this type then has only atomic operations and an internal state that is
not observable directly.
So, here we distinguish the following atomic modifications in the modification order of a mutex:
memory_order_relaxed
),memory_order_acquire
),memory_order_relaxed
),memory_order_release
).Additions by this paper here are:
Replace the whole clause 7.30.4.1, General,
1
For purposes of determining the existence of a data race, lock and unlock operations behave as atomic operations. All lock and unlock operations on a particular mutex occur in some particular total order.
2 NOTE This total order can be viewed as the modification order of the mutex.
by
1 A mutex is an atomic object that implements specific operations corresponding to calls to the functions as described in this subclause. It has two states, locked and unlocked,FTN0) that are only observable by the behavior of the operations associated with the type. The atomic operations are described by lock (mtx_lock
,mtx_timedlock
,mtx_trylock
) and unlock (mtx_unlock
) operations that operate on this state. The entry to a lock operation and the return from it are two distinct atomic modifications in the modification order of the mutex, lock-entry and lock-return. Unless the function return value isthrd_error
, the calling thread is suspended between the lock-entry and the lock-return events performed during amtx_lock
ormtx_timedlock
operation; after writing the lock-entry the calling thread is said to be blocked, the writing of lock-return is said to unblock the calling thread.
FTN0) If the mutex is recursive, a given mutex can be locked several times by the same thread.
2 The lock-return of a successful lock operation and any unlock operation are synchronization operations with respect to the atomic mutex object; they havememory_order_acquire
andmemory_order_release
semantics, respectively. A lock-entry and the lock-return from an operation that is unsuccessful have a memory order that is at least as strong asmemory_order_relaxed
. In addition to the atomic operations, there are themtx_init
andmtx_destroy
operations as well as modifications of the object representationFTN1) that also are modifications in the modification order of a mutex.
FTN1) These include for example a copy operation of a
structure type that has a mtx_t
member.
3 A mutex that is not initialized bymtx_init
, or whose last operation has been amtx_destroy
operation, or such that its object representation has been modified directly, has an indeterminate representation; performing any operation other thanmtx_init
on such a mutex has undefined behavior.
4 As the consequence of amtx_init
operation the state of the mutex is unlocked, and, for any thread, the first subsequent modification in the modification order shall be a lock-entry or amtx_destroy
operation.
5 Before a mtx_destroy
operation the
state of the mutex shall be unlocked, and, for any thread, the last
preceding modification in the modification order shall not be the entry
to a lock operation; similar requirements hold for a mutex that is not
in an indeterminate state and to which a direct modification of the
object representation is applied.
6 NOTE That means that if a thread is suspended to acquire the lock of a mutex and another thread concurrently callsmtx_destroy
on that same mutex, the behavior is undefined. Similarly, if a thread holds a lock on a mutex and the same or another thread concurrently callsmtx_destroy
on that same mutex, the behavior is undefined.
…
7.30.4.2 The mtx_destroy function
…
Transform the second sentence into a note.
2 The
mtx_destroy
function releases any resources used by the mutex pointed to bymtx
.
3 NOTE In an execution that respects the requirements (7.30.4.1) for the modification order, the mutex is initialized prior to a call tomtx_destroy
and no threadscan beare blocked waitingforto acquire the lock of the mutex pointed to bymtx
.
…
7.30.4.3 The
mtx_init
function
…
3 If the
mtx_init
function succeeds, it sets the mutex pointed to bymtx
to avaluevalid representation that uniquely identifies the newly created mutex and that corresponds to the unlocked state.
Returns
4 The
mtx_init
function returnsthrd_success
on success, orthrd_error
if the request could not be honoredotherwise.
7.30.4.4 The
mtx_lock
function
…
Returns
3 The
mtx_lock
function returnsthrd_success
on successif the mutex has been successfully locked by the calling thread, orthrd_error
if the request could not be honoredotherwise.
…
7.30.4.5 The mtx_timedlock function
…
Returns
3 The
mtx_timedlock
function returnsthrd_success
on successif the mutex has been successfully locked by the calling thread, or otherwisethrd_timedout
if the time specified was reachedwithout acquiring the requested resource, orthrd_error
if the request could not be honoredotherwise.
…
7.30.4.6 The mtx_trylock function
…
Returns
3 The
mtx_trylock
function returnsthrd_success
on successif the mutex has been successfully locked by the calling thread, or otherwisethrd_busy
ifthe resource requested is already in usethe mutex is in a valid state but could not be locked, orthrd_error
if the request could not be honoredotherwise.
Split the last sentence off and make it a note.
4 NOTE
mtx_trylock
can spuriously fail to lockan unused resourcean unlocked but otherwise valid mutex, in which case it returnsthrd_busy
.
…
7.30.4.7 The mtx_unlock function
…
Returns
4 The
mtx_unlock
function returnsthrd_success
on success, orthrd_error
if the request could not be honoredotherwise.
…
Annex J .2 Undefined behavior
(181c) An operation other than a call to mtx_init
is performed on a mutex that has an
indeterminate representation (7.30.4.1).
(181d) For any thread the last operation on a mutex M has been the entry to a lock
operation when another thread issues a call to mtx_destroy
with M, or modifies the object
representation of M directly
(7.30.4.1).
(181e) For any thread the last operation on a mutex M has been the return from a
successful lock operation when the same or any other thread issues a
call to mtx_destroy
with M, or modifies the object
representation of M directly
(7.30.4.1).
(181f) For any thread the first atomic operation on the mutex passed to
a call to mtx_init
is not the entry to
a call to a lock operation (7.30.4.1).
The changes here add mtx_t
to the notion
of atomic types. If n3706
is accepted into C2Y (there should be an online vote for inclusion
before the end of 2025) the list of atomic types that are exempted from
the generic atomic operations (7.17.7.2) should be amended with mtx_t
.
… that operate on all atomic types other than
atomic_flag
andmtx_t
Thanks to Dave Banham, Hans Boehm and Joseph Myers for discussions and suggestions for improvements.