1515 * Portions Copyright (c) 1994, Regents of the University of California
1616 *
1717 * 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 $
1919 *
2020 *-------------------------------------------------------------------------
2121 */
@@ -38,12 +38,32 @@ typedef struct LWLock
3838/* tail is undefined when head is NULL */
3939}LWLock ;
4040
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+
4161/*
4262 * 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) .
4565 */
46- NON_EXEC_STATIC LWLock * LWLockArray = NULL ;
66+ NON_EXEC_STATIC LWLockPadded * LWLockArray = NULL ;
4767
4868/* shared counter for dynamic allocation of LWLockIds */
4969static int * LWLockCounter ;
@@ -135,10 +155,11 @@ LWLockShmemSize(void)
135155Size size ;
136156int numLocks = NumLWLocks ();
137157
138- /*Allocate the LWLocks plus space forshared allocation counter . */
139- size = mul_size (numLocks ,sizeof (LWLock ));
158+ /*Space forthe LWLock array . */
159+ size = mul_size (numLocks ,sizeof (LWLockPadded ));
140160
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 );
142163
143164return size ;
144165}
@@ -152,23 +173,29 @@ CreateLWLocks(void)
152173{
153174int numLocks = NumLWLocks ();
154175Size spaceLocks = LWLockShmemSize ();
155- LWLock * lock ;
176+ LWLockPadded * lock ;
177+ char * ptr ;
156178int id ;
157179
158180/* 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 ;
160187
161188/*
162189 * Initialize all LWLocks to "unlocked" state
163190 */
164191for (id = 0 ,lock = LWLockArray ;id < numLocks ;id ++ ,lock ++ )
165192{
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 ;
172199}
173200
174201/*
@@ -206,7 +233,7 @@ LWLockAssign(void)
206233void
207234LWLockAcquire (LWLockId lockid ,LWLockMode mode )
208235{
209- volatile LWLock * lock = LWLockArray + lockid ;
236+ volatile LWLock * lock = & ( LWLockArray [ lockid ]. lock ) ;
210237PGPROC * proc = MyProc ;
211238bool retry = false;
212239int extraWaits = 0 ;
@@ -358,7 +385,7 @@ LWLockAcquire(LWLockId lockid, LWLockMode mode)
358385bool
359386LWLockConditionalAcquire (LWLockId lockid ,LWLockMode mode )
360387{
361- volatile LWLock * lock = LWLockArray + lockid ;
388+ volatile LWLock * lock = & ( LWLockArray [ lockid ]. lock ) ;
362389bool mustwait ;
363390
364391PRINT_LWDEBUG ("LWLockConditionalAcquire" ,lockid ,lock );
@@ -423,7 +450,7 @@ LWLockConditionalAcquire(LWLockId lockid, LWLockMode mode)
423450void
424451LWLockRelease (LWLockId lockid )
425452{
426- volatile LWLock * lock = LWLockArray + lockid ;
453+ volatile LWLock * lock = & ( LWLockArray [ lockid ]. lock ) ;
427454PGPROC * head ;
428455PGPROC * proc ;
429456int i ;