15
15
* Portions Copyright (c) 1994, Regents of the University of California
16
16
*
17
17
* IDENTIFICATION
18
- * $PostgreSQL: pgsql/src/backend/storage/lmgr/lwlock.c,v 1.29 2005/08/20 23:26:24 tgl Exp $
18
+ * $PostgreSQL: pgsql/src/backend/storage/lmgr/lwlock.c,v 1.30 2005/09/16 00:30:05 tgl Exp $
19
19
*
20
20
*-------------------------------------------------------------------------
21
21
*/
@@ -38,12 +38,32 @@ typedef struct LWLock
38
38
/* tail is undefined when head is NULL */
39
39
} LWLock ;
40
40
41
+ /*
42
+ * All the LWLock structs are allocated as an array in shared memory.
43
+ * (LWLockIds are indexes into the array.) We force the array stride to
44
+ * be a power of 2, which saves a few cycles in indexing, but more
45
+ * importantly also ensures that individual LWLocks don't cross cache line
46
+ * boundaries. This reduces cache contention problems, especially on AMD
47
+ * Opterons. (Of course, we have to also ensure that the array start
48
+ * address is suitably aligned.)
49
+ *
50
+ * LWLock is between 16 and 32 bytes on all known platforms, so these two
51
+ * cases are sufficient.
52
+ */
53
+ #define LWLOCK_PADDED_SIZE (sizeof(LWLock) <= 16 ? 16 : 32)
54
+
55
+ typedef union LWLockPadded
56
+ {
57
+ LWLock lock ;
58
+ char pad [LWLOCK_PADDED_SIZE ];
59
+ } LWLockPadded ;
60
+
41
61
/*
42
62
* This points to the array of LWLocks in shared memory. Backends inherit
43
- * the pointer by fork from the postmaster. LWLockIds are indexes into
44
- * the array .
63
+ * the pointer by fork from the postmaster (except in the EXEC_BACKEND case,
64
+ * where we have special measures to pass it down) .
45
65
*/
46
- NON_EXEC_STATIC LWLock * LWLockArray = NULL ;
66
+ NON_EXEC_STATIC LWLockPadded * LWLockArray = NULL ;
47
67
48
68
/* shared counter for dynamic allocation of LWLockIds */
49
69
static int * LWLockCounter ;
@@ -135,10 +155,11 @@ LWLockShmemSize(void)
135
155
Size size ;
136
156
int numLocks = NumLWLocks ();
137
157
138
- /* Allocate the LWLocks plus space for shared allocation counter . */
139
- size = mul_size (numLocks , sizeof (LWLock ));
158
+ /* Space for the LWLock array . */
159
+ size = mul_size (numLocks , sizeof (LWLockPadded ));
140
160
141
- size = add_size (size , 2 * sizeof (int ));
161
+ /* Space for shared allocation counter, plus room for alignment. */
162
+ size = add_size (size , 2 * sizeof (int ) + LWLOCK_PADDED_SIZE );
142
163
143
164
return size ;
144
165
}
@@ -152,23 +173,29 @@ CreateLWLocks(void)
152
173
{
153
174
int numLocks = NumLWLocks ();
154
175
Size spaceLocks = LWLockShmemSize ();
155
- LWLock * lock ;
176
+ LWLockPadded * lock ;
177
+ char * ptr ;
156
178
int id ;
157
179
158
180
/* Allocate space */
159
- LWLockArray = (LWLock * ) ShmemAlloc (spaceLocks );
181
+ ptr = (char * ) ShmemAlloc (spaceLocks );
182
+
183
+ /* Ensure desired alignment of LWLock array */
184
+ ptr += LWLOCK_PADDED_SIZE - ((unsigned long ) ptr ) % LWLOCK_PADDED_SIZE ;
185
+
186
+ LWLockArray = (LWLockPadded * ) ptr ;
160
187
161
188
/*
162
189
* Initialize all LWLocks to "unlocked" state
163
190
*/
164
191
for (id = 0 , lock = LWLockArray ; id < numLocks ; id ++ , lock ++ )
165
192
{
166
- SpinLockInit (& lock -> mutex );
167
- lock -> releaseOK = true;
168
- lock -> exclusive = 0 ;
169
- lock -> shared = 0 ;
170
- lock -> head = NULL ;
171
- lock -> tail = NULL ;
193
+ SpinLockInit (& lock -> lock . mutex );
194
+ lock -> lock . releaseOK = true;
195
+ lock -> lock . exclusive = 0 ;
196
+ lock -> lock . shared = 0 ;
197
+ lock -> lock . head = NULL ;
198
+ lock -> lock . tail = NULL ;
172
199
}
173
200
174
201
/*
@@ -206,7 +233,7 @@ LWLockAssign(void)
206
233
void
207
234
LWLockAcquire (LWLockId lockid , LWLockMode mode )
208
235
{
209
- volatile LWLock * lock = LWLockArray + lockid ;
236
+ volatile LWLock * lock = & ( LWLockArray [ lockid ]. lock ) ;
210
237
PGPROC * proc = MyProc ;
211
238
bool retry = false;
212
239
int extraWaits = 0 ;
@@ -358,7 +385,7 @@ LWLockAcquire(LWLockId lockid, LWLockMode mode)
358
385
bool
359
386
LWLockConditionalAcquire (LWLockId lockid , LWLockMode mode )
360
387
{
361
- volatile LWLock * lock = LWLockArray + lockid ;
388
+ volatile LWLock * lock = & ( LWLockArray [ lockid ]. lock ) ;
362
389
bool mustwait ;
363
390
364
391
PRINT_LWDEBUG ("LWLockConditionalAcquire" , lockid , lock );
@@ -423,7 +450,7 @@ LWLockConditionalAcquire(LWLockId lockid, LWLockMode mode)
423
450
void
424
451
LWLockRelease (LWLockId lockid )
425
452
{
426
- volatile LWLock * lock = LWLockArray + lockid ;
453
+ volatile LWLock * lock = & ( LWLockArray [ lockid ]. lock ) ;
427
454
PGPROC * head ;
428
455
PGPROC * proc ;
429
456
int i ;
0 commit comments