rtmutex.h 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  1. /*
  2. * Copyright (c) 2017 Richard Braun.
  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. *
  18. * Real-time mutual exclusion locks.
  19. *
  20. * A real-time mutex is similar to a regular mutex, except priority
  21. * inheritance is unconditionally enabled.
  22. */
  23. #ifndef KERN_RTMUTEX_H
  24. #define KERN_RTMUTEX_H
  25. #include <assert.h>
  26. #include <errno.h>
  27. #include <stdbool.h>
  28. #include <stdint.h>
  29. #include <kern/atomic.h>
  30. #include <kern/init.h>
  31. #include <kern/macros.h>
  32. #include <kern/rtmutex_i.h>
  33. #include <kern/rtmutex_types.h>
  34. struct rtmutex;
  35. static inline bool
  36. rtmutex_locked(const struct rtmutex *rtmutex)
  37. {
  38. uintptr_t owner;
  39. owner = atomic_load(&rtmutex->owner, ATOMIC_RELAXED);
  40. return (owner != 0);
  41. }
  42. /*
  43. * Initialize a real-time mutex.
  44. */
  45. static inline void
  46. rtmutex_init(struct rtmutex *rtmutex)
  47. {
  48. rtmutex->owner = 0;
  49. }
  50. /*
  51. * Attempt to lock the given real-time mutex.
  52. *
  53. * This function may not sleep.
  54. *
  55. * Return 0 on success, EBUSY if the mutex is already locked.
  56. */
  57. static inline int
  58. rtmutex_trylock(struct rtmutex *rtmutex)
  59. {
  60. uintptr_t prev_owner;
  61. prev_owner = rtmutex_lock_fast(rtmutex);
  62. if (unlikely(prev_owner != 0)) {
  63. return EBUSY;
  64. }
  65. return 0;
  66. }
  67. /*
  68. * Lock a real-time mutex.
  69. *
  70. * If the mutex is already locked, the calling thread sleeps until the
  71. * mutex is unlocked, and its priority is propagated as needed to prevent
  72. * unbounded priority inversion.
  73. *
  74. * A mutex can only be locked once.
  75. *
  76. * This function may sleep.
  77. */
  78. static inline void
  79. rtmutex_lock(struct rtmutex *rtmutex)
  80. {
  81. uintptr_t prev_owner;
  82. prev_owner = rtmutex_lock_fast(rtmutex);
  83. if (unlikely(prev_owner != 0)) {
  84. rtmutex_lock_slow(rtmutex);
  85. }
  86. }
  87. /*
  88. * Lock a real-time mutex, with a time boundary.
  89. *
  90. * The time boundary is an absolute time in ticks.
  91. *
  92. * If successful, the mutex is locked, otherwise an error is returned.
  93. * A mutex can only be locked once.
  94. *
  95. * This function may sleep.
  96. */
  97. static inline int
  98. rtmutex_timedlock(struct rtmutex *rtmutex, uint64_t ticks)
  99. {
  100. uintptr_t prev_owner;
  101. prev_owner = rtmutex_lock_fast(rtmutex);
  102. if (unlikely(prev_owner != 0)) {
  103. return rtmutex_timedlock_slow(rtmutex, ticks);
  104. }
  105. return 0;
  106. }
  107. /*
  108. * Unlock a real-time mutex.
  109. *
  110. * The mutex must be locked, and must have been locked by the calling
  111. * thread.
  112. */
  113. static inline void
  114. rtmutex_unlock(struct rtmutex *rtmutex)
  115. {
  116. uintptr_t prev_owner;
  117. prev_owner = rtmutex_unlock_fast(rtmutex);
  118. if (unlikely(prev_owner & RTMUTEX_CONTENDED)) {
  119. rtmutex_unlock_slow(rtmutex);
  120. }
  121. }
  122. /*
  123. * Mutex init operations. See kern/mutex.h.
  124. */
  125. INIT_OP_DECLARE(rtmutex_bootstrap);
  126. INIT_OP_DECLARE(rtmutex_setup);
  127. #endif /* KERN_RTMUTEX_H */