On 29/05/19 15:45 +0100, Jonathan Wakely wrote:
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.
This fixes a test that started to fail in mingw. Tested x86_64-linux, powerpc64le-linux and x86_64-w64-ming32. Committed to trunk.
commit 08208e0f68c842dcec9bcfa0352145e14d10315a Author: Jonathan Wakely <[email protected]> Date: Wed May 29 22:46:42 2019 +0100 PR libstdc++/85494 fix failing test This test now fails on mingw-w64 because it's no longer always true that the mt19937 engine is used when _GLIBCXX_USE_DEV_RANDOM is not defined. Add tests for all the known tokens to ensure that at least one is accepted. * testsuite/26_numerics/random/random_device/cons/token.cc: Fix test that fails on mingw-w64. diff --git a/libstdc++-v3/testsuite/26_numerics/random/random_device/cons/token.cc b/libstdc++-v3/testsuite/26_numerics/random/random_device/cons/token.cc index c1f3963e57d..cf5e81edd7b 100644 --- a/libstdc++-v3/testsuite/26_numerics/random/random_device/cons/token.cc +++ b/libstdc++-v3/testsuite/26_numerics/random/random_device/cons/token.cc @@ -20,27 +20,79 @@ // with this library; see the file COPYING3. If not see // <http://www.gnu.org/licenses/>. -// 26.4.6 class random_device [rand.device] -// 26.4.6 [3] +// C++11 26.5.6 class random_device [rand.device] #include <random> +#include <stdexcept> #include <testsuite_hooks.h> void test01() { -#ifdef _GLIBCXX_USE_DEV_RANDOM - std::random_device x("/dev/random"); -#else - std::random_device x("0"); -#endif + std::random_device x("default"); VERIFY( x.min() == std::numeric_limits<std::random_device::result_type>::min() ); VERIFY( x.max() == std::numeric_limits<std::random_device::result_type>::max() ); + +} + +void +test02() +{ +#ifdef _GLIBCXX_USE_DEV_RANDOM + std::random_device x1("/dev/urandom"); + std::random_device x2("/dev/random"); +#endif +} + +void +test03() +{ + // At least one of these tokens should be valid. + const std::string tokens[] = { + "rdseed", "rdrand", "rand_s", "/dev/urandom", "/dev/random", "mt19337" + }; + int count = 0; + for (const std::string& token : tokens) + { + try + { + std::random_device x(token); + ++count; + } + catch (const std::runtime_error&) + { + } + } + VERIFY( count != 0 ); +} + +void +test04() +{ + bool can_use_mt19937 = true; + try + { + std::random_device x("mt19937"); + } + catch (const std::runtime_error&) + { + can_use_mt19937 = false; + } + + // If "mt19337" is a valid token then numeric seeds should be too. + if (can_use_mt19937) + { + std::random_device x1("0"); + std::random_device x2("1234"); + std::random_device x3("0xc0fefe"); + } } int main() { test01(); - return 0; + test02(); + test03(); + test04(); }
