1996-08-28 03:59:28 +02:00
|
|
|
/*-------------------------------------------------------------------------
|
|
|
|
*
|
1999-02-14 00:22:53 +01:00
|
|
|
* spin.h
|
2001-09-29 06:02:27 +02:00
|
|
|
* Hardware-independent implementation of spinlocks.
|
|
|
|
*
|
|
|
|
*
|
|
|
|
* The hardware-independent interface to spinlocks is defined by the
|
|
|
|
* typedef "slock_t" and these macros:
|
|
|
|
*
|
2005-10-13 08:17:34 +02:00
|
|
|
* void SpinLockInit(volatile slock_t *lock)
|
2001-09-29 06:02:27 +02:00
|
|
|
* Initialize a spinlock (to the unlocked state).
|
|
|
|
*
|
2005-10-13 08:17:34 +02:00
|
|
|
* void SpinLockAcquire(volatile slock_t *lock)
|
2001-09-29 06:02:27 +02:00
|
|
|
* Acquire a spinlock, waiting if necessary.
|
|
|
|
* Time out and abort() if unable to acquire the lock in a
|
|
|
|
* "reasonable" amount of time --- typically ~ 1 minute.
|
|
|
|
*
|
2005-10-13 08:17:34 +02:00
|
|
|
* void SpinLockRelease(volatile slock_t *lock)
|
2001-09-29 06:02:27 +02:00
|
|
|
* Unlock a previously acquired lock.
|
|
|
|
*
|
|
|
|
* bool SpinLockFree(slock_t *lock)
|
2017-08-16 06:22:32 +02:00
|
|
|
* Tests if the lock is free. Returns true if free, false if locked.
|
2001-09-29 06:02:27 +02:00
|
|
|
* This does *not* change the state of the lock.
|
|
|
|
*
|
|
|
|
* Callers must beware that the macro argument may be evaluated multiple
|
|
|
|
* times!
|
|
|
|
*
|
2015-10-16 20:06:22 +02:00
|
|
|
* Load and store operations in calling code are guaranteed not to be
|
|
|
|
* reordered with respect to these operations, because they include a
|
|
|
|
* compiler barrier. (Before PostgreSQL 9.5, callers needed to use a
|
|
|
|
* volatile qualifier to access data protected by spinlocks.)
|
2005-10-13 08:17:34 +02:00
|
|
|
*
|
2005-12-29 19:08:05 +01:00
|
|
|
* Keep in mind the coding rule that spinlocks must not be held for more
|
|
|
|
* than a few instructions. In particular, we assume it is not possible
|
|
|
|
* for a CHECK_FOR_INTERRUPTS() to occur while holding a spinlock, and so
|
|
|
|
* it is not necessary to do HOLD/RESUME_INTERRUPTS() in these macros.
|
|
|
|
*
|
2005-10-13 08:17:34 +02:00
|
|
|
* These macros are implemented in terms of hardware-dependent macros
|
2005-12-29 19:08:05 +01:00
|
|
|
* supplied by s_lock.h. There is not currently any extra functionality
|
|
|
|
* added by this header, but there has been in the past and may someday
|
|
|
|
* be again.
|
1996-08-28 03:59:28 +02:00
|
|
|
*
|
|
|
|
*
|
2023-01-02 21:00:37 +01:00
|
|
|
* Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
|
2000-01-26 06:58:53 +01:00
|
|
|
* Portions Copyright (c) 1994, Regents of the University of California
|
1996-08-28 03:59:28 +02:00
|
|
|
*
|
2010-09-20 22:08:53 +02:00
|
|
|
* src/include/storage/spin.h
|
1996-08-28 03:59:28 +02:00
|
|
|
*
|
|
|
|
*-------------------------------------------------------------------------
|
|
|
|
*/
|
|
|
|
#ifndef SPIN_H
|
|
|
|
#define SPIN_H
|
|
|
|
|
2001-09-29 06:02:27 +02:00
|
|
|
#include "storage/s_lock.h"
|
2014-01-09 02:58:22 +01:00
|
|
|
#ifndef HAVE_SPINLOCKS
|
|
|
|
#include "storage/pg_sema.h"
|
|
|
|
#endif
|
1996-08-28 03:59:28 +02:00
|
|
|
|
|
|
|
|
2001-09-29 06:02:27 +02:00
|
|
|
#define SpinLockInit(lock) S_INIT_LOCK(lock)
|
|
|
|
|
2005-12-29 19:08:05 +01:00
|
|
|
#define SpinLockAcquire(lock) S_LOCK(lock)
|
2001-03-22 05:01:46 +01:00
|
|
|
|
2005-12-29 19:08:05 +01:00
|
|
|
#define SpinLockRelease(lock) S_UNLOCK(lock)
|
2000-05-31 02:28:42 +02:00
|
|
|
|
2001-09-29 06:02:27 +02:00
|
|
|
#define SpinLockFree(lock) S_LOCK_FREE(lock)
|
2000-11-29 00:27:57 +01:00
|
|
|
|
|
|
|
|
2002-05-05 02:03:29 +02:00
|
|
|
extern int SpinlockSemas(void);
|
Reduce the number of semaphores used under --disable-spinlocks.
Instead of allocating a semaphore from the operating system for every
spinlock, allocate a fixed number of semaphores (by default, 1024)
from the operating system and multiplex all the spinlocks that get
created onto them. This could self-deadlock if a process attempted
to acquire more than one spinlock at a time, but since processes
aren't supposed to execute anything other than short stretches of
straight-line code while holding a spinlock, that shouldn't happen.
One motivation for this change is that, with the introduction of
dynamic shared memory, it may be desirable to create spinlocks that
last for less than the lifetime of the server. Without this change,
attempting to use such facilities under --disable-spinlocks would
quickly exhaust any supply of available semaphores. Quite apart
from that, it's desirable to contain the quantity of semaphores
needed to run the server simply on convenience grounds, since using
too many may make it harder to get PostgreSQL running on a new
platform, which is mostly the point of --disable-spinlocks in the
first place.
Patch by me; review by Tom Lane.
2014-01-09 00:49:14 +01:00
|
|
|
extern Size SpinlockSemaSize(void);
|
|
|
|
|
|
|
|
#ifndef HAVE_SPINLOCKS
|
Make the different Unix-y semaphore implementations ABI-compatible.
Previously, the "sem" field of PGPROC varied in size depending on which
kernel semaphore API we were using. That was okay as long as there was
only one likely choice per platform, but in the wake of commit ecb0d20a9,
that assumption seems rather shaky. It doesn't seem out of the question
anymore that an extension compiled against one API choice might be loaded
into a postmaster built with another choice. Moreover, this prevents any
possibility of selecting the semaphore API at postmaster startup, which
might be something we want to do in future.
Hence, change PGPROC.sem to be PGSemaphore (i.e. a pointer) for all Unix
semaphore APIs, and turn the pointed-to data into an opaque struct whose
contents are only known within the responsible modules.
For the SysV and unnamed-POSIX APIs, the pointed-to data has to be
allocated elsewhere in shared memory, which takes a little bit of
rejiggering of the InitShmemAllocation code sequence. (I invented a
ShmemAllocUnlocked() function to make that a little cleaner than it used
to be. That function is not meant for any uses other than the ones it
has now, but it beats having InitShmemAllocation() know explicitly about
allocation of space for semaphores and spinlocks.) This change means an
extra indirection to access the semaphore data, but since we only touch
that when blocking or awakening a process, there shouldn't be any
meaningful performance penalty. Moreover, at least for the unnamed-POSIX
case on Linux, the sem_t type is quite a bit wider than a pointer, so this
reduces sizeof(PGPROC) which seems like a good thing.
For the named-POSIX API, there's effectively no change: the PGPROC.sem
field was and still is a pointer to something returned by sem_open() in
the postmaster's memory space. Document and check the pre-existing
limitation that this case can't work in EXEC_BACKEND mode.
It did not seem worth unifying the Windows semaphore ABI with the Unix
cases, since there's no likelihood of needing ABI compatibility much less
runtime switching across those cases. However, we can simplify the Windows
code a bit if we define PGSemaphore as being directly a HANDLE, rather than
pointer to HANDLE, so let's do that while we're here. (This also ends up
being no change in what's physically stored in PGPROC.sem. We're just
moving the HANDLE fetch from callees to callers.)
It would take a bunch of additional code shuffling to get to the point of
actually choosing a semaphore API at postmaster start, but the effects
of that would now be localized in the port/XXX_sema.c files, so it seems
like fit material for a separate patch. The need for it is unproven as
yet, anyhow, whereas the ABI risk to extensions seems real enough.
Discussion: https://postgr.es/m/4029.1481413370@sss.pgh.pa.us
2016-12-12 19:32:10 +01:00
|
|
|
extern void SpinlockSemaInit(void);
|
2022-04-08 14:16:38 +02:00
|
|
|
extern PGDLLIMPORT PGSemaphore *SpinlockSemaArray;
|
Reduce the number of semaphores used under --disable-spinlocks.
Instead of allocating a semaphore from the operating system for every
spinlock, allocate a fixed number of semaphores (by default, 1024)
from the operating system and multiplex all the spinlocks that get
created onto them. This could self-deadlock if a process attempted
to acquire more than one spinlock at a time, but since processes
aren't supposed to execute anything other than short stretches of
straight-line code while holding a spinlock, that shouldn't happen.
One motivation for this change is that, with the introduction of
dynamic shared memory, it may be desirable to create spinlocks that
last for less than the lifetime of the server. Without this change,
attempting to use such facilities under --disable-spinlocks would
quickly exhaust any supply of available semaphores. Quite apart
from that, it's desirable to contain the quantity of semaphores
needed to run the server simply on convenience grounds, since using
too many may make it harder to get PostgreSQL running on a new
platform, which is mostly the point of --disable-spinlocks in the
first place.
Patch by me; review by Tom Lane.
2014-01-09 00:49:14 +01:00
|
|
|
#endif
|
2001-10-28 07:26:15 +01:00
|
|
|
|
1996-08-28 03:59:28 +02:00
|
|
|
#endif /* SPIN_H */
|