@@ -144,8 +144,20 @@ typedef struct LWLockHandle
144
144
static int num_held_lwlocks = 0 ;
145
145
static LWLockHandle held_lwlocks [MAX_SIMUL_LWLOCKS ];
146
146
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;
149
161
150
162
#ifdef LWLOCK_STATS
151
163
typedef struct lwlock_stats_key
@@ -335,6 +347,22 @@ get_lwlock_stats_entry(LWLock *lock)
335
347
#endif /* LWLOCK_STATS */
336
348
337
349
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
+
338
366
/*
339
367
* Compute number of LWLocks to allocate in the main array.
340
368
*/
@@ -353,64 +381,49 @@ NumLWLocks(void)
353
381
/* Predefined LWLocks */
354
382
numLocks = NUM_FIXED_LWLOCKS ;
355
383
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;
363
386
364
387
return numLocks ;
365
388
}
366
389
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
-
388
390
/*
389
- * Compute shmem space needed for LWLocks.
391
+ * Compute shmem space needed for LWLocks and named tranches .
390
392
*/
391
393
Size
392
394
LWLockShmemSize (void )
393
395
{
394
396
Size size ;
397
+ int i ;
395
398
int numLocks = NumLWLocks ();
396
399
400
+ numLocks += NumLWLocksByNamedTranches ();
401
+
397
402
/* Space for the LWLock array. */
398
403
size = mul_size (numLocks , sizeof (LWLockPadded ));
399
404
400
405
/* Space for dynamic allocation counter, plus room for alignment. */
401
406
size = add_size (size , 3 * sizeof (int ) + LWLOCK_PADDED_SIZE );
402
407
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
+
403
415
return size ;
404
416
}
405
417
406
-
407
418
/*
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.
410
421
*/
411
422
void
412
423
CreateLWLocks (void )
413
424
{
425
+ int i ;
426
+
414
427
StaticAssertExpr (LW_VAL_EXCLUSIVE > (uint32 ) MAX_BACKENDS ,
415
428
"MAX_BACKENDS too big for lwlock.c" );
416
429
@@ -421,11 +434,13 @@ CreateLWLocks(void)
421
434
if (!IsUnderPostmaster )
422
435
{
423
436
int numLocks = NumLWLocks ();
437
+ int numNamedLocks = NumLWLocksByNamedTranches ();
424
438
Size spaceLocks = LWLockShmemSize ();
425
439
LWLockPadded * lock ;
426
440
int * LWLockCounter ;
427
441
char * ptr ;
428
442
int id ;
443
+ int j ;
429
444
430
445
/* Allocate space */
431
446
ptr = (char * ) ShmemAlloc (spaceLocks );
@@ -438,7 +453,7 @@ CreateLWLocks(void)
438
453
439
454
MainLWLockArray = (LWLockPadded * ) ptr ;
440
455
441
- /* Initialize all LWLocks in main array */
456
+ /* Initialize all fixed LWLocks in main array */
442
457
for (id = 0 , lock = MainLWLockArray ; id < numLocks ; id ++ , lock ++ )
443
458
LWLockInitialize (& lock -> lock , LWTRANCHE_MAIN );
444
459
@@ -453,6 +468,40 @@ CreateLWLocks(void)
453
468
LWLockCounter [0 ] = NUM_FIXED_LWLOCKS ;
454
469
LWLockCounter [1 ] = numLocks ;
455
470
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
+ }
456
505
}
457
506
458
507
if (LWLockTrancheArray == NULL )
@@ -468,6 +517,11 @@ CreateLWLocks(void)
468
517
MainLWLockTranche .array_base = MainLWLockArray ;
469
518
MainLWLockTranche .array_stride = sizeof (LWLockPadded );
470
519
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 );
471
525
}
472
526
473
527
/*
@@ -507,6 +561,45 @@ LWLockAssign(void)
507
561
return result ;
508
562
}
509
563
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
+
510
603
/*
511
604
* Allocate a new tranche ID.
512
605
*/
@@ -551,6 +644,55 @@ LWLockRegisterTranche(int tranche_id, LWLockTranche *tranche)
551
644
LWLockTrancheArray [tranche_id ] = tranche ;
552
645
}
553
646
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
+
554
696
/*
555
697
* LWLockInitialize - initialize a new lwlock; it's initially unlocked
556
698
*/
0 commit comments