[libc-commits] [libc] 75747c7 - [libc] Remove the remaining uses of stdatomic.h.

Siva Chandra Reddy via libc-commits libc-commits at lists.llvm.org
Tue Mar 1 09:13:01 PST 2022


Author: Siva Chandra Reddy
Date: 2022-03-01T17:12:39Z
New Revision: 75747c73946546fb9f9163b9a813b54f96874948

URL: https://github.com/llvm/llvm-project/commit/75747c73946546fb9f9163b9a813b54f96874948
DIFF: https://github.com/llvm/llvm-project/commit/75747c73946546fb9f9163b9a813b54f96874948.diff

LOG: [libc] Remove the remaining uses of stdatomic.h.

New methods to the Atomic class have been added as required. Futex
related types have been consolidated at a common place.

Reviewed By: lntue

Differential Revision: https://reviews.llvm.org/D120705

Added: 
    libc/include/llvm-libc-types/__futex_word.h

Modified: 
    libc/config/linux/api.td
    libc/include/llvm-libc-types/CMakeLists.txt
    libc/include/llvm-libc-types/mtx_t.h
    libc/include/llvm-libc-types/once_flag.h
    libc/include/llvm-libc-types/thrd_t.h
    libc/src/__support/CPP/atomic.h
    libc/src/threads/linux/CMakeLists.txt
    libc/src/threads/linux/Futex.h
    libc/src/threads/linux/Mutex.h
    libc/src/threads/linux/Thread.h
    libc/src/threads/linux/call_once.cpp
    libc/src/threads/linux/thrd_create.cpp
    libc/src/threads/linux/thrd_join.cpp
    libc/test/src/threads/CMakeLists.txt
    libc/test/src/threads/call_once_test.cpp
    libc/test/src/threads/cnd_test.cpp

Removed: 
    


