Re: Atomic operations within spinlocks
Andres Freund <andres@anarazel.de>
From: Andres Freund <andres@anarazel.de>
To: Tom Lane <tgl@sss.pgh.pa.us>
Cc: pgsql-hackers@lists.postgresql.org
Date: 2020-06-05T02:33:02Z
Lists: pgsql-hackers
Hi, On 2020-06-04 15:07:34 -0400, Tom Lane wrote: > Andres Freund <andres@anarazel.de> writes: > > I'd still like to know which problem we're actually trying to solve > > here. I don't understand the "error" issues you mentioned upthread. > > If you error out of getting the inner spinlock, the outer spinlock > is stuck, permanently, because there is no mechanism for spinlock > release during transaction abort. Admittedly it's not very likely > for the inner acquisition to fail, but it's possible. We PANIC on stuck spinlocks, so I don't think that's a problem. > * We map all spinlocks onto a set of NUM_SPINLOCK_SEMAPHORES semaphores. > * It's okay to map multiple spinlocks onto one semaphore because no process > * should ever hold more than one at a time. > > You've falsified that argument ... and no, I don't want to upgrade > the spinlock infrastructure enough to make this OK. Well, theoretically we take care to avoid this problem. That's why we have a separate define for spinlocks and atomics: /* * When we don't have native spinlocks, we use semaphores to simulate them. * Decreasing this value reduces consumption of OS resources; increasing it * may improve performance, but supplying a real spinlock implementation is * probably far better. */ #define NUM_SPINLOCK_SEMAPHORES 128 /* * When we have neither spinlocks nor atomic operations support we're * implementing atomic operations on top of spinlock on top of semaphores. To * be safe against atomic operations while holding a spinlock separate * semaphores have to be used. */ #define NUM_ATOMICS_SEMAPHORES 64 and #ifndef HAVE_SPINLOCKS /* * NB: If we're using semaphore based TAS emulation, be careful to use a * separate set of semaphores. Otherwise we'd get in trouble if an atomic * var would be manipulated while spinlock is held. */ s_init_lock_sema((slock_t *) &ptr->sema, true); #else SpinLockInit((slock_t *) &ptr->sema); #endif But it looks like that code is currently buggy (and looks like it always has been), because we don't look at the nested argument when initializing the semaphore. So we currently allocate too many semaphores, without benefiting from them :(. > We shouldn't ever be holding spinlocks long enough, or doing anything > complicated enough inside them, for such an upgrade to have merit. Well, I don't think atomic instructions are that complicated. And I think prohibiting atomics-within-spinlock adds a problematic restriction, without much in the way of benefits: There's plenty things where it's somewhat easy to make the fast-path lock-free, but the slow path still needs a lock (e.g. around a freelist). And for those it's really useful to still be able to have a coherent update to an atomic variable, to synchronize with the fast-path that doesn't take the spinlock. Greetings, Andres Freund
Commits
-
Convert SpinLock* macros to static inline functions.
- bfc321b4723e 19 (unreleased) landed
-
Clean up includes of s_lock.h.
- f219167910ad 14.0 landed
-
Fix deadlock danger when atomic ops are done under spinlock.
- 5fffa8fce37b 13.0 landed
- 6cc2866c4cdf 12.4 landed
- 825d89dda5ad 11.9 landed
- c2a84bee1228 10.14 landed
- 8bc13287ed3e 9.6.19 landed
- 3e69bf3b142b 9.5.23 landed
- cf1234a10e50 14.0 landed
-
Add basic spinlock tests to regression tests.
- 3f66e1c5a576 10.14 landed
- e027219f2131 11.9 landed
- 008c119928a3 12.4 landed
- 59225dcefef2 13.0 landed
- 3b37a6de027c 14.0 landed
- e8302f107af9 9.6.19 landed
- 7e91f90a8ed4 9.5.23 landed
-
spinlock emulation: Fix bug when more than INT_MAX spinlocks are initialized.
- dcf3cb60cbef 9.5.23 landed
- 660622053419 9.6.19 landed
- b295f666b7f0 10.14 landed
- 34d29222a0bb 11.9 landed
- b91cfaa34f44 12.4 landed
- 276bdc93924a 13.0 landed
- 4d4ca24efe8e 14.0 landed
-
Avoid potential spinlock in a signal handler as part of global barriers.
- 09bff91b316e 13.0 landed
- fd49d5380757 14.0 landed
-
Make pg_stat_wal_receiver consistent with the WAL receiver's shmem info
- 2c8dd05d6cbc 13.0 cited
-
Improve 64bit atomics support.
- e8fdbd58fe56 10.0 cited