Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 01d206a7 authored by Adrian Bunk's avatar Adrian Bunk Committed by Adrian Bunk
Browse files
parents 9c4b562a d6c8f6aa
Loading
Loading
Loading
Loading
+14 −11
Original line number Original line Diff line number Diff line
@@ -90,16 +90,20 @@ at OLS. The resulting abundance of RCU patches was presented the
following year [McKenney02a], and use of RCU in dcache was first
following year [McKenney02a], and use of RCU in dcache was first
described that same year [Linder02a].
described that same year [Linder02a].


Also in 2002, Michael [Michael02b,Michael02a] presented techniques
Also in 2002, Michael [Michael02b,Michael02a] presented "hazard-pointer"
that defer the destruction of data structures to simplify non-blocking
techniques that defer the destruction of data structures to simplify
synchronization (wait-free synchronization, lock-free synchronization,
non-blocking synchronization (wait-free synchronization, lock-free
and obstruction-free synchronization are all examples of non-blocking
synchronization, and obstruction-free synchronization are all examples of
synchronization).  In particular, this technique eliminates locking,
non-blocking synchronization).  In particular, this technique eliminates
reduces contention, reduces memory latency for readers, and parallelizes
locking, reduces contention, reduces memory latency for readers, and
pipeline stalls and memory latency for writers.  However, these
parallelizes pipeline stalls and memory latency for writers.  However,
techniques still impose significant read-side overhead in the form of
these techniques still impose significant read-side overhead in the
memory barriers.  Researchers at Sun worked along similar lines in the
form of memory barriers.  Researchers at Sun worked along similar lines
same timeframe [HerlihyLM02,HerlihyLMS03].
in the same timeframe [HerlihyLM02,HerlihyLMS03].  These techniques
can be thought of as inside-out reference counts, where the count is
represented by the number of hazard pointers referencing a given data
structure (rather than the more conventional counter field within the
data structure itself).


In 2003, the K42 group described how RCU could be used to create
In 2003, the K42 group described how RCU could be used to create
hot-pluggable implementations of operating-system functions.  Later that
hot-pluggable implementations of operating-system functions.  Later that
@@ -113,7 +117,6 @@ number of operating-system kernels [PaulEdwardMcKenneyPhD], a paper
describing how to make RCU safe for soft-realtime applications [Sarma04c],
describing how to make RCU safe for soft-realtime applications [Sarma04c],
and a paper describing SELinux performance with RCU [JamesMorris04b].
and a paper describing SELinux performance with RCU [JamesMorris04b].



2005 has seen further adaptation of RCU to realtime use, permitting
2005 has seen further adaptation of RCU to realtime use, permitting
preemption of RCU realtime critical sections [PaulMcKenney05a,
preemption of RCU realtime critical sections [PaulMcKenney05a,
PaulMcKenney05b].
PaulMcKenney05b].
+6 −0
Original line number Original line Diff line number Diff line
@@ -177,3 +177,9 @@ over a rather long period of time, but improvements are always welcome!


	If you want to wait for some of these other things, you might
	If you want to wait for some of these other things, you might
	instead need to use synchronize_irq() or synchronize_sched().
	instead need to use synchronize_irq() or synchronize_sched().

12.	Any lock acquired by an RCU callback must be acquired elsewhere
	with irq disabled, e.g., via spin_lock_irqsave().  Failing to
	disable irq on a given acquisition of that lock will result in
	deadlock as soon as the RCU callback happens to interrupt that
	acquisition's critical section.
