Skip to content

Commit 91df033

Browse files
author
redi
committed
PR libstdc++/85494 use rdseed and rand_s in std::random_device
Add support for additional sources of randomness to std::random_device, to allow using RDSEED for Intel CPUs and rand_s for Windows. When supported these can be selected using the tokens "rdseed" and "rand_s". For *-w64-mingw32 targets the "default" token will now use rand_s, and for other i?86-*-* and x86_64-*-* targets it will try to use "rdseed" first, then "rdrand", and finally "/dev/urandom". To simplify the declaration of std::random_device in <bits/random.h> the constructors now unconditionally call _M_init instead of _M_init_pretr1, and the function call operator now unconditionally calls _M_getval. The library code now decides whether _M_init and _M_getval should use a real source of randomness or the mt19937 engine. Existing code compiled against old libstdc++ headers will still call _M_init_pretr1 and _M_getval_pretr1, but those functions now forward to _M_init and _M_getval if a real source of randomness is available. This means existing code compiled for mingw-w64 will start to use rand_s just by linking to a new libstdc++.dll. * acinclude.m4 (GLIBCXX_CHECK_X86_RDSEED): Define macro to check if the assembler supports rdseed. * config.h.in: Regenerate. * configure: Regenerate. * configure.ac: Use GLIBCXX_CHECK_X86_RDSEED. * config/os/mingw32-w64/os_defines.h (_GLIBCXX_USE_CRT_RAND_S): Define. * doc/html/*: Regenerate. * doc/xml/manual/status_cxx2011.xml: Document new tokens. * include/bits/random.h (random_device::random_device()): Always call _M_init rather than _M_init_pretr1. (random_device::random_device(const string&)): Likewise. (random_device::operator()()): Always call _M_getval(). (random_device::_M_file): Replace first member of union with an anonymous struct, with _M_file as its first member. * src/c++11/random.cc [_GLIBCXX_X86_RDRAND] (USE_RDRAND): Define. [_GLIBCXX_X86_RDSEED] (USE_RDSEED): Define. (USE_MT19937): Define if none of the above are defined. (USE_POSIX_FILE_IO): Define. (_M_strtoul): Remove. [USE_RDSEED] (__x86_rdseed): Define new function. [_GLIBCXX_USE_CRT_RAND_S] (__winxp_rand_s): Define new function. (random_device::_M_init(const string&)): Initialize new union members. Add support for "rdseed" and "rand_s" tokens. Decide what the "default" token does according to which USE_* macros are defined. [USE_POSIX_FILE_IO]: Store a file descriptor. [USE_MT19937]: Forward to _M_init_pretr1 instead. (random_device::_M_init_pretr1(const string&)) [USE_MT19937]: Inline code from _M_strtoul. [!USE_MT19937]: Call _M_init, transforming the old default token or numeric tokens to "default". (random_device::_M_fini()) [USE_POSIX_FILE_IO]: Use close not fclose. (random_device::_M_getval()): Use new union members to obtain a random number from the stored function pointer or file descriptor. [USE_MT19937]: Obtain a value from the mt19937 engine. (random_device::_M_getval_pretr1()): Call _M_getval(). (random_device::_M_getentropy()) [USE_POSIX_FILE_IO]: Use _M_fd instead of fileno. [!USE_MT19937] (mersenne_twister): Do not instantiate when not needed. * testsuite/26_numerics/random/random_device/85494.cc: New test. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@271740 138bc75d-0d04-0410-961f-82ee72b054a4
1 parent 662e190 commit 91df033

File tree

12 files changed

+490
-95
lines changed

12 files changed

+490
-95
lines changed

libstdc++-v3/ChangeLog

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,46 @@
1+
2019-05-29 Jonathan Wakely <jwakely@redhat.com>
2+
3+
PR libstdc++/85494 use rdseed and rand_s in std::random_device
4+
* acinclude.m4 (GLIBCXX_CHECK_X86_RDSEED): Define macro to check if
5+
the assembler supports rdseed.
6+
* config.h.in: Regenerate.
7+
* configure: Regenerate.
8+
* configure.ac: Use GLIBCXX_CHECK_X86_RDSEED.
9+
* config/os/mingw32-w64/os_defines.h (_GLIBCXX_USE_CRT_RAND_S): Define.
10+
* doc/html/*: Regenerate.
11+
* doc/xml/manual/status_cxx2011.xml: Document new tokens.
12+
* include/bits/random.h (random_device::random_device()): Always call
13+
_M_init rather than _M_init_pretr1.
14+
(random_device::random_device(const string&)): Likewise.
15+
(random_device::operator()()): Always call _M_getval().
16+
(random_device::_M_file): Replace first member of union with an
17+
anonymous struct, with _M_file as its first member.
18+
* src/c++11/random.cc [_GLIBCXX_X86_RDRAND] (USE_RDRAND): Define.
19+
[_GLIBCXX_X86_RDSEED] (USE_RDSEED): Define.
20+
(USE_MT19937): Define if none of the above are defined.
21+
(USE_POSIX_FILE_IO): Define.
22+
(_M_strtoul): Remove.
23+
[USE_RDSEED] (__x86_rdseed): Define new function.
24+
[_GLIBCXX_USE_CRT_RAND_S] (__winxp_rand_s): Define new function.
25+
(random_device::_M_init(const string&)): Initialize new union members.
26+
Add support for "rdseed" and "rand_s" tokens. Decide what the
27+
"default" token does according to which USE_* macros are defined.
28+
[USE_POSIX_FILE_IO]: Store a file descriptor.
29+
[USE_MT19937]: Forward to _M_init_pretr1 instead.
30+
(random_device::_M_init_pretr1(const string&)) [USE_MT19937]: Inline
31+
code from _M_strtoul.
32+
[!USE_MT19937]: Call _M_init, transforming the old default token or
33+
numeric tokens to "default".
34+
(random_device::_M_fini()) [USE_POSIX_FILE_IO]: Use close not fclose.
35+
(random_device::_M_getval()): Use new union members to obtain a
36+
random number from the stored function pointer or file descriptor.
37+
[USE_MT19937]: Obtain a value from the mt19937 engine.
38+
(random_device::_M_getval_pretr1()): Call _M_getval().
39+
(random_device::_M_getentropy()) [USE_POSIX_FILE_IO]: Use _M_fd
40+
instead of fileno.
41+
[!USE_MT19937] (mersenne_twister): Do not instantiate when not needed.
42+
* testsuite/26_numerics/random/random_device/85494.cc: New test.
43+
144
2019-05-28 Jonathan Wakely <jwakely@redhat.com>
245

346
PR libstdc++/90634

libstdc++-v3/acinclude.m4

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4053,6 +4053,26 @@ AC_DEFUN([GLIBCXX_CHECK_X86_RDRAND], [
40534053
AC_MSG_RESULT($ac_cv_x86_rdrand)
40544054
])
40554055

4056+
dnl
4057+
dnl Check whether rdseed is supported in the assembler.
4058+
AC_DEFUN([GLIBCXX_CHECK_X86_RDSEED], [
4059+
AC_MSG_CHECKING([for rdseed support in assembler])
4060+
AC_CACHE_VAL(ac_cv_x86_rdseed, [
4061+
ac_cv_x86_rdseed=no
4062+
case "$target" in
4063+
i?86-*-* | \
4064+
x86_64-*-*)
4065+
AC_TRY_COMPILE(, [asm("rdseed %eax");],
4066+
[ac_cv_x86_rdseed=yes], [ac_cv_x86_rdseed=no])
4067+
esac
4068+
])
4069+
if test $ac_cv_x86_rdseed = yes; then
4070+
AC_DEFINE(_GLIBCXX_X86_RDSEED, 1,
4071+
[ Defined if as can handle rdseed. ])
4072+
fi
4073+
AC_MSG_RESULT($ac_cv_x86_rdseed)
4074+
])
4075+
40564076
dnl
40574077
dnl Check whether get_nprocs is available in <sys/sysinfo.h>, and define _GLIBCXX_USE_GET_NPROCS.
40584078
dnl

libstdc++-v3/config.h.in

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1038,6 +1038,9 @@
10381038
/* Defined if as can handle rdrand. */
10391039
#undef _GLIBCXX_X86_RDRAND
10401040

