summaryrefslogtreecommitdiff
path: root/libc/src/stdlib/rand.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'libc/src/stdlib/rand.cpp')
-rw-r--r--libc/src/stdlib/rand.cpp18
1 files changed, 12 insertions, 6 deletions
diff --git a/libc/src/stdlib/rand.cpp b/libc/src/stdlib/rand.cpp
index ad543b4048a9..ff3875c2f695 100644
--- a/libc/src/stdlib/rand.cpp
+++ b/libc/src/stdlib/rand.cpp
@@ -8,6 +8,7 @@
#include "src/stdlib/rand.h"
#include "src/__support/common.h"
+#include "src/__support/threads/sleep.h"
#include "src/stdlib/rand_util.h"
namespace LIBC_NAMESPACE {
@@ -15,12 +16,17 @@ namespace LIBC_NAMESPACE {
// An implementation of the xorshift64star pseudo random number generator. This
// is a good general purpose generator for most non-cryptographics applications.
LLVM_LIBC_FUNCTION(int, rand, (void)) {
- unsigned long x = rand_next;
- x ^= x >> 12;
- x ^= x << 25;
- x ^= x >> 27;
- rand_next = x;
- return static_cast<int>((x * 0x2545F4914F6CDD1Dul) >> 32) & RAND_MAX;
+ unsigned long orig = rand_next.load(cpp::MemoryOrder::RELAXED);
+ for (;;) {
+ unsigned long x = orig;
+ x ^= x >> 12;
+ x ^= x << 25;
+ x ^= x >> 27;
+ if (rand_next.compare_exchange_strong(orig, x, cpp::MemoryOrder::ACQUIRE,
+ cpp::MemoryOrder::RELAXED))
+ return static_cast<int>((x * 0x2545F4914F6CDD1Dul) >> 32) & RAND_MAX;
+ sleep_briefly();
+ }
}
} // namespace LIBC_NAMESPACE