llist: Clarify comments about when locking is needed
llist.h comments are confusing about when locking is needed versus when it isn't. Clarify these comments by being more descriptive about why locking is needed for llist_del_first. Cc: Ingo Molnar <mingo@kernel.org> Cc: Will Deacon <will.deacon@arm.com> Cc: Paul McKenney <paulmck@linux.vnet.ibm.com> Acked-by: Huang Ying <ying.huang@intel.com> Acked-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com> Signed-off-by: Joel Fernandes <joelaf@google.com> Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com> Reviewed-by: Josh Triplett <josh@joshtriplett.org>
This commit is contained in:
parent
9831ce3bb4
commit
d78973c32a
|
@ -3,28 +3,33 @@
|
||||||
/*
|
/*
|
||||||
* Lock-less NULL terminated single linked list
|
* Lock-less NULL terminated single linked list
|
||||||
*
|
*
|
||||||
* If there are multiple producers and multiple consumers, llist_add
|
* Cases where locking is not needed:
|
||||||
* can be used in producers and llist_del_all can be used in
|
* If there are multiple producers and multiple consumers, llist_add can be
|
||||||
* consumers. They can work simultaneously without lock. But
|
* used in producers and llist_del_all can be used in consumers simultaneously
|
||||||
* llist_del_first can not be used here. Because llist_del_first
|
* without locking. Also a single consumer can use llist_del_first while
|
||||||
* depends on list->first->next does not changed if list->first is not
|
* multiple producers simultaneously use llist_add, without any locking.
|
||||||
* changed during its operation, but llist_del_first, llist_add,
|
|
||||||
* llist_add (or llist_del_all, llist_add, llist_add) sequence in
|
|
||||||
* another consumer may violate that.
|
|
||||||
*
|
*
|
||||||
* If there are multiple producers and one consumer, llist_add can be
|
* Cases where locking is needed:
|
||||||
* used in producers and llist_del_all or llist_del_first can be used
|
* If we have multiple consumers with llist_del_first used in one consumer, and
|
||||||
* in the consumer.
|
* llist_del_first or llist_del_all used in other consumers, then a lock is
|
||||||
|
* needed. This is because llist_del_first depends on list->first->next not
|
||||||
|
* changing, but without lock protection, there's no way to be sure about that
|
||||||
|
* if a preemption happens in the middle of the delete operation and on being
|
||||||
|
* preempted back, the list->first is the same as before causing the cmpxchg in
|
||||||
|
* llist_del_first to succeed. For example, while a llist_del_first operation
|
||||||
|
* is in progress in one consumer, then a llist_del_first, llist_add,
|
||||||
|
* llist_add (or llist_del_all, llist_add, llist_add) sequence in another
|
||||||
|
* consumer may cause violations.
|
||||||
*
|
*
|
||||||
* This can be summarized as follow:
|
* This can be summarized as follows:
|
||||||
*
|
*
|
||||||
* | add | del_first | del_all
|
* | add | del_first | del_all
|
||||||
* add | - | - | -
|
* add | - | - | -
|
||||||
* del_first | | L | L
|
* del_first | | L | L
|
||||||
* del_all | | | -
|
* del_all | | | -
|
||||||
*
|
*
|
||||||
* Where "-" stands for no lock is needed, while "L" stands for lock
|
* Where, a particular row's operation can happen concurrently with a column's
|
||||||
* is needed.
|
* operation, with "-" being no lock needed, while "L" being lock is needed.
|
||||||
*
|
*
|
||||||
* The list entries deleted via llist_del_all can be traversed with
|
* The list entries deleted via llist_del_all can be traversed with
|
||||||
* traversing function such as llist_for_each etc. But the list
|
* traversing function such as llist_for_each etc. But the list
|
||||||
|
|
Loading…
Reference in a new issue