1041+
/* Defined if as can handle rdseed. */
1042+
#undef _GLIBCXX_X86_RDSEED
1043+
10411044
/* Define to 1 if mutex_timedlock is available. */
10421045
#undef _GTHREAD_USE_MUTEX_TIMEDLOCK
10431046

libstdc++-v3/config/os/mingw32-w64/os_defines.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,4 +88,6 @@
8888
// See libstdc++/59807
8989
#define _GTHREAD_USE_MUTEX_INIT_FUNC 1
9090

91+
#define _GLIBCXX_USE_CRT_RAND_S 1
92+
9193
#endif

libstdc++-v3/configure

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79870,6 +79870,47 @@ $as_echo "#define _GLIBCXX_X86_RDRAND 1" >>confdefs.h
7987079870
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_x86_rdrand" >&5
7987179871
$as_echo "$ac_cv_x86_rdrand" >&6; }
7987279872

79873+
# Check if assembler supports rdseed opcode.
79874+
79875+
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for rdseed support in assembler" >&5
79876+
$as_echo_n "checking for rdseed support in assembler... " >&6; }
79877+
if test "${ac_cv_x86_rdseed+set}" = set; then :
79878+
$as_echo_n "(cached) " >&6
79879+
else
79880+
79881+
ac_cv_x86_rdseed=no
79882+
case "$target" in
79883+
i?86-*-* | \
79884+
x86_64-*-*)
79885+
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
79886+
/* end confdefs.h. */
79887+
79888+
int
79889+
main ()
79890+
{
79891+
asm("rdseed %eax");
79892+
;
79893+
return 0;
79894+
}
79895+
_ACEOF
79896+
if ac_fn_c_try_compile "$LINENO"; then :
79897+
ac_cv_x86_rdseed=yes
79898+
else
79899+
ac_cv_x86_rdseed=no
79900+
fi
79901+
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
79902+
esac
79903+
79904+
fi
79905+
79906+
if test $ac_cv_x86_rdseed = yes; then
79907+
79908+
$as_echo "#define _GLIBCXX_X86_RDSEED 1" >>confdefs.h
79909+
79910+
fi
79911+
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_x86_rdseed" >&5
79912+
$as_echo "$ac_cv_x86_rdseed" >&6; }
79913+
7987379914

