PostgreSQL Source Code  git master
s_lock.h File Reference
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Data Structures

struct  SpinDelayStatus
 

Macros

#define S_LOCK_FREE(lock)   s_lock_free_sema(lock)
 
#define S_UNLOCK(lock)   s_unlock_sema(lock)
 
#define S_INIT_LOCK(lock)   s_init_lock_sema(lock, false)
 
#define TAS(lock)   tas_sema(lock)
 
#define S_LOCK(lock)   (TAS(lock) ? s_lock((lock), __FILE__, __LINE__, PG_FUNCNAME_MACRO) : 0)
 
#define SPIN_DELAY()   ((void) 0)
 
#define TAS_SPIN(lock)   TAS(lock)
 
#define DEFAULT_SPINS_PER_DELAY   100
 
#define init_local_spin_delay(status)   init_spin_delay(status, __FILE__, __LINE__, PG_FUNCNAME_MACRO)
 

Typedefs

typedef int slock_t
 

Functions

bool s_lock_free_sema (volatile slock_t *lock)
 
void s_unlock_sema (volatile slock_t *lock)
 
void s_init_lock_sema (volatile slock_t *lock, bool nested)
 
int tas_sema (volatile slock_t *lock)
 
int s_lock (volatile slock_t *lock, const char *file, int line, const char *func)
 
void set_spins_per_delay (int shared_spins_per_delay)
 
int update_spins_per_delay (int shared_spins_per_delay)
 
static void init_spin_delay (SpinDelayStatus *status, const char *file, int line, const char *func)
 
void perform_spin_delay (SpinDelayStatus *status)
 
void finish_spin_delay (SpinDelayStatus *status)
 

Variables

slock_t dummy_spinlock
 

Macro Definition Documentation

◆ DEFAULT_SPINS_PER_DELAY

#define DEFAULT_SPINS_PER_DELAY   100

Definition at line 990 of file s_lock.h.

Referenced by InitProcGlobal().

◆ init_local_spin_delay

#define init_local_spin_delay (   status)    init_spin_delay(status, __FILE__, __LINE__, PG_FUNCNAME_MACRO)

Definition at line 1021 of file s_lock.h.

Referenced by LockBufHdr(), LWLockWaitListLock(), and WaitBufHdrUnlocked().

◆ S_INIT_LOCK

#define S_INIT_LOCK (   lock)    s_init_lock_sema(lock, false)

Definition at line 921 of file s_lock.h.

Referenced by update_spins_per_delay().

◆ S_LOCK

#define S_LOCK (   lock)    (TAS(lock) ? s_lock((lock), __FILE__, __LINE__, PG_FUNCNAME_MACRO) : 0)

Definition at line 933 of file s_lock.h.

Referenced by update_spins_per_delay().

◆ S_LOCK_FREE

#define S_LOCK_FREE (   lock)    s_lock_free_sema(lock)

Definition at line 919 of file s_lock.h.

Referenced by update_spins_per_delay().

◆ S_UNLOCK

#define S_UNLOCK (   lock)    s_unlock_sema(lock)

Definition at line 920 of file s_lock.h.

Referenced by pg_atomic_clear_flag_impl(), and update_spins_per_delay().

◆ SPIN_DELAY

#define SPIN_DELAY ( )    ((void) 0)

Definition at line 968 of file s_lock.h.

Referenced by perform_spin_delay().

◆ TAS

#define TAS (   lock)    tas_sema(lock)

Definition at line 922 of file s_lock.h.

Referenced by pg_atomic_test_set_flag_impl().

◆ TAS_SPIN

#define TAS_SPIN (   lock)    TAS(lock)

Definition at line 979 of file s_lock.h.

Referenced by s_lock().

Typedef Documentation

◆ slock_t

Definition at line 912 of file s_lock.h.

Function Documentation

◆ finish_spin_delay()

void finish_spin_delay ( SpinDelayStatus status)

Definition at line 175 of file s_lock.c.

References SpinDelayStatus::cur_delay, Max, MAX_SPINS_PER_DELAY, Min, MIN_SPINS_PER_DELAY, and spins_per_delay.

Referenced by LockBufHdr(), LWLockWaitListLock(), s_lock(), and WaitBufHdrUnlocked().

