PostgreSQL Source Code  git master
s_lock.c File Reference
#include "postgres.h"
#include <time.h>
#include <unistd.h>
#include "port/atomics.h"
#include "storage/s_lock.h"
Include dependency graph for s_lock.c:

Go to the source code of this file.

Macros

#define MIN_SPINS_PER_DELAY   10
 
#define MAX_SPINS_PER_DELAY   1000
 
#define NUM_DELAYS   1000
 
#define MIN_DELAY_USEC   1000L
 
#define MAX_DELAY_USEC   1000000L
 

Functions

static void s_lock_stuck (const char *file, int line, const char *func)
 
int s_lock (volatile slock_t *lock, const char *file, int line, const char *func)
 
void perform_spin_delay (SpinDelayStatus *status)
 
void finish_spin_delay (SpinDelayStatus *status)
 
void set_spins_per_delay (int shared_spins_per_delay)
 
int update_spins_per_delay (int shared_spins_per_delay)
 

Variables

slock_t dummy_spinlock
 
static int spins_per_delay = DEFAULT_SPINS_PER_DELAY
 

Macro Definition Documentation

◆ MAX_DELAY_USEC

#define MAX_DELAY_USEC   1000000L

Definition at line 60 of file s_lock.c.

Referenced by perform_spin_delay().

◆ MAX_SPINS_PER_DELAY

#define MAX_SPINS_PER_DELAY   1000

Definition at line 57 of file s_lock.c.

Referenced by finish_spin_delay().

◆ MIN_DELAY_USEC

#define MIN_DELAY_USEC   1000L

Definition at line 59 of file s_lock.c.

Referenced by perform_spin_delay().

◆ MIN_SPINS_PER_DELAY

#define MIN_SPINS_PER_DELAY   10

Definition at line 56 of file s_lock.c.

Referenced by finish_spin_delay().

◆ NUM_DELAYS

#define NUM_DELAYS   1000

Definition at line 58 of file s_lock.c.

Referenced by perform_spin_delay(), and update_spins_per_delay().

Function Documentation

◆ finish_spin_delay()

void finish_spin_delay ( SpinDelayStatus status)

Definition at line 174 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().

175 {
176  if (status->cur_delay == 0)
177  {
178  /* we never had to delay */
181  }
182  else
183  {
186  }
187 }
#define Min(x, y)
Definition: c.h:905
#define MAX_SPINS_PER_DELAY
Definition: s_lock.c:57
static int spins_per_delay
Definition: s_lock.c:65
#define Max(x, y)
Definition: c.h:899
#define MIN_SPINS_PER_DELAY
Definition: s_lock.c:56

◆ perform_spin_delay()

void perform_spin_delay ( SpinDelayStatus status)

Definition at line 124 of file s_lock.c.

References SpinDelayStatus::cur_delay, SpinDelayStatus::delays, SpinDelayStatus::file, fprintf, 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, spins_per_delay, and generate_unaccent_rules::stdout.

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

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

◆ s_lock()

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

Definition at line 91 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().

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

◆ s_lock_stuck()

static void s_lock_stuck ( const char *  file,
int  line,
const char *  func 
)
static

Definition at line 72 of file s_lock.c.

References elog, fprintf, and PANIC.

Referenced by perform_spin_delay().

73 {
74  if (!func)
75  func = "(unknown)";
76 #if defined(S_LOCK_TEST)
77  fprintf(stderr,
78  "\nStuck spinlock detected at %s, %s:%d.\n",
79  func, file, line);
80  exit(1);
81 #else
82  elog(PANIC, "stuck spinlock detected at %s, %s:%d",
83  func, file, line);
84 #endif
85 }
#define fprintf
Definition: port.h:196
#define PANIC
Definition: elog.h:53
#define elog(elevel,...)
Definition: elog.h:228

◆ set_spins_per_delay()

void set_spins_per_delay ( int  shared_spins_per_delay)

Definition at line 195 of file s_lock.c.

References spins_per_delay.

Referenced by InitAuxiliaryProcess(), and InitProcess().

196 {
197  spins_per_delay = shared_spins_per_delay;
198 }
static int spins_per_delay
Definition: s_lock.c:65

◆ update_spins_per_delay()

int update_spins_per_delay ( int  shared_spins_per_delay)

Definition at line 206 of file s_lock.c.

References main(), NUM_DELAYS, printf, S_INIT_LOCK, s_lock(), S_LOCK, S_LOCK_FREE, S_UNLOCK, spins_per_delay, srandom(), and generate_unaccent_rules::stdout.

Referenced by AuxiliaryProcKill(), and ProcKill().

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

Variable Documentation

◆ dummy_spinlock

slock_t dummy_spinlock

Definition at line 63 of file s_lock.c.

Referenced by startup_hacks().

◆ spins_per_delay

int spins_per_delay = DEFAULT_SPINS_PER_DELAY
static