QtBase  v6.3.1
qrandom.cpp
Go to the documentation of this file.
1 /****************************************************************************
2 **
3 ** Copyright (C) 2021 Intel Corporation.
4 ** Copyright (C) 2021 The Qt Company Ltd.
5 ** Contact: https://www.qt.io/licensing/
6 **
7 ** This file is part of the QtCore module of the Qt Toolkit.
8 **
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** Commercial License Usage
11 ** Licensees holding valid commercial Qt licenses may use this file in
12 ** accordance with the commercial license agreement provided with the
13 ** Software or, alternatively, in accordance with the terms contained in
14 ** a written agreement between you and The Qt Company. For licensing terms
15 ** and conditions see https://www.qt.io/terms-conditions. For further
16 ** information use the contact form at https://www.qt.io/contact-us.
17 **
18 ** GNU Lesser General Public License Usage
19 ** Alternatively, this file may be used under the terms of the GNU Lesser
20 ** General Public License version 3 as published by the Free Software
21 ** Foundation and appearing in the file LICENSE.LGPL3 included in the
22 ** packaging of this file. Please review the following information to
23 ** ensure the GNU Lesser General Public License version 3 requirements
24 ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
25 **
26 ** GNU General Public License Usage
27 ** Alternatively, this file may be used under the terms of the GNU
28 ** General Public License version 2.0 or (at your option) the GNU General
29 ** Public license version 3 or any later version approved by the KDE Free
30 ** Qt Foundation. The licenses are as published by the Free Software
31 ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
32 ** included in the packaging of this file. Please review the following
33 ** information to ensure the GNU General Public License requirements will
34 ** be met: https://www.gnu.org/licenses/gpl-2.0.html and
35 ** https://www.gnu.org/licenses/gpl-3.0.html.
36 **
37 ** $QT_END_LICENSE$
38 **
39 ****************************************************************************/
40 
41 // for rand_s
42 #define _CRT_RAND_S
43 
44 #include "qrandom.h"
45 #include "qrandom_p.h"
46 #include <qendian.h>
47 #include <qmutex.h>
48 #include <qobjectdefs.h>
49 #include <qthreadstorage.h>
50 
51 #include <errno.h>
52 
53 #if QT_CONFIG(getauxval)
54 # include <sys/auxv.h>
55 #endif
56 
57 #if QT_CONFIG(getentropy) && __has_include(<sys/random.h>)
58 # include <sys/random.h>
59 #elif !QT_CONFIG(getentropy) && (!defined(Q_OS_BSD4) || defined(__GLIBC__)) && !defined(Q_OS_WIN)
60 # include "qdeadlinetimer.h"
61 # include "qhashfunctions.h"
62 #endif // !QT_CONFIG(getentropy)
63 
64 #ifdef Q_OS_UNIX
65 # include <fcntl.h>
66 # include <private/qcore_unix_p.h>
67 #else
68 # include <qt_windows.h>
69 
70 // RtlGenRandom is not exported by its name in advapi32.dll, but as SystemFunction036
71 // See https://msdn.microsoft.com/en-us/library/windows/desktop/aa387694(v=vs.85).aspx
72 // Implementation inspired on https://hg.mozilla.org/mozilla-central/file/722fdbff1efc/security/nss/lib/freebl/win_rand.c#l146
73 // Argument why this is safe to use: https://bugzilla.mozilla.org/show_bug.cgi?id=504270
74 extern "C" {
75 DECLSPEC_IMPORT BOOLEAN WINAPI SystemFunction036(PVOID RandomBuffer, ULONG RandomBufferLength);
76 }
77 #endif
78 
79 // This file is too low-level for regular Q_ASSERT (the logging framework may
80 // recurse back), so use regular assert()
81 #undef NDEBUG
82 #undef Q_ASSERT_X
83 #undef Q_ASSERT
84 #define Q_ASSERT(cond) assert(cond)
85 #define Q_ASSERT_X(cond, x, msg) assert(cond && msg)
86 #if defined(QT_NO_DEBUG) && !defined(QT_FORCE_ASSERTS)
87 # define NDEBUG 1
88 #endif
89 #include <assert.h>
90 
92 
93 enum {
94  // may be "overridden" by a member enum
95  FillBufferNoexcept = true
96 };
97 
98 #if defined(QT_BUILD_INTERNAL)
99 QBasicAtomicInteger<uint> qt_randomdevice_control = Q_BASIC_ATOMIC_INITIALIZER(0U);
100 #endif
101 
103 {
104 #if QT_CONFIG(getentropy)
105  static qsizetype fillBuffer(void *buffer, qsizetype count) noexcept
106  {
107  // getentropy can read at most 256 bytes, so break the reading
108  qsizetype read = 0;
109  while (count - read > 256) {
110  // getentropy can't fail under normal circumstances
111  int ret = getentropy(reinterpret_cast<uchar *>(buffer) + read, 256);
112  Q_ASSERT(ret == 0);
113  Q_UNUSED(ret);
114  read += 256;
115  }
116 
117  int ret = getentropy(reinterpret_cast<uchar *>(buffer) + read, count - read);
118  Q_ASSERT(ret == 0);
119  Q_UNUSED(ret);
120  return count;
121  }
122 
123 #elif defined(Q_OS_UNIX)
124  enum { FillBufferNoexcept = false };
125 
126  QBasicAtomicInt fdp1; // "file descriptor plus 1"
127  int openDevice()
128  {
129  int fd = fdp1.loadAcquire() - 1;
130  if (fd != -1)
131  return fd;
132 
133  fd = qt_safe_open("/dev/urandom", O_RDONLY);
134  if (fd == -1)
135  fd = qt_safe_open("/dev/random", O_RDONLY | O_NONBLOCK);
136  if (fd == -1) {
137  // failed on both, set to -2 so we won't try again
138  fd = -2;
139  }
140 
141  int opened_fdp1;
142  if (fdp1.testAndSetOrdered(0, fd + 1, opened_fdp1))
143  return fd;
144 
145  // failed, another thread has opened the file descriptor
146  if (fd >= 0)
147  qt_safe_close(fd);
148  return opened_fdp1 - 1;
149  }
150 
151 #ifdef Q_CC_GNU
152  // If it's not GCC or GCC-like, then we'll leak the file descriptor
153  __attribute__((destructor))
154 #endif
155  static void closeDevice()
156  {
157  int fd = self().fdp1.loadRelaxed() - 1;
158  if (fd >= 0)
159  qt_safe_close(fd);
160  }
161 
162  constexpr SystemGenerator() : fdp1 Q_BASIC_ATOMIC_INITIALIZER(0) {}
163 
164  qsizetype fillBuffer(void *buffer, qsizetype count)
165  {
166  int fd = openDevice();
167  if (Q_UNLIKELY(fd < 0))
168  return 0;
169 
170  qint64 n = qt_safe_read(fd, buffer, count);
171  return qMax<qsizetype>(n, 0); // ignore any errors
172  }
173 
174 #elif defined(Q_OS_WIN)
175  static qsizetype fillBuffer(void *buffer, qsizetype count) noexcept
176  {
177  auto RtlGenRandom = SystemFunction036;
178  return RtlGenRandom(buffer, ULONG(count)) ? count: 0;
179  }
180 #endif // Q_OS_WIN
181 
182  static SystemGenerator &self();
184  void generate(quint32 *begin, quint32 *end) noexcept(FillBufferNoexcept);
185 
186  // For std::mersenne_twister_engine implementations that use something
187  // other than quint32 (unsigned int) to fill their buffers.
188  template<typename T>
189  void generate(T *begin, T *end)
190  {
191  static_assert(sizeof(T) >= sizeof(quint32));
192  if (sizeof(T) == sizeof(quint32)) {
193  // Microsoft Visual Studio uses unsigned long, but that's still 32-bit
194  generate(reinterpret_cast<quint32 *>(begin), reinterpret_cast<quint32 *>(end));
195  } else {
196  // Slow path. Fix your C++ library.
197  std::generate(begin, end, [this]() {
198  quint32 datum;
199  generate(&datum, &datum + 1);
200  return datum;
201  });
202  }
203  }
204 };
205 
206 #if defined(Q_OS_WIN)
207 static void fallback_update_seed(unsigned) {}
208 static void fallback_fill(quint32 *ptr, qsizetype left) noexcept
209 {
210  // on Windows, rand_s is a high-quality random number generator
211  // and it requires no seeding
212  std::generate(ptr, ptr + left, []() {
213  unsigned value;
214  rand_s(&value);
215  return value;
216  });
217 }
218 #elif QT_CONFIG(getentropy)
219 static void fallback_update_seed(unsigned) {}
220 static void fallback_fill(quint32 *, qsizetype) noexcept
221 {
222  // no fallback necessary, getentropy cannot fail under normal circumstances
224 }
225 #elif defined(Q_OS_BSD4) && !defined(__GLIBC__)
226 static void fallback_update_seed(unsigned) {}
227 static void fallback_fill(quint32 *ptr, qsizetype left) noexcept
228 {
229  // BSDs have arc4random(4) and these work even in chroot(2)
230  arc4random_buf(ptr, left * sizeof(*ptr));
231 }
232 #else
234 static void fallback_update_seed(unsigned value)
235 {
236  // Update the seed to be used for the fallback mechanism, if we need to.
237  // We can't use QtPrivate::QHashCombine here because that is not an atomic
238  // operation. A simple XOR will have to do then.
239  seed.fetchAndXorRelaxed(value);
240 }
241 
242 Q_NEVER_INLINE
243 #ifdef Q_CC_GNU
244 __attribute__((cold)) // this function is pretty big, so optimize for size
245 #endif
246 static void fallback_fill(quint32 *ptr, qsizetype left) noexcept
247 {
248  quint32 scratch[12]; // see element count below
249  quint32 *end = scratch;
250 
251  auto foldPointer = [](quintptr v) {
252  if (sizeof(quintptr) == sizeof(quint32)) {
253  // For 32-bit systems, we simply return the pointer.
254  return quint32(v);
255  } else {
256  // For 64-bit systems, we try to return the variable part of the
257  // pointer. On current x86-64 and AArch64, the top 17 bits are
258  // architecturally required to be the same, but in reality the top
259  // 24 bits on Linux are likely to be the same for all processes.
260  return quint32(v >> (32 - 24));
261  }
262  };
263 
264  Q_ASSERT(left);
265 
266  *end++ = foldPointer(quintptr(&seed)); // 1: variable in this library/executable's .data
267  *end++ = foldPointer(quintptr(&scratch)); // 2: variable in the stack
268  *end++ = foldPointer(quintptr(&errno)); // 3: veriable either in libc or thread-specific
269  *end++ = foldPointer(quintptr(reinterpret_cast<void*>(strerror))); // 4: function in libc (and unlikely to be a macro)
270 
271 #ifndef QT_BOOTSTRAPPED
273  *end++ = quint32(nsecs); // 5
274 #endif
275 
276  if (quint32 v = seed.loadRelaxed())
277  *end++ = v; // 6
278 
279 #if QT_CONFIG(getauxval)
280  // works on Linux -- all modern libc have getauxval
281 # ifdef AT_RANDOM
282  // ELF's auxv AT_RANDOM has 16 random bytes
283  // (other ELF-based systems don't seem to have AT_RANDOM)
284  ulong auxvSeed = getauxval(AT_RANDOM);
285  if (auxvSeed) {
286  memcpy(end, reinterpret_cast<void *>(auxvSeed), 16);
287  end += 4; // 7 to 10
288  }
289 # endif
290 
291  // Both AT_BASE and AT_SYSINFO_EHDR have some randomness in them due to the
292  // system's ASLR, even if many bits are the same. They also have randomness
293  // between them.
294 # ifdef AT_BASE
295  // present at least on the BSDs too, indicates the address of the loader
296  ulong base = getauxval(AT_BASE);
297  if (base)
298  *end++ = foldPointer(base); // 11
299 # endif
300 # ifdef AT_SYSINFO_EHDR
301  // seems to be Linux-only, indicates the global page of the sysinfo
302  ulong sysinfo_ehdr = getauxval(AT_SYSINFO_EHDR);
303  if (sysinfo_ehdr)
304  *end++ = foldPointer(sysinfo_ehdr); // 12
305 # endif
306 #endif
307 
308  Q_ASSERT(end <= std::end(scratch));
309 
310  // this is highly inefficient, we should save the generator across calls...
311  std::seed_seq sseq(scratch, end);
312  std::mt19937 generator(sseq);
313  std::generate(ptr, ptr + left, generator);
314 
315  fallback_update_seed(*ptr);
316 }
317 #endif
318 
320  noexcept(FillBufferNoexcept)
321 {
322  quint32 *buffer = begin;
323  qsizetype count = end - begin;
324 
325  if (Q_UNLIKELY(uint(qt_randomdevice_control.loadAcquire()) & SetRandomData)) {
326  uint value = uint(qt_randomdevice_control.loadAcquire()) & RandomDataMask;
327  std::fill_n(buffer, count, value);
328  return;
329  }
330 
331  qsizetype filled = 0;
332  if (qHasHwrng() && (uint(qt_randomdevice_control.loadAcquire()) & SkipHWRNG) == 0)
333  filled += qRandomCpu(buffer, count);
334 
335  if (filled != count && (uint(qt_randomdevice_control.loadAcquire()) & SkipSystemRNG) == 0) {
336  qsizetype bytesFilled =
337  fillBuffer(buffer + filled, (count - filled) * qsizetype(sizeof(*buffer)));
338  filled += bytesFilled / qsizetype(sizeof(*buffer));
339  }
340  if (filled)
341  fallback_update_seed(*buffer);
342 
343  if (Q_UNLIKELY(filled != count)) {
344  // failed to fill the entire buffer, try the faillback mechanism
345  fallback_fill(buffer + filled, count - filled);
346  }
347 }
348 
350 {
351  // Construction notes:
352  // 1) The global PRNG state is in a different cacheline compared to the
353  // mutex that protects it. This avoids any false cacheline sharing of
354  // the state in case another thread tries to lock the mutex. It's not
355  // a common scenario, but since sizeof(QRandomGenerator) >= 2560, the
356  // overhead is actually acceptable.
357  // 2) We use both alignas(T) and alignas(64) because some implementations
358  // can't align to more than a primitive type's alignment.
359  // 3) We don't store the entire system QRandomGenerator, only the space
360  // used by the QRandomGenerator::type member. This is fine because we
361  // (ab)use the common initial sequence exclusion to aliasing rules.
365  alignas(64) struct {
368 
370  : globalPRNGMutex{}, system_{0}, sys{}, global_{}
371  {}
372 
374  {
375 #if !defined(Q_OS_INTEGRITY)
376  // Integrity's compiler is unable to guarantee g's alignment for some reason.
377  constexpr SystemAndGlobalGenerators g = {};
378  Q_UNUSED(g);
379 #endif
380  }
381 
383  {
385  static_assert(sizeof(g) > sizeof(QRandomGenerator64));
386  return &g;
387  }
388 
390  {
391  // Though we never call the constructor, the system QRandomGenerator is
392  // properly initialized by the zero initialization performed in self().
393  // Though QRandomGenerator is has non-vacuous initialization, we
394  // consider it initialized because of the common initial sequence.
395  return reinterpret_cast<QRandomGenerator64 *>(&self()->system_);
396  }
397 
399  {
400  // This function returns the pointer to the global QRandomGenerator,
401  // but does not initialize it. Only call it directly if you meant to do
402  // a pointer comparison.
403  return reinterpret_cast<QRandomGenerator64 *>(&self()->global_);
404  }
405 
407  {
408  // force reconstruction, just to be pedantic
409  new (rng) QRandomGenerator{System{}};
410 
411  rng->type = MersenneTwister;
412  new (&rng->storage.engine()) RandomEngine(self()->sys);
413  }
414 
415  struct PRNGLocker
416  {
417  const bool locked;
419  : locked(that == globalNoInit())
420  {
421  if (locked)
422  self()->globalPRNGMutex.lock();
423  }
425  {
426  if (locked)
427  self()->globalPRNGMutex.unlock();
428  }
429  };
430 };
431 
433 {
435 }
436 
1152 constexpr QRandomGenerator::Storage::Storage()
1153  : dummy(0)
1154 {
1155  // nothing
1156 }
1157 
1159  : QRandomGenerator(s)
1160 {
1161 }
1162 
1164 {
1165  auto self = SystemAndGlobalGenerators::system();
1166  Q_ASSERT(self->type == SystemRNG);
1167  return self;
1168 }
1169 
1171 {
1173 
1174  // Yes, this is a double-checked lock.
1175  // We can return even if the type is not completely initialized yet:
1176  // any thread trying to actually use the contents of the random engine
1177  // will necessarily wait on the lock.
1178  if (Q_LIKELY(self->type != SystemRNG))
1179  return self;
1180 
1181  SystemAndGlobalGenerators::PRNGLocker locker(self);
1182  if (self->type == SystemRNG)
1184 
1185  return self;
1186 }
1187 
1189 {
1192  return result;
1193 }
1194 
1199  : type(SystemRNG)
1200 {
1201  // don't touch storage
1202 }
1203 
1205  : type(other.type)
1206 {
1207  Q_ASSERT(this != system());
1209 
1210  if (type != SystemRNG) {
1212  storage.engine() = other.storage.engine();
1213  }
1214 }
1215 
1217 {
1219  qFatal("Attempted to overwrite a QRandomGenerator to system() or global().");
1220 
1221  if ((type = other.type) != SystemRNG) {
1223  storage.engine() = other.storage.engine();
1224  }
1225  return *this;
1226 }
1227 
1230 {
1231  Q_ASSERT(this != system());
1232  Q_ASSERT(this != SystemAndGlobalGenerators::globalNoInit());
1233 
1234  new (&storage.engine()) RandomEngine(sseq);
1235 }
1236 
1239 {
1240  Q_ASSERT(this != system());
1242 
1243  std::seed_seq s(begin, end);
1244  new (&storage.engine()) RandomEngine(s);
1245 }
1246 
1247 void QRandomGenerator::discard(unsigned long long z)
1248 {
1249  if (Q_UNLIKELY(type == SystemRNG))
1250  return;
1251 
1253  storage.engine().discard(z);
1254 }
1255 
1256 bool operator==(const QRandomGenerator &rng1, const QRandomGenerator &rng2)
1257 {
1258  if (rng1.type != rng2.type)
1259  return false;
1260  if (rng1.type == SystemRNG)
1261  return true;
1262 
1263  // Lock global() if either is it (otherwise this locking is a no-op)
1265  PRNGLocker locker(&rng1 == QRandomGenerator::global() ? &rng1 : &rng2);
1266  return rng1.storage.engine() == rng2.storage.engine();
1267 }
1268 
1277 quint64 QRandomGenerator::_fillRange(void *buffer, qptrdiff count)
1278 {
1279  // Verify that the pointers are properly aligned for 32-bit
1280  Q_ASSERT(quintptr(buffer) % sizeof(quint32) == 0);
1281  Q_ASSERT(count >= 0);
1282  Q_ASSERT(buffer || count <= 2);
1283 
1284  quint64 dummy;
1285  quint32 *begin = static_cast<quint32 *>(buffer ? buffer : &dummy);
1286  quint32 *end = begin + count;
1287 
1288  if (type == SystemRNG || Q_UNLIKELY(uint(qt_randomdevice_control.loadAcquire()) & (UseSystemRNG|SetRandomData))) {
1290  } else {
1291  SystemAndGlobalGenerators::PRNGLocker lock(this);
1292  std::generate(begin, end, [this]() { return storage.engine()(); });
1293  }
1294 
1295  if (end - begin == 1)
1296  return *begin;
1297  return begin[0] | (quint64(begin[1]) << 32);
1298 }
1299 
1300 // helper function to call fillBuffer, since we need something to be
1301 // argument-dependent
1302 template <typename Generator, typename FillBufferType, typename T>
1303 static qsizetype callFillBuffer(FillBufferType f, T *v)
1304 {
1305  if constexpr (std::is_member_function_pointer_v<FillBufferType>) {
1306  // member function, need an object
1307  return (Generator::self().*f)(v, sizeof(*v));
1308  } else {
1309  // static, call directly
1310  return f(v, sizeof(*v));
1311  }
1312 }
1313 
1324 QRandomGenerator::InitialRandomData qt_initial_random_value() noexcept
1325 {
1326 #if QT_CONFIG(getauxval) && defined(AT_RANDOM)
1327  auto at_random_ptr = reinterpret_cast<size_t *>(getauxval(AT_RANDOM));
1328  if (at_random_ptr)
1329  return qFromUnaligned<QRandomGenerator::InitialRandomData>(at_random_ptr);
1330 #endif
1331 
1332  // bypass the hardware RNG, which would mean initializing qsimd.cpp
1333 
1334  QRandomGenerator::InitialRandomData v;
1335  for (int attempts = 16; attempts; --attempts) {
1337  auto fillBuffer = &Generator::fillBuffer;
1338  if (callFillBuffer<Generator>(fillBuffer, &v) != sizeof(v))
1339  continue;
1340 
1341  return v;
1342  }
1343 
1344  quint32 data[sizeof(v) / sizeof(quint32)];
1345  fallback_fill(data, std::size(data));
1346  memcpy(v.data, data, sizeof(v.data));
1347  return v;
1348 }
1349 
#define value
[5]
bool testAndSetOrdered(T expectedValue, T newValue) noexcept
Definition: qbasicatomic.h:113
T loadAcquire() const noexcept
Definition: qbasicatomic.h:93
T loadRelaxed() const noexcept
Definition: qbasicatomic.h:90
static QDeadlineTimer current(Qt::TimerType timerType=Qt::CoarseTimer) noexcept
qint64 deadline() const noexcept Q_DECL_PURE_FUNCTION
template< typename Enum > bool operator==(Enum lhs, QFlags< Enum > rhs)
The QMutex class provides access serialization between threads.
Definition: qmutex.h:285
void unlock() noexcept
Definition: qmutex.h:293
void lock() noexcept
Definition: qmutex.h:290
The QRandomGenerator64 class allows one to obtain 64-bit random values from a high-quality,...
Definition: qrandom.h:245
static Q_CORE_EXPORT QRandomGenerator64 securelySeeded()
Definition: qrandom.cpp:1188
static Q_DECL_CONST_FUNCTION Q_CORE_EXPORT QRandomGenerator64 * global()
Definition: qrandom.cpp:1170
static Q_DECL_CONST_FUNCTION Q_CORE_EXPORT QRandomGenerator64 * system()
Definition: qrandom.cpp:1163
The QRandomGenerator class allows one to obtain random values from a high-quality Random Number Gener...
Definition: qrandom.h:57
friend class QRandomGenerator64
Definition: qrandom.h:224
static Q_DECL_CONST_FUNCTION QRandomGenerator * system()
Definition: qrandom.h:306
Q_CORE_EXPORT QRandomGenerator & operator=(const QRandomGenerator &other)
Definition: qrandom.cpp:1216
Q_CORE_EXPORT void discard(unsigned long long z)
Definition: qrandom.cpp:1247
QRandomGenerator(quint32 seedValue=1)
Definition: qrandom.h:62
static Q_DECL_CONST_FUNCTION QRandomGenerator * global()
Definition: qrandom.h:311
Definition: base.h:37
#define __attribute__(x)
Definition: hb.hh:256
auto generate(StringRef generatorName, SourceLineInfo const &lineInfo, L const &generatorExpression) -> decltype(std::declval< decltype(generatorExpression())>().get())
Definition: catch_p_p.h:4085
SimplePcg32 & rng()
@ PreciseTimer
Definition: qnamespace.h:1690
QString self
Definition: language.cpp:80
#define Q_BASIC_ATOMIC_INITIALIZER(a)
#define Q_UNLIKELY(x)
#define Q_LIKELY(x)
#define Q_UNREACHABLE()
EGLOutputLayerEXT EGLint EGLAttrib value
unsigned int quint32
Definition: qglobal.h:288
QT_BEGIN_INCLUDE_NAMESPACE typedef unsigned char uchar
Definition: qglobal.h:332
size_t quintptr
Definition: qglobal.h:310
unsigned long ulong
Definition: qglobal.h:335
ptrdiff_t qptrdiff
Definition: qglobal.h:307
unsigned long long quint64
Definition: qglobal.h:299
ptrdiff_t qsizetype
Definition: qglobal.h:308
unsigned int uint
Definition: qglobal.h:334
long long qint64
Definition: qglobal.h:298
#define qFatal
Definition: qlogging.h:181
GLenum type
Definition: qopengl.h:270
GLsizei const GLfloat * v
[13]
GLuint GLfloat GLfloat GLfloat GLfloat GLfloat z
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLuint GLuint end
GLenum GLenum GLsizei count
GLfloat GLfloat f
GLenum GLuint buffer
GLint left
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLboolean GLboolean g
GLuint64 GLenum GLint fd
GLfloat n
GLuint64EXT * result
[6]
Definition: qopenglext.h:10932
GLdouble s
[6]
Definition: qopenglext.h:235
DECLSPEC_IMPORT BOOLEAN WINAPI SystemFunction036(PVOID RandomBuffer, ULONG RandomBufferLength)
#define Q_ASSERT(cond)
Definition: qrandom.cpp:84
@ FillBufferNoexcept
Definition: qrandom.cpp:95
QRandomGenerator::InitialRandomData qt_initial_random_value() noexcept
Definition: qrandom.cpp:1324
@ MersenneTwister
Definition: qrandom_p.h:72
@ SystemRNG
Definition: qrandom_p.h:71
@ UseSystemRNG
Definition: qrandom_p.h:61
@ SkipSystemRNG
Definition: qrandom_p.h:62
@ SetRandomData
Definition: qrandom_p.h:64
@ SkipHWRNG
Definition: qrandom_p.h:63
@ RandomDataMask
Definition: qrandom_p.h:67
QtPrivate::QRegularExpressionMatchIteratorRangeBasedForIterator begin(const QRegularExpressionMatchIterator &iterator)
Q_UNUSED(salary)
[21]
std::seed_seq sseq(seedBuffer, seedBuffer+len)
[3]
QRandomGenerator generator(sseq)
QStorageInfo storage
[1]
QReadWriteLock lock
[0]
QSharedPointer< T > other(t)
[5]
static QRandomGenerator64 * system()
Definition: qrandom.cpp:389
struct QRandomGenerator::SystemAndGlobalGenerators::@314 global_
static SystemAndGlobalGenerators * self()
Definition: qrandom.cpp:382
static QRandomGenerator64 * globalNoInit()
Definition: qrandom.cpp:398
static void securelySeed(QRandomGenerator *rng)
Definition: qrandom.cpp:406
struct QRandomGenerator::SystemAndGlobalGenerators::ShortenedSystem system_
void generate(quint32 *begin, quint32 *end) noexcept(FillBufferNoexcept)
Definition: qrandom.cpp:319
static SystemGenerator & self()
Definition: qrandom.cpp:432
void generate(T *begin, T *end)
Definition: qrandom.cpp:189
Definition: main.cpp:38
QThreadStorage< int * > dummy[8]