In mt_list_delete(), if the element was not in a list, then n and p will
point to it, and so setting n->prev and n->next will be enough to unlock it.
Don't do it twice, as once it's been done the first time, another thread may
be working with it, and may have added it to a list already, and doing it
a second time can lead to list inconsistencies.
This should be backported up to 2.8.
p->next = n;
__atomic_thread_fence(__ATOMIC_RELEASE);
- el->prev = el->next = el;
- __atomic_thread_fence(__ATOMIC_RELEASE);
+ /*
+ * If the element was not in the list, then n and p
+ * pointed to it already, and it is unlocked.
+ * If this is the case, we don't want to do it again,
+ * because at this point it has been unlocked and
+ * somebody may be using it already.
+ */
+ if (el != n) {
+ el->prev = el->next = el;
+ __atomic_thread_fence(__ATOMIC_RELEASE);
+ }
if (p != el && n != el)
ret = 1;