projects
/
urcu.git
/ blobdiff
commit
grep
author
committer
pickaxe
?
search:
re
summary
|
shortlog
|
log
|
commit
|
commitdiff
|
tree
raw
|
inline
| side by side
urcu-ht: fix mistake in previous commit
[urcu.git]
/
urcu-ht.c
diff --git
a/urcu-ht.c
b/urcu-ht.c
index 0bbdb5d4e8284d28e8de006cb0ea5476eb9dc7f4..324ebed93420dd7957ffd03963aae07340e5001a 100644
(file)
--- a/
urcu-ht.c
+++ b/
urcu-ht.c
@@
-134,10
+134,12
@@
restart:
/*
* Restart until we successfully remove the entry, or no entry is left
* ((void *)(unsigned long)-ENOENT).
/*
* Restart until we successfully remove the entry, or no entry is left
* ((void *)(unsigned long)-ENOENT).
+ * Deal with concurrent stealers by verifying that there are no element
+ * in the list still pointing to the element stolen. (del_node)
*/
void *ht_steal(struct rcu_ht *ht, void *key)
{
*/
void *ht_steal(struct rcu_ht *ht, void *key)
{
- struct rcu_ht_node **prev, *node;
+ struct rcu_ht_node **prev, *node
, *del_node = NULL
;
unsigned long hash;
void *data;
unsigned long hash;
void *data;
@@
-150,8
+152,12
@@
retry:
node = rcu_dereference(*prev);
for (;;) {
if (likely(!node)) {
node = rcu_dereference(*prev);
for (;;) {
if (likely(!node)) {
- data = (void *)(unsigned long)-ENOENT;
- goto error;
+ if (del_node) {
+ goto end;
+ } else {
+ data = (void *)(unsigned long)-ENOENT;
+ goto error;
+ }
}
if (node->key == key) {
break;
}
if (node->key == key) {
break;
@@
-161,13
+167,18
@@
retry:
}
/* Found it ! pointer to object is in "prev" */
if (rcu_cmpxchg_pointer(prev, node, node->next) != node)
}
/* Found it ! pointer to object is in "prev" */
if (rcu_cmpxchg_pointer(prev, node, node->next) != node)
- goto restart;
+ del_node = node;
+ goto restart;
- /* From that point, we own node. We can free it outside of read lock */
+end:
+ /*
+ * From that point, we own node. Note that there can still be concurrent
+ * RCU readers using it. We can free it outside of read lock after a GP.
+ */
rcu_read_unlock();
rcu_read_unlock();
- data = node->data;
- call_rcu(free, node);
+ data =
del_
node->data;
+ call_rcu(free,
del_
node);
return data;
error:
return data;
error:
This page took
0.025711 seconds
and
4
git commands to generate.