Baselib_SystemFutex.h 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263
  1. #pragma once
  2. // Baselib_SystemFutex
  3. // In computing, a futex (short for "fast userspace mutex") is a kernel system call that programmers can use to implement basic locking, or as a building block
  4. // for higher-level locking abstractions such as semaphores and POSIX mutexes or condition variables.
  5. //
  6. // A futex consists of a kernelspace wait queue that is attached to an atomic integer in userspace. Multiple processes or threads operate on the integer
  7. // entirely in userspace (using atomic operations to avoid interfering with one another), and only resort to relatively expensive system calls to request
  8. // operations on the wait queue (for example to wake up waiting processes, or to put the current process on the wait queue). A properly programmed futex-based
  9. // lock will not use system calls except when the lock is contended; since most operations do not require arbitration between processes, this will not happen
  10. // in most cases.
  11. //
  12. // "Futex", Wikipedia: The Free Encyclopedia
  13. // https://en.wikipedia.org/w/index.php?title=Futex&oldid=850172014
  14. #include "Baselib_WakeupFallbackStrategy.h"
  15. #ifdef __cplusplus
  16. BASELIB_C_INTERFACE
  17. {
  18. #endif
  19. // Determines if the platform has access to a kernel level futex api
  20. //
  21. // If native support is not present the futex will fallback to an emulated futex setup.
  22. //
  23. // Notes on the emulation:
  24. // * It uses a single synchronization primitive to multiplex all potential addresses. This means there will be
  25. // additional contention as well as spurious wakeups compared to a native implementation.
  26. // * While the fallback implementation is not something that should be used in production it can still provide value
  27. // when bringing up new platforms or to test features built on top of the futex api.
  28. BASELIB_INLINE_API bool Baselib_SystemFutex_NativeSupport(void) { return PLATFORM_FUTEX_NATIVE_SUPPORT == 1; }
  29. // Wait for notification.
  30. //
  31. // Address will be checked atomically against expected before entering wait. This can be used to guarantee there are no lost wakeups.
  32. // Note: When notified the thread always wake up regardless if the expectation match the value at address or not.
  33. //
  34. // | Problem this solves
  35. // | Thread 1: checks condition and determine we should enter wait
  36. // | Thread 2: change condition and notify waiting threads
  37. // | Thread 1: enters waiting state
  38. // |
  39. // | With a futex the two Thread 1 operations become a single op.
  40. //
  41. // Spurious Wakeup - This function is subject to spurious wakeups.
  42. //
  43. // \param address Any address that can be read from both user and kernel space.
  44. // \param expected What address points to will be checked against this value. If the values don't match thread will not enter a waiting state.
  45. // \param timeoutInMilliseconds A timeout indicating to the kernel when to wake the thread. Regardless of being notified or not.
  46. BASELIB_API void Baselib_SystemFutex_Wait(int32_t* address, int32_t expected, uint32_t timeoutInMilliseconds);
  47. // Notify threads waiting on a specific address.
  48. //
  49. // \param address Any address that can be read from both user and kernel space
  50. // \param count Number of waiting threads to wakeup.
  51. // \param wakeupFallbackStrategy Platforms that don't support waking up a specific number of threads will use this strategy.
  52. BASELIB_API void Baselib_SystemFutex_Notify(int32_t* address, uint32_t count, Baselib_WakeupFallbackStrategy wakeupFallbackStrategy);
  53. #ifdef __cplusplus
  54. } // BASELIB_C_INTERFACE
  55. #endif