rcuref.txt 2.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374
  1. Refcounter framework for elements of lists/arrays protected by
  2. RCU.
  3. Refcounting on elements of lists which are protected by traditional
  4. reader/writer spinlocks or semaphores are straight forward as in:
  5. 1. 2.
  6. add() search_and_reference()
  7. { {
  8. alloc_object read_lock(&list_lock);
  9. ... search_for_element
  10. atomic_set(&el->rc, 1); atomic_inc(&el->rc);
  11. write_lock(&list_lock); ...
  12. add_element read_unlock(&list_lock);
  13. ... ...
  14. write_unlock(&list_lock); }
  15. }
  16. 3. 4.
  17. release_referenced() delete()
  18. { {
  19. ... write_lock(&list_lock);
  20. atomic_dec(&el->rc, relfunc) ...
  21. ... delete_element
  22. } write_unlock(&list_lock);
  23. ...
  24. if (atomic_dec_and_test(&el->rc))
  25. kfree(el);
  26. ...
  27. }
  28. If this list/array is made lock free using rcu as in changing the
  29. write_lock in add() and delete() to spin_lock and changing read_lock
  30. in search_and_reference to rcu_read_lock(), the rcuref_get in
  31. search_and_reference could potentially hold reference to an element which
  32. has already been deleted from the list/array. rcuref_lf_get_rcu takes
  33. care of this scenario. search_and_reference should look as;
  34. 1. 2.
  35. add() search_and_reference()
  36. { {
  37. alloc_object rcu_read_lock();
  38. ... search_for_element
  39. atomic_set(&el->rc, 1); if (rcuref_inc_lf(&el->rc)) {
  40. write_lock(&list_lock); rcu_read_unlock();
  41. return FAIL;
  42. add_element }
  43. ... ...
  44. write_unlock(&list_lock); rcu_read_unlock();
  45. } }
  46. 3. 4.
  47. release_referenced() delete()
  48. { {
  49. ... write_lock(&list_lock);
  50. rcuref_dec(&el->rc, relfunc) ...
  51. ... delete_element
  52. } write_unlock(&list_lock);
  53. ...
  54. if (rcuref_dec_and_test(&el->rc))
  55. call_rcu(&el->head, el_free);
  56. ...
  57. }
  58. Sometimes, reference to the element need to be obtained in the
  59. update (write) stream. In such cases, rcuref_inc_lf might be an overkill
  60. since the spinlock serialising list updates are held. rcuref_inc
  61. is to be used in such cases.
  62. For arches which do not have cmpxchg rcuref_inc_lf
  63. api uses a hashed spinlock implementation and the same hashed spinlock
  64. is acquired in all rcuref_xxx primitives to preserve atomicity.
  65. Note: Use rcuref_inc api only if you need to use rcuref_inc_lf on the
  66. refcounter atleast at one place. Mixing rcuref_inc and atomic_xxx api
  67. might lead to races. rcuref_inc_lf() must be used in lockfree
  68. RCU critical sections only.