Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. // futex -*- C++ -*-
  2.  
  3. // Copyright (C) 2015 Free Software Foundation, Inc.
  4. //
  5. // This file is part of the GNU ISO C++ Library.  This library is free
  6. // software; you can redistribute it and/or modify it under the
  7. // terms of the GNU General Public License as published by the
  8. // Free Software Foundation; either version 3, or (at your option)
  9. // any later version.
  10.  
  11. // This library is distributed in the hope that it will be useful,
  12. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14. // GNU General Public License for more details.
  15.  
  16. // Under Section 7 of GPL version 3, you are granted additional
  17. // permissions described in the GCC Runtime Library Exception, version
  18. // 3.1, as published by the Free Software Foundation.
  19.  
  20. // You should have received a copy of the GNU General Public License and
  21. // a copy of the GCC Runtime Library Exception along with this program;
  22. // see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
  23. // <http://www.gnu.org/licenses/>.
  24.  
  25. #include <bits/atomic_futex.h>
  26. #if defined(_GLIBCXX_HAS_GTHREADS) && defined(_GLIBCXX_USE_C99_STDINT_TR1)
  27. #if defined(_GLIBCXX_HAVE_LINUX_FUTEX) && ATOMIC_INT_LOCK_FREE > 1
  28. #include <chrono>
  29. #include <climits>
  30. #include <syscall.h>
  31. #include <unistd.h>
  32. #include <sys/time.h>
  33. #include <errno.h>
  34. #include <debug/debug.h>
  35.  
  36. // Constants for the wait/wake futex syscall operations
  37. const unsigned futex_wait_op = 0;
  38. const unsigned futex_wake_op = 1;
  39.  
  40. namespace std _GLIBCXX_VISIBILITY(default)
  41. {
  42. _GLIBCXX_BEGIN_NAMESPACE_VERSION
  43.  
  44.   bool
  45.   __atomic_futex_unsigned_base::_M_futex_wait_until(unsigned *__addr,
  46.       unsigned __val,
  47.       bool __has_timeout, chrono::seconds __s, chrono::nanoseconds __ns)
  48.   {
  49.     if (!__has_timeout)
  50.       {
  51.         // Ignore whether we actually succeeded to block because at worst,
  52.         // we will fall back to spin-waiting.  The only thing we could do
  53.         // here on errors is abort.
  54.         int ret __attribute__((unused));
  55.         ret = syscall (SYS_futex, __addr, futex_wait_op, __val, nullptr);
  56.         _GLIBCXX_DEBUG_ASSERT(ret == 0 || errno == EINTR || errno == EAGAIN);
  57.         return true;
  58.       }
  59.     else
  60.       {
  61.         struct timeval tv;
  62.         gettimeofday (&tv, NULL);
  63.         // Convert the absolute timeout value to a relative timeout
  64.         struct timespec rt;
  65.         rt.tv_sec = __s.count() - tv.tv_sec;
  66.         rt.tv_nsec = __ns.count() - tv.tv_usec * 1000;
  67.         if (rt.tv_nsec < 0)
  68.           {
  69.             rt.tv_nsec += 1000000000;
  70.             --rt.tv_sec;
  71.           }
  72.         // Did we already time out?
  73.         if (rt.tv_sec < 0)
  74.           return false;
  75.  
  76.         if (syscall (SYS_futex, __addr, futex_wait_op, __val, &rt) == -1)
  77.           {
  78.             _GLIBCXX_DEBUG_ASSERT(errno == EINTR || errno == EAGAIN
  79.                                   || errno == ETIMEDOUT);
  80.             if (errno == ETIMEDOUT)
  81.               return false;
  82.           }
  83.         return true;
  84.       }
  85.   }
  86.  
  87.   void
  88.   __atomic_futex_unsigned_base::_M_futex_notify_all(unsigned* __addr)
  89.   {
  90.     // This syscall can fail for various reasons, including in situations
  91.     // in which there is no real error.  Thus, we don't bother checking
  92.     // the error codes.  See the futex documentation and glibc for background.
  93.     syscall (SYS_futex, __addr, futex_wake_op, INT_MAX);
  94.   }
  95.  
  96. _GLIBCXX_END_NAMESPACE_VERSION
  97. }
  98. #endif
  99. #endif
  100.