176 {
177  if (status->cur_delay == 0)
178  {
179  /* we never had to delay */
182  }
183  else
184  {
187  }
188 }
#define Min(x, y)
Definition: c.h:812
#define MAX_SPINS_PER_DELAY
Definition: s_lock.c:58
static int spins_per_delay
Definition: s_lock.c:66
#define Max(x, y)
Definition: c.h:806
#define MIN_SPINS_PER_DELAY
Definition: s_lock.c:57

◆ init_spin_delay()

static void init_spin_delay ( SpinDelayStatus status,
const char *  file,
int  line,
const char *  func 
)
inlinestatic

Definition at line 1010 of file s_lock.h.

References SpinDelayStatus::cur_delay, SpinDelayStatus::delays, SpinDelayStatus::file, SpinDelayStatus::func, SpinDelayStatus::line, and SpinDelayStatus::spins.

Referenced by s_lock().

1012 {
1013  status->spins = 0;
1014  status->delays = 0;
1015  status->cur_delay = 0;
1016  status->file = file;
1017  status->line = line;
1018  status->func = func;
1019 }
const char * func
Definition: s_lock.h:1006
const char * file
Definition: s_lock.h:1004

◆ perform_spin_delay()

void perform_spin_delay ( SpinDelayStatus status)

Definition at line 125 of file s_lock.c.

References SpinDelayStatus::cur_delay, SpinDelayStatus::delays, SpinDelayStatus::file, SpinDelayStatus::func, SpinDelayStatus::line, MAX_DELAY_USEC, MAX_RANDOM_VALUE, MIN_DELAY_USEC, NUM_DELAYS, pg_usleep(), random(), s_lock_stuck(), SPIN_DELAY, SpinDelayStatus::spins, and spins_per_delay.

Referenced by LockBufHdr(), LWLockWaitListLock(), s_lock(), and WaitBufHdrUnlocked().

126 {
127  /* CPU-specific delay each time through the loop */
128  SPIN_DELAY();
129 
130  /* Block the process every spins_per_delay tries */
131  if (++(status->spins) >= spins_per_delay)
132  {
133  if (++(status->delays) > NUM_DELAYS)
134  s_lock_stuck(status->file, status->line, status->func);
135 
136  if (status->cur_delay == 0) /* first time to delay? */
137  status->cur_delay = MIN_DELAY_USEC;
138 
139  pg_usleep(status->cur_delay);
140 
141 #if defined(S_LOCK_TEST)
142  fprintf(stdout, "*");
143  fflush(stdout);
144 #endif
145 
146  /* increase delay by a random fraction between 1X and 2X */
147  status->cur_delay += (int) (status->cur_delay *
148  ((double) random() / (double) MAX_RANDOM_VALUE) + 0.5);
149  /* wrap back to minimum delay when max is exceeded */
150  if (status->cur_delay > MAX_DELAY_USEC)
151  status->cur_delay = MIN_DELAY_USEC;
152 
153  status->spins = 0;
154  }
155 }
#define NUM_DELAYS
Definition: s_lock.c:59
#define SPIN_DELAY()
Definition: s_lock.h:968
long random(void)
Definition: random.c:22
const char * func
Definition: s_lock.h:1006
#define MAX_DELAY_USEC
Definition: s_lock.c:61
static void s_lock_stuck(const char *file, int line, const char *func)
Definition: s_lock.c:73
#define MIN_DELAY_USEC
Definition: s_lock.c:60
void pg_usleep(long microsec)
Definition: signal.c:53
#define MAX_RANDOM_VALUE
static int spins_per_delay
Definition: s_lock.c:66
const char * file
Definition: s_lock.h:1004

◆ s_init_lock_sema()

void s_init_lock_sema ( volatile slock_t lock,
bool  nested 
)

Definition at line 107 of file spin.c.

References NUM_SPINLOCK_SEMAPHORES.

Referenced by pg_atomic_init_flag_impl(), pg_atomic_init_u32_impl(), and pg_atomic_init_u64_impl().

108 {
109  static int counter = 0;
110 
111  *lock = ((++counter) % NUM_SPINLOCK_SEMAPHORES) + 1;
112 }
#define NUM_SPINLOCK_SEMAPHORES

◆ s_lock()

int s_lock ( volatile slock_t lock,
const char *  file,
int  line,
const char *  func 
)

Definition at line 92 of file s_lock.c.

References SpinDelayStatus::delays, finish_spin_delay(), init_spin_delay(), perform_spin_delay(), and TAS_SPIN.

Referenced by update_spins_per_delay().

