Skip to content

Commit 4039c73

Browse files
committed
Adjust spin.c's spinlock emulation so that 0 is not a valid spinlock value.
We've had repeated troubles over the years with failures to initialize spinlocks correctly; see 6b93fcd for a recent example. Most of the time, on most platforms, such oversights can escape notice because all-zeroes is the expected initial content of an slock_t variable. The only platform we have where the initialized state of an slock_t isn't zeroes is HPPA, and that's practically gone in the wild. To make it easier to catch such errors without needing one of those, adjust the --disable-spinlocks code so that zero is not a valid value for an slock_t for it. In passing, remove a bunch of unnecessary #include's from spin.c; commit daa7527 removed all the intermodule coupling that made them necessary.
1 parent 5fdda1c commit 4039c73

File tree

1 file changed

+22
-8
lines changed
  • src/backend/storage/lmgr

1 file changed

+22
-8
lines changed

src/backend/storage/lmgr/spin.c

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,6 @@
2222
*/
2323
#include "postgres.h"
2424

25-
#include "access/xlog.h"
26-
#include "miscadmin.h"
27-
#include "replication/walsender.h"
28-
#include "storage/lwlock.h"
2925
#include "storage/pg_sema.h"
3026
#include "storage/spin.h"
3127

@@ -85,21 +81,35 @@ SpinlockSemaInit(PGSemaphore spinsemas)
8581
}
8682

8783
/*
88-
* s_lock.h hardware-spinlock emulation
84+
* s_lock.h hardware-spinlock emulation using semaphores
85+
*
86+
* We map all spinlocks onto a set of NUM_SPINLOCK_SEMAPHORES semaphores.
87+
* It's okay to map multiple spinlocks onto one semaphore because no process
88+
* should ever hold more than one at a time. We just need enough semaphores
89+
* so that we aren't adding too much extra contention from that.
90+
*
91+
* slock_t is just an int for this implementation; it holds the spinlock
92+
* number from 1..NUM_SPINLOCK_SEMAPHORES. We intentionally ensure that 0
93+
* is not a valid value, so that testing with this code can help find
94+
* failures to initialize spinlocks.
8995
*/
9096

9197
void
9298
s_init_lock_sema(volatile slock_t *lock, bool nested)
9399
{
94100
static int counter = 0;
95101

96-
*lock = (++counter) % NUM_SPINLOCK_SEMAPHORES;
102+
*lock = ((++counter) % NUM_SPINLOCK_SEMAPHORES) + 1;
97103
}
98104

99105
void
100106
s_unlock_sema(volatile slock_t *lock)
101107
{
102-
PGSemaphoreUnlock(&SpinlockSemaArray[*lock]);
108+
int lockndx = *lock;
109+
110+
if (lockndx <= 0 || lockndx > NUM_SPINLOCK_SEMAPHORES)
111+
elog(ERROR, "invalid spinlock number: %d", lockndx);
112+
PGSemaphoreUnlock(&SpinlockSemaArray[lockndx - 1]);
103113
}
104114

105115
bool
@@ -113,8 +123,12 @@ s_lock_free_sema(volatile slock_t *lock)
113123
int
114124
tas_sema(volatile slock_t *lock)
115125
{
126+
int lockndx = *lock;
127+
128+
if (lockndx <= 0 || lockndx > NUM_SPINLOCK_SEMAPHORES)
129+
elog(ERROR, "invalid spinlock number: %d", lockndx);
116130
/* Note that TAS macros return 0 if *success* */
117-
return !PGSemaphoreTryLock(&SpinlockSemaArray[*lock]);
131+
return !PGSemaphoreTryLock(&SpinlockSemaArray[lockndx - 1]);
118132
}
119133

120134
#endif /* !HAVE_SPINLOCKS */

0 commit comments

Comments
 (0)