lockcnt.rst 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278
  1. Locked Counters (aka ``QemuLockCnt``)
  2. =====================================
  3. QEMU often uses reference counts to track data structures that are being
  4. accessed and should not be freed. For example, a loop that invoke
  5. callbacks like this is not safe::
  6. QLIST_FOREACH_SAFE(ioh, &io_handlers, next, pioh) {
  7. if (ioh->revents & G_IO_OUT) {
  8. ioh->fd_write(ioh->opaque);
  9. }
  10. }
  11. ``QLIST_FOREACH_SAFE`` protects against deletion of the current node (``ioh``)
  12. by stashing away its ``next`` pointer. However, ``ioh->fd_write`` could
  13. actually delete the next node from the list. The simplest way to
  14. avoid this is to mark the node as deleted, and remove it from the
  15. list in the above loop::
  16. QLIST_FOREACH_SAFE(ioh, &io_handlers, next, pioh) {
  17. if (ioh->deleted) {
  18. QLIST_REMOVE(ioh, next);
  19. g_free(ioh);
  20. } else {
  21. if (ioh->revents & G_IO_OUT) {
  22. ioh->fd_write(ioh->opaque);
  23. }
  24. }
  25. }
  26. If however this loop must also be reentrant, i.e. it is possible that
  27. ``ioh->fd_write`` invokes the loop again, some kind of counting is needed::
  28. walking_handlers++;
  29. QLIST_FOREACH_SAFE(ioh, &io_handlers, next, pioh) {
  30. if (ioh->deleted) {
  31. if (walking_handlers == 1) {
  32. QLIST_REMOVE(ioh, next);
  33. g_free(ioh);
  34. }
  35. } else {
  36. if (ioh->revents & G_IO_OUT) {
  37. ioh->fd_write(ioh->opaque);
  38. }
  39. }
  40. }
  41. walking_handlers--;
  42. One may think of using the RCU primitives, ``rcu_read_lock()`` and
  43. ``rcu_read_unlock()``; effectively, the RCU nesting count would take
  44. the place of the walking_handlers global variable. Indeed,
  45. reference counting and RCU have similar purposes, but their usage in
  46. general is complementary:
  47. - reference counting is fine-grained and limited to a single data
  48. structure; RCU delays reclamation of *all* RCU-protected data
  49. structures;
  50. - reference counting works even in the presence of code that keeps
  51. a reference for a long time; RCU critical sections in principle
  52. should be kept short;
  53. - reference counting is often applied to code that is not thread-safe
  54. but is reentrant; in fact, usage of reference counting in QEMU predates
  55. the introduction of threads by many years. RCU is generally used to
  56. protect readers from other threads freeing memory after concurrent
  57. modifications to a data structure.
  58. - reclaiming data can be done by a separate thread in the case of RCU;
  59. this can improve performance, but also delay reclamation undesirably.
  60. With reference counting, reclamation is deterministic.
  61. This file documents ``QemuLockCnt``, an abstraction for using reference
  62. counting in code that has to be both thread-safe and reentrant.
  63. ``QemuLockCnt`` concepts
  64. ------------------------
  65. A ``QemuLockCnt`` comprises both a counter and a mutex; it has primitives
  66. to increment and decrement the counter, and to take and release the
  67. mutex. The counter notes how many visits to the data structures are
  68. taking place (the visits could be from different threads, or there could
  69. be multiple reentrant visits from the same thread). The basic rules
  70. governing the counter/mutex pair then are the following:
  71. - Data protected by the QemuLockCnt must not be freed unless the
  72. counter is zero and the mutex is taken.
  73. - A new visit cannot be started while the counter is zero and the
  74. mutex is taken.
  75. Most of the time, the mutex protects all writes to the data structure,
  76. not just frees, though there could be cases where this is not necessary.
  77. Reads, instead, can be done without taking the mutex, as long as the
  78. readers and writers use the same macros that are used for RCU, for
  79. example ``qatomic_rcu_read``, ``qatomic_rcu_set``, ``QLIST_FOREACH_RCU``,
  80. etc. This is because the reads are done outside a lock and a set
  81. or ``QLIST_INSERT_HEAD``
  82. can happen concurrently with the read. The RCU API ensures that the
  83. processor and the compiler see all required memory barriers.
  84. This could be implemented simply by protecting the counter with the
  85. mutex, for example::
  86. // (1)
  87. qemu_mutex_lock(&walking_handlers_mutex);
  88. walking_handlers++;
  89. qemu_mutex_unlock(&walking_handlers_mutex);
  90. ...
  91. // (2)
  92. qemu_mutex_lock(&walking_handlers_mutex);
  93. if (--walking_handlers == 0) {
  94. QLIST_FOREACH_SAFE(ioh, &io_handlers, next, pioh) {
  95. if (ioh->deleted) {
  96. QLIST_REMOVE(ioh, next);
  97. g_free(ioh);
  98. }
  99. }
  100. }
  101. qemu_mutex_unlock(&walking_handlers_mutex);
  102. Here, no frees can happen in the code represented by the ellipsis.
  103. If another thread is executing critical section (2), that part of
  104. the code cannot be entered, because the thread will not be able
  105. to increment the ``walking_handlers`` variable. And of course
  106. during the visit any other thread will see a nonzero value for
  107. ``walking_handlers``, as in the single-threaded code.
  108. Note that it is possible for multiple concurrent accesses to delay
  109. the cleanup arbitrarily; in other words, for the ``walking_handlers``
  110. counter to never become zero. For this reason, this technique is
  111. more easily applicable if concurrent access to the structure is rare.
  112. However, critical sections are easy to forget since you have to do
  113. them for each modification of the counter. ``QemuLockCnt`` ensures that
  114. all modifications of the counter take the lock appropriately, and it
  115. can also be more efficient in two ways:
  116. - it avoids taking the lock for many operations (for example
  117. incrementing the counter while it is non-zero);
  118. - on some platforms, one can implement ``QemuLockCnt`` to hold the lock
  119. and the mutex in a single word, making the fast path no more expensive
  120. than simply managing a counter using atomic operations (see
  121. :doc:`atomics`). This can be very helpful if concurrent access to
  122. the data structure is expected to be rare.
  123. Using the same mutex for frees and writes can still incur some small
  124. inefficiencies; for example, a visit can never start if the counter is
  125. zero and the mutex is taken -- even if the mutex is taken by a write,
  126. which in principle need not block a visit of the data structure.
  127. However, these are usually not a problem if any of the following
  128. assumptions are valid:
  129. - concurrent access is possible but rare
  130. - writes are rare
  131. - writes are frequent, but this kind of write (e.g. appending to a
  132. list) has a very small critical section.
  133. For example, QEMU uses ``QemuLockCnt`` to manage an ``AioContext``'s list of
  134. bottom halves and file descriptor handlers. Modifications to the list
  135. of file descriptor handlers are rare. Creation of a new bottom half is
  136. frequent and can happen on a fast path; however: 1) it is almost never
  137. concurrent with a visit to the list of bottom halves; 2) it only has
  138. three instructions in the critical path, two assignments and a ``smp_wmb()``.
  139. ``QemuLockCnt`` API
  140. -------------------
  141. .. kernel-doc:: include/qemu/lockcnt.h
  142. ``QemuLockCnt`` usage
  143. ---------------------
  144. This section explains the typical usage patterns for ``QemuLockCnt`` functions.
  145. Setting a variable to a non-NULL value can be done between
  146. ``qemu_lockcnt_lock`` and ``qemu_lockcnt_unlock``::
  147. qemu_lockcnt_lock(&xyz_lockcnt);
  148. if (!xyz) {
  149. new_xyz = g_new(XYZ, 1);
  150. ...
  151. qatomic_rcu_set(&xyz, new_xyz);
  152. }
  153. qemu_lockcnt_unlock(&xyz_lockcnt);
  154. Accessing the value can be done between ``qemu_lockcnt_inc`` and
  155. ``qemu_lockcnt_dec``::
  156. qemu_lockcnt_inc(&xyz_lockcnt);
  157. if (xyz) {
  158. XYZ *p = qatomic_rcu_read(&xyz);
  159. ...
  160. /* Accesses can now be done through "p". */
  161. }
  162. qemu_lockcnt_dec(&xyz_lockcnt);
  163. Freeing the object can similarly use ``qemu_lockcnt_lock`` and
  164. ``qemu_lockcnt_unlock``, but you also need to ensure that the count
  165. is zero (i.e. there is no concurrent visit). Because ``qemu_lockcnt_inc``
  166. takes the ``QemuLockCnt``'s lock, the count cannot become non-zero while
  167. the object is being freed. Freeing an object looks like this::
  168. qemu_lockcnt_lock(&xyz_lockcnt);
  169. if (!qemu_lockcnt_count(&xyz_lockcnt)) {
  170. g_free(xyz);
  171. xyz = NULL;
  172. }
  173. qemu_lockcnt_unlock(&xyz_lockcnt);
  174. If an object has to be freed right after a visit, you can combine
  175. the decrement, the locking and the check on count as follows::
  176. qemu_lockcnt_inc(&xyz_lockcnt);
  177. if (xyz) {
  178. XYZ *p = qatomic_rcu_read(&xyz);
  179. ...
  180. /* Accesses can now be done through "p". */
  181. }
  182. if (qemu_lockcnt_dec_and_lock(&xyz_lockcnt)) {
  183. g_free(xyz);
  184. xyz = NULL;
  185. qemu_lockcnt_unlock(&xyz_lockcnt);
  186. }
  187. ``QemuLockCnt`` can also be used to access a list as follows::
  188. qemu_lockcnt_inc(&io_handlers_lockcnt);
  189. QLIST_FOREACH_RCU(ioh, &io_handlers, pioh) {
  190. if (ioh->revents & G_IO_OUT) {
  191. ioh->fd_write(ioh->opaque);
  192. }
  193. }
  194. if (qemu_lockcnt_dec_and_lock(&io_handlers_lockcnt)) {
  195. QLIST_FOREACH_SAFE(ioh, &io_handlers, next, pioh) {
  196. if (ioh->deleted) {
  197. QLIST_REMOVE(ioh, next);
  198. g_free(ioh);
  199. }
  200. }
  201. qemu_lockcnt_unlock(&io_handlers_lockcnt);
  202. }
  203. Again, the RCU primitives are used because new items can be added to the
  204. list during the walk. ``QLIST_FOREACH_RCU`` ensures that the processor and
  205. the compiler see the appropriate memory barriers.
  206. An alternative pattern uses ``qemu_lockcnt_dec_if_lock``::
  207. qemu_lockcnt_inc(&io_handlers_lockcnt);
  208. QLIST_FOREACH_SAFE_RCU(ioh, &io_handlers, next, pioh) {
  209. if (ioh->deleted) {
  210. if (qemu_lockcnt_dec_if_lock(&io_handlers_lockcnt)) {
  211. QLIST_REMOVE(ioh, next);
  212. g_free(ioh);
  213. qemu_lockcnt_inc_and_unlock(&io_handlers_lockcnt);
  214. }
  215. } else {
  216. if (ioh->revents & G_IO_OUT) {
  217. ioh->fd_write(ioh->opaque);
  218. }
  219. }
  220. }
  221. qemu_lockcnt_dec(&io_handlers_lockcnt);
  222. Here you can use ``qemu_lockcnt_dec`` instead of ``qemu_lockcnt_dec_and_lock``,
  223. because there is no special task to do if the count goes from 1 to 0.