clinuxlinux-kernellockingrcu

How RCU handles the condition of a reader started reading critical section while synchronize_rcu() is waiting


As per the RCU documentation (I believe kernel and userspace RCU frameworks are similar), synchronize_rcu() waits for all the readers (who started before synchronize_rcu was called ) to finish.
What happens to the readers which are started after synchronize_rcu() is waiting in its grace period?
What is the difference between the readers started after synchronize_rcu() returns, and readers started while synchronize_rcu() waits? How RCU framework handles this?


Solution

  • The new reader (which started executing in critical section after synchronize_rcu() is waiting in its grace period) reads the new data structure?

    All the readers entering the critical section after rcu_assign_pointer() read the new data structure.

    What is the difference between the readers started after synchronize_rcu() returns, and readers started while synchronize_rcu() waits?

    All you are talking about depends on if/when the new pointer is assigned. Assigning and reading are related things.


    synchronize_rcu() on Linux generally waits until all CPUs will have their context switched - it guarantees that no one who saw the old pointer doesn't use it anymore (context switch happens after reader exits their critical section) - so we can free this memory. From this post:

    ..if a given CPU executes a context switch, we know that it must have completed all preceding RCU read-side critical sections. Once all CPUs have executed a context switch, then all preceding RCU read-side critical sections will have completed.
    So, suppose that we remove a data item from its structure and then invoke synchronize_rcu(). Once synchronize_rcu() returns, we are guaranteed that there are no RCU read-side critical sections holding a reference to that data item, so we can safely reclaim it.

    New readers know nothing about old data structure. "Swapping" of pointers is atomic.
    One more time: synchronize_rcu() has no effect on readers - it just guarantees that after it returns, we can free the memory the pointer points to (kfree()).

    It seems you have not explored the basics of Linux RCU.
    Must read: