1996-07-09 08:22:35 +02:00
|
|
|
/*-------------------------------------------------------------------------
|
|
|
|
*
|
1999-02-14 00:22:53 +01:00
|
|
|
* spin.c
|
2001-09-29 06:02:27 +02:00
|
|
|
* Hardware-independent implementation of spinlocks.
|
|
|
|
*
|
|
|
|
*
|
|
|
|
* For machines that have test-and-set (TAS) instructions, s_lock.h/.c
|
2014-05-06 18:12:18 +02:00
|
|
|
* define the spinlock implementation. This file contains only a stub
|
2002-05-05 02:03:29 +02:00
|
|
|
* implementation for spinlocks using PGSemaphores. Unless semaphores
|
|
|
|
* are implemented in a way that doesn't involve a kernel call, this
|
2001-09-29 06:02:27 +02:00
|
|
|
* is too slow to be very useful :-(
|
1996-07-09 08:22:35 +02:00
|
|
|
*
|
2000-11-29 00:27:57 +01:00
|
|
|
*
|
2014-01-07 22:05:30 +01:00
|
|
|
* Portions Copyright (c) 1996-2014, PostgreSQL Global Development Group
|
2000-01-26 06:58:53 +01:00
|
|
|
* Portions Copyright (c) 1994, Regents of the University of California
|
1996-07-09 08:22:35 +02:00
|
|
|
*
|
|
|
|
*
|
|
|
|
* IDENTIFICATION
|
2010-09-20 22:08:53 +02:00
|
|
|
* src/backend/storage/lmgr/spin.c
|
1996-07-09 08:22:35 +02:00
|
|
|
*
|
|
|
|
*-------------------------------------------------------------------------
|
|
|
|
*/
|
|
|
|
#include "postgres.h"
|
|
|
|
|
2013-07-08 10:23:56 +02:00
|
|
|
#include "access/xlog.h"
|
2006-07-22 23:04:40 +02:00
|
|
|
#include "miscadmin.h"
|
2013-04-04 15:31:44 +02:00
|
|
|
#include "replication/walsender.h"
|
2006-07-22 23:04:40 +02:00
|
|
|
#include "storage/lwlock.h"
|
2014-01-09 02:58:22 +01:00
|
|
|
#include "storage/pg_sema.h"
|
2001-09-29 06:02:27 +02:00
|
|
|
#include "storage/spin.h"
|
1996-07-09 08:22:35 +02:00
|
|
|
|
2000-05-31 02:28:42 +02:00
|
|
|
|
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
|
|
|
PGSemaphore SpinlockSemaArray;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Report the amount of shared memory needed to store semaphores for spinlock
|
|
|
|
* support.
|
|
|
|
*/
|
|
|
|
Size
|
|
|
|
SpinlockSemaSize(void)
|
|
|
|
{
|
|
|
|
return SpinlockSemas() * sizeof(PGSemaphoreData);
|
|
|
|
}
|
|
|
|
|
2003-12-23 19:13:17 +01:00
|
|
|
#ifdef HAVE_SPINLOCKS
|
2000-11-29 00:27:57 +01:00
|
|
|
|
|
|
|
/*
|
2002-05-05 02:03:29 +02:00
|
|
|
* Report number of semaphores needed to support spinlocks.
|
2000-11-29 00:27:57 +01:00
|
|
|
*/
|
2002-05-05 02:03:29 +02:00
|
|
|
int
|
|
|
|
SpinlockSemas(void)
|
1996-07-09 08:22:35 +02:00
|
|
|
{
|
2002-05-05 02:03:29 +02:00
|
|
|
return 0;
|
2000-11-29 00:27:57 +01:00
|
|
|
}
|
2003-12-23 19:13:17 +01:00
|
|
|
#else /* !HAVE_SPINLOCKS */
|
2000-11-29 00:27:57 +01:00
|
|
|
|
|
|
|
/*
|
2002-05-05 02:03:29 +02:00
|
|
|
* No TAS, so spinlocks are implemented as PGSemaphores.
|
2000-11-29 00:27:57 +01:00
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
2002-05-05 02:03:29 +02:00
|
|
|
* Report number of semaphores needed to support spinlocks.
|
2000-11-29 00:27:57 +01:00
|
|
|
*/
|
2002-05-05 02:03:29 +02:00
|
|
|
int
|
|
|
|
SpinlockSemas(void)
|
2000-11-29 00:27:57 +01:00
|
|
|
{
|
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
|
|
|
return NUM_SPINLOCK_SEMAPHORES;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Initialize semaphores.
|
|
|
|
*/
|
|
|
|
extern void
|
|
|
|
SpinlockSemaInit(PGSemaphore spinsemas)
|
|
|
|
{
|
2014-05-06 18:12:18 +02:00
|
|
|
int i;
|
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
|
|
|
|
|
|
|
for (i = 0; i < NUM_SPINLOCK_SEMAPHORES; ++i)
|
|
|
|
PGSemaphoreCreate(&spinsemas[i]);
|
|
|
|
SpinlockSemaArray = spinsemas;
|
2000-11-29 00:27:57 +01:00
|
|
|
}
|
1997-08-19 23:40:56 +02:00
|
|
|
|
1996-07-09 08:22:35 +02:00
|
|
|
/*
|
2000-11-29 00:27:57 +01:00
|
|
|
* s_lock.h hardware-spinlock emulation
|
1996-07-09 08:22:35 +02:00
|
|
|
*/
|
2000-11-29 00:27:57 +01:00
|
|
|
|
1999-10-06 23:58:18 +02:00
|
|
|
void
|
2000-11-29 00:27:57 +01:00
|
|
|
s_init_lock_sema(volatile slock_t *lock)
|
1996-07-09 08:22:35 +02:00
|
|
|
{
|
2014-05-06 18:12:18 +02:00
|
|
|
static int counter = 0;
|
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
|
|
|
|
|
|
|
*lock = (++counter) % NUM_SPINLOCK_SEMAPHORES;
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
|
|
|
|
1999-10-06 23:58:18 +02:00
|
|
|
void
|
2000-11-29 00:27:57 +01:00
|
|
|
s_unlock_sema(volatile slock_t *lock)
|
1996-07-09 08:22:35 +02:00
|
|
|
{
|
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
|
|
|
PGSemaphoreUnlock(&SpinlockSemaArray[*lock]);
|
2000-11-29 00:27:57 +01:00
|
|
|
}
|
1997-09-07 07:04:48 +02:00
|
|
|
|
2000-11-29 00:27:57 +01:00
|
|
|
bool
|
|
|
|
s_lock_free_sema(volatile slock_t *lock)
|
|
|
|
{
|
2002-05-05 02:03:29 +02:00
|
|
|
/* We don't currently use S_LOCK_FREE anyway */
|
|
|
|
elog(ERROR, "spin.c does not support S_LOCK_FREE()");
|
|
|
|
return false;
|
2000-11-29 00:27:57 +01:00
|
|
|
}
|
1997-09-07 07:04:48 +02:00
|
|
|
|
2000-11-29 00:27:57 +01:00
|
|
|
int
|
|
|
|
tas_sema(volatile slock_t *lock)
|
|
|
|
{
|
|
|
|
/* Note that TAS macros return 0 if *success* */
|
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
|
|
|
return !PGSemaphoreTryLock(&SpinlockSemaArray[*lock]);
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
2001-10-28 07:26:15 +01:00
|
|
|
|
2003-12-23 19:13:17 +01:00
|
|
|
#endif /* !HAVE_SPINLOCKS */
|