This is the mail archive of the libstdc++@gcc.gnu.org mailing list for the libstdc++ 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]

Re: [PATCH] PR libstdc++/85494 use rdseed and rand_s in std::random_device


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 <jwakely@redhat.com>
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();
 }

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