@@ -144,8 +144,20 @@ typedef struct LWLockHandle
144144static int num_held_lwlocks = 0 ;
145145static LWLockHandle held_lwlocks [MAX_SIMUL_LWLOCKS ];
146146
147- static int lock_addin_request = 0 ;
148- static bool lock_addin_request_allowed = true;
147+ /* struct representing the LWLock tranche request for named tranche */
148+ typedef struct NamedLWLockTrancheRequest
149+ {
150+ char tranche_name [NAMEDATALEN ];
151+ int num_lwlocks ;
152+ } NamedLWLockTrancheRequest ;
153+
154+ NamedLWLockTrancheRequest * NamedLWLockTrancheRequestArray = NULL ;
155+ static int NamedLWLockTrancheRequestsAllocated = 0 ;
156+ int NamedLWLockTrancheRequests = 0 ;
157+
158+ NamedLWLockTranche * NamedLWLockTrancheArray = NULL ;
159+
160+ static bool lock_named_request_allowed = true;
149161
150162#ifdef LWLOCK_STATS
151163typedef struct lwlock_stats_key
@@ -335,6 +347,22 @@ get_lwlock_stats_entry(LWLock *lock)
335347#endif /* LWLOCK_STATS */
336348
337349
350+ /*
351+ * Compute number of LWLocks required by named tranches. These will be
352+ * allocated in the main array.
353+ */
354+ static int
355+ NumLWLocksByNamedTranches (void )
356+ {
357+ int numLocks = 0 ;
358+ int i ;
359+
360+ for (i = 0 ; i < NamedLWLockTrancheRequests ; i ++ )
361+ numLocks += NamedLWLockTrancheRequestArray [i ].num_lwlocks ;
362+
363+ return numLocks ;
364+ }
365+
338366/*
339367 * Compute number of LWLocks to allocate in the main array.
340368 */
@@ -353,64 +381,49 @@ NumLWLocks(void)
353381 /* Predefined LWLocks */
354382 numLocks = NUM_FIXED_LWLOCKS ;
355383
356- /*
357- * Add any requested by loadable modules; for backwards-compatibility
358- * reasons, allocate at least NUM_USER_DEFINED_LWLOCKS of them even if
359- * there are no explicit requests.
360- */
361- lock_addin_request_allowed = false;
362- numLocks += Max (lock_addin_request , NUM_USER_DEFINED_LWLOCKS );
384+ /* Disallow named LWLocks' requests after startup */
385+ lock_named_request_allowed = false;
363386
364387 return numLocks ;
365388}
366389
367-
368- /*
369- * RequestAddinLWLocks
370- * Request that extra LWLocks be allocated for use by
371- * a loadable module.
372- *
373- * This is only useful if called from the _PG_init hook of a library that
374- * is loaded into the postmaster via shared_preload_libraries. Once
375- * shared memory has been allocated, calls will be ignored. (We could
376- * raise an error, but it seems better to make it a no-op, so that
377- * libraries containing such calls can be reloaded if needed.)
378- */
379- void
380- RequestAddinLWLocks (int n )
381- {
382- if (IsUnderPostmaster || !lock_addin_request_allowed )
383- return ; /* too late */
384- lock_addin_request += n ;
385- }
386-
387-
388390/*
389- * Compute shmem space needed for LWLocks.
391+ * Compute shmem space needed for LWLocks and named tranches .
390392 */
391393Size
392394LWLockShmemSize (void )
393395{
394396 Size size ;
397+ int i ;
395398 int numLocks = NumLWLocks ();
396399
400+ numLocks += NumLWLocksByNamedTranches ();
401+
397402 /* Space for the LWLock array. */
398403 size = mul_size (numLocks , sizeof (LWLockPadded ));
399404
400405 /* Space for dynamic allocation counter, plus room for alignment. */
401406 size = add_size (size , 3 * sizeof (int ) + LWLOCK_PADDED_SIZE );
402407
408+ /* space for named tranches. */
409+ size = add_size (size , mul_size (NamedLWLockTrancheRequests , sizeof (NamedLWLockTranche )));
410+
411+ /* space for name of each tranche. */
412+ for (i = 0 ; i < NamedLWLockTrancheRequests ; i ++ )
413+ size = add_size (size , strlen (NamedLWLockTrancheRequestArray [i ].tranche_name ) + 1 );
414+
403415 return size ;
404416}
405417
406-
407418/*
408- * Allocate shmem space for the main LWLock array and initialize it. We also
409- * register the main tranch here.
419+ * Allocate shmem space for the main LWLock array and named tranches and
420+ * initialize it. We also register the main and named tranche here.
410421 */
411422void
412423CreateLWLocks (void )
413424{
425+ int i ;
426+
414427 StaticAssertExpr (LW_VAL_EXCLUSIVE > (uint32 ) MAX_BACKENDS ,
415428 "MAX_BACKENDS too big for lwlock.c" );
416429
@@ -421,11 +434,13 @@ CreateLWLocks(void)
421434 if (!IsUnderPostmaster )
422435 {
423436 int numLocks = NumLWLocks ();
437+ int numNamedLocks = NumLWLocksByNamedTranches ();
424438 Size spaceLocks = LWLockShmemSize ();
425439 LWLockPadded * lock ;
426440 int * LWLockCounter ;
427441 char * ptr ;
428442 int id ;
443+ int j ;
429444
430445 /* Allocate space */
431446 ptr = (char * ) ShmemAlloc (spaceLocks );
@@ -438,7 +453,7 @@ CreateLWLocks(void)
438453
439454 MainLWLockArray = (LWLockPadded * ) ptr ;
440455
441- /* Initialize all LWLocks in main array */
456+ /* Initialize all fixed LWLocks in main array */
442457 for (id = 0 , lock = MainLWLockArray ; id < numLocks ; id ++ , lock ++ )
443458 LWLockInitialize (& lock -> lock , LWTRANCHE_MAIN );
444459
@@ -453,6 +468,40 @@ CreateLWLocks(void)
453468 LWLockCounter [0 ] = NUM_FIXED_LWLOCKS ;
454469 LWLockCounter [1 ] = numLocks ;
455470 LWLockCounter [2 ] = LWTRANCHE_FIRST_USER_DEFINED ;
471+
472+ /* Initialize named tranches. */
473+ if (NamedLWLockTrancheRequests > 0 )
474+ {
475+ char * trancheNames ;
476+
477+ NamedLWLockTrancheArray = (NamedLWLockTranche * )
478+ & MainLWLockArray [numLocks + numNamedLocks ];
479+
480+ trancheNames = (char * ) NamedLWLockTrancheArray +
481+ (NamedLWLockTrancheRequests * sizeof (NamedLWLockTranche ));
482+ lock = & MainLWLockArray [numLocks ];
483+
484+ for (i = 0 ; i < NamedLWLockTrancheRequests ; i ++ )
485+ {
486+ NamedLWLockTrancheRequest * request ;
487+ NamedLWLockTranche * tranche ;
488+ char * name ;
489+
490+ request = & NamedLWLockTrancheRequestArray [i ];
491+ tranche = & NamedLWLockTrancheArray [i ];
492+
493+ name = trancheNames ;
494+ trancheNames += strlen (request -> tranche_name ) + 1 ;
495+ strcpy (name , request -> tranche_name );
496+ tranche -> lwLockTranche .name = name ;
497+ tranche -> trancheId = LWLockNewTrancheId ();
498+ tranche -> lwLockTranche .array_base = lock ;
499+ tranche -> lwLockTranche .array_stride = sizeof (LWLockPadded );
500+
501+ for (j = 0 ; j < request -> num_lwlocks ; j ++ , lock ++ )
502+ LWLockInitialize (& lock -> lock , tranche -> trancheId );
503+ }
504+ }
456505 }
457506
458507 if (LWLockTrancheArray == NULL )
@@ -468,6 +517,11 @@ CreateLWLocks(void)
468517 MainLWLockTranche .array_base = MainLWLockArray ;
469518 MainLWLockTranche .array_stride = sizeof (LWLockPadded );
470519 LWLockRegisterTranche (LWTRANCHE_MAIN , & MainLWLockTranche );
520+
521+ /* Register named tranches. */
522+ for (i = 0 ; i < NamedLWLockTrancheRequests ; i ++ )
523+ LWLockRegisterTranche (NamedLWLockTrancheArray [i ].trancheId ,
524+ & NamedLWLockTrancheArray [i ].lwLockTranche );
471525}
472526
473527/*
@@ -507,6 +561,45 @@ LWLockAssign(void)
507561 return result ;
508562}
509563
564+ /*
565+ * GetNamedLWLockTranche - returns the base address of LWLock from the
566+ * specified tranche.
567+ *
568+ * Caller needs to retrieve the requested number of LWLocks starting from
569+ * the base lock address returned by this API. This can be used for
570+ * tranches that are requested by using RequestNamedLWLockTranche() API.
571+ */
572+ LWLockPadded *
573+ GetNamedLWLockTranche (const char * tranche_name )
574+ {
575+ int lock_pos ;
576+ int i ;
577+ int * LWLockCounter ;
578+
579+ LWLockCounter = (int * ) ((char * ) MainLWLockArray - 3 * sizeof (int ));
580+
581+ /*
582+ * Obtain the position of base address of LWLock belonging to requested
583+ * tranche_name in MainLWLockArray. LWLocks for named tranches are placed
584+ * in MainLWLockArray after LWLocks specified by LWLockCounter[1].
585+ */
586+ lock_pos = LWLockCounter [1 ];
587+ for (i = 0 ; i < NamedLWLockTrancheRequests ; i ++ )
588+ {
589+ if (strcmp (NamedLWLockTrancheRequestArray [i ].tranche_name ,
590+ tranche_name ) == 0 )
591+ return & MainLWLockArray [lock_pos ];
592+
593+ lock_pos += NamedLWLockTrancheRequestArray [i ].num_lwlocks ;
594+ }
595+
596+ if (i >= NamedLWLockTrancheRequests )
597+ elog (ERROR , "requested tranche is not registered" );
598+
599+ /* just to keep compiler quiet */
600+ return NULL ;
601+ }
602+
510603/*
511604 * Allocate a new tranche ID.
512605 */
@@ -551,6 +644,55 @@ LWLockRegisterTranche(int tranche_id, LWLockTranche *tranche)
551644 LWLockTrancheArray [tranche_id ] = tranche ;
552645}
553646
647+ /*
648+ * RequestNamedLWLockTranche
649+ * Request that extra LWLocks be allocated during postmaster
650+ * startup.
651+ *
652+ * This is only useful for extensions if called from the _PG_init hook
653+ * of a library that is loaded into the postmaster via
654+ * shared_preload_libraries. Once shared memory has been allocated, calls
655+ * will be ignored. (We could raise an error, but it seems better to make
656+ * it a no-op, so that libraries containing such calls can be reloaded if
657+ * needed.)
658+ */
659+ void
660+ RequestNamedLWLockTranche (const char * tranche_name , int num_lwlocks )
661+ {
662+ NamedLWLockTrancheRequest * request ;
663+
664+ if (IsUnderPostmaster || !lock_named_request_allowed )
665+ return ; /* too late */
666+
667+ if (NamedLWLockTrancheRequestArray == NULL )
668+ {
669+ NamedLWLockTrancheRequestsAllocated = 16 ;
670+ NamedLWLockTrancheRequestArray = (NamedLWLockTrancheRequest * )
671+ MemoryContextAlloc (TopMemoryContext ,
672+ NamedLWLockTrancheRequestsAllocated
673+ * sizeof (NamedLWLockTrancheRequest ));
674+ }
675+
676+ if (NamedLWLockTrancheRequests >= NamedLWLockTrancheRequestsAllocated )
677+ {
678+ int i = NamedLWLockTrancheRequestsAllocated ;
679+
680+ while (i <= NamedLWLockTrancheRequests )
681+ i *= 2 ;
682+
683+ NamedLWLockTrancheRequestArray = (NamedLWLockTrancheRequest * )
684+ repalloc (NamedLWLockTrancheRequestArray ,
685+ i * sizeof (NamedLWLockTrancheRequest ));
686+ NamedLWLockTrancheRequestsAllocated = i ;
687+ }
688+
689+ request = & NamedLWLockTrancheRequestArray [NamedLWLockTrancheRequests ];
690+ Assert (strlen (tranche_name ) + 1 < NAMEDATALEN );
691+ StrNCpy (request -> tranche_name , tranche_name , NAMEDATALEN );
692+ request -> num_lwlocks = num_lwlocks ;
693+ NamedLWLockTrancheRequests ++ ;
694+ }
695+
554696/*
555697 * LWLockInitialize - initialize a new lwlock; it's initially unlocked
556698 */
0 commit comments