Skip to content
This repository was archived by the owner on Oct 12, 2022. It is now read-only.

Commit b3edb17

Browse files
authored
Merge pull request #2248 from n8sh/rt-defaultSeed-rdtsc
Fix Issue 19075 - rt.util.random.Rand48.defaultSeed should prefer RDTSC or mach_absolute_time or QueryPerformanceCounter to ctime.time
2 parents c97beb8 + 449ef52 commit b3edb17

File tree

1 file changed

+48
-3
lines changed

1 file changed

+48
-3
lines changed

src/rt/util/random.d

Lines changed: 48 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,55 @@ struct Rand48
1212

1313
@safe @nogc nothrow:
1414

15-
void defaultSeed()
15+
void defaultSeed() @trusted
1616
{
17-
import ctime = core.stdc.time : time;
18-
seed(cast(uint)ctime.time(null));
17+
version(D_InlineAsm_X86_64)
18+
{
19+
// RDTSC takes around 22 clock cycles.
20+
ulong result = void; // Workaround for LDC issue #950, cannot access struct members in DMD asm.
21+
asm @nogc nothrow
22+
{
23+
rdtsc;
24+
// RAX: low 32 bits are low bits of timestamp, high 32 bits are 0.
25+
// RDX: low 32 bits are high bits of timestamp, high 32 bits are 0.
26+
// We combine these into a 48 bit value instead of a full 64 bits
27+
// because `front` and `popFront` only make use of the bottom 48
28+
// bits of `rng_state`.
29+
shl RDX, 16;
30+
xor RDX, RAX;
31+
mov result, RDX;
32+
}
33+
rng_state = result;
34+
popFront();
35+
}
36+
//else version(D_InlineAsm_X86)
37+
//{
38+
// // We don't use `rdtsc` with version(D_InlineAsm_X86) because
39+
// // some x86 processors don't support `rdtsc` and because on
40+
// // x86 (but not x86-64) Linux `prctl` can disable a process's
41+
// // ability to use `rdtsc`.
42+
// static assert(0);
43+
//}
44+
else version(Windows)
45+
{
46+
// QueryPerformanceCounter takes about 1/4 the time of ctime.time.
47+
import core.sys.windows.winbase : QueryPerformanceCounter;
48+
QueryPerformanceCounter(cast(long*) &rng_state);
49+
popFront();
50+
}
51+
else version(OSX)
52+
{
53+
// mach_absolute_time is much faster than ctime.time.
54+
import core.time : mach_absolute_time;
55+
rng_state = mach_absolute_time();
56+
popFront();
57+
}
58+
else
59+
{
60+
// Fallback to libc timestamp in seconds.
61+
import ctime = core.stdc.time : time;
62+
seed((cast(uint) ctime.time(null)));
63+
}
1964
}
2065

2166
pure:

0 commit comments

Comments
 (0)