PostgreSQL Source Code: src/backend/storage/lmgr/s_lock.c Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
49
52
56
57#define MIN_SPINS_PER_DELAY 10
58#define MAX_SPINS_PER_DELAY 1000
59#define NUM_DELAYS 1000
60#define MIN_DELAY_USEC 1000L
61#define MAX_DELAY_USEC 1000000L
62
63#ifdef S_LOCK_TEST
64
65
66
67
70#endif
71
73
74
75
76
77
78static void
79s_lock_stuck(const char *file, int line, const char *func)
80{
81 if (!func)
82 func = "(unknown)";
83#if defined(S_LOCK_TEST)
85 "\nStuck spinlock detected at %s, %s:%d.\n",
86 func, file, line);
87 exit(1);
88#else
89 elog(PANIC, "stuck spinlock detected at %s, %s:%d",
90 func, file, line);
91#endif
92}
93
94
95
96
97int
98s_lock(volatile slock_t *lock, const char *file, int line, const char *func)
99{
101
103
105 {
107 }
108
110
111 return delayStatus.delays;
112}
113
114#ifdef USE_DEFAULT_S_UNLOCK
115void
117{
118 *lock = 0;
119}
120#endif
121
122
123
124
125void
127{
128
130
131
133 {
136
137 if (status->cur_delay == 0)
139
140
141
142
143
144
145
146
147
151
152#if defined(S_LOCK_TEST)
155#endif
156
157
160
163
164 status->spins = 0;
165 }
166}
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185void
187{
189 {
190
193 }
194 else
195 {
198 }
199}
200
201
202
203
204
205
206void
208{
210}
211
212
213
214
215
216
217int
219{
220
221
222
223
224
225
226
227
228
229
230 return (shared_spins_per_delay * 15 + spins_per_delay) / 16;
231}
232
233
234
235#if defined(S_LOCK_TEST)
236
237
238
239
240
241struct test_lock_struct
242{
243 char pad1;
244 slock_t lock;
245 char pad2;
246};
247
248volatile struct test_lock_struct test_lock;
249
250int
252{
254
255 test_lock.pad1 = test_lock.pad2 = 0x44;
256
258
259 if (test_lock.pad1 != 0x44 || test_lock.pad2 != 0x44)
260 {
261 printf("S_LOCK_TEST: failed, declared datatype is wrong size\n");
262 return 1;
263 }
264
266 {
267 printf("S_LOCK_TEST: failed, lock not initialized\n");
268 return 1;
269 }
270
271 S_LOCK(&test_lock.lock);
272
273 if (test_lock.pad1 != 0x44 || test_lock.pad2 != 0x44)
274 {
275 printf("S_LOCK_TEST: failed, declared datatype is wrong size\n");
276 return 1;
277 }
278
280 {
281 printf("S_LOCK_TEST: failed, lock not locked\n");
282 return 1;
283 }
284
286
287 if (test_lock.pad1 != 0x44 || test_lock.pad2 != 0x44)
288 {
289 printf("S_LOCK_TEST: failed, declared datatype is wrong size\n");
290 return 1;
291 }
292
294 {
295 printf("S_LOCK_TEST: failed, lock not unlocked\n");
296 return 1;
297 }
298
299 S_LOCK(&test_lock.lock);
300
301 if (test_lock.pad1 != 0x44 || test_lock.pad2 != 0x44)
302 {
303 printf("S_LOCK_TEST: failed, declared datatype is wrong size\n");
304 return 1;
305 }
306
308 {
309 printf("S_LOCK_TEST: failed, lock not re-locked\n");
310 return 1;
311 }
312
313 printf("S_LOCK_TEST: this will print %d stars and then\n", NUM_DELAYS);
314 printf(" exit with a 'stuck spinlock' message\n");
315 printf(" if S_LOCK() and TAS() are working.\n");
317
318 s_lock(&test_lock.lock, __FILE__, __LINE__, __func__);
319
320 printf("S_LOCK_TEST: failed, lock not locked\n");
321 return 1;
322}
323
324#endif
#define fprintf(file, fmt, msg)
int main(int argc, char **argv)
double pg_prng_double(pg_prng_state *state)
void pg_prng_seed(pg_prng_state *state, uint64 seed)
pg_prng_state pg_global_prng_state
void set_spins_per_delay(int shared_spins_per_delay)
void perform_spin_delay(SpinDelayStatus *status)
void finish_spin_delay(SpinDelayStatus *status)
int s_lock(volatile slock_t *lock, const char *file, int line, const char *func)
#define MAX_SPINS_PER_DELAY
void s_unlock(volatile slock_t *lock)
#define MIN_SPINS_PER_DELAY
int update_spins_per_delay(int shared_spins_per_delay)
static int spins_per_delay
static void s_lock_stuck(const char *file, int line, const char *func)
#define DEFAULT_SPINS_PER_DELAY
#define S_LOCK_FREE(lock)
static void init_spin_delay(SpinDelayStatus *status, const char *file, int line, const char *func)
#define S_INIT_LOCK(lock)
void pg_usleep(long microsec)
static uint32 local_my_wait_event_info
uint32 * my_wait_event_info
static void pgstat_report_wait_start(uint32 wait_event_info)
static void pgstat_report_wait_end(void)