This is an archive of the discontinued LLVM Phabricator instance.

sanitizer_common: add Semaphore
ClosedPublic

Authored by dvyukov on Jul 15 2021, 8:19 AM.

Details

Summary

Semaphore is a portable way to park/unpark threads.
The plan is to use it to implement a portable blocking
mutex in subsequent changes. Semaphore can also be used
to efficiently wait for other things (e.g. we currently
spin to synchronize thread creation and start).

Diff Detail

Event Timeline

dvyukov created this revision.Jul 15 2021, 8:19 AM
dvyukov requested review of this revision.Jul 15 2021, 8:19 AM
Herald added a project: Restricted Project. · View Herald TranscriptJul 15 2021, 8:19 AM
Herald added a subscriber: Restricted Project. · View Herald Transcript

I've separated this from actual mutex implementation because this contains lots of OS-dependent code, which has higher risks of breaking things and being reverted. So I want to land and secure this first.

Looking into adding tests.

dvyukov updated this revision to Diff 358988.Jul 15 2021, 8:30 AM

added test

FTR the mutex change that uses this semaphore is implemented here:
https://github.com/dvyukov/llvm-project/pull/3/files
(but it's a huge uncleaned change that I am slowly merging)

vitalybuka accepted this revision.Jul 15 2021, 12:19 PM
vitalybuka added inline comments.
compiler-rt/lib/sanitizer_common/sanitizer_mac.cpp
512

So we just spin here?
maybe TODO?

compiler-rt/lib/sanitizer_common/sanitizer_mutex.cpp
22–34

isn't this the same?

void Semaphore::Wait() {
  
  for(;;) {
    u32 count = atomic_load(&state_, memory_order_relaxed);
    if (count == 0) {
      FutexWait(&state_, 0);
      continue;
    }
    if (atomic_compare_exchange_weak(&state_, &count, count - 1,
                                     memory_order_acquire))
      break;
  };
}
This revision is now accepted and ready to land.Jul 15 2021, 12:19 PM
melver accepted this revision.Jul 16 2021, 9:45 AM
melver added inline comments.
compiler-rt/lib/sanitizer_common/sanitizer_mutex.cpp
38

Do we care if count==0? My guess is we probably don't, but just checking.

compiler-rt/lib/sanitizer_common/sanitizer_mutex.h
77

Depending on how early they should be initialized, it might be worth it to make this a constexpr constructor. Probably would mean inline initializing state_ below.

compiler-rt/lib/tsan/go/buildgo.sh
31

s/ /\t/
if this should be consistent with rest of file.

dvyukov updated this revision to Diff 359378.Jul 16 2021, 10:19 AM
dvyukov marked 2 inline comments as done.

addressed comments

compiler-rt/lib/sanitizer_common/sanitizer_mutex.cpp
22–34

It's subtly different.
atomic_compare_exchange returns the current value of the variable on failure (in count).
In the current version of the code, we use that value and don't re-load the variable after atomic_compare_exchange failure. In your version we re-load after failure.
On stress benchmarks for lock-free containers in makes 2x difference in overall performance. Here it does not matter much because we block/unblock threads anyway (slow). But I prefer to write it in the canonical way w/o unnecessary pessimization.

38

Added CHECK_NE(count, 0). Callers should not increment by 0.

dvyukov marked an inline comment as done.Jul 16 2021, 10:19 AM

Addressed all comments and uploaded a new version.

This revision was landed with ongoing or failed builds.Jul 16 2021, 10:34 AM
This revision was automatically updated to reflect the committed changes.
hans added a subscriber: hans.Aug 4 2021, 8:54 AM
hans added inline comments.
compiler-rt/lib/sanitizer_common/sanitizer_win.cpp
817

This adds a dependency on API-MS-Win-Core-Synch-l1-2-0.dll, which according to https://docs.microsoft.com/en-us/windows/win32/api/synchapi/nf-synchapi-waitonaddress is only available on Windows 8 and later.

This is a problem for Chrome, which still supports Windows 7.

Is there some way this could be done without depending on a new API?

See https://bugs.chromium.org/p/chromium/issues/detail?id=1236586

hans added inline comments.Aug 4 2021, 9:16 AM
compiler-rt/lib/sanitizer_common/sanitizer_win.cpp
817

Actually, Reid pointed out to me that I'm wrong about shipping Chrome/ASan builds anywhere outside our own testing infrastructure, in which case this is not a problem.

dvyukov added inline comments.Aug 4 2021, 9:17 AM
compiler-rt/lib/sanitizer_common/sanitizer_win.cpp
817

Does Chrome need to support Windows 7 _with_ TSAN? I assume TSAN build is only used by few developers and on bots.

hans added inline comments.Aug 4 2021, 9:24 AM
compiler-rt/lib/sanitizer_common/sanitizer_win.cpp
817

I thought we shipped our ASan builds to some small subset of users, but it turns out I was mistaken. Sorry for the noise.

There's a bug report https://github.com/llvm/llvm-project/issues/63786 mentioning Windows 7; I guess it's the same WaitOnAddress thing discussed previously? Maybe someone can reply on the bug report.

Herald added a project: Restricted Project. · View Herald TranscriptJul 12 2023, 10:56 AM