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.31 2005/10/07 20:11:03 tgl Exp $
18
+ * $PostgreSQL: pgsql/src/backend/storage/lmgr/lwlock.c,v 1.32 2005/10/07 21:42:38 tgl Exp $
19
19
*
20
20
*-------------------------------------------------------------------------
21
21
*/
27
27
#include "storage/spin.h"
28
28
29
29
30
+ /* We use the ShmemLock spinlock to protect LWLockAssign */
31
+ extern slock_t * ShmemLock ;
32
+
33
+
30
34
typedef struct LWLock
31
35
{
32
36
slock_t mutex ; /* Protects LWLock and queue of PGPROCs */
@@ -65,9 +69,6 @@ typedef union LWLockPadded
65
69
*/
66
70
NON_EXEC_STATIC LWLockPadded * LWLockArray = NULL ;
67
71
68
- /* shared counter for dynamic allocation of LWLockIds */
69
- static int * LWLockCounter ;
70
-
71
72
72
73
/*
73
74
* We use this structure to keep track of locked LWLocks for release
@@ -159,7 +160,7 @@ LWLockShmemSize(void)
159
160
/* Space for the LWLock array. */
160
161
size = mul_size (numLocks , sizeof (LWLockPadded ));
161
162
162
- /* Space for shared allocation counter, plus room for alignment. */
163
+ /* Space for dynamic allocation counter, plus room for alignment. */
163
164
size = add_size (size , 2 * sizeof (int ) + LWLOCK_PADDED_SIZE );
164
165
165
166
return size ;
@@ -175,12 +176,16 @@ CreateLWLocks(void)
175
176
int numLocks = NumLWLocks ();
176
177
Size spaceLocks = LWLockShmemSize ();
177
178
LWLockPadded * lock ;
179
+ int * LWLockCounter ;
178
180
char * ptr ;
179
181
int id ;
180
182
181
183
/* Allocate space */
182
184
ptr = (char * ) ShmemAlloc (spaceLocks );
183
185
186
+ /* Leave room for dynamic allocation counter */
187
+ ptr += 2 * sizeof (int );
188
+
184
189
/* Ensure desired alignment of LWLock array */
185
190
ptr += LWLOCK_PADDED_SIZE - ((unsigned long ) ptr ) % LWLOCK_PADDED_SIZE ;
186
191
@@ -200,9 +205,10 @@ CreateLWLocks(void)
200
205
}
201
206
202
207
/*
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.
204
210
*/
205
- LWLockCounter = (int * ) lock ;
211
+ LWLockCounter = (int * ) (( char * ) LWLockArray - 2 * sizeof ( int )) ;
206
212
LWLockCounter [0 ] = (int ) NumFixedLWLocks ;
207
213
LWLockCounter [1 ] = numLocks ;
208
214
}
@@ -211,16 +217,27 @@ CreateLWLocks(void)
211
217
/*
212
218
* LWLockAssign - assign a dynamically-allocated LWLock number
213
219
*
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.
217
224
*/
218
225
LWLockId
219
226
LWLockAssign (void )
220
227
{
228
+ LWLockId result ;
229
+ int * LWLockCounter ;
230
+
231
+ LWLockCounter = (int * ) ((char * ) LWLockArray - 2 * sizeof (int ));
232
+ SpinLockAcquire (ShmemLock );
221
233
if (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 ;
224
241
}
225
242
226
243
0 commit comments