This document proposes to allow implementations to use thread storage duration for the internal state used by the pseudo-random number generator functions and the multibyte/wide conversion functions. It is related to papers N2225, N2226, N2228.
The core observation which motivates this document is that while the standard does not require to detect data races for the affected functions, it does rule out an implementation based on internal state objects with thread storage duration. The reason is that a strictly conforming program can use external synchronization and call these functions from different threads. With internal objects of thread storage duration, the lack of global state sharing would be observable.
Many libraries which are thread-aware (because they use
synchronization primitives or even create threads
themselves) still call
rand, which introduces
data races. One way to fix all these libraries is to give
the random number generator state optional thread storage
Another option would be to encourage implementations to avoid data races, either by using locks or atomic memory accesses internally. However, historically, some benchmarks are quite dependent on random number generator performance, so this change might not be desirable to implementors. The implementation in the GNU C library uses a lock.
POSIX suggests the possiblity of a thread-safe
but does not voice any preference for per-thread state or
synchronized access to the global state.
Likewise, the multibyte/wide character and string conversion
functions use internal state if the
is a null pointer. For these functions, eliminating the data
race would still leave a semantic race condition because the
state needs to remain consistent between subsequent calls of
The proposal is to give permission to assign thread storage duration to the internal state. The functions have error return values, so the necessary storage could even be allocated dynamically, on demand, to avoid penalizing programs which use an explicit conversion state argument.
A simpler approach would make it undefined to call the
conversion functions from a multi-threaded program (similar
to what the
signal function does today).
POSIX suggests that a thread-safe implementation of these functions is possible, but does not go into details. It does not discuss the ability of strictly conforming programs to discover whether the hidden internal state has thread storage duration or not.
TheIn 126.96.36.199 (The
randfunction is not required to avoid data races with other calls to pseudo-random sequence generation functions.
In J.3.12 (Library functions), add:
srandfunction is not required to avoid data races with other calls to pseudo-random sequence generation functions.
IfIn 188.8.131.52 (Restartable multibyte/wide string conversion functions), add:
psis a null pointer, each function uses its own internal
mbstate_tobject instead, which is initialized at program startup to the initial conversion state; the functions are not required to avoid data races with other calls to the same function in this case. The implementation behaves as if no library function calls these functions with a null pointer for
IfIn J.3.12 (Library functions), add:
psis a null pointer, each function uses its own internal mbstate_t object instead, which is initialized at program startup to the initial conversion state; the functions are not required to avoid data races with other calls to the same function in this case. The implementation behaves as if no library function calls these functions with a null pointer for