7
7
*
8
8
*
9
9
* IDENTIFICATION
10
- * $Header: /cvsroot/pgsql/src/backend/storage/buffer/Attic/s_lock.c,v 1.7 1998/05/04 23:49:09 scrappy Exp $
10
+ * $Header: /cvsroot/pgsql/src/backend/storage/buffer/Attic/s_lock.c,v 1.8 1998/06/16 07:18:15 momjian Exp $
11
11
*
12
12
*-------------------------------------------------------------------------
13
13
*/
14
14
15
15
#include <stdio.h>
16
+ #include <sys/time.h>
16
17
17
18
#include "config.h"
18
19
#include "c.h"
22
23
/*
23
24
* Each time we busy spin we select the next element of this array as the
24
25
* number of microseconds to wait. This accomplishes pseudo random back-off.
25
- * Values are not critical and are weighted to the low end of the range. They
26
- * were chosen to work even with different select() timer resolutions on
27
- * different platforms.
28
- * note: total time to cycle through all 16 entries might be about .1 second.
26
+ * Values are not critical but 10 milliseconds is a common platform
27
+ * granularity.
28
+ * note: total time to cycle through all 16 entries might be about .07 sec.
29
29
*/
30
- int s_spincycle [S_NSPINCYCLE ] =
31
- {0 , 0 , 0 , 1000 , 5000 , 0 , 10000 , 3000 ,
32
- 0 , 10000 , 0 , 15000 , 9000 , 21000 , 6000 , 30000
30
+ #define S_NSPINCYCLE 20
31
+ #define S_MAX_BUSY 500 * S_NSPINCYCLE
32
+
33
+ int s_spincycle [S_NSPINCYCLE ] =
34
+ { 0 , 0 , 0 , 0 , 10000 , 0 , 0 , 0 , 10000 , 0 ,
35
+ 0 , 10000 , 0 , 0 , 10000 , 0 , 10000 , 0 , 10000 , 10000
33
36
};
34
37
35
38
36
- #if defined(S_LOCK_DEBUG )
37
39
/*
38
- * s_lock(lock) - take a spinlock
39
- * add intrumentation code to this and define S_LOCK_DEBUG
40
- * instead of hacking up the macro in s_lock.h
40
+ * s_lock_stuck(lock) - complain about a stuck spinlock
41
+ */
42
+ static void
43
+ s_lock_stuck (volatile slock_t * lock , const char * file , const int line )
44
+ {
45
+ fprintf (stderr ,
46
+ "\nFATAL: s_lock(%08x) at %s:%d, stuck spinlock. Aborting.\n" ,
47
+ (unsigned int ) lock , file , line );
48
+ fprintf (stdout ,
49
+ "\nFATAL: s_lock(%08x) at %s:%d, stuck spinlock. Aborting.\n" ,
50
+ (unsigned int ) lock , file , line );
51
+ abort ();
52
+ }
53
+
54
+
55
+
56
+ /*
57
+ * s_lock(lock) - take a spinlock with backoff
41
58
*/
42
59
void
43
- s_lock (slock_t * lock , char * file , int line )
60
+ s_lock (volatile slock_t * lock , const char * file , const int line )
44
61
{
45
62
int spins = 0 ;
46
63
@@ -49,114 +66,39 @@ s_lock(slock_t *lock, char *file, int line)
49
66
struct timeval delay ;
50
67
51
68
delay .tv_sec = 0 ;
52
- delay .tv_usec = s_spincycle [spins ++ % S_NSPINCYCLE ];
69
+ delay .tv_usec = s_spincycle [spins % S_NSPINCYCLE ];
53
70
(void ) select (0 , NULL , NULL , NULL , & delay );
54
- if (spins > S_MAX_BUSY )
71
+ if (++ spins > S_MAX_BUSY )
55
72
{
56
- /* It's been well over a minute... */
73
+ /* It's been over a minute... */
57
74
s_lock_stuck (lock , file , line );
58
75
}
59
76
}
60
77
}
61
- #endif /* S_LOCK_DEBUG */
62
-
63
78
64
- /*
65
- * s_lock_stuck(lock) - deal with stuck spinlock
66
- */
67
- void
68
- s_lock_stuck (slock_t * lock , char * file , int line )
69
- {
70
- fprintf (stderr ,
71
- "\nFATAL: s_lock(%08x) at %s:%d, stuck spinlock. Aborting.\n" ,
72
- (unsigned int ) lock , file , line );
73
- fprintf (stdout ,
74
- "\nFATAL: s_lock(%08x) at %s:%d, stuck spinlock. Aborting.\n" ,
75
- (unsigned int ) lock , file , line );
76
- abort ();
77
- }
78
79
79
80
80
81
81
82
/*
82
- * Various TAS implementations moved from s_lock.h to avoid redundant
83
- * definitions of the same routine.
84
- * RESOLVE: move this to tas.c. Alternatively get rid of tas.[cso] and fold
85
- * all that into this file.
83
+ * Various TAS implementations that cannot live in s_lock.h as no inline
84
+ * definition exists (yet).
85
+ * In the future, get rid of tas.[cso] and fold it into this file.
86
86
*/
87
87
88
88
89
- #if defined(linux )
89
+ #if defined(__GNUC__ )
90
90
/*************************************************************************
91
- * All the Linux flavors
91
+ * All the gcc flavors that are not inlined
92
92
*/
93
93
94
94
95
- #if defined(__alpha )
96
- int
97
- tas (slock_t * lock )
98
- {
99
- slock_t _res ;
100
-
101
- __asm__(" ldq $0, %0 \n\
102
- bne $0, already_set \n\
103
- ldq_l $0, %0 \n\
104
- bne $0, already_set \n\
105
- or $31, 1, $0 \n\
106
- stq_c $0, %0 \n\
107
- beq $0, stqc_fail \n\
108
- success: bis $31, $31, %1 \n\
109
- mb \n\
110
- jmp $31, end \n\
111
- stqc_fail: or $31, 1, $0 \n\
112
- already_set: bis $0, $0, %1 \n\
113
- end: nop " : "=m" (* lock ), "=r" (_res ): :"0" );
114
-
115
- return (_res != 0 );
116
- }
117
- #endif /* __alpha */
118
-
119
-
120
-
121
- #if defined(i386 )
122
- int
123
- tas (slock_t * lock )
124
- {
125
- slock_t _res = 1 ;
126
-
127
- __asm__("lock; xchgb %0,%1" : "=q" (_res ), "=m" (* lock ):"0" (0x1 ));
128
- return (_res != 0 );
129
- }
130
- #endif /* i386 */
131
-
132
-
133
-
134
- #if defined(sparc )
135
-
136
- int
137
- tas (slock_t * lock )
138
- {
139
- slock_t _res ;
140
- slock_t * tmplock = lock ;
141
-
142
- __asm__("ldstub [%1], %0" \
143
- : "=&r" (_res ), "=r" (tmplock ) \
144
- : "1" (tmplock ));
145
- return (_res != 0 );
146
- }
147
-
148
- #endif /* sparc */
149
-
150
-
151
95
152
96
#if defined(PPC )
153
-
154
- static int
155
- tas_dummy ( )
97
+ /* Note: need a nice gcc constrained asm version so it can be inlined */
98
+ int
99
+ tas ( volatile slock_t * lock )
156
100
{
157
- __asm__(" \n\
158
- tas: \n\
159
- lwarx 5,0,3 \n\
101
+ __asm__("lwarx 5,0,3 \n\
160
102
cmpwi 5,0 \n\
161
103
bne fail \n\
162
104
addi 5,5,1 \n\
@@ -169,21 +111,20 @@ success: \n\
169
111
blr \n\
170
112
" );
171
113
}
172
-
173
114
#endif /* PPC */
174
115
175
116
176
117
177
- #else /* defined(linux ) */
118
+ #else /* defined(__GNUC__ ) */
178
119
/***************************************************************************
179
- * All Non-Linux
120
+ * All non gcc
180
121
*/
181
122
182
123
183
124
184
125
#if defined(sun3 )
185
126
static void
186
- tas_dummy () /* really means: extern int tas(slock_t *lock); */
127
+ tas_dummy () /* really means: extern int tas(slock_t *lock); */
187
128
{
188
129
asm("LLA0:" );
189
130
asm(" .data" );
@@ -208,26 +149,18 @@ tas_dummy() /* really means: extern int tas(slock_t *lock); */
208
149
209
150
#if defined(NEED_SPARC_TAS_ASM )
210
151
/*
211
- * bsd and bsdi sparc machines
152
+ * sparc machines not using gcc
212
153
*/
213
-
214
- /* if we're using -ansi w/ gcc, use __asm__ instead of asm */
215
- #if defined(__STRICT_ANSI__ )
216
- #define asm (x ) __asm__(x)
217
- #endif /* __STRICT_ANSI__ */
218
-
219
154
static void
220
- tas_dummy () /* really means: extern int tas(slock_t *lock); */
155
+ tas_dummy () /* really means: extern int tas(slock_t *lock); */
221
156
{
222
157
asm(".seg \"data\"" );
223
158
asm(".seg \"text\"" );
224
159
asm("_tas:" );
225
-
226
160
/*
227
161
* Sparc atomic test and set (sparc calls it "atomic load-store")
228
162
*/
229
163
asm("ldstub [%r8], %r8" );
230
-
231
164
asm("retl" );
232
165
asm("nop" );
233
166
}
@@ -237,76 +170,25 @@ tas_dummy() /* really means: extern int tas(slock_t *lock); */
237
170
238
171
239
172
240
- #if defined(NEED_VAX_TAS_ASM )
241
- /*
242
- * VAXen -- even multiprocessor ones
243
- * (thanks to Tom Ivar Helbekkmo)
244
- */
245
- typedef unsigned char slock_t ;
246
-
247
- int
248
- tas (slock_t * lock )
249
- {
250
- register ret ;
251
-
252
- asm(" movl $1, r0
253
- bbssi $0 , (%1 ), 1f
254
- clrl r0
255
- 1 : movl r0 , %0 "
256
- : "=r" (ret ) /* return value, in register */
257
- : "r" (lock ) /* argument, 'lock pointer', in register */
258
- : "r0" ); /* inline code uses this register */
259
-
260
- return ret ;
261
- }
262
-
263
- #endif /* NEED_VAX_TAS_ASM */
264
-
265
-
266
-
267
173
#if defined(NEED_I386_TAS_ASM )
268
- /*
269
- * i386 based things
270
- */
271
-
272
- #if defined(USE_UNIVEL_CC )
273
- asm int
274
- tas (slock_t * s_lock )
275
- {
276
- %lab locked ;
277
- /* Upon entry, %eax will contain the pointer to the lock byte */
278
- pushl % ebx
279
- xchgl % eax , %ebx
280
- xor % eax , %eax
281
- movb $255 , %al
282
- lock
283
- xchgb % al , (%ebx )
284
- popl % ebx
285
- }
286
-
287
-
288
- #else /* USE_UNIVEL_CC */
289
-
290
- int
291
- tas (slock_t * lock )
292
- {
293
- slock_t _res = 1 ;
174
+ /* non gcc i386 based things */
175
+ #endif /* NEED_I386_TAS_ASM */
294
176
295
- __asm__("lock; xchgb %0,%1" : "=q" (_res ), "=m" (* lock ):"0" (0x1 ));
296
- return (_res != 0 );
297
- }
298
177
299
- #endif /* USE_UNIVEL_CC */
300
178
301
- #endif /* NEED_I386_TAS_ASM */
179
+ #endif /* not __GNUC__ */
302
180
303
181
304
- #endif /* linux */
305
182
306
183
184
+ /*****************************************************************************/
307
185
#if defined(S_LOCK_TEST )
308
186
309
- slock_t test_lock ;
187
+ /*
188
+ * test program for verifying a port.
189
+ */
190
+
191
+ volatile slock_t test_lock ;
310
192
311
193
void
312
194
main ()
@@ -330,11 +212,12 @@ main()
330
212
printf ("S_LOCK_TEST: this will hang for a few minutes and then abort\n" );
331
213
printf (" with a 'stuck spinlock' message if S_LOCK()\n" );
332
214
printf (" and TAS() are working.\n" );
333
- S_LOCK (& test_lock );
215
+ s_lock (& test_lock , __FILE__ , __LINE__ );
334
216
335
217
printf ("S_LOCK_TEST: failed, lock not locked~\n" );
336
218
exit (3 );
337
219
338
220
}
339
221
340
222
#endif /* S_LOCK_TEST */
223
+
0 commit comments