ProcArrayGroupClearXid() has this: while (true) { nextidx = pg_atomic_read_u32(&procglobal->procArrayGroupFirst);
... if (pg_atomic_compare_exchange_u32(&procglobal->procArrayGroupFirst, &nextidx, (uint32) proc->pgprocno)) break; } This, from UnpinBuffer(), is our more-typical style: old_buf_state = pg_atomic_read_u32(&buf->state); for (;;) { ... if (pg_atomic_compare_exchange_u32(&buf->state, &old_buf_state, buf_state)) break; } That is, we typically put the pg_atomic_read_u32() outside the loop. After the first iteration, it is redundant with the side effect of pg_atomic_compare_exchange_u32(). I haven't checked whether this materially improves performance, but, for style, I would like to change it in HEAD.
diff --git a/src/backend/storage/ipc/procarray.c b/src/backend/storage/ipc/procarray.c index 8abcfdf..3da5307 100644 --- a/src/backend/storage/ipc/procarray.c +++ b/src/backend/storage/ipc/procarray.c @@ -490,15 +490,15 @@ ProcArrayGroupClearXid(PGPROC *proc, TransactionId latestXid) /* We should definitely have an XID to clear. */ Assert(TransactionIdIsValid(allPgXact[proc->pgprocno].xid)); /* Add ourselves to the list of processes needing a group XID clear. */ proc->procArrayGroupMember = true; proc->procArrayGroupMemberXid = latestXid; + nextidx = pg_atomic_read_u32(&procglobal->procArrayGroupFirst); while (true) { - nextidx = pg_atomic_read_u32(&procglobal->procArrayGroupFirst); pg_atomic_write_u32(&proc->procArrayGroupNext, nextidx); if (pg_atomic_compare_exchange_u32(&procglobal->procArrayGroupFirst, &nextidx, (uint32) proc->pgprocno)) break;