Skip to content

[compiler-rt][builtins] Switch libatomic locks to pthread_mutex_t. #94374

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

Merged
merged 1 commit into from
Jun 4, 2024

Conversation

Logikable
Copy link
Contributor

@Logikable Logikable commented Jun 4, 2024

When an uninstrumented libatomic is used with a TSan instrumented
memcpy, TSan may report a data race in circumstances where writes are
arguably safe.

This occurs because __atomic_compare_exchange won't be instrumented in
an uninstrumented libatomic, so TSan doesn't know that the subsequent
memcpy is race-free.

On the other hand, pthread_mutex_(un)lock will be intercepted by TSan,
meaning an uninstrumented libatomic will not report this false-positive.

pthread_mutexes also may try a number of different strategies to acquire
the lock, which may bound the amount of time a thread has to wait for a
lock during contention.

While pthread_mutex_lock has a larger overhead (due to the function
call and some dispatching), a dispatch to libatomic already predicates
a lack of performance guarantees.

Copy link

github-actions bot commented Jun 4, 2024

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

When an uninstrumented libatomic is used with a TSan instrumented
memcpy, TSan may report a data race in circumstances where writes are
arguably safe.

This occurs because __atomic_compare_exchange won't be instrumented in
an uninstrumented libatomic, so TSan doesn't know that the subsequent
memcpy is race-free.

On the other hand, pthread_mutex_(un)lock will be intercepted by TSan,
meaning an uninstrumented libatomic will not report this false-positive.

pthread_mutexes also may try a number of different strategies to acquire
the lock, which may bound the amount of time a thread has to wait for a
lock during contention.

While pthread_mutex_lock has a larger overhead (due to the function
call and some dispatching), a dispatch to libatomic already predicates
a lack of performance guarantees.
@MaskRay
Copy link
Member

MaskRay commented Jun 4, 2024

LGTM. It's perhaps worth mentioning that GCC libatomic also uses pthread_mutex_t. So this change would bring three advantages:

  • The uninstrumented atomic.c will work seemlessly with tsan (thanks to the pthread_mutex_lock interceptor). We don't need a separate tsan version of libatomic
  • It would prevent potential issues with high thread competition for the spin lock.
  • It aligns with GCC libatomic.

It seems that glibc's pthread_mutex_lock implementation has slightly larger overhead (a few instructions before and after lock cmpxchg %edx,(%rdi) including __libc_single_threaded test which is always 0 for non-trivial google3 code) while other implementations seem to optimize the PTHREAD_MUTEX_NORMAL common scenarios better, e.g. https://git.musl-libc.org/cgit/musl/tree/src/thread/pthread_mutex_lock.c

@MaskRay MaskRay merged commit b62b7a4 into llvm:main Jun 4, 2024
4 of 5 checks passed
@MaskRay
Copy link
Member

MaskRay commented Jun 4, 2024

It seems that we forgot PTHREAD_MUTEX_INITIALIZER (benign issue since it is all zeroes in glibc and musl). Perhaps we should avoid false sharing as well:
#94374

MaskRay added a commit that referenced this pull request Jun 4, 2024
PTHREAD_MUTEX_INITIALIZER is zeroes for glibc and musl, but it improves
conformance and might work with more libc implementations.

Follow-up to #94374

Pull Request: #94387
@pirama-arumuga-nainar
Copy link
Collaborator

This PR broke the armv8-a builtins build in Android toolchain - which can lower _Atomic but the baremetal environment doesn't have <pthread.h>. Can you specialize this change to fall back to _Atomic when COMPILER_RT_HAS_LIBPTHREAD is off?

@mstorsjo
Copy link
Member

mstorsjo commented Jun 5, 2024

This also broke builds for Windows: https://github.com/mstorsjo/llvm-mingw/actions/runs/9376329007/job/25816083980

Can you specialize this change to fall back to _Atomic when COMPILER_RT_HAS_LIBPTHREAD is off?

This sounds like a good idea, but I'd also like to make it dependent on platform. E.g. on Windows, libpthread may exist - there are third party libraries that provide the pthreads API, but we don't want to use it here even if it happens to exist while building compiler-rt.

@appujee
Copy link
Contributor

appujee commented Jun 5, 2024

This also broke builds for Windows: https://github.com/mstorsjo/llvm-mingw/actions/runs/9376329007/job/25816083980

Can you specialize this change to fall back to _Atomic when COMPILER_RT_HAS_LIBPTHREAD is off?

This sounds like a good idea, but I'd also like to make it dependent on platform. E.g. on Windows, libpthread may exist - there are third party libraries that provide the pthreads API, but we don't want to use it here even if it happens to exist while building compiler-rt.

Yeah, i agree that users should have a choice to opt-in to pthreads. As it seems like there are a few things to clarify, should this patch be reverted?

@mstorsjo
Copy link
Member

mstorsjo commented Jun 5, 2024

This also broke builds for Windows: https://github.com/mstorsjo/llvm-mingw/actions/runs/9376329007/job/25816083980

Can you specialize this change to fall back to _Atomic when COMPILER_RT_HAS_LIBPTHREAD is off?

This sounds like a good idea, but I'd also like to make it dependent on platform. E.g. on Windows, libpthread may exist - there are third party libraries that provide the pthreads API, but we don't want to use it here even if it happens to exist while building compiler-rt.

Yeah, i agree that users should have a choice to opt-in to pthreads. As it seems like there are a few things to clarify, should this patch be reverted?

Yes, this should be reverted for now. I can push a revert shortly.

mstorsjo added a commit that referenced this pull request Jun 5, 2024
…ex_t (#94374)"

This reverts commit b62b7a4 and
a5729b7.

This commit broke compilation for systems that lack pthreads.
@mstorsjo
Copy link
Member

mstorsjo commented Jun 5, 2024

This also broke builds for Windows: https://github.com/mstorsjo/llvm-mingw/actions/runs/9376329007/job/25816083980

Can you specialize this change to fall back to _Atomic when COMPILER_RT_HAS_LIBPTHREAD is off?

This sounds like a good idea, but I'd also like to make it dependent on platform. E.g. on Windows, libpthread may exist - there are third party libraries that provide the pthreads API, but we don't want to use it here even if it happens to exist while building compiler-rt.

Yeah, i agree that users should have a choice to opt-in to pthreads. As it seems like there are a few things to clarify, should this patch be reverted?

Yes, this should be reverted for now. I can push a revert shortly.

Reverted now in a4b32c2.

@MaskRay
Copy link
Member

MaskRay commented Jun 6, 2024

Perhaps we can keep the current spin locks for #if defined(__ANDROID__) || defined(_WIN32)

@pirama-arumuga-nainar
Copy link
Collaborator

Perhaps we can keep the current spin locks for #if defined(__ANDROID__) || defined(_WIN32)

The breakage in the Android toolchain is not when targeting Android but a baremetal configuration needed in Android. So the above will not work. This target does set COMPILER_RT_BAREMETAL_BUILD=ON - if you want to key off of that. But !COMPILER_RT_HAS_LIBPTHREAD || defined(_WIN32) is probably the correct check here.

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.

6 participants