futex_like.cpp 1.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455
  1. #include <util/system/platform.h>
  2. #ifdef _linux_
  3. #include <sys/syscall.h>
  4. #include <linux/futex.h>
  5. #if !defined(SYS_futex)
  6. #define SYS_futex __NR_futex
  7. #endif
  8. #endif
  9. #include <errno.h>
  10. #include <util/system/yassert.h>
  11. #include "futex_like.h"
  12. #ifdef _linux_
  13. namespace {
  14. int futex(int* uaddr, int op, int val, const struct timespec* timeout,
  15. int* uaddr2, int val3) {
  16. return syscall(SYS_futex, uaddr, op, val, timeout, uaddr2, val3);
  17. }
  18. }
  19. #endif
  20. void TFutexLike::Wake(size_t count) {
  21. Y_ASSERT(count > 0);
  22. #ifdef _linux_
  23. if (count > unsigned(Max<int>())) {
  24. count = Max<int>();
  25. }
  26. int r = futex(&Value, FUTEX_WAKE, count, nullptr, nullptr, 0);
  27. Y_ABORT_UNLESS(r >= 0, "futex_wake failed: %s", strerror(errno));
  28. #else
  29. TGuard<TMutex> guard(Mutex);
  30. if (count == 1) {
  31. CondVar.Signal();
  32. } else {
  33. CondVar.BroadCast();
  34. }
  35. #endif
  36. }
  37. void TFutexLike::Wait(int expected) {
  38. #ifdef _linux_
  39. int r = futex(&Value, FUTEX_WAIT, expected, nullptr, nullptr, 0);
  40. Y_ABORT_UNLESS(r >= 0 || errno == EWOULDBLOCK, "futex_wait failed: %s", strerror(errno));
  41. #else
  42. TGuard<TMutex> guard(Mutex);
  43. if (expected == Get()) {
  44. CondVar.WaitI(Mutex);
  45. }
  46. #endif
  47. }