Skip to content

[Support/rpmalloc] Updated fake atomics with Interlocked functions #148303

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

slydiman
Copy link
Contributor

Most atomic functions used Interlocked functions in case of MSVC (since MSVC does not do C11 yet).
But few load/store functions are dummy.
Use Interlocked functions for these atomics to ensure they are thread-safe.

This PR fixes #146205.

@llvmbot
Copy link
Member

llvmbot commented Jul 11, 2025

@llvm/pr-subscribers-llvm-support

Author: Dmitry Vasilyev (slydiman)

Changes

Most atomic functions used Interlocked functions in case of MSVC (since MSVC does not do C11 yet).
But few load/store functions are dummy.
Use Interlocked functions for these atomics to ensure they are thread-safe.

This PR fixes #146205.


Full diff: https://github.com/llvm/llvm-project/pull/148303.diff

1 Files Affected:

  • (modified) llvm/lib/Support/rpmalloc/rpmalloc.c (+11-7)
diff --git a/llvm/lib/Support/rpmalloc/rpmalloc.c b/llvm/lib/Support/rpmalloc/rpmalloc.c
index a06d3cdb5b52e..7e30922cbabc6 100644
--- a/llvm/lib/Support/rpmalloc/rpmalloc.c
+++ b/llvm/lib/Support/rpmalloc/rpmalloc.c
@@ -275,9 +275,11 @@ typedef volatile long atomic32_t;
 typedef volatile long long atomic64_t;
 typedef volatile void *atomicptr_t;
 