7987479915
# This depends on GLIBCXX_ENABLE_SYMVERS and GLIBCXX_IS_NATIVE.
7987579916

libstdc++-v3/configure.ac

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -417,6 +417,8 @@ GCC_CHECK_ASSEMBLER_HWCAP
417417

418418
# Check if assembler supports rdrand opcode.
419419
GLIBCXX_CHECK_X86_RDRAND
420+
# Check if assembler supports rdseed opcode.
421+
GLIBCXX_CHECK_X86_RDSEED
420422

421423
# This depends on GLIBCXX_ENABLE_SYMVERS and GLIBCXX_IS_NATIVE.
422424
GLIBCXX_CONFIGURE_TESTSUITE

libstdc++-v3/doc/html/manual/appendix_contributing.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
organization. In the USA, this national standards
2727
organization is
2828
<a class="link" href="https://www.ansi.org" target="_top">ANSI</a>.
29-
(And if you've already registered with them you can <a class="link" href="https://webstore.ansi.org/RecordDetail.aspx?sku=ISO%2fIEC+14882%3a2014" target="_top">buy
29+
(And if you've already registered with them you can <a class="link" href="https://webstore.ansi.org/Standards/ISO/ISOIEC148822014" target="_top">buy
3030
the standard on-line</a>.)
3131
</p></li><li class="listitem"><p>
3232
The library working group bugs, and known defects, can

libstdc++-v3/doc/html/manual/status.html

Lines changed: 31 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -303,18 +303,38 @@
303303
<code class="classname">minstd_rand0</code>.
304304
</p><p>
305305
<span class="emphasis"><em> 26.5.6 [rand.device] </em></span>
306-
The default <code class="code">token</code> argument to the
307-
<code class="classname">random_device</code> constructor is
308-
<code class="literal">"default"</code>. Other valid arguments are
309-
<code class="literal">"/dev/random"</code> and <code class="literal">"/dev/urandom"</code>,
310-
which determine the character special file to read random bytes from.
311-
The <code class="literal">"default"</code> token will read bytes from a hardware
312-
RNG if available (currently this only supports the IA-32 RDRAND
313-
instruction) otherwise it is equivalent to
314-
<code class="literal">"/dev/urandom"</code>.
306+
The <code class="code">token</code> parameter of the
307+
<code class="classname">random_device</code> constructor can be used to select
308+
a specific source of random bytes. The valid token values are shown
309+
in the list below.
310+
The default constructor uses the token <code class="literal">"default"</code>.
311+
</p><div class="variablelist"><dl class="variablelist"><dt><span class="term"><code class="literal">"default"</code></span></dt><dd>
312+
Select the first available source from the other entries below.
313+
This is the only token that is always valid.
314+
</dd><dt><span class="term"><code class="literal">"rand_s"</code></span></dt><dd>
315+
Use the MSVCRT <code class="function">rand_s</code> function.
316+
This token is only valid for mingw-w64 targets.
317+
</dd><dt><span class="term"><code class="literal">"rdseed"</code>, </span><span class="term"><code class="literal">"rdrand"</code> or <code class="literal">"rdrnd"</code></span></dt><dd>
318+
Use the IA-32 <code class="literal">RDSEED</code> or <code class="literal">RDRAND</code>
319+
instruction to read from an on-chip hardware random number generator.
320+
These tokens are only valid for x86 and x86_64 targets when both
321+
the assembler and CPU support the corresponding instruction.
322+
</dd><dt><span class="term"><code class="literal">"/dev/urandom"</code>, </span><span class="term"><code class="literal">"/dev/random"</code></span></dt><dd>
323+
Use the named character special file to read random bytes from.
324+
These tokens are only valid when the device files are present
325+
and readable by the current user.
326+
</dd><dt><span class="term"><code class="literal">"mt19937"</code>, </span><span class="term">seed value</span></dt><dd>
327+
When no source of nondeterministic random numbers is available a
328+
<code class="classname">mersenne_twister_engine</code> will be used.
329+
An integer seed value can be used as the token and will be converted
330+
to an <code class="code">unsigned long</code> using <code class="function">strtoul</code>.
331+
These tokens are only valid when no other source of random bytes
332+
is available.
333+
</dd></dl></div><p>
315334
An exception of type <code class="classname">runtime_error</code> will be
316-
thrown if a <code class="classname">random_device</code> object cannot open
317-
or read from the source of random bytes.
335+
thrown if a <code class="classname">random_device</code> object is constructed
336+
with an invalid token, or if it cannot open or read from the source
337+
of random bytes.
318338
</p><p>
319339
<span class="emphasis"><em>26.5.8.1 [rand.dist.general]</em></span>
320340
The algorithms used by the distributions should be documented here.

libstdc++-v3/doc/xml/manual/status_cxx2011.xml

Lines changed: 55 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2682,18 +2682,62 @@ particular release.
26822682

26832683
<para>
26842684
<emphasis> 26.5.6 [rand.device] </emphasis>
2685-
The default <code>token</code> argument to the
2686-
<classname>random_device</classname> constructor is
2687-
<literal>"default"</literal>. Other valid arguments are
2688-
<literal>"/dev/random"</literal> and <literal>"/dev/urandom"</literal>,
2689-
which determine the character special file to read random bytes from.
2690-
The <literal>"default"</literal> token will read bytes from a hardware
2691-
RNG if available (currently this only supports the IA-32 RDRAND
2692-
instruction) otherwise it is equivalent to
2693-
<literal>"/dev/urandom"</literal>.
2685+
The <code>token</code> parameter of the
2686+
<classname>random_device</classname> constructor can be used to select
2687+
a specific source of random bytes. The valid token values are shown
2688+
in the list below.
2689+
The default constructor uses the token <literal>"default"</literal>.
2690+
<variablelist>
2691+
<varlistentry>
2692+
<term><literal>"default"</literal></term>
2693+
<listitem>
2694+
Select the first available source from the other entries below.
2695+
This is the only token that is always valid.
2696+
</listitem>
2697+
</varlistentry>
2698+
<varlistentry>
2699+
<term><literal>"rand_s"</literal></term>
2700+
<listitem>
2701+
Use the MSVCRT <function>rand_s</function> function.
2702+
This token is only valid for mingw-w64 targets.
2703+
</listitem>
2704+
</varlistentry>
2705+
<varlistentry>
2706+
<term><literal>"rdseed"</literal></term>
2707+
<term><literal>"rdrand"</literal> or <literal>"rdrnd"</literal></term>
2708+
<listitem>
2709+
Use the IA-32 <literal>RDSEED</literal> or <literal>RDRAND</literal>
2710+
instruction to read from an on-chip hardware random number generator.
2711+
These tokens are only valid for x86 and x86_64 targets when both
2712+
the assembler and CPU support the corresponding instruction.
2713+
</listitem>
2714+
</varlistentry>
2715+
<varlistentry>
2716+
<term><literal>"/dev/urandom"</literal></term>
2717+
<term><literal>"/dev/random"</literal></term>
2718+
<listitem>
2719+
Use the named character special file to read random bytes from.
2720+
These tokens are only valid when the device files are present
2721+
and readable by the current user.
2722+
</listitem>
2723+
</varlistentry>
2724+
<varlistentry>
2725+
<term><literal>"mt19937"</literal></term>
2726+
<term>seed value</term>
2727+
<listitem>
2728+
When no source of nondeterministic random numbers is available a
2729+
<classname>mersenne_twister_engine</classname> will be used.
2730+
An integer seed value can be used as the token and will be converted
2731+
to an <code>unsigned long</code> using <function>strtoul</function>.
2732+
These tokens are only valid when no other source of random bytes
2733+
is available.
2734+
</listitem>
2735+
</varlistentry>
2736+
</variablelist>
26942737
An exception of type <classname>runtime_error</classname> will be
2695-
thrown if a <classname>random_device</classname> object cannot open
2696-
or read from the source of random bytes.
2738+
thrown if a <classname>random_device</classname> object is constructed
2739+
with an invalid token, or if it cannot open or read from the source
2740+
of random bytes.
26972741
</para>
26982742

26992743
<para>

libstdc++-v3/include/bits/random.h

Lines changed: 8 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1602,20 +1602,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
16021602

16031603
// constructors, destructors and member functions
16041604

1605-
#ifdef _GLIBCXX_USE_DEV_RANDOM
16061605
random_device() { _M_init("default"); }
16071606

16081607
explicit
16091608
random_device(const std::string& __token) { _M_init(__token); }
16101609

1610+
#if defined _GLIBCXX_USE_DEV_RANDOM
16111611
~random_device()
16121612
{ _M_fini(); }
1613-
#else
1614-
random_device() { _M_init_pretr1("mt19937"); }
1615-
1616-
explicit
1617-
random_device(const std::string& __token)
1618-
{ _M_init_pretr1(__token); }
16191613
#endif
16201614

16211615
static constexpr result_type
@@ -1638,13 +1632,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
16381632

16391633
result_type
16401634
operator()()
1641-
{
1642-
#ifdef _GLIBCXX_USE_DEV_RANDOM
1643-
return this->_M_getval();
1644-
#else
1645-
return this->_M_getval_pretr1();
1646-
#endif
1647-
}
1635+
{ return this->_M_getval(); }
16481636

16491637
// No copy functions.
16501638
random_device(const random_device&) = delete;
@@ -1662,7 +1650,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
16621650

16631651
union
16641652
{
1665-
void* _M_file;
1653+
struct
1654+
{
1655+
void* _M_file;
1656+
result_type (*_M_func)(void*);
1657+
int _M_fd;
1658+
};
16661659
mt19937 _M_mt;
16671660
};
16681661
};

0 commit comments

Comments
 (0)