Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 0d8e7f6

Browse files
committed
Here is the long awaited optimized version of the S_LOCK patch.
This incorporates all the precedeing patches and emailed suggestions and the results of the performance testing I posted last week. I would like to get this tested on as many platforms as possible so I can verify it went in correctly (as opposed to the horrorshow last time I sent in a patch). Once this is confirmed, I will make a tarball of files that can be dropped into a 6.3.2 source tree as a few people have asked for this in 6.3.2 as well. David Gould
1 parent 7784312 commit 0d8e7f6

File tree

3 files changed

+187
-244
lines changed

3 files changed

+187
-244
lines changed

src/backend/storage/buffer/Makefile

+2-2
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
# Makefile for storage/buffer
55
#
66
# IDENTIFICATION
7-
# $Header: /cvsroot/pgsql/src/backend/storage/buffer/Makefile,v 1.10 1998/05/04 16:58:37 scrappy Exp $
7+
# $Header: /cvsroot/pgsql/src/backend/storage/buffer/Makefile,v 1.11 1998/06/16 07:18:15 momjian Exp $
88
#
99
#-------------------------------------------------------------------------
1010

@@ -27,7 +27,7 @@ clean:
2727
rm -f SUBSYS.o $(OBJS) s_lock_test
2828

2929
s_lock_test: s_lock.c
30-
$(CC) $(CFLAGS) -DS_LOCK_TEST=1 -g s_lock.c -o s_lock_test
30+
$(CC) $(CFLAGS) -DS_LOCK_TEST=1 s_lock.c -o s_lock_test
3131
./s_lock_test
3232

3333
ifeq (depend,$(wildcard depend))

src/backend/storage/buffer/s_lock.c

+58-175
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,13 @@
77
*
88
*
99
* 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 $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
1414

1515
#include <stdio.h>
16+
#include <sys/time.h>
1617

1718
#include "config.h"
1819
#include "c.h"
@@ -22,25 +23,41 @@
2223
/*
2324
* Each time we busy spin we select the next element of this array as the
2425
* 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.
2929
*/
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
3336
};
3437

3538

36-
#if defined(S_LOCK_DEBUG)
3739
/*
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
4158
*/
4259
void
43-
s_lock(slock_t *lock, char *file, int line)
60+
s_lock(volatile slock_t *lock, const char *file, const int line)
4461
{
4562
int spins = 0;
4663

@@ -49,114 +66,39 @@ s_lock(slock_t *lock, char *file, int line)
4966
struct timeval delay;
5067

5168
delay.tv_sec = 0;
52-
delay.tv_usec = s_spincycle[spins++ % S_NSPINCYCLE];
69+
delay.tv_usec = s_spincycle[spins % S_NSPINCYCLE];
5370
(void) select(0, NULL, NULL, NULL, &delay);
54-
if (spins > S_MAX_BUSY)
71+
if (++spins > S_MAX_BUSY)
5572
{
56-
/* It's been well over a minute... */
73+
/* It's been over a minute... */
5774
s_lock_stuck(lock, file, line);
5875
}
5976
}
6077
}
61-
#endif /* S_LOCK_DEBUG */
62-
6378

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-
}
7879

7980

8081

8182
/*
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.
8686
*/
8787

8888

89-
#if defined(linux)
89+
#if defined(__GNUC__)
9090
/*************************************************************************
91-
* All the Linux flavors
91+
* All the gcc flavors that are not inlined
9292
*/
9393

9494

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-
15195

15296
#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)
156100
{
157-
__asm__(" \n\
158-
tas: \n\
159-
lwarx 5,0,3 \n\
101+
__asm__("lwarx 5,0,3 \n\
160102
cmpwi 5,0 \n\
161103
bne fail \n\
162104
addi 5,5,1 \n\
@@ -169,21 +111,20 @@ success: \n\
169111
blr \n\
170112
");
171113
}
172-
173114
#endif /* PPC */
174115

175116

176117

177-
#else /* defined(linux) */
118+
#else /* defined(__GNUC__) */
178119
/***************************************************************************
179-
* All Non-Linux
120+
* All non gcc
180121
*/
181122

182123

183124

184125
#if defined(sun3)
185126
static void
186-
tas_dummy() /* really means: extern int tas(slock_t *lock); */
127+
tas_dummy() /* really means: extern int tas(slock_t *lock); */
187128
{
188129
asm("LLA0:");
189130
asm(" .data");
@@ -208,26 +149,18 @@ tas_dummy() /* really means: extern int tas(slock_t *lock); */
208149

209150
#if defined(NEED_SPARC_TAS_ASM)
210151
/*
211-
* bsd and bsdi sparc machines
152+
* sparc machines not using gcc
212153
*/
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-
219154
static void
220-
tas_dummy() /* really means: extern int tas(slock_t *lock); */
155+
tas_dummy() /* really means: extern int tas(slock_t *lock); */
221156
{
222157
asm(".seg \"data\"");
223158
asm(".seg \"text\"");
224159
asm("_tas:");
225-
226160
/*
227161
* Sparc atomic test and set (sparc calls it "atomic load-store")
228162
*/
229163
asm("ldstub [%r8], %r8");
230-
231164
asm("retl");
232165
asm("nop");
233166
}
@@ -237,76 +170,25 @@ tas_dummy() /* really means: extern int tas(slock_t *lock); */
237170

238171

239172

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-
267173
#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 */
294176

295-
__asm__("lock; xchgb %0,%1": "=q"(_res), "=m"(*lock):"0"(0x1));
296-
return (_res != 0);
297-
}
298177

299-
#endif /* USE_UNIVEL_CC */
300178

301-
#endif /* NEED_I386_TAS_ASM */
179+
#endif /* not __GNUC__ */
302180

303181

304-
#endif /* linux */
305182

306183

184+
/*****************************************************************************/
307185
#if defined(S_LOCK_TEST)
308186

309-
slock_t test_lock;
187+
/*
188+
* test program for verifying a port.
189+
*/
190+
191+
volatile slock_t test_lock;
310192

311193
void
312194
main()
@@ -330,11 +212,12 @@ main()
330212
printf("S_LOCK_TEST: this will hang for a few minutes and then abort\n");
331213
printf(" with a 'stuck spinlock' message if S_LOCK()\n");
332214
printf(" and TAS() are working.\n");
333-
S_LOCK(&test_lock);
215+
s_lock(&test_lock, __FILE__, __LINE__);
334216

335217
printf("S_LOCK_TEST: failed, lock not locked~\n");
336218
exit(3);
337219

338220
}
339221

340222
#endif /* S_LOCK_TEST */
223+

0 commit comments

Comments
 (0)