-static FORCEINLINE int32_t atomic_load32(atomic32_t *src) { return *src; }
+static FORCEINLINE int32_t atomic_load32(atomic32_t *src) {
+  return (int32_t)InterlockedOr(src, 0);
+}
 static FORCEINLINE void atomic_store32(atomic32_t *dst, int32_t val) {
-  *dst = val;
+  InterlockedExchange(dst, val);
 }
 static FORCEINLINE int32_t atomic_incr32(atomic32_t *val) {
   return (int32_t)InterlockedIncrement(val);
@@ -293,20 +295,22 @@ static FORCEINLINE int atomic_cas32_acquire(atomic32_t *dst, int32_t val,
   return (InterlockedCompareExchange(dst, val, ref) == ref) ? 1 : 0;
 }
 static FORCEINLINE void atomic_store32_release(atomic32_t *dst, int32_t val) {
-  *dst = val;
+  InterlockedExchange(dst, val);
+}
+static FORCEINLINE int64_t atomic_load64(atomic64_t *src) { 
+  return (int64_t)InterlockedOr64(src, 0);
 }
-static FORCEINLINE int64_t atomic_load64(atomic64_t *src) { return *src; }
 static FORCEINLINE int64_t atomic_add64(atomic64_t *val, int64_t add) {
   return (int64_t)InterlockedExchangeAdd64(val, add) + add;
 }
 static FORCEINLINE void *atomic_load_ptr(atomicptr_t *src) {
-  return (void *)*src;
+  return InterlockedCompareExchangePointer(src, 0, 0);
 }
 static FORCEINLINE void atomic_store_ptr(atomicptr_t *dst, void *val) {
-  *dst = val;
+  InterlockedExchangePointer(dst, val);
 }
 static FORCEINLINE void atomic_store_ptr_release(atomicptr_t *dst, void *val) {
-  *dst = val;
+  InterlockedExchangePointer(dst, val);
 }
 static FORCEINLINE void *atomic_exchange_ptr_acquire(atomicptr_t *dst,
                                                      void *val) {

Copy link

github-actions bot commented Jul 11, 2025

✅ With the latest revision this PR passed the C/C++ code formatter.

Most atomic functions used Interlocked functions in case of MSVC (since MSVC does not do C11 yet).
But few load/store functions are dummy.
Use Interlocked functions for these atomics to ensure they are thread-safe.

This PR fixes llvm#146205.
@slydiman slydiman force-pushed the fix-rpmalloc-intrinsics branch from 0d16751 to f300dcb Compare July 11, 2025 21:58
@aganea
Copy link
Member

aganea commented Jul 12, 2025

I'd like to see this merged upstream rpmalloc before merging it here. @slydiman Can you please send a PR there first? https://github.com/mjansson/rpmalloc/pulls

The point being, like for BLAKE3, I think we should keep in sync with upstream rpmalloc and only make integrations here into LLVM.

You might also want to experiment with the compiler flag /experimental:c11atomics in which case the codepath would be the same as for Clang. I suppose we could add that flag only files in llvm/lib/Support/rpmalloc/.

@slydiman
Copy link
Contributor Author

slydiman commented Jul 13, 2025

I'd like to see this merged upstream rpmalloc before merging it here. @slydiman Can you please send a PR there first? https://github.com/mjansson/rpmalloc/pulls

The point being, like for BLAKE3, I think we should keep in sync with upstream rpmalloc and only make integrations here into LLVM.

The usage of Interlocked* functions is the workaround since MSVC does not do C11.
The upstream code does not contain the section Atomic access abstraction at all. It just uses stdatomic.
Currently LLVM requires Visual Studio 2019 or later (no exact version specified).
According to the doc (Install C11 and C17 support in Visual Studio) support for C11 and C17 standards is available starting in Visual Studio 2019 version 16.8. Support requires an updated Universal C Runtime (UCRT) and the latest Windows SDK updates.
So we can

  • update our copy of rpmalloc with this PR for now
  • or update requirements to Visual Studio 2019 version 16.8 or later and remove the workaround with all Interlocked* functions.

@aganea
Copy link
Member

aganea commented Jul 13, 2025

We do require VS 2019 version 16.8 minimally in LLVM, please see 28bba0d

However that is not enough afaik for C11 stdatomics, it needs VS 2022 version 17.5 minimally: https://devblogs.microsoft.com/cppblog/c11-atomics-in-visual-studio-2022-version-17-5-preview-2/

I am fine with the Interlocked versions, but again, I'd like to keep this in sync with upstream rpmalloc, and not diverge with custom changes. We could:

  1. Send a PR with your changes to https://github.com/mjansson/rpmalloc/pulls
  2. Once that is approved and merged, we integrate the latest rpmalloc in LLVM.

Are you able to do that first step?

@slydiman
Copy link
Contributor Author

slydiman commented Jul 13, 2025

All Atomic access abstraction related code has been removed from the upstream rpmalloc 2 years ago.
The initial rpmalloc code in LLVM (since 2024) contained Atomic access abstraction.
So these implementations were out of sync from the beginning.

Send a PR with your changes to https://github.com/mjansson/rpmalloc/pulls
Once that is approved and merged, we integrate the latest rpmalloc in LLVM.
Are you able to do that first step?

rpmalloc upstream does not have this problem any more, thus the fix is not needed there.
We need it here till we will sync with rpmalloc upstream when LLVM will require Visual Studio 2022.

@aganea
Copy link
Member

aganea commented Jul 14, 2025

All Atomic access abstraction related code has been removed from the upstream rpmalloc 2 years ago. The initial rpmalloc code in LLVM (since 2024) contained Atomic access abstraction. So these implementations were out of sync from the beginning.

Actually the rpmalloc fork in LLVM is version 1.4.5 verbatim. What you might looking at is the develop branch which indeed had the "Atomic access abstraction" part removed from the code in this commit mjansson/rpmalloc@ed40516.

Send a PR with your changes to https://github.com/mjansson/rpmalloc/pulls
Once that is approved and merged, we integrate the latest rpmalloc in LLVM.
Are you able to do that first step?

rpmalloc upstream does not have this problem any more, thus the fix is not needed there. We need it here till we will sync with rpmalloc upstream when LLVM will require Visual Studio 2022.

@mjansson Is there a possibility that you release a new rpmalloc version soon with the contents of the develop branch? There haven't been any releases for the past year. We're trying to see what avenues we should take with the change proposed in this PR. Ideally I'd like not to diverge from your repo. One other option would be to integrate into LLVM from develop at head (if you think that should be stable enough).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[rpmalloc] Fake atomic operations in case of MSVC
3 participants