Commit 71cb46ae authored by Joel Fernandes (Google)'s avatar Joel Fernandes (Google) Committed by Paul E. McKenney

Restore docs "rcu: Restore barrier() to rcu_read_lock() and rcu_read_unlock()"

This restores docs back in ReST format.
Signed-off-by: default avatarJoel Fernandes (Google) <joel@joelfernandes.org>
[ paulmck: Added Joel's SoB per Stephen Rothwell feedback. ]
[ paulmck: Joel approved via private email. ]
Signed-off-by: default avatarPaul E. McKenney <paulmck@kernel.org>
parent d7424e28
...@@ -1691,6 +1691,7 @@ follows: ...@@ -1691,6 +1691,7 @@ follows:
#. `Hotplug CPU`_ #. `Hotplug CPU`_
#. `Scheduler and RCU`_ #. `Scheduler and RCU`_
#. `Tracing and RCU`_ #. `Tracing and RCU`_
#. `Accesses to User Memory and RCU`_
#. `Energy Efficiency`_ #. `Energy Efficiency`_
#. `Scheduling-Clock Interrupts and RCU`_ #. `Scheduling-Clock Interrupts and RCU`_
#. `Memory Efficiency`_ #. `Memory Efficiency`_
...@@ -2004,6 +2005,59 @@ where RCU readers execute in environments in which tracing cannot be ...@@ -2004,6 +2005,59 @@ where RCU readers execute in environments in which tracing cannot be
used. The tracing folks both located the requirement and provided the used. The tracing folks both located the requirement and provided the
needed fix, so this surprise requirement was relatively painless. needed fix, so this surprise requirement was relatively painless.
Accesses to User Memory and RCU
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The kernel needs to access user-space memory, for example, to access data
referenced by system-call parameters. The ``get_user()`` macro does this job.
However, user-space memory might well be paged out, which means that
``get_user()`` might well page-fault and thus block while waiting for the
resulting I/O to complete. It would be a very bad thing for the compiler to
reorder a ``get_user()`` invocation into an RCU read-side critical section.
For example, suppose that the source code looked like this:
::
1 rcu_read_lock();
2 p = rcu_dereference(gp);
3 v = p->value;
4 rcu_read_unlock();
5 get_user(user_v, user_p);
6 do_something_with(v, user_v);
The compiler must not be permitted to transform this source code into
the following:
::
1 rcu_read_lock();
2 p = rcu_dereference(gp);
3 get_user(user_v, user_p); // BUG: POSSIBLE PAGE FAULT!!!
4 v = p->value;
5 rcu_read_unlock();
6 do_something_with(v, user_v);
If the compiler did make this transformation in a ``CONFIG_PREEMPT=n`` kernel
build, and if ``get_user()`` did page fault, the result would be a quiescent
state in the middle of an RCU read-side critical section. This misplaced
quiescent state could result in line 4 being a use-after-free access,
which could be bad for your kernel's actuarial statistics. Similar examples
can be constructed with the call to ``get_user()`` preceding the
``rcu_read_lock()``.
Unfortunately, ``get_user()`` doesn't have any particular ordering properties,
and in some architectures the underlying ``asm`` isn't even marked
``volatile``. And even if it was marked ``volatile``, the above access to
``p->value`` is not volatile, so the compiler would not have any reason to keep
those two accesses in order.
Therefore, the Linux-kernel definitions of ``rcu_read_lock()`` and
``rcu_read_unlock()`` must act as compiler barriers, at least for outermost
instances of ``rcu_read_lock()`` and ``rcu_read_unlock()`` within a nested set
of RCU read-side critical sections.
Energy Efficiency Energy Efficiency
~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment