condition_variable_linux.cpp 1.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152
  1. //===-- condition_variable_linux.cpp ----------------------------*- C++ -*-===//
  2. //
  3. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  4. // See https://llvm.org/LICENSE.txt for license information.
  5. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8. #include "platform.h"
  9. #if SCUDO_LINUX
  10. #include "condition_variable_linux.h"
  11. #include "atomic_helpers.h"
  12. #include <limits.h>
  13. #include <linux/futex.h>
  14. #include <sys/syscall.h>
  15. #include <unistd.h>
  16. namespace scudo {
  17. void ConditionVariableLinux::notifyAllImpl(UNUSED HybridMutex &M) {
  18. const u32 V = atomic_load_relaxed(&Counter);
  19. atomic_store_relaxed(&Counter, V + 1);
  20. // TODO(chiahungduan): Move the waiters from the futex waiting queue
  21. // `Counter` to futex waiting queue `M` so that the awoken threads won't be
  22. // blocked again due to locked `M` by current thread.
  23. if (LastNotifyAll != V) {
  24. syscall(SYS_futex, reinterpret_cast<uptr>(&Counter), FUTEX_WAKE_PRIVATE,
  25. INT_MAX, nullptr, nullptr, 0);
  26. }
  27. LastNotifyAll = V + 1;
  28. }
  29. void ConditionVariableLinux::waitImpl(HybridMutex &M) {
  30. const u32 V = atomic_load_relaxed(&Counter) + 1;
  31. atomic_store_relaxed(&Counter, V);
  32. // TODO: Use ScopedUnlock when it's supported.
  33. M.unlock();
  34. syscall(SYS_futex, reinterpret_cast<uptr>(&Counter), FUTEX_WAIT_PRIVATE, V,
  35. nullptr, nullptr, 0);
  36. M.lock();
  37. }
  38. } // namespace scudo
  39. #endif // SCUDO_LINUX