futex.h 3.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  1. /*
  2. * Copyright (c) 2023 Agustina Arzille.
  3. *
  4. * This program is free software: you can redistribute it and/or modify
  5. * it under the terms of the GNU General Public License as published by
  6. * the Free Software Foundation, either version 3 of the License, or
  7. * (at your option) any later version.
  8. *
  9. * This program is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU General Public License
  15. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  16. *
  17. * Futexes: Building block for user-space synchronization primitives.
  18. */
  19. #ifndef KERN_FUTEX_H
  20. #define KERN_FUTEX_H
  21. #include <assert.h>
  22. #include <stdint.h>
  23. #define FUTEX_SHARED 0x01 // Futex may be shared across tasks.
  24. #define FUTEX_TIMED 0x02 // Wait is time bound.
  25. #define FUTEX_MUTATE 0x04 // Change the futex contents before waking.
  26. #define FUTEX_BROADCAST 0x08 // Wake all waiters, or move all waiters.
  27. #define FUTEX_ABSTIME 0x10 // Time passed is an absolute value.
  28. #define FUTEX_PI 0x20 // Futex has priority-inheritance semantics.
  29. struct futex_robust_list
  30. {
  31. int futex;
  32. int flags;
  33. uint64_t next __attribute__ ((aligned (8)));
  34. };
  35. struct futex_td
  36. {
  37. struct futex_robust_list *pending;
  38. struct futex_robust_list *list;
  39. };
  40. static inline void
  41. futex_td_init (struct futex_td *td)
  42. {
  43. td->pending = td->list = NULL;
  44. }
  45. // Bits used in the futex word for PI and robust futexes.
  46. #define FUTEX_WAITERS (1u << 31)
  47. #define FUTEX_OWNER_DIED (1u << 30)
  48. #define FUTEX_TID_MASK (~(FUTEX_WAITERS | FUTEX_OWNER_DIED))
  49. // Ensure binary layout is correct.
  50. static_assert (sizeof (struct futex_robust_list) == 16,
  51. "invalid size for futex_robust_list");
  52. static_assert (__builtin_offsetof (struct futex_robust_list, next) == 8,
  53. "invalid layout for futex_robust_list");
  54. /*
  55. * Wait for a 'futex_wake' on this address, checking before that
  56. * it containts the specified value (failing with EAGAIN otherwise).
  57. * If flags hast the 'FUTEX_TIMED' set, wait no more than the specified
  58. * timeout, and fail with ETIMEDOUT if no wake call was done.
  59. */
  60. int futex_wait (int *addr, int value, uint32_t flags, uint64_t ticks);
  61. /*
  62. * Wake up threads waiting on an address. Either one thread (default) or
  63. * all threads (if FLAGS_BROADCAST is set) may be woken up. In addition,
  64. * if the FUTEX_MUTATE bit is set, the address' contents may be set to
  65. * a specified value (useful for robust futexes).
  66. */
  67. int futex_wake (int *addr, uint32_t flags, int value);
  68. /*
  69. * Move waiters sleeping on one futex to another one, optionally waking
  70. * up a waiter in the process. If FUTEX_BROADCAST is set in flags, moves
  71. * all waiters; otherwise only one is moved.
  72. *
  73. * This function is not implemented for PI futexes.
  74. */
  75. int futex_requeue (int *dst_addr, int *src_addr,
  76. int wake_one, uint32_t flags);
  77. // Clean up all held robust futexes by the calling thread.
  78. void futex_td_exit (struct futex_td *td);
  79. #endif