]> git.ipfire.org Git - thirdparty/openssl.git/commit
rcu: Ensure that updates to the ID field of a qp don't lose refs
authorNeil Horman <nhorman@openssl.org>
Sun, 19 Jan 2025 21:43:37 +0000 (16:43 -0500)
committerTomas Mraz <tomas@openssl.org>
Wed, 22 Jan 2025 19:20:56 +0000 (20:20 +0100)
commit2117b0464b269e5f402faa142ebced73bfbbbb68
treec35f52ebbcd9eff8bcd5b13261aa2563e23bbfbb
parent22fafd3f205ab85042bf24bae83e415bc0f92010
rcu: Ensure that updates to the ID field of a qp don't lose refs

ppc64le occasionally still fails the threadstest on __rcu_torture

From several days of debugging, I think I've landed on the problem.

Occasionally, under high load I observe the following pattern

CPU0                                     CPU1
update_qp                                get_hold_current_qp
  atomic_and_fetch(qp->users, ID_MASK, RELEASE)
                                         atomic_add_fetch(qp->users, 1, RELEASE
  atomic_or_fetch(qp->users, ID_VAL++, RELEASE)

When this pattern occurs, the atomic or operation fails to see the published
value of CPU1 and when the or-ed value is written back to ram, the incremented
value in get_hold_current_qp is overwritten, meaning the hold that the reader
placed on the rcu lock is lost, allowing the writer to complete early, freeing
memory before a reader is done reading any held memory.

Why this is only observed on ppc64le I'm not sure, but it seems like a pretty
clear problem.

fix it by implementing ATOMIC_COMPARE_EXCHANGE_N, so that, on the write side in
update_qp, we can ensure that updates are only done if the read side hasn't
changed anything.  If it has, retry the operation.

With this fix, I'm able to run the threads test overnight (4000 iterations and
counting) without failure.

Reviewed-by: Saša Nedvědický <sashan@openssl.org>
Reviewed-by: Tomas Mraz <tomas@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/26478)

(cherry picked from commit fbd34c03e3ca94d3805e97a01defdf8b6037f61c)
crypto/threads_pthread.c