################################################################################
diff  --git a/libc/config/linux/api.td b/libc/config/linux/api.td
index d584de545f22b..3841e36b1ba98 100644
--- a/libc/config/linux/api.td
+++ b/libc/config/linux/api.td
@@ -216,7 +216,7 @@ def SignalAPI : PublicAPI<"signal.h"> {
 
 def ThreadsAPI : PublicAPI<"threads.h"> {
   let Macros = [
-    SimpleMacroDef<"ONCE_FLAG_INIT", "0">,
+    SimpleMacroDef<"ONCE_FLAG_INIT", "{0}">,
   ];
 
   let Types = [

diff  --git a/libc/include/llvm-libc-types/CMakeLists.txt b/libc/include/llvm-libc-types/CMakeLists.txt
index dfb34c0696773..08d7f8c911d7f 100644
--- a/libc/include/llvm-libc-types/CMakeLists.txt
+++ b/libc/include/llvm-libc-types/CMakeLists.txt
@@ -1,5 +1,6 @@
 add_header(__bsearchcompare_t HDR __bsearchcompare_t.h)
 add_header(__call_once_func_t HDR __call_once_func_t.h)
+add_header(__futex_word HDR __futex_word.h)
 add_header(__qsortcompare_t HDR __qsortcompare_t.h)
 add_header(__sighandler_t HDR __sighandler_t.h)
 add_header(cnd_t HDR cnd_t.h)
@@ -13,9 +14,9 @@ add_header(fexcept_t HDR fexcept_t.h)
 add_header(float_t HDR float_t.h)
 add_header(imaxdiv_t HDR imaxdiv_t.h)
 add_header(mode_t HDR mode_t.h)
-add_header(mtx_t HDR mtx_t.h)
+add_header(mtx_t HDR mtx_t.h DEPENDS .__futex_word)
 add_header(off_t HDR off_t.h)
-add_header(once_flag HDR once_flag.h)
+add_header(once_flag HDR once_flag.h DEPENDS .__futex_word)
 add_header(size_t HDR size_t.h)
 add_header(ssize_t HDR ssize_t.h)
 add_header(struct_sigaction HDR struct_sigaction.h)

diff  --git a/libc/include/llvm-libc-types/__futex_word.h b/libc/include/llvm-libc-types/__futex_word.h
new file mode 100644
index 0000000000000..17b0dda8496e9
--- /dev/null
+++ b/libc/include/llvm-libc-types/__futex_word.h
@@ -0,0 +1,24 @@
+//===-- Definition of type which can represent a futex word ---------------===//
+//
+// 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_TYPES_FUTEX_WORD_H__
+#define __LLVM_LIBC_TYPES_FUTEX_WORD_H__
+
+typedef struct {
+#if defined(__unix__) && (defined(__x86_64__) || defined(__aarch64__))
+  // Futex word should be aligned appropriately to allow target atomic
+  // instructions. This declaration mimics the internal setup.
+  _Alignas(sizeof(unsigned int) > _Alignof(unsigned int)
+               ? sizeof(unsigned int)
+               : _Alignof(unsigned int)) unsigned int __word;
+#else
+#error "A type to represent a futex word is not available for the target arch."
+#endif
+} __futex_word;
+
+#endif // __LLVM_LIBC_TYPES_FUTEX_WORD_H__

diff  --git a/libc/include/llvm-libc-types/mtx_t.h b/libc/include/llvm-libc-types/mtx_t.h
index 9586f21f7e28b..d0b5491ee9e9e 100644
--- a/libc/include/llvm-libc-types/mtx_t.h
+++ b/libc/include/llvm-libc-types/mtx_t.h
@@ -9,17 +9,13 @@
 #ifndef __LLVM_LIBC_TYPES_MTX_T_H__
 #define __LLVM_LIBC_TYPES_MTX_T_H__
 
+#include <llvm-libc-types/__futex_word.h>
+
 typedef struct {
-#if defined(__x86_64__) || defined(__aarch64__)
-  // Futex word should be aligned appropriately to allow target atomic
-  // instructions. This declaration mimics the internal setup.
-  struct {
-    _Alignas(sizeof(unsigned int) > _Alignof(unsigned int)
-                 ? sizeof(unsigned int)
-                 : _Alignof(unsigned int)) unsigned int __word;
-  } __futex_word;
+#ifdef __unix__
+  __futex_word __ftxw;
 #else
-#error "Mutex type mtx_t is not available for the target architecture."
+#error "mtx_t type not defined for the target platform."
 #endif
   int __mtx_type;
 } mtx_t;

diff  --git a/libc/include/llvm-libc-types/once_flag.h b/libc/include/llvm-libc-types/once_flag.h
index 4987bda38bbe4..e6aec5e6522d6 100644
--- a/libc/include/llvm-libc-types/once_flag.h
+++ b/libc/include/llvm-libc-types/once_flag.h
@@ -9,6 +9,12 @@
 #ifndef __LLVM_LIBC_TYPES_ONCE_FLAG_H__
 #define __LLVM_LIBC_TYPES_ONCE_FLAG_H__
 
-typedef unsigned int once_flag;
+#include <llvm-libc-types/__futex_word.h>
 
-#endif // __LLVM_LIBC_TYPES_ONCE_FLAg_H__
+#ifdef __unix__
+typedef __futex_word once_flag;
+#else
+#error "Once flag type not defined for the target platform."
+#endif
+
+#endif // __LLVM_LIBC_TYPES_ONCE_FLAG_H__

diff  --git a/libc/include/llvm-libc-types/thrd_t.h b/libc/include/llvm-libc-types/thrd_t.h
index ebbf9b0a36506..ae41ac846e563 100644
--- a/libc/include/llvm-libc-types/thrd_t.h
+++ b/libc/include/llvm-libc-types/thrd_t.h
@@ -9,8 +9,10 @@
 #ifndef __LLVM_LIBC_TYPES_THRD_T_H__
 #define __LLVM_LIBC_TYPES_THRD_T_H__
 
+#include <llvm-libc-types/__futex_word.h>
+
 typedef struct {
-  unsigned char __clear_tid[4];
+  __futex_word __clear_tid;
   int __tid;
   void *__stack;
   int __stack_size;

diff  --git a/libc/src/__support/CPP/atomic.h b/libc/src/__support/CPP/atomic.h
index 4496472bf4252..72addbc523938 100644
--- a/libc/src/__support/CPP/atomic.h
+++ b/libc/src/__support/CPP/atomic.h
@@ -43,6 +43,8 @@ template <typename T> struct Atomic {
   // operations should be performed using the atomic methods however.
   alignas(ALIGNMENT) value_type val;
 
+  constexpr Atomic() = default;
+
   // Intializes the value without using atomic operations.
   constexpr Atomic(value_type v) : val(v) {}
 
@@ -73,6 +75,18 @@ template <typename T> struct Atomic {
                                        int(mem_ord), int(mem_ord));
   }
 
+  T exchange(T desired, MemoryOrder mem_ord = MemoryOrder::SEQ_CST) {
+    return __atomic_exchange_n(&val, desired, int(mem_ord));
+  }
+
+  T fetch_add(T increment, MemoryOrder mem_ord = MemoryOrder::SEQ_CST) {
+    return __atomic_fetch_add(&val, increment, int(mem_ord));
+  }
+
+  T fetch_sub(T decrement, MemoryOrder mem_ord = MemoryOrder::SEQ_CST) {
+    return __atomic_fetch_sub(&val, decrement, int(mem_ord));
+  }
+
   // Set the value without using an atomic operation. This is useful
   // in initializing atomic values without a constructor.
   void set(T rhs) { val = rhs; }

diff  --git a/libc/src/threads/linux/CMakeLists.txt b/libc/src/threads/linux/CMakeLists.txt
index d25b23caf4056..6fdca98ebe849 100644
--- a/libc/src/threads/linux/CMakeLists.txt
+++ b/libc/src/threads/linux/CMakeLists.txt
@@ -18,6 +18,7 @@ add_entrypoint_object(
     .threads_utils
     libc.include.sys_syscall
     libc.include.threads
+    libc.src.__support.CPP.atomic
     libc.src.__support.OSUtil.osutil
 )
 
@@ -67,6 +68,7 @@ add_entrypoint_object(
     .threads_utils
     libc.include.sys_syscall
     libc.include.threads
+    libc.src.__support.CPP.atomic
     libc.src.__support.common
     libc.src.__support.OSUtil.osutil
     libc.src.sys.mman.munmap

diff  --git a/libc/src/threads/linux/Futex.h b/libc/src/threads/linux/Futex.h
index e80816f5f5239..fab1b6ddc74bd 100644
--- a/libc/src/threads/linux/Futex.h
+++ b/libc/src/threads/linux/Futex.h
@@ -9,19 +9,22 @@
 #ifndef LLVM_LIBC_SRC_THREADS_LINUX_FUTEX_H
 #define LLVM_LIBC_SRC_THREADS_LINUX_FUTEX_H
 
-#include <stdatomic.h>
+#include "src/__support/architectures.h" // Architecture macros
 
 namespace __llvm_libc {
 
+#if (defined(LLVM_LIBC_ARCH_AARCH64) || defined(LLVM_LIBC_ARCH_X86_64))
 // The futex data has to be exactly 4 bytes long. However, we use a uint type
-// here as we do not want to use `_Atomic uint32_t` as the _Atomic keyword which
-// is C only. The header stdatomic.h does not define an atomic type
-// corresponding to `uint32_t` or to something which is exactly 4 bytes wide.
-using FutexWord = atomic_uint;
-static_assert(sizeof(atomic_uint) == 4,
-              "Size of the `atomic_uint` type is not 4 bytes on your platform. "
-              "The implementation of the standard threads library for linux "
-              "requires that size of `atomic_uint` be 4 bytes.");
+// here as we do not want to use `uint32_t` type to match the public definitions
+// of types which include a field for a futex word. With public definitions, we
+// cannot include <stdint.h> so we stick to the `unsigned int` type for x86_64
+// and aarch64
+using FutexWordType = unsigned int;
+static_assert(sizeof(FutexWordType) == 4,
+              "Unexpected size of unsigned int type.");
+#else
+#error "Futex word base type not defined for the target architecture."
+#endif
 
 } // namespace __llvm_libc
 

diff  --git a/libc/src/threads/linux/Mutex.h b/libc/src/threads/linux/Mutex.h
index c32bd39ae88dd..a8fe8537d064b 100644
--- a/libc/src/threads/linux/Mutex.h
+++ b/libc/src/threads/linux/Mutex.h
@@ -9,6 +9,8 @@
 #ifndef LLVM_LIBC_SRC_THREADS_LINUX_MUTEX_H
 #define LLVM_LIBC_SRC_THREADS_LINUX_MUTEX_H
 
+#include "Futex.h"
+
 #include "include/sys/syscall.h"          // For syscall numbers.
 #include "include/threads.h"              // For values like thrd_success etc.
 #include "src/__support/CPP/atomic.h"     // For atomics support
@@ -18,14 +20,6 @@
 
 namespace __llvm_libc {
 
-#if (defined(LLVM_LIBC_ARCH_AARCH64) || defined(LLVM_LIBC_ARCH_X86_64))
-static_assert(sizeof(unsigned int) == 4,
-              "Unexpected size of unsigned int type.");
-typedef unsigned int FutexWordType;
-#else
-#error "Futex word base type not defined for the target architecture."
-#endif
-
 struct Mutex {
   enum Status : FutexWordType {
     MS_Free,

diff  --git a/libc/src/threads/linux/Thread.h b/libc/src/threads/linux/Thread.h
index 55aa2719673fb..a14ed49c33b12 100644
--- a/libc/src/threads/linux/Thread.h
+++ b/libc/src/threads/linux/Thread.h
@@ -11,7 +11,6 @@
 
 #include "thread_start_args.h"
 
-#include <stdatomic.h>
 #include <stdint.h>
 
 namespace __llvm_libc {

diff  --git a/libc/src/threads/linux/call_once.cpp b/libc/src/threads/linux/call_once.cpp
index 9b9664634a1f3..e04c4e47853b8 100644
--- a/libc/src/threads/linux/call_once.cpp
+++ b/libc/src/threads/linux/call_once.cpp
@@ -6,27 +6,32 @@
 //
 //===----------------------------------------------------------------------===//
 
-#include "src/threads/call_once.h"
+#include "Futex.h"
+
 #include "include/sys/syscall.h" // For syscall numbers.
 #include "include/threads.h"     // For call_once related type definition.
+#include "src/__support/CPP/atomic.h"
 #include "src/__support/OSUtil/syscall.h" // For syscall functions.
 #include "src/__support/common.h"
+#include "src/threads/call_once.h"
 #include "src/threads/linux/Futex.h"
 
 #include <limits.h>
 #include <linux/futex.h>
-#include <stdatomic.h>
 
 namespace __llvm_libc {
 
-static constexpr unsigned START = 0x11;
-static constexpr unsigned WAITING = 0x22;
-static constexpr unsigned FINISH = 0x33;
+static constexpr FutexWordType START = 0x11;
+static constexpr FutexWordType WAITING = 0x22;
+static constexpr FutexWordType FINISH = 0x33;
+static constexpr once_flag ONCE_FLAG_INIT_VAL = ONCE_FLAG_INIT;
 
 LLVM_LIBC_FUNCTION(void, call_once,
                    (once_flag * flag, __call_once_func_t func)) {
-  FutexWord *futex_word = reinterpret_cast<FutexWord *>(flag);
-  unsigned int not_called = ONCE_FLAG_INIT;
+  auto *futex_word = reinterpret_cast<cpp::Atomic<FutexWordType> *>(flag);
+  static_assert(sizeof(*futex_word) == sizeof(once_flag));
+
+  FutexWordType not_called = ONCE_FLAG_INIT_VAL.__word;
 
   // The C standard wording says:
   //
@@ -37,21 +42,21 @@ LLVM_LIBC_FUNCTION(void, call_once,
   // What this means is that, the call_once call can return only after
   // the called function |func| returns. So, we use futexes to synchronize
   // calls with the same flag value.
-  if (::atomic_compare_exchange_strong(futex_word, &not_called, START)) {
+  if (futex_word->compare_exchange_strong(not_called, START)) {
     func();
-    auto status = ::atomic_exchange(futex_word, FINISH);
+    auto status = futex_word->exchange(FINISH);
     if (status == WAITING) {
-      __llvm_libc::syscall(SYS_futex, futex_word, FUTEX_WAKE_PRIVATE,
+      __llvm_libc::syscall(SYS_futex, &futex_word->val, FUTEX_WAKE_PRIVATE,
                            INT_MAX, // Wake all waiters.
                            0, 0, 0);
     }
     return;
   }
 
-  unsigned int status = START;
-  if (::atomic_compare_exchange_strong(futex_word, &status, WAITING) ||
+  FutexWordType status = START;
+  if (futex_word->compare_exchange_strong(status, WAITING) ||
       status == WAITING) {
-    __llvm_libc::syscall(SYS_futex, futex_word, FUTEX_WAIT_PRIVATE,
+    __llvm_libc::syscall(SYS_futex, &futex_word->val, FUTEX_WAIT_PRIVATE,
                          WAITING, // Block only if status is still |WAITING|.
                          0, 0, 0);
   }

diff  --git a/libc/src/threads/linux/thrd_create.cpp b/libc/src/threads/linux/thrd_create.cpp
index 5421c96775b7f..34b50399b98c2 100644
--- a/libc/src/threads/linux/thrd_create.cpp
+++ b/libc/src/threads/linux/thrd_create.cpp
@@ -6,7 +6,8 @@
 //
 //===----------------------------------------------------------------------===//
 
-#include "src/threads/thrd_create.h"
+#include "Futex.h"
+
 #include "include/errno.h"                // For E* error values.
 #include "include/sys/mman.h"             // For PROT_* and MAP_* definitions.
 #include "include/sys/syscall.h"          // For syscall numbers.
@@ -16,8 +17,8 @@
 #include "src/errno/llvmlibc_errno.h"
 #include "src/sys/mman/mmap.h"
 #include "src/sys/mman/munmap.h"
-#include "src/threads/linux/Futex.h"
 #include "src/threads/linux/Thread.h"
+#include "src/threads/thrd_create.h"
 
 #include <linux/sched.h> // For CLONE_* flags.
 #include <stdint.h>
@@ -61,8 +62,7 @@ LLVM_LIBC_FUNCTION(int, thrd_create,
   thread->__stack = stack;
   thread->__stack_size = ThreadParams::DEFAULT_STACK_SIZE;
   thread->__retval = -1;
-  FutexWord *clear_tid_address =
-      reinterpret_cast<FutexWord *>(thread->__clear_tid);
+  FutexWordType *clear_tid_address = &thread->__clear_tid.__word;
   *clear_tid_address = ThreadParams::CLEAR_TID_VALUE;
 
   // When the new thread is spawned by the kernel, the new thread gets the

diff  --git a/libc/src/threads/linux/thrd_join.cpp b/libc/src/threads/linux/thrd_join.cpp
index f55f5a3af3f5f..361c5877d86c8 100644
--- a/libc/src/threads/linux/thrd_join.cpp
+++ b/libc/src/threads/linux/thrd_join.cpp
@@ -6,31 +6,32 @@
 //
 //===----------------------------------------------------------------------===//
 
-#include "src/threads/thrd_join.h"
-#include "include/sys/syscall.h"          // For syscall numbers.
-#include "include/threads.h"              // For thrd_* type definitions.
+#include "Futex.h"
+
+#include "include/sys/syscall.h" // For syscall numbers.
+#include "include/threads.h"     // For thrd_* type definitions.
+#include "src/__support/CPP/atomic.h"
 #include "src/__support/OSUtil/syscall.h" // For syscall function.
 #include "src/__support/common.h"
 #include "src/sys/mman/munmap.h"
-#include "src/threads/linux/Futex.h"
 #include "src/threads/linux/Thread.h"
+#include "src/threads/thrd_join.h"
 
 #include <linux/futex.h> // For futex operations.
-#include <stdatomic.h>   // For atomic_load.
 
 namespace __llvm_libc {
 
 LLVM_LIBC_FUNCTION(int, thrd_join, (thrd_t * thread, int *retval)) {
-  FutexWord *clear_tid_address =
-      reinterpret_cast<FutexWord *>(thread->__clear_tid);
+  auto *clear_tid_address =
+      reinterpret_cast<cpp::Atomic<FutexWordType> *>(&thread->__clear_tid);
 
   // The kernel should set the value at the clear tid address to zero.
   // If not, it is a spurious wake and we should continue to wait on
   // the futex.
-  while (atomic_load(clear_tid_address) != 0) {
+  while (clear_tid_address->load() != 0) {
     // We cannot do a FUTEX_WAIT_PRIVATE here as the kernel does a
     // FUTEX_WAKE and not a FUTEX_WAKE_PRIVATE.
-    __llvm_libc::syscall(SYS_futex, clear_tid_address, FUTEX_WAIT,
+    __llvm_libc::syscall(SYS_futex, &clear_tid_address->val, FUTEX_WAIT,
                          ThreadParams::CLEAR_TID_VALUE, nullptr);
   }
 

diff  --git a/libc/test/src/threads/CMakeLists.txt b/libc/test/src/threads/CMakeLists.txt
index 356a8b06e4084..2e23623327932 100644
--- a/libc/test/src/threads/CMakeLists.txt
+++ b/libc/test/src/threads/CMakeLists.txt
@@ -15,6 +15,7 @@ add_libc_unittest(
     libc.src.threads.mtx_unlock
     libc.src.threads.thrd_create
     libc.src.threads.thrd_join
+    libc.src.__support.CPP.atomic
 )
 
 add_libc_unittest(

diff  --git a/libc/test/src/threads/call_once_test.cpp b/libc/test/src/threads/call_once_test.cpp
index b0e9fb8ccc715..6090e63435af4 100644
--- a/libc/test/src/threads/call_once_test.cpp
+++ b/libc/test/src/threads/call_once_test.cpp
@@ -7,6 +7,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "include/threads.h"
+#include "src/__support/CPP/atomic.h"
 #include "src/threads/call_once.h"
 #include "src/threads/mtx_destroy.h"
 #include "src/threads/mtx_init.h"
@@ -16,10 +17,8 @@
 #include "src/threads/thrd_join.h"
 #include "utils/UnitTest/Test.h"
 
-#include <stdatomic.h>
-
 static constexpr unsigned int NUM_THREADS = 5;
-static atomic_uint thread_count;
+static __llvm_libc::cpp::Atomic<unsigned int> thread_count;
 
 static unsigned int call_count;
 static void call_once_func() { ++call_count; }
@@ -28,7 +27,7 @@ static int func(void *) {
   static once_flag flag = ONCE_FLAG_INIT;
   __llvm_libc::call_once(&flag, call_once_func);
 
-  ++thread_count; // This is a an atomic update.
+  thread_count.fetch_add(1);
 
   return 0;
 }
@@ -51,7 +50,7 @@ TEST(LlvmLibcCallOnceTest, CallFrom5Threads) {
     ASSERT_EQ(retval, 0);
   }
 
-  EXPECT_EQ(static_cast<unsigned int>(thread_count), 5U);
+  EXPECT_EQ(thread_count.val, 5U);
   EXPECT_EQ(call_count, 1U);
 }
 
@@ -61,13 +60,13 @@ static void blocking_once_func() {
   __llvm_libc::mtx_unlock(&once_func_blocker);
 }
 
-static atomic_uint start_count;
-static atomic_uint done_count;
+static __llvm_libc::cpp::Atomic<unsigned int> start_count;
+static __llvm_libc::cpp::Atomic<unsigned int> done_count;
 static int once_func_caller(void *) {
   static once_flag flag;
-  ++start_count;
+  start_count.fetch_add(1);
   __llvm_libc::call_once(&flag, blocking_once_func);
-  ++done_count;
+  done_count.fetch_add(1);
   return 0;
 }
 
@@ -90,11 +89,11 @@ TEST(LlvmLibcCallOnceTest, TestSynchronization) {
   ASSERT_EQ(__llvm_libc::thrd_create(&t2, once_func_caller, nullptr),
             static_cast<int>(thrd_success));
 
-  while (start_count != 2)
+  while (start_count.load() != 2)
     ; // Spin until both threads start.
 
   // Since the once func is blocked, the threads should not be done yet.
-  EXPECT_EQ(static_cast<unsigned int>(done_count), 0U);
+  EXPECT_EQ(done_count.val, 0U);
 
   // Unlock the blocking mutex so that the once func blocks.
   ASSERT_EQ(__llvm_libc::mtx_unlock(&once_func_blocker),
@@ -108,7 +107,7 @@ TEST(LlvmLibcCallOnceTest, TestSynchronization) {
             static_cast<int>(thrd_success));
   ASSERT_EQ(retval, 0);
 
-  ASSERT_EQ(static_cast<unsigned int>(done_count), 2U);
+  ASSERT_EQ(done_count.val, 2U);
 
   __llvm_libc::mtx_destroy(&once_func_blocker);
 }

diff  --git a/libc/test/src/threads/cnd_test.cpp b/libc/test/src/threads/cnd_test.cpp
index 38f12eaa22639..960c0c1a389e8 100644
--- a/libc/test/src/threads/cnd_test.cpp
+++ b/libc/test/src/threads/cnd_test.cpp
@@ -6,9 +6,8 @@
 //
 //===----------------------------------------------------------------------===//
 
-#include <stdatomic.h>
-
 #include "include/threads.h"
+#include "src/__support/CPP/atomic.h"
 #include "src/threads/cnd_broadcast.h"
 #include "src/threads/cnd_destroy.h"
 #include "src/threads/cnd_init.h"
@@ -34,15 +33,15 @@ namespace wait_notify_broadcast_test {
 // |broadcast_count| by 1 before they start waiting on |broadcast_cnd|, and
 // decrement it by 1 after getting signalled on |broadcast_cnd|.
 
-constexpr int THRD_COUNT = 10000;
+constexpr unsigned int THRD_COUNT = 10000;
 
-static atomic_uint broadcast_count = 0;
+static __llvm_libc::cpp::Atomic<unsigned int> broadcast_count(0);
 static cnd_t broadcast_cnd, threads_ready_cnd;
 static mtx_t broadcast_mtx, threads_ready_mtx;
 
 int broadcast_thread_func(void *) {
   __llvm_libc::mtx_lock(&broadcast_mtx);
-  int oldval = atomic_fetch_add(&broadcast_count, 1);
+  int oldval = broadcast_count.fetch_add(1);
   if (oldval == THRD_COUNT - 1) {
     __llvm_libc::mtx_lock(&threads_ready_mtx);
     __llvm_libc::cnd_signal(&threads_ready_cnd);
@@ -51,7 +50,7 @@ int broadcast_thread_func(void *) {
 
   __llvm_libc::cnd_wait(&broadcast_cnd, &broadcast_mtx);
   __llvm_libc::mtx_unlock(&broadcast_mtx);
-  atomic_fetch_sub(&broadcast_count, 1);
+  broadcast_count.fetch_sub(1);
   return 0;
 }
 
@@ -70,7 +69,7 @@ TEST(LlvmLibcCndVarTest, WaitNotifyBroadcastTest) {
   __llvm_libc::mtx_unlock(&threads_ready_mtx);
 
   __llvm_libc::mtx_lock(&broadcast_mtx);
-  ASSERT_EQ(int(broadcast_count), THRD_COUNT);
+  ASSERT_EQ(broadcast_count.val, THRD_COUNT);
   __llvm_libc::cnd_broadcast(&broadcast_cnd);
   __llvm_libc::mtx_unlock(&broadcast_mtx);
 
@@ -80,7 +79,7 @@ TEST(LlvmLibcCndVarTest, WaitNotifyBroadcastTest) {
     ASSERT_EQ(retval, 0);
   }
 
-  ASSERT_EQ(int(broadcast_count), 0);
+  ASSERT_EQ(broadcast_count.val, 0U);
 
   __llvm_libc::cnd_destroy(&broadcast_cnd);
   __llvm_libc::cnd_destroy(&threads_ready_cnd);


        


More information about the libc-commits mailing list