This is the mail archive of the libc-alpha@sourceware.org mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

C11 threads ABI - mtx_t and cnd_t types


Another issue I have on the ABI for C11 threads pertains to the types
for mtx_t and cnd_t. My understanding, and I agree with this, is that
it was already decided to use the same underlying sizes/alignment, and
for now representations, as the corresponding POSIX types. However,
it's impossible to use the existing types directly due to namespace
issues. If the following were used:

typedef pthread_mutex_t mtx_t;
typedef pthread_cond_t cnd_t;

this would require pthread_mutex_t and pthread_cond_t to be visible
when threads.h is included.

It's possible to consider adding union tags (the underlying types of
pthread_mutex_t and pthread_cond_t are both unions without tags) in a
protected namespace, so that you could have:

union __mutex { ... };
typedef union __mutex pthread_mutex_t;
typedef union __mutex mtx_t;

but this is not acceptable because it would change the C++ ABI for the
pthread types. Since they currently do not have tags, the effective
tag name (for C++ ABI/manging purposes) for the union defining
pthread_mutex_t comes from the typedef name, pthread_mutex_t. Adding
an explicit tag would change this (unless the explicit tag were still
pthread_mutex_t, but then it's not in the namespace that can be used
in threads.h).

This issue has been discussed in detail (I might say, to exhaustion)
on the musl libc mailing list, and the conclusion we reached is that
pthread_mutex_t and mtx_t (and likewise pthread_cond_t and cnd_t)
should be defined with identical types (we happen to have a structure
rather than a union for the outermost layer in musl, but that's an
irrelevant difference), both without tags. This will give effective
C++ tag names (for name mangling ABI) of mtx_t and cnd_t for the C11
types.

The rationale for this conclusion is to allow a shared implementation.
If pthread_mutex_t and mtx_t are not compatible types, then it's an
aliasing violation for pthread_mutex_* functions to use the ->
operator to access the members of mtx_t as if it were an object of
type pthread_mutex_t -- this is what would happen when an application
declares an object of type mtx_t and passes it to mtx_*(), which in
turn calls pthread_mutex_*() and dereferences. By having both be
tagless with the same definitions, we make the instance of either type
in a given translation unit a compatible type with the instance of
either one in a separate translation unit (but neither is compatible
with the other within the same translation unit).

If anyone wants to check this reasoning, the relevant portions of C11
seem to be 6.2.7p1 and 6.5p7.

TL;DR:

mtx_t and cnd_t should be defined without tags and with definitions
identical to the corresponding pthread types. Other choices of
definition make it difficult to implement the C11 functions as pure
wrappers around the pthread functions without risking aliasing
violations which may result in actual breakage at some point in the
future with LTO enabled.

Rich


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]