93 {
94  SpinDelayStatus delayStatus;
95 
96  init_spin_delay(&delayStatus, file, line, func);
97 
98  while (TAS_SPIN(lock))
99  {
100  perform_spin_delay(&delayStatus);
101  }
102 
103  finish_spin_delay(&delayStatus);
104 
105  return delayStatus.delays;
106 }
static void init_spin_delay(SpinDelayStatus *status, const char *file, int line, const char *func)
Definition: s_lock.h:1010
void finish_spin_delay(SpinDelayStatus *status)
Definition: s_lock.c:175
#define TAS_SPIN(lock)
Definition: s_lock.h:979
void perform_spin_delay(SpinDelayStatus *status)
Definition: s_lock.c:125

◆ s_lock_free_sema()

bool s_lock_free_sema ( volatile slock_t lock)

Definition at line 125 of file spin.c.

References elog, and ERROR.

126 {
127  /* We don't currently use S_LOCK_FREE anyway */
128  elog(ERROR, "spin.c does not support S_LOCK_FREE()");
129  return false;
130 }
#define ERROR
Definition: elog.h:43
#define elog
Definition: elog.h:219

◆ s_unlock_sema()

void s_unlock_sema ( volatile slock_t lock)

Definition at line 115 of file spin.c.

References elog, ERROR, NUM_SPINLOCK_SEMAPHORES, and PGSemaphoreUnlock().

116 {
117  int lockndx = *lock;
118 
119  if (lockndx <= 0 || lockndx > NUM_SPINLOCK_SEMAPHORES)
120  elog(ERROR, "invalid spinlock number: %d", lockndx);
121  PGSemaphoreUnlock(SpinlockSemaArray[lockndx - 1]);
122 }
void PGSemaphoreUnlock(PGSemaphore sema)
Definition: posix_sema.c:323
#define ERROR
Definition: elog.h:43
PGSemaphore * SpinlockSemaArray
Definition: spin.c:31
#define elog
Definition: elog.h:219
#define NUM_SPINLOCK_SEMAPHORES

◆ set_spins_per_delay()

void set_spins_per_delay ( int  shared_spins_per_delay)

Definition at line 196 of file s_lock.c.

References spins_per_delay.

Referenced by InitAuxiliaryProcess(), and InitProcess().

197 {
198  spins_per_delay = shared_spins_per_delay;
199 }
static int spins_per_delay
Definition: s_lock.c:66

◆ tas_sema()

int tas_sema ( volatile slock_t lock)

Definition at line 133 of file spin.c.

References elog, ERROR, NUM_SPINLOCK_SEMAPHORES, and PGSemaphoreTryLock().

134 {
135  int lockndx = *lock;
136 
137  if (lockndx <= 0 || lockndx > NUM_SPINLOCK_SEMAPHORES)
138  elog(ERROR, "invalid spinlock number: %d", lockndx);
139  /* Note that TAS macros return 0 if *success* */
140  return !PGSemaphoreTryLock(SpinlockSemaArray[lockndx - 1]);
141 }
#define ERROR
Definition: elog.h:43
PGSemaphore * SpinlockSemaArray
Definition: spin.c:31
bool PGSemaphoreTryLock(PGSemaphore sema)
Definition: posix_sema.c:348
#define elog
Definition: elog.h:219
#define NUM_SPINLOCK_SEMAPHORES

◆ update_spins_per_delay()

int update_spins_per_delay ( int  shared_spins_per_delay)

Definition at line 207 of file s_lock.c.

References main(), NUM_DELAYS, S_INIT_LOCK, s_lock(), S_LOCK, S_LOCK_FREE, S_UNLOCK, spins_per_delay, and srandom().

Referenced by AuxiliaryProcKill(), and ProcKill().

208 {
209  /*
210  * We use an exponential moving average with a relatively slow adaption
211  * rate, so that noise in any one backend's result won't affect the shared
212  * value too much. As long as both inputs are within the allowed range,
213  * the result must be too, so we need not worry about clamping the result.
214  *
215  * We deliberately truncate rather than rounding; this is so that single
216  * adjustments inside a backend can affect the shared estimate (see the
217  * asymmetric adjustment rules above).
218  */
219  return (shared_spins_per_delay * 15 + spins_per_delay) / 16;
220 }
static int spins_per_delay
Definition: s_lock.c:66

Variable Documentation

◆ dummy_spinlock

slock_t dummy_spinlock

Definition at line 64 of file s_lock.c.

Referenced by startup_hacks().