Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitc1772ad

Browse files
committed
Change the way that LWLocks for extensions are allocated.
The previous RequestAddinLWLocks() method had several disadvantages.First, the locks would be in the main tranche; we've recently decidedthat it's useful for LWLocks used for separate purposes to haveseparate tranche IDs. Second, there wasn't any correlation betweenwhat code called RequestAddinLWLocks() and what code calledLWLockAssign(); when multiple modules are in use, it could becomequite difficult to troubleshoot problems where LWLockAssign() ran outof locks. To fix, create a concept of named LWLock tranches whichcan be used either by extension or by core code.Amit Kapila and Robert Haas
1 parent5ef244a commitc1772ad

File tree

7 files changed

+210
-50
lines changed

7 files changed

+210
-50
lines changed

‎contrib/pg_stat_statements/pg_stat_statements.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -404,7 +404,7 @@ _PG_init(void)
404404
* resources in pgss_shmem_startup().
405405
*/
406406
RequestAddinShmemSpace(pgss_memsize());
407-
RequestAddinLWLocks(1);
407+
RequestNamedLWLockTranche("pg_stat_statements",1);
408408

409409
/*
410410
* Install hooks.
@@ -480,7 +480,7 @@ pgss_shmem_startup(void)
480480
if (!found)
481481
{
482482
/* First time through ... */
483-
pgss->lock=LWLockAssign();
483+
pgss->lock=&(GetNamedLWLockTranche("pg_stat_statements"))->lock;
484484
pgss->cur_median_usage=ASSUMED_MEDIAN_INIT;
485485
pgss->mean_query_len=ASSUMED_LENGTH_INIT;
486486
SpinLockInit(&pgss->mutex);

‎doc/src/sgml/xfunc.sgml

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3335,9 +3335,12 @@ void RequestAddinShmemSpace(int size)
33353335
<para>
33363336
LWLocks are reserved by calling:
33373337
<programlisting>
3338-
voidRequestAddinLWLocks(intn)
3338+
voidRequestNamedLWLockTranche(const char *tranche_name,intnum_lwlocks)
33393339
</programlisting>
3340-
from <function>_PG_init</>.
3340+
from <function>_PG_init</>. This will ensure that an array of
3341+
<literal>num_lwlocks</> LWLocks is available under the name
3342+
<literal>tranche_name</>. Use <function>GetNamedLWLockTranche</>
3343+
to get a pointer to this array.
33413344
</para>
33423345
<para>
33433346
To avoid possible race-conditions, each backend should use the LWLock
@@ -3356,7 +3359,7 @@ if (!ptr)
33563359
{
33573360
initialize contents of shmem area;
33583361
acquire any requested LWLocks using:
3359-
ptr->mylockid =LWLockAssign();
3362+
ptr->locks =GetNamedLWLockTranche("my tranche name");
33603363
}
33613364
LWLockRelease(AddinShmemInitLock);
33623365
}

‎src/backend/postmaster/postmaster.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -485,6 +485,8 @@ typedef struct
485485
#ifndefHAVE_SPINLOCKS
486486
PGSemaphoreSpinlockSemaArray;
487487
#endif
488+
intNamedLWLockTrancheRequests;
489+
NamedLWLockTranche*NamedLWLockTrancheArray;
488490
LWLockPadded*MainLWLockArray;
489491
slock_t*ProcStructLock;
490492
PROC_HDR*ProcGlobal;
@@ -5800,6 +5802,8 @@ save_backend_variables(BackendParameters *param, Port *port,
58005802
#ifndefHAVE_SPINLOCKS
58015803
param->SpinlockSemaArray=SpinlockSemaArray;
58025804
#endif
5805+
param->NamedLWLockTrancheRequests=NamedLWLockTrancheRequests;
5806+
param->NamedLWLockTrancheArray=NamedLWLockTrancheArray;
58035807
param->MainLWLockArray=MainLWLockArray;
58045808
param->ProcStructLock=ProcStructLock;
58055809
param->ProcGlobal=ProcGlobal;
@@ -6031,6 +6035,8 @@ restore_backend_variables(BackendParameters *param, Port *port)
60316035
#ifndefHAVE_SPINLOCKS
60326036
SpinlockSemaArray=param->SpinlockSemaArray;
60336037
#endif
6038+
NamedLWLockTrancheRequests=param->NamedLWLockTrancheRequests;
6039+
NamedLWLockTrancheArray=param->NamedLWLockTrancheArray;
60346040
MainLWLockArray=param->MainLWLockArray;
60356041
ProcStructLock=param->ProcStructLock;
60366042
ProcGlobal=param->ProcGlobal;

‎src/backend/storage/lmgr/lwlock.c

Lines changed: 177 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -144,8 +144,20 @@ typedef struct LWLockHandle
144144
staticintnum_held_lwlocks=0;
145145
staticLWLockHandleheld_lwlocks[MAX_SIMUL_LWLOCKS];
146146

147-
staticintlock_addin_request=0;
148-
staticboollock_addin_request_allowed= true;
147+
/* struct representing the LWLock tranche request for named tranche */
148+
typedefstructNamedLWLockTrancheRequest
149+
{
150+
chartranche_name[NAMEDATALEN];
151+
intnum_lwlocks;
152+
}NamedLWLockTrancheRequest;
153+
154+
NamedLWLockTrancheRequest*NamedLWLockTrancheRequestArray=NULL;
155+
staticintNamedLWLockTrancheRequestsAllocated=0;
156+
intNamedLWLockTrancheRequests=0;
157+
158+
NamedLWLockTranche*NamedLWLockTrancheArray=NULL;
159+
160+
staticboollock_named_request_allowed= true;
149161

150162
#ifdefLWLOCK_STATS
151163
typedefstructlwlock_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+
staticint
355+
NumLWLocksByNamedTranches(void)
356+
{
357+
intnumLocks=0;
358+
inti;
359+
360+
for (i=0;i<NamedLWLockTrancheRequests;i++)
361+
numLocks+=NamedLWLockTrancheRequestArray[i].num_lwlocks;
362+
363+
returnnumLocks;
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
returnnumLocks;
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(intn)
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
*/
391393
Size
392394
LWLockShmemSize(void)
393395
{
394396
Sizesize;
397+
inti;
395398
intnumLocks=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
returnsize;
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 alsoregister the mainand named tranche here.
410421
*/
411422
void
412423
CreateLWLocks(void)
413424
{
425+
inti;
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
intnumLocks=NumLWLocks();
437+
intnumNamedLocks=NumLWLocksByNamedTranches();
424438
SizespaceLocks=LWLockShmemSize();
425439
LWLockPadded*lock;
426440
int*LWLockCounter;
427441
char*ptr;
428442
intid;
443+
intj;
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 allfixedLWLocks 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
returnresult;
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(constchar*tranche_name)
574+
{
575+
intlock_pos;
576+
inti;
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+
returnNULL;
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(constchar*tranche_name,intnum_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+
inti=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
*/

‎src/include/pg_config_manual.h

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -51,11 +51,6 @@
5151
#defineSEQ_MAXVALUEPG_INT64_MAX
5252
#defineSEQ_MINVALUE(-SEQ_MAXVALUE)
5353

54-
/*
55-
* Number of spare LWLocks to allocate for user-defined add-on code.
56-
*/
57-
#defineNUM_USER_DEFINED_LWLOCKS4
58-
5954
/*
6055
* When we don't have native spinlocks, we use semaphores to simulate them.
6156
* Decreasing this value reduces consumption of OS resources; increasing it

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp