[libc-commits] [libc] [libc] Add separate `rand` implementation for baremetal (PR #96798)

Joseph Huber via libc-commits libc-commits at lists.llvm.org
Wed Jun 26 10:42:32 PDT 2024


https://github.com/jhuber6 updated https://github.com/llvm/llvm-project/pull/96798

>From 7c80ee0d82361b98e060c02b444fb5e4b29dc6a0 Mon Sep 17 00:00:00 2001
From: Joseph Huber <huberjn at outlook.com>
Date: Wed, 26 Jun 2024 12:00:10 -0500
Subject: [PATCH 1/2] [libc] Add separate `rand` implementation for baremetal

Summary:
Baremetal targets likely do now want multi-threaded support. Split the
implementation out to make it separate.
---
 libc/src/stdlib/CMakeLists.txt           | 89 ++++++++++++++----------
 libc/src/stdlib/baremetal/CMakeLists.txt | 36 ++++++++++
 libc/src/stdlib/baremetal/rand.cpp       | 26 +++++++
 libc/src/stdlib/baremetal/rand_util.cpp  | 18 +++++
 libc/src/stdlib/baremetal/rand_util.h    | 21 ++++++
 libc/src/stdlib/baremetal/srand.cpp      | 17 +++++
 libc/src/stdlib/linux/CMakeLists.txt     |  4 ++
 libc/src/stdlib/rand.cpp                 |  6 --
 libc/src/stdlib/srand.cpp                |  6 --
 9 files changed, 173 insertions(+), 50 deletions(-)
 create mode 100644 libc/src/stdlib/baremetal/rand.cpp
 create mode 100644 libc/src/stdlib/baremetal/rand_util.cpp
 create mode 100644 libc/src/stdlib/baremetal/rand_util.h
 create mode 100644 libc/src/stdlib/baremetal/srand.cpp

diff --git a/libc/src/stdlib/CMakeLists.txt b/libc/src/stdlib/CMakeLists.txt
index 677bf358c82c4..61aa14a8cb0d0 100644
--- a/libc/src/stdlib/CMakeLists.txt
+++ b/libc/src/stdlib/CMakeLists.txt
@@ -1,3 +1,7 @@
+if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${LIBC_TARGET_OS})
+  add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/${LIBC_TARGET_OS})
+endif()
+
 add_entrypoint_object(
   atoi
   SRCS
@@ -285,38 +289,55 @@ add_entrypoint_object(
     libc.include.stdlib
 )
 
-add_object_library(
-  rand_util
-  SRCS
-    rand_util.cpp
-  HDRS
-    rand_util.h
-  DEPENDS
-    libc.src.__support.common
-)
 
-add_entrypoint_object(
-  rand
-  SRCS
-    rand.cpp
-  HDRS
-    rand.h
-  DEPENDS
-    .rand_util
-    libc.include.stdlib
-    libc.src.__support.threads.sleep
-)
+if(NOT LIBC_TARGET_OS_IS_BAREMETAL)
+  add_object_library(
+    rand_util
+    SRCS
+      rand_util.cpp
+    HDRS
+      rand_util.h
+    DEPENDS
+      libc.src.__support.common
+  )
 
-add_entrypoint_object(
-  srand
-  SRCS
-    srand.cpp
-  HDRS
-    srand.h
-  DEPENDS
-    .rand_util
-    libc.include.stdlib
-)
+  add_entrypoint_object(
+    rand
+    SRCS
+      rand.cpp
+    HDRS
+      rand.h
+    DEPENDS
+      .rand_util
+      libc.include.stdlib
+      libc.src.__support.threads.sleep
+  )
+
+  add_entrypoint_object(
+    srand
+    SRCS
+      srand.cpp
+    HDRS
+      srand.h
+    DEPENDS
+      .rand_util
+      libc.include.stdlib
+  )
+else()
+  add_entrypoint_object(
+    rand
+    ALIAS
+    DEPENDS
+      .${LIBC_TARGET_OS}.rand
+  )
+
+  add_entrypoint_object(
+    srand
+    ALIAS
+    DEPENDS
+      .${LIBC_TARGET_OS}.srand
+  )
+endif()
 
 if(NOT LIBC_TARGET_OS_IS_GPU)
   if(LLVM_LIBC_INCLUDE_SCUDO)
@@ -413,14 +434,6 @@ if(NOT LIBC_TARGET_OS_IS_GPU)
   endif()
 endif()
 
-if(NOT LLVM_LIBC_FULL_BUILD)
-  return()
-endif()
-
-if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${LIBC_TARGET_OS})
-  add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/${LIBC_TARGET_OS})
-endif()
-
 if(LIBC_TARGET_OS_IS_GPU)
   add_entrypoint_object(
     malloc
diff --git a/libc/src/stdlib/baremetal/CMakeLists.txt b/libc/src/stdlib/baremetal/CMakeLists.txt
index 551a83a36b20e..fc43bf3d16b26 100644
--- a/libc/src/stdlib/baremetal/CMakeLists.txt
+++ b/libc/src/stdlib/baremetal/CMakeLists.txt
@@ -1,3 +1,39 @@
+add_object_library(
+  rand_util
+  SRCS
+    rand_util.cpp
+  HDRS
+    rand_util.h
+  DEPENDS
+    libc.src.__support.common
+)
+
+add_entrypoint_object(
+  rand
+  SRCS
+    rand.cpp
+  HDRS
+    ../rand.h
+  DEPENDS
+    .rand_util
+    libc.include.stdlib
+)
+
+add_entrypoint_object(
+  srand
+  SRCS
+    srand.cpp
+  HDRS
+    srand.h
+  DEPENDS
+    .rand_util
+    libc.include.stdlib
+)
+
+if(NOT LLVM_LIBC_FULL_BUILD)
+  return()
+endif()
+
 add_entrypoint_object(
   abort
   SRCS
diff --git a/libc/src/stdlib/baremetal/rand.cpp b/libc/src/stdlib/baremetal/rand.cpp
new file mode 100644
index 0000000000000..a36b6f8da5d8f
--- /dev/null
+++ b/libc/src/stdlib/baremetal/rand.cpp
@@ -0,0 +1,26 @@
+//===-- Implementation of rand --------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "src/stdlib/rand.h"
+#include "src/__support/common.h"
+#include "src/__support/threads/sleep.h"
+#include "src/stdlib/baremetal/rand_util.h"
+
+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;
+  return static_cast<int>((x * 0x2545F4914F6CDD1Dul) >> 32) & RAND_MAX;
+}
+
+} // namespace LIBC_NAMESPACE
diff --git a/libc/src/stdlib/baremetal/rand_util.cpp b/libc/src/stdlib/baremetal/rand_util.cpp
new file mode 100644
index 0000000000000..4057930758c8f
--- /dev/null
+++ b/libc/src/stdlib/baremetal/rand_util.cpp
@@ -0,0 +1,18 @@
+//===-- Shared utility for rand -------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "src/stdlib/rand_util.h"
+#include "src/__support/macros/attributes.h"
+
+namespace LIBC_NAMESPACE {
+
+//  C standard 7.10p2: If 'rand' is called before 'srand' it is to
+// proceed as if the 'srand' function was called with a value of '1'.
+unsigned long rand_next = 1;
+
+} // namespace LIBC_NAMESPACE
diff --git a/libc/src/stdlib/baremetal/rand_util.h b/libc/src/stdlib/baremetal/rand_util.h
new file mode 100644
index 0000000000000..6f8839d093971
--- /dev/null
+++ b/libc/src/stdlib/baremetal/rand_util.h
@@ -0,0 +1,21 @@
+//===-- Implementation header for rand utilities ----------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC_STDLIB_RAND_UTIL_H
+#define LLVM_LIBC_SRC_STDLIB_RAND_UTIL_H
+
+#include "src/__support/macros/attributes.h"
+
+namespace LIBC_NAMESPACE {
+
+// We provide the baremetal version of `rand` without any thread-safety.
+extern unsigned long rand_next;
+
+} // namespace LIBC_NAMESPACE
+
+#endif // LLVM_LIBC_SRC_STDLIB_RAND_UTIL_H
diff --git a/libc/src/stdlib/baremetal/srand.cpp b/libc/src/stdlib/baremetal/srand.cpp
new file mode 100644
index 0000000000000..008c7a9e565e4
--- /dev/null
+++ b/libc/src/stdlib/baremetal/srand.cpp
@@ -0,0 +1,17 @@
+//===-- Implementation of srand -------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "src/stdlib/srand.h"
+#include "src/__support/common.h"
+#include "src/stdlib/rand_util.h"
+
+namespace LIBC_NAMESPACE {
+
+LLVM_LIBC_FUNCTION(void, srand, (unsigned int seed)) { rand_next = seed; }
+
+} // namespace LIBC_NAMESPACE
diff --git a/libc/src/stdlib/linux/CMakeLists.txt b/libc/src/stdlib/linux/CMakeLists.txt
index 1d3c00a5e0ddb..df9c25abf3cba 100644
--- a/libc/src/stdlib/linux/CMakeLists.txt
+++ b/libc/src/stdlib/linux/CMakeLists.txt
@@ -1,3 +1,7 @@
+if(NOT LLVM_LIBC_FULL_BUILD)
+  return()
+endif()
+
 add_entrypoint_object(
   abort
   SRCS
diff --git a/libc/src/stdlib/rand.cpp b/libc/src/stdlib/rand.cpp
index 8f2ae90336d51..ff3875c2f6959 100644
--- a/libc/src/stdlib/rand.cpp
+++ b/libc/src/stdlib/rand.cpp
@@ -13,10 +13,6 @@
 
 namespace LIBC_NAMESPACE {
 
-// Silence warnings on targets with slow atomics.
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Watomic-alignment"
-
 // 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)) {
@@ -33,6 +29,4 @@ LLVM_LIBC_FUNCTION(int, rand, (void)) {
   }
 }
 
-#pragma GCC diagnostic pop
-
 } // namespace LIBC_NAMESPACE
diff --git a/libc/src/stdlib/srand.cpp b/libc/src/stdlib/srand.cpp
index 681aad8fac4e8..21166c7a6754e 100644
--- a/libc/src/stdlib/srand.cpp
+++ b/libc/src/stdlib/srand.cpp
@@ -12,14 +12,8 @@
 
 namespace LIBC_NAMESPACE {
 
-// Silence warnings on targets with slow atomics.
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Watomic-alignment"
-
 LLVM_LIBC_FUNCTION(void, srand, (unsigned int seed)) {
   rand_next.store(seed, cpp::MemoryOrder::RELAXED);
 }
 
-#pragma GCC diagnostic pop
-
 } // namespace LIBC_NAMESPACE

>From 0e2c05e465798f8b27a3686553d682d119072208 Mon Sep 17 00:00:00 2001
From: Joseph Huber <huberjn at outlook.com>
Date: Wed, 26 Jun 2024 12:42:22 -0500
Subject: [PATCH 2/2] Address comments

---
 libc/src/stdlib/CMakeLists.txt        | 1 +
 libc/src/stdlib/baremetal/rand.cpp    | 3 ++-
 libc/src/stdlib/baremetal/rand_util.h | 2 --
 libc/src/stdlib/rand_util.h           | 1 -
 4 files changed, 3 insertions(+), 4 deletions(-)

diff --git a/libc/src/stdlib/CMakeLists.txt b/libc/src/stdlib/CMakeLists.txt
index 61aa14a8cb0d0..2ff2fbb480ba9 100644
--- a/libc/src/stdlib/CMakeLists.txt
+++ b/libc/src/stdlib/CMakeLists.txt
@@ -324,6 +324,7 @@ if(NOT LIBC_TARGET_OS_IS_BAREMETAL)
       libc.include.stdlib
   )
 else()
+  # Baremetal targets use a non MT-safe implementation.
   add_entrypoint_object(
     rand
     ALIAS
diff --git a/libc/src/stdlib/baremetal/rand.cpp b/libc/src/stdlib/baremetal/rand.cpp
index a36b6f8da5d8f..39e9b45fef052 100644
--- a/libc/src/stdlib/baremetal/rand.cpp
+++ b/libc/src/stdlib/baremetal/rand.cpp
@@ -8,13 +8,14 @@
 
 #include "src/stdlib/rand.h"
 #include "src/__support/common.h"
-#include "src/__support/threads/sleep.h"
 #include "src/stdlib/baremetal/rand_util.h"
 
 namespace LIBC_NAMESPACE {
 
 // An implementation of the xorshift64star pseudo random number generator. This
 // is a good general purpose generator for most non-cryptographics applications.
+// This function is *not* MT-safe, baremetal callers will need to provide
+// synchronization externally.
 LLVM_LIBC_FUNCTION(int, rand, (void)) {
   unsigned long x = rand_next;
   x ^= x >> 12;
diff --git a/libc/src/stdlib/baremetal/rand_util.h b/libc/src/stdlib/baremetal/rand_util.h
index 6f8839d093971..c9153ac7dd432 100644
--- a/libc/src/stdlib/baremetal/rand_util.h
+++ b/libc/src/stdlib/baremetal/rand_util.h
@@ -9,8 +9,6 @@
 #ifndef LLVM_LIBC_SRC_STDLIB_RAND_UTIL_H
 #define LLVM_LIBC_SRC_STDLIB_RAND_UTIL_H
 
-#include "src/__support/macros/attributes.h"
-
 namespace LIBC_NAMESPACE {
 
 // We provide the baremetal version of `rand` without any thread-safety.
diff --git a/libc/src/stdlib/rand_util.h b/libc/src/stdlib/rand_util.h
index 5d7febf8248d8..762448bc87eda 100644
--- a/libc/src/stdlib/rand_util.h
+++ b/libc/src/stdlib/rand_util.h
@@ -10,7 +10,6 @@
 #define LLVM_LIBC_SRC_STDLIB_RAND_UTIL_H
 
 #include "src/__support/CPP/atomic.h"
-#include "src/__support/macros/attributes.h"
 
 namespace LIBC_NAMESPACE {
 



More information about the libc-commits mailing list