+12 −9
Original line number Original line Diff line number Diff line
@@ -275,8 +275,8 @@ flag under the spinlock as follows:
	{
	{
		struct audit_entry  *e;
		struct audit_entry  *e;


		/* Do not use the _rcu iterator here, since this is the only
		/* Do not need to use the _rcu iterator here, since this
		 * deletion routine. */
		 * is the only deletion routine. */
		list_for_each_entry(e, list, list) {
		list_for_each_entry(e, list, list) {
			if (!audit_compare_rule(rule, &e->rule)) {
			if (!audit_compare_rule(rule, &e->rule)) {
				spin_lock(&e->lock);
				spin_lock(&e->lock);
@@ -304,9 +304,12 @@ function to reject newly deleted data.




Answer to Quick Quiz
Answer to Quick Quiz

	Why does the search function need to return holding the per-entry
If the search function drops the per-entry lock before returning, then
	lock for this deleted-flag technique to be helpful?
the caller will be processing stale data in any case.  If it is really

OK to be processing stale data, then you don't need a "deleted" flag.
	If the search function drops the per-entry lock before returning,
If processing stale data really is a problem, then you need to hold the
	then the caller will be processing stale data in any case.  If it
per-entry lock across all of the code that uses the value looked up.
	is really OK to be processing stale data, then you don't need a
	"deleted" flag.  If processing stale data really is a problem,
	then you need to hold the per-entry lock across all of the code
	that uses the value that was returned.
+5 −0
Original line number Original line Diff line number Diff line
@@ -111,6 +111,11 @@ o What are all these files in this directory?


		You are reading it!
		You are reading it!


	rcuref.txt

		Describes how to combine use of reference counts
		with RCU.

	whatisRCU.txt
	whatisRCU.txt


		Overview of how the RCU implementation works.  Along
		Overview of how the RCU implementation works.  Along
+15 −16
Original line number Original line Diff line number Diff line
Refcounter design for elements of lists/arrays protected by RCU.
Reference-count design for elements of lists/arrays protected by RCU.


Refcounting on elements of  lists which are protected by traditional
Reference counting on elements of lists which are protected by traditional
reader/writer spinlocks or semaphores are straight forward as in:
reader/writer spinlocks or semaphores are straightforward:


1.				2.
1.				2.
add()				search_and_reference()
add()				search_and_reference()
@@ -28,12 +28,12 @@ release_referenced() delete()
					    ...
					    ...
					}
					}


If this list/array is made lock free using rcu as in changing the
If this list/array is made lock free using RCU as in changing the
write_lock in add() and delete() to spin_lock and changing read_lock
write_lock() in add() and delete() to spin_lock and changing read_lock
in search_and_reference to rcu_read_lock(), the atomic_get in
in search_and_reference to rcu_read_lock(), the atomic_get in
search_and_reference could potentially hold reference to an element which
search_and_reference could potentially hold reference to an element which
has already been deleted from the list/array.  atomic_inc_not_zero takes
has already been deleted from the list/array.  Use atomic_inc_not_zero()
care of this scenario. search_and_reference should look as;
in this scenario as follows:


1.					2.
1.					2.
add()					search_and_reference()
add()					search_and_reference()
@@ -51,17 +51,16 @@ add() search_and_reference()
release_referenced()			delete()
release_referenced()			delete()
{					{
{					{
    ...					    write_lock(&list_lock);
    ...					    write_lock(&list_lock);
    atomic_dec(&el->rc, relfunc)	    ...
    if (atomic_dec_and_test(&el->rc))       ...
    ...					    delete_element
        call_rcu(&el->head, el_free);       delete_element
}					    write_unlock(&list_lock);
    ...                                     write_unlock(&list_lock);
 					    ...
} 					    ...
					    if (atomic_dec_and_test(&el->rc))
					    if (atomic_dec_and_test(&el->rc))
					        call_rcu(&el->head, el_free);
					        call_rcu(&el->head, el_free);
					    ...
					    ...
					}
					}


Sometimes, reference to the element need to be obtained in the
Sometimes, a reference to the element needs to be obtained in the
update (write) stream.  In such cases, atomic_inc_not_zero might be an
update (write) stream.  In such cases, atomic_inc_not_zero() might be
overkill since the spinlock serialising list updates are held. atomic_inc
overkill, since we hold the update-side spinlock.  One might instead
is to be used in such cases.
use atomic_inc() in such cases.
Loading