@@ -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 */
354382numLocks = 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
364387return 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{
394396Size size ;
397+ int i ;
395398int numLocks = NumLWLocks ();
396399
400+ numLocks += NumLWLocksByNamedTranches ();
401+
397402/* Space for the LWLock array. */
398403size = mul_size (numLocks ,sizeof (LWLockPadded ));
399404
400405/* Space for dynamic allocation counter, plus room for alignment. */
401406size = 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+
403415return size ;
404416}
405417
406-
407418/*
408- * Allocate shmem space for the main LWLock array andinitialize it. We also
409- * register the maintranch here.
419+ * Allocate shmem space for the main LWLock array andnamed tranches and
420+ *initialize it. We also register the mainand named tranche here.
410421 */
411422void
412423CreateLWLocks (void )
413424{
425+ int i ;
426+
414427StaticAssertExpr (LW_VAL_EXCLUSIVE > (uint32 )MAX_BACKENDS ,
415428"MAX_BACKENDS too big for lwlock.c" );
416429
@@ -421,11 +434,13 @@ CreateLWLocks(void)
421434if (!IsUnderPostmaster )
422435{
423436int numLocks = NumLWLocks ();
437+ int numNamedLocks = NumLWLocksByNamedTranches ();
424438Size spaceLocks = LWLockShmemSize ();
425439LWLockPadded * lock ;
426440int * LWLockCounter ;
427441char * ptr ;
428442int id ;
443+ int j ;
429444
430445/* Allocate space */
431446ptr = (char * )ShmemAlloc (spaceLocks );
@@ -438,7 +453,7 @@ CreateLWLocks(void)
438453
439454MainLWLockArray = (LWLockPadded * )ptr ;
440455
441- /* Initialize all LWLocks in main array */
456+ /* Initialize allfixed LWLocks in main array */
442457for (id = 0 ,lock = MainLWLockArray ;id < numLocks ;id ++ ,lock ++ )
443458LWLockInitialize (& lock -> lock ,LWTRANCHE_MAIN );
444459
@@ -453,6 +468,40 @@ CreateLWLocks(void)
453468LWLockCounter [0 ]= NUM_FIXED_LWLOCKS ;
454469LWLockCounter [1 ]= numLocks ;
455470LWLockCounter [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
458507if (LWLockTrancheArray == NULL )
@@ -468,6 +517,11 @@ CreateLWLocks(void)
468517MainLWLockTranche .array_base = MainLWLockArray ;
469518MainLWLockTranche .array_stride = sizeof (LWLockPadded );
470519LWLockRegisterTranche (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)
507561return 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)
551644LWLockTrancheArray [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 */