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.31 2005/10/0720:11:03 tgl Exp $
18+ * $PostgreSQL: pgsql/src/backend/storage/lmgr/lwlock.c,v 1.32 2005/10/0721:42:38 tgl Exp $
1919 *
2020 *-------------------------------------------------------------------------
2121 */
2727#include "storage/spin.h"
2828
2929
30+ /* We use the ShmemLock spinlock to protect LWLockAssign */
31+ extern slock_t * ShmemLock ;
32+
33+
3034typedef struct LWLock
3135{
3236slock_t mutex ;/* Protects LWLock and queue of PGPROCs */
@@ -65,9 +69,6 @@ typedef union LWLockPadded
6569 */
6670NON_EXEC_STATIC LWLockPadded * LWLockArray = NULL ;
6771
68- /* shared counter for dynamic allocation of LWLockIds */
69- static int * LWLockCounter ;
70-
7172
7273/*
7374 * We use this structure to keep track of locked LWLocks for release
@@ -159,7 +160,7 @@ LWLockShmemSize(void)
159160/* Space for the LWLock array. */
160161size = mul_size (numLocks ,sizeof (LWLockPadded ));
161162
162- /* Space forshared allocation counter, plus room for alignment. */
163+ /* Space fordynamic allocation counter, plus room for alignment. */
163164size = add_size (size ,2 * sizeof (int )+ LWLOCK_PADDED_SIZE );
164165
165166return size ;
@@ -175,12 +176,16 @@ CreateLWLocks(void)
175176int numLocks = NumLWLocks ();
176177Size spaceLocks = LWLockShmemSize ();
177178LWLockPadded * lock ;
179+ int * LWLockCounter ;
178180char * ptr ;
179181int id ;
180182
181183/* Allocate space */
182184ptr = (char * )ShmemAlloc (spaceLocks );
183185
186+ /* Leave room for dynamic allocation counter */
187+ ptr += 2 * sizeof (int );
188+
184189/* Ensure desired alignment of LWLock array */
185190ptr += LWLOCK_PADDED_SIZE - ((unsigned long )ptr ) %LWLOCK_PADDED_SIZE ;
186191
@@ -200,9 +205,10 @@ CreateLWLocks(void)
200205}
201206
202207/*
203- * Initialize the dynamic-allocation counter at the end of the array
208+ * Initialize the dynamic-allocation counter, which is stored just before
209+ * the first LWLock.
204210 */
205- LWLockCounter = (int * )lock ;
211+ LWLockCounter = (int * )(( char * ) LWLockArray - 2 * sizeof ( int )) ;
206212LWLockCounter [0 ]= (int )NumFixedLWLocks ;
207213LWLockCounter [1 ]= numLocks ;
208214}
@@ -211,16 +217,27 @@ CreateLWLocks(void)
211217/*
212218 * LWLockAssign - assign a dynamically-allocated LWLock number
213219 *
214- * NB: we do not currently try to interlock this. Could perhaps use
215- * ShmemLock spinlock if there were any need to assign LWLockIds after
216- * shmem setup.
220+ * We interlock this using the same spinlock that is used to protect
221+ * ShmemAlloc(). Interlocking is not really necessary during postmaster
222+ * startup, but it is needed if any user-defined code tries to allocate
223+ * LWLocks after startup.
217224 */
218225LWLockId
219226LWLockAssign (void )
220227{
228+ LWLockId result ;
229+ int * LWLockCounter ;
230+
231+ LWLockCounter = (int * ) ((char * )LWLockArray - 2 * sizeof (int ));
232+ SpinLockAcquire (ShmemLock );
221233if (LWLockCounter [0 ] >=LWLockCounter [1 ])
222- elog (FATAL ,"no more LWLockIds available" );
223- return (LWLockId ) (LWLockCounter [0 ]++ );
234+ {
235+ SpinLockRelease (ShmemLock );
236+ elog (ERROR ,"no more LWLockIds available" );
237+ }
238+ result = (LWLockId ) (LWLockCounter [0 ]++ );
239+ SpinLockRelease (ShmemLock );
240+ return result ;
224241}
225242
226243