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

2019-05-31 Thread Jonathan Wakely

On 31/05/19 10:47 +0100, Jonathan Wakely wrote:

On 31/05/19 10:46 +0100, Jonathan Wakely wrote:

On 31/05/19 09:26 +, Szabolcs Nagy wrote:

On 29/05/2019 23:03, Jonathan Wakely wrote:

This fixes a test that started to fail in mingw.

Tested x86_64-linux, powerpc64le-linux and x86_64-w64-ming32.

Committed to trunk.


note that the updated test fails on baremetal

FAIL: 26_numerics/random/random_device/cons/token.cc execution test

26_numerics/random/random_device/cons/token.cc:67: void test03(): Assertion 
'count != 0' failed.

(if i add "default" to the token list in test03 then it passes)


Hmm, then I messed something up. If the "default" token works then one
of the others should too (I would expect that to be "mt19937" for bare
metal).

I'll take a look, thanks.



Doh:

--- a/libstdc++-v3/testsuite/26_numerics/random/random_device/cons/token.cc
+++ b/libstdc++-v3/testsuite/26_numerics/random/random_device/cons/token.cc
@@ -51,7 +51,7 @@ test03()
{
 // At least one of these tokens should be valid.
 const std::string tokens[] = {
-"rdseed", "rdrand", "rand_s", "/dev/urandom", "/dev/random", "mt19337"
+"rdseed", "rdrand", "rand_s", "/dev/urandom", "/dev/random", "mt19937"
 };
 int count = 0;
 for (const std::string& token : tokens)



Here's what I've committed to fix the COW string failures and the
baremetal failure. Tested powerpc64le-linux and x86_64-linux, old and
new ABIs.


commit a7d8558fdd74dc96dc0bd73c4a663b658f4155ba
Author: Jonathan Wakely 
Date:   Fri May 31 08:47:47 2019 +0100

Fix random_device to work with COW strings again

Instead of duplicating the initialization functions that take string,
add a new member taking a raw pointer that can be used to convert the
constructor token from the old string to the new.

Also fix "mt19337" typos in a testcase.

* include/bits/random.h (random_device::_M_init(const char*, size_t)):
Add new private member function.
* src/c++11/cow-string-inst.cc (random_device::_M_init(const string&))
(random_device::_M_init_pretr1(const string&)): Call new private
member with string data.
* src/c++11/random.cc (random_device::_M_init(const char*, size_t)):
Define.
* testsuite/26_numerics/random/random_device/cons/default-cow.cc: New
test using COW strings.
* testsuite/26_numerics/random/random_device/cons/default.cc: Generate
a value from the device.
* testsuite/26_numerics/random/random_device/cons/token.cc: Likewise.
Fix typo in token string.

diff --git a/libstdc++-v3/include/bits/random.h b/libstdc++-v3/include/bits/random.h
index 9c959d6dc84..e63dbcf5a25 100644
--- a/libstdc++-v3/include/bits/random.h
+++ b/libstdc++-v3/include/bits/random.h
@@ -1648,6 +1648,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 result_type _M_getval_pretr1();
 double _M_getentropy() const noexcept;
 
+void _M_init(const char*, size_t); // not exported from the shared library
+
 union
 {
   struct
diff --git a/libstdc++-v3/src/c++11/cow-string-inst.cc b/libstdc++-v3/src/c++11/cow-string-inst.cc
index c36f297438e..107a45750f2 100644
--- a/libstdc++-v3/src/c++11/cow-string-inst.cc
+++ b/libstdc++-v3/src/c++11/cow-string-inst.cc
@@ -35,61 +35,15 @@
 
 #ifdef  _GLIBCXX_USE_C99_STDINT_TR1
 #include 
-#if defined __i386__ || defined __x86_64__
-# include 
-#endif
-#include 
 
 namespace std _GLIBCXX_VISIBILITY(default)
 {
   void
   random_device::_M_init(const std::string& token)
-  {
-const char *fname = token.c_str();
-
-if (token == "default")
-  {
-#if (defined __i386__ || defined __x86_64__) && defined _GLIBCXX_X86_RDRAND
-	unsigned int eax, ebx, ecx, edx;
-	// Check availability of cpuid and, for now at least, also the
-	// CPU signature for Intel's
-	if (__get_cpuid_max(0, ) > 0 && ebx == signature_INTEL_ebx)
-	  {
-	__cpuid(1, eax, ebx, ecx, edx);
-	if (ecx & bit_RDRND)
-	  {
-		_M_file = nullptr;
-		return;
-	  }
-	  }
-#endif
-
-	fname = "/dev/urandom";
-  }
-else if (token != "/dev/urandom" && token != "/dev/random")
-fail:
-  std::__throw_runtime_error(__N("random_device::"
- "random_device(const std::string&)"));
-
-_M_file = static_cast(std::fopen(fname, "rb"));
-if (!_M_file)
-  goto fail;
-  }
+  { _M_init(token.c_str(), token.length()); }
 
   void
   random_device::_M_init_pretr1(const std::string& token)
-  {
-unsigned long __seed = 5489UL;
-if (token != "mt19937")
-  {
-	const char* __nptr = token.c_str();
-	char* __endptr;
-	__seed = std::strtoul(__nptr, &__endptr, 0);
-	if (*__nptr == '\0' || *__endptr != '\0')
-	  std::__throw_runtime_error(__N("random_device::random_device"
-	 "(const std::string&)"));
-  }
-_M_mt.seed(__seed);
-  }
+  { _M_init(token.c_str(), token.length()); }
 } // namespace
 #endif
diff --git a/libstdc++-v3/src/c++11/random.cc 

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

2019-05-31 Thread Jonathan Wakely

On 31/05/19 10:46 +0100, Jonathan Wakely wrote:

On 31/05/19 09:26 +, Szabolcs Nagy wrote:

On 29/05/2019 23:03, Jonathan Wakely wrote:

This fixes a test that started to fail in mingw.

Tested x86_64-linux, powerpc64le-linux and x86_64-w64-ming32.

Committed to trunk.


note that the updated test fails on baremetal

FAIL: 26_numerics/random/random_device/cons/token.cc execution test

26_numerics/random/random_device/cons/token.cc:67: void test03(): Assertion 
'count != 0' failed.

(if i add "default" to the token list in test03 then it passes)


Hmm, then I messed something up. If the "default" token works then one
of the others should too (I would expect that to be "mt19937" for bare
metal).

I'll take a look, thanks.



Doh:

--- a/libstdc++-v3/testsuite/26_numerics/random/random_device/cons/token.cc
+++ b/libstdc++-v3/testsuite/26_numerics/random/random_device/cons/token.cc
@@ -51,7 +51,7 @@ test03()
{
  // At least one of these tokens should be valid.
  const std::string tokens[] = {
-"rdseed", "rdrand", "rand_s", "/dev/urandom", "/dev/random", "mt19337"
+"rdseed", "rdrand", "rand_s", "/dev/urandom", "/dev/random", "mt19937"
  };
  int count = 0;
  for (const std::string& token : tokens)



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

2019-05-31 Thread Jonathan Wakely

On 31/05/19 09:26 +, Szabolcs Nagy wrote:

On 29/05/2019 23:03, Jonathan Wakely wrote:

This fixes a test that started to fail in mingw.

Tested x86_64-linux, powerpc64le-linux and x86_64-w64-ming32.

Committed to trunk.


note that the updated test fails on baremetal

FAIL: 26_numerics/random/random_device/cons/token.cc execution test

26_numerics/random/random_device/cons/token.cc:67: void test03(): Assertion 
'count != 0' failed.

(if i add "default" to the token list in test03 then it passes)


Hmm, then I messed something up. If the "default" token works then one
of the others should too (I would expect that to be "mt19937" for bare
metal).

I'll take a look, thanks.



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

2019-05-31 Thread Szabolcs Nagy
On 29/05/2019 23:03, Jonathan Wakely wrote:
> This fixes a test that started to fail in mingw.
> 
> Tested x86_64-linux, powerpc64le-linux and x86_64-w64-ming32.
> 
> Committed to trunk.

note that the updated test fails on baremetal

FAIL: 26_numerics/random/random_device/cons/token.cc execution test

26_numerics/random/random_device/cons/token.cc:67: void test03(): Assertion 
'count != 0' failed.

(if i add "default" to the token list in test03 then it passes)


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

2019-05-30 Thread Jonathan Wakely

On 29/05/19 23:03 +0100, Jonathan Wakely wrote:

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  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.


I forgot that the random_device::_M_init member is duplicated in
src/c++11/cow-string-inst.cc for the old strings, so tests using the
old string now fail.

I'll try to find a better way to define those member functions for old
strings.




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

2019-05-29 Thread Jonathan Wakely

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  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 
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
 // .
 
-// 26.4.6 class random_device [rand.device]
-// 26.4.6 [3]
+// C++11 26.5.6 class random_device [rand.device]
 
 #include 
+#include 
 #include 
 
 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::min() );
   VERIFY( x.max() == std::numeric_limits::max() );
+
+}
+

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

2019-05-29 Thread Jonathan Wakely

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  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.

Tested x86_64-linux, powerpc64le-linux and x86_64-w64-ming32.

Committed to trunk.

commit dc337c84a7db52035f6b6efb87338e950bb7490e
Author: Jonathan Wakely 
Date:   Tue May 28 15:01:08 2019 +0100

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  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.
*