rcu.h 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185
  1. /*
  2. * Copyright (c) 2018 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. * Read-Copy Update.
  19. *
  20. * This module provides a synchronization framework for read-only lockless
  21. * operations, best used on read-mostly data structures.
  22. *
  23. * To learn more about RCU, see "Is Parallel Programming Hard, And, If So,
  24. * What Can You Do About It ?" by Paul E. McKenney.
  25. *
  26. * A thorough discussion of RCU's requirements can be found at [1].
  27. * However, the memory model and terminology used in that document being
  28. * different from C11, the memory barrier guarantees are hereby translated
  29. * into memory ordering guarantees :
  30. *
  31. * 1. Release-acquire ordering is enforced between the end of all
  32. * read-side critical sections starting before a grace period starts
  33. * and the start of all works deferred before the same grace period
  34. * starts.
  35. * 2. Release-acquire ordering is enforced between the start of all
  36. * read-side critical sections ending after a grace period ends
  37. * and all the work deferrals done before the same grace period
  38. * starts.
  39. * 3. Release-acquire ordering is enforced between all the work deferrals
  40. * done before a grace period starts and the start of all works deferred
  41. * before the same grace period starts.
  42. *
  43. * [1] https://www.kernel.org/doc/Documentation/RCU/Design/Requirements/Requirements.html.
  44. */
  45. #ifndef KERN_RCU_H
  46. #define KERN_RCU_H
  47. #include <assert.h>
  48. #include <stdbool.h>
  49. #include <kern/atomic.h>
  50. #include <kern/init.h>
  51. #include <kern/macros.h>
  52. #include <kern/rcu_types.h>
  53. #include <kern/thread.h>
  54. #include <kern/work.h>
  55. void rcu_reader_leave (struct rcu_reader *reader);
  56. static inline bool
  57. rcu_reader_in_cs (const struct rcu_reader *reader)
  58. {
  59. return (reader->level != 0);
  60. }
  61. static inline bool
  62. rcu_reader_linked (const struct rcu_reader *reader)
  63. {
  64. assert (reader == thread_rcu_reader (thread_self ()));
  65. return (reader->linked);
  66. }
  67. static inline void
  68. rcu_reader_inc (struct rcu_reader *reader)
  69. {
  70. ++reader->level;
  71. assert (reader->level != 0);
  72. }
  73. static inline void
  74. rcu_reader_dec (struct rcu_reader *reader)
  75. {
  76. assert (reader->level != 0);
  77. --reader->level;
  78. if (unlikely (!rcu_reader_in_cs (reader) && rcu_reader_linked (reader)))
  79. rcu_reader_leave (reader);
  80. }
  81. /*
  82. * Safely store a pointer.
  83. *
  84. * This macro enforces release ordering on the given pointer.
  85. */
  86. #define rcu_store(ptr, value) atomic_store ((ptr), (value), ATOMIC_RELEASE)
  87. /*
  88. * Safely load a pointer.
  89. *
  90. * This macro enforces consume ordering on the given pointer.
  91. */
  92. #define rcu_load(ptr) atomic_load ((ptr), ATOMIC_CONSUME)
  93. /*
  94. * Read-side critical section functions.
  95. *
  96. * Critical sections are preemptible, may safely nest, and may safely
  97. * be used in interrupt context. It is not allowed to sleep inside a
  98. * read-side critical section. However, it is allowed to acquire locks
  99. * that don't sleep, such as spin locks.
  100. *
  101. * Entering or leaving a critical section doesn't provide any memory
  102. * ordering guarantee.
  103. */
  104. static inline void
  105. rcu_read_enter (void)
  106. {
  107. rcu_reader_inc (thread_rcu_reader (thread_self ()));
  108. barrier ();
  109. }
  110. static inline void
  111. rcu_read_leave (void)
  112. {
  113. barrier ();
  114. rcu_reader_dec (thread_rcu_reader (thread_self ()));
  115. }
  116. // Initialize a RCU reader.
  117. void rcu_reader_init (struct rcu_reader *reader);
  118. /*
  119. * Report a context switch on the current processor.
  120. *
  121. * The argument is the RCU reader of the preempted thread.
  122. *
  123. * Interrupts and preemption must be disabled when calling this function.
  124. */
  125. void rcu_report_context_switch (struct rcu_reader *reader);
  126. /*
  127. * Report a periodic event on the current processor.
  128. *
  129. * Interrupts and preemption must be disabled when calling this function.
  130. */
  131. void rcu_report_periodic_event (void);
  132. /*
  133. * Defer a work until all existing read-side references are dropped,
  134. * without blocking.
  135. *
  136. * The given work is scheduled when all existing read-side references
  137. * are dropped.
  138. */
  139. void rcu_defer (struct work *work);
  140. /*
  141. * Wait for all existing read-side references to be dropped.
  142. *
  143. * This function sleeps, and may do so for a moderately long duration,
  144. * at leat a few system timer ticks, sometimes a lot more.
  145. */
  146. void rcu_wait (void);
  147. // RCU guards.
  148. static inline void
  149. rcu_guard_fini (void *ptr __unused)
  150. {
  151. rcu_read_leave ();
  152. }
  153. #define RCU_GUARD() \
  154. CLEANUP (rcu_guard_fini) int __unused UNIQ (rg) = (rcu_read_enter (), 0)
  155. /*
  156. * This init operation provides :
  157. * - read-side critical sections usable
  158. */
  159. INIT_OP_DECLARE (rcu_bootstrap);
  160. #endif