00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032 #include "postgres.h"
00033
00034 #include <signal.h>
00035 #include <unistd.h>
00036 #include <sys/time.h>
00037
00038 #include "access/transam.h"
00039 #include "access/twophase.h"
00040 #include "access/xact.h"
00041 #include "miscadmin.h"
00042 #include "postmaster/autovacuum.h"
00043 #include "replication/syncrep.h"
00044 #include "storage/ipc.h"
00045 #include "storage/lmgr.h"
00046 #include "storage/pmsignal.h"
00047 #include "storage/proc.h"
00048 #include "storage/procarray.h"
00049 #include "storage/procsignal.h"
00050 #include "storage/spin.h"
00051 #include "utils/timeout.h"
00052 #include "utils/timestamp.h"
00053
00054
00055
00056 int DeadlockTimeout = 1000;
00057 int StatementTimeout = 0;
00058 int LockTimeout = 0;
00059 bool log_lock_waits = false;
00060
00061
00062 PGPROC *MyProc = NULL;
00063 PGXACT *MyPgXact = NULL;
00064
00065
00066
00067
00068
00069
00070
00071
00072 NON_EXEC_STATIC slock_t *ProcStructLock = NULL;
00073
00074
00075 PROC_HDR *ProcGlobal = NULL;
00076 NON_EXEC_STATIC PGPROC *AuxiliaryProcs = NULL;
00077 PGPROC *PreparedXactProcs = NULL;
00078
00079
00080 static LOCALLOCK *lockAwaited = NULL;
00081
00082
00083 static volatile DeadLockState deadlock_state = DS_NOT_YET_CHECKED;
00084
00085
00086 static void RemoveProcFromArray(int code, Datum arg);
00087 static void ProcKill(int code, Datum arg);
00088 static void AuxiliaryProcKill(int code, Datum arg);
00089
00090
00091
00092
00093
00094 Size
00095 ProcGlobalShmemSize(void)
00096 {
00097 Size size = 0;
00098
00099
00100 size = add_size(size, sizeof(PROC_HDR));
00101
00102 size = add_size(size, mul_size(MaxBackends, sizeof(PGPROC)));
00103
00104 size = add_size(size, mul_size(NUM_AUXILIARY_PROCS, sizeof(PGPROC)));
00105
00106 size = add_size(size, mul_size(max_prepared_xacts, sizeof(PGPROC)));
00107
00108 size = add_size(size, sizeof(slock_t));
00109
00110 size = add_size(size, mul_size(MaxBackends, sizeof(PGXACT)));
00111 size = add_size(size, mul_size(NUM_AUXILIARY_PROCS, sizeof(PGXACT)));
00112 size = add_size(size, mul_size(max_prepared_xacts, sizeof(PGXACT)));
00113
00114 return size;
00115 }
00116
00117
00118
00119
00120 int
00121 ProcGlobalSemas(void)
00122 {
00123
00124
00125
00126
00127 return MaxBackends + NUM_AUXILIARY_PROCS;
00128 }
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156 void
00157 InitProcGlobal(void)
00158 {
00159 PGPROC *procs;
00160 PGXACT *pgxacts;
00161 int i,
00162 j;
00163 bool found;
00164 uint32 TotalProcs = MaxBackends + NUM_AUXILIARY_PROCS + max_prepared_xacts;
00165
00166
00167 ProcGlobal = (PROC_HDR *)
00168 ShmemInitStruct("Proc Header", sizeof(PROC_HDR), &found);
00169 Assert(!found);
00170
00171
00172
00173
00174 ProcGlobal->spins_per_delay = DEFAULT_SPINS_PER_DELAY;
00175 ProcGlobal->freeProcs = NULL;
00176 ProcGlobal->autovacFreeProcs = NULL;
00177 ProcGlobal->bgworkerFreeProcs = NULL;
00178 ProcGlobal->startupProc = NULL;
00179 ProcGlobal->startupProcPid = 0;
00180 ProcGlobal->startupBufferPinWaitBufId = -1;
00181 ProcGlobal->walwriterLatch = NULL;
00182 ProcGlobal->checkpointerLatch = NULL;
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192 procs = (PGPROC *) ShmemAlloc(TotalProcs * sizeof(PGPROC));
00193 ProcGlobal->allProcs = procs;
00194 ProcGlobal->allProcCount = TotalProcs;
00195 if (!procs)
00196 ereport(FATAL,
00197 (errcode(ERRCODE_OUT_OF_MEMORY),
00198 errmsg("out of shared memory")));
00199 MemSet(procs, 0, TotalProcs * sizeof(PGPROC));
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209 pgxacts = (PGXACT *) ShmemAlloc(TotalProcs * sizeof(PGXACT));
00210 MemSet(pgxacts, 0, TotalProcs * sizeof(PGXACT));
00211 ProcGlobal->allPgXact = pgxacts;
00212
00213 for (i = 0; i < TotalProcs; i++)
00214 {
00215
00216
00217
00218
00219
00220
00221
00222 if (i < MaxBackends + NUM_AUXILIARY_PROCS)
00223 {
00224 PGSemaphoreCreate(&(procs[i].sem));
00225 InitSharedLatch(&(procs[i].procLatch));
00226 procs[i].backendLock = LWLockAssign();
00227 }
00228 procs[i].pgprocno = i;
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238 if (i < MaxConnections)
00239 {
00240
00241 procs[i].links.next = (SHM_QUEUE *) ProcGlobal->freeProcs;
00242 ProcGlobal->freeProcs = &procs[i];
00243 }
00244 else if (i < MaxConnections + autovacuum_max_workers + 1)
00245 {
00246
00247 procs[i].links.next = (SHM_QUEUE *) ProcGlobal->autovacFreeProcs;
00248 ProcGlobal->autovacFreeProcs = &procs[i];
00249 }
00250 else if (i < MaxBackends)
00251 {
00252
00253 procs[i].links.next = (SHM_QUEUE *) ProcGlobal->bgworkerFreeProcs;
00254 ProcGlobal->bgworkerFreeProcs = &procs[i];
00255 }
00256
00257
00258 for (j = 0; j < NUM_LOCK_PARTITIONS; j++)
00259 SHMQueueInit(&(procs[i].myProcLocks[j]));
00260 }
00261
00262
00263
00264
00265
00266 AuxiliaryProcs = &procs[MaxBackends];
00267 PreparedXactProcs = &procs[MaxBackends + NUM_AUXILIARY_PROCS];
00268
00269
00270 ProcStructLock = (slock_t *) ShmemAlloc(sizeof(slock_t));
00271 SpinLockInit(ProcStructLock);
00272 }
00273
00274
00275
00276
00277 void
00278 InitProcess(void)
00279 {
00280
00281 volatile PROC_HDR *procglobal = ProcGlobal;
00282
00283
00284
00285
00286
00287 if (procglobal == NULL)
00288 elog(PANIC, "proc header uninitialized");
00289
00290 if (MyProc != NULL)
00291 elog(ERROR, "you already exist");
00292
00293
00294
00295
00296
00297
00298 InitializeLatchSupport();
00299
00300
00301
00302
00303
00304
00305
00306
00307 SpinLockAcquire(ProcStructLock);
00308
00309 set_spins_per_delay(procglobal->spins_per_delay);
00310
00311 if (IsAnyAutoVacuumProcess())
00312 MyProc = procglobal->autovacFreeProcs;
00313 else if (IsBackgroundWorker)
00314 MyProc = procglobal->bgworkerFreeProcs;
00315 else
00316 MyProc = procglobal->freeProcs;
00317
00318 if (MyProc != NULL)
00319 {
00320 if (IsAnyAutoVacuumProcess())
00321 procglobal->autovacFreeProcs = (PGPROC *) MyProc->links.next;
00322 else if (IsBackgroundWorker)
00323 procglobal->bgworkerFreeProcs = (PGPROC *) MyProc->links.next;
00324 else
00325 procglobal->freeProcs = (PGPROC *) MyProc->links.next;
00326 SpinLockRelease(ProcStructLock);
00327 }
00328 else
00329 {
00330
00331
00332
00333
00334
00335
00336 SpinLockRelease(ProcStructLock);
00337 ereport(FATAL,
00338 (errcode(ERRCODE_TOO_MANY_CONNECTIONS),
00339 errmsg("sorry, too many clients already")));
00340 }
00341 MyPgXact = &ProcGlobal->allPgXact[MyProc->pgprocno];
00342
00343
00344
00345
00346
00347
00348
00349 if (IsUnderPostmaster && !IsAutoVacuumLauncherProcess())
00350 MarkPostmasterChildActive();
00351
00352
00353
00354
00355
00356 SHMQueueElemInit(&(MyProc->links));
00357 MyProc->waitStatus = STATUS_OK;
00358 MyProc->lxid = InvalidLocalTransactionId;
00359 MyProc->fpVXIDLock = false;
00360 MyProc->fpLocalTransactionId = InvalidLocalTransactionId;
00361 MyPgXact->xid = InvalidTransactionId;
00362 MyPgXact->xmin = InvalidTransactionId;
00363 MyProc->pid = MyProcPid;
00364
00365 MyProc->backendId = InvalidBackendId;
00366 MyProc->databaseId = InvalidOid;
00367 MyProc->roleId = InvalidOid;
00368 MyPgXact->delayChkpt = false;
00369 MyPgXact->vacuumFlags = 0;
00370
00371 if (IsAutoVacuumWorkerProcess())
00372 MyPgXact->vacuumFlags |= PROC_IS_AUTOVACUUM;
00373 MyProc->lwWaiting = false;
00374 MyProc->lwWaitMode = 0;
00375 MyProc->lwWaitLink = NULL;
00376 MyProc->waitLock = NULL;
00377 MyProc->waitProcLock = NULL;
00378 #ifdef USE_ASSERT_CHECKING
00379 if (assert_enabled)
00380 {
00381 int i;
00382
00383
00384 for (i = 0; i < NUM_LOCK_PARTITIONS; i++)
00385 Assert(SHMQueueEmpty(&(MyProc->myProcLocks[i])));
00386 }
00387 #endif
00388 MyProc->recoveryConflictPending = false;
00389
00390
00391 MyProc->waitLSN = 0;
00392 MyProc->syncRepState = SYNC_REP_NOT_WAITING;
00393 SHMQueueElemInit(&(MyProc->syncRepLinks));
00394
00395
00396
00397
00398
00399 OwnLatch(&MyProc->procLatch);
00400
00401
00402
00403
00404
00405
00406 PGSemaphoreReset(&MyProc->sem);
00407
00408
00409
00410
00411 on_shmem_exit(ProcKill, 0);
00412
00413
00414
00415
00416
00417 InitDeadLockChecking();
00418 }
00419
00420
00421
00422
00423
00424
00425
00426
00427 void
00428 InitProcessPhase2(void)
00429 {
00430 Assert(MyProc != NULL);
00431
00432
00433
00434
00435 ProcArrayAdd(MyProc);
00436
00437
00438
00439
00440 on_shmem_exit(RemoveProcFromArray, 0);
00441 }
00442
00443
00444
00445
00446
00447
00448
00449
00450
00451
00452
00453
00454
00455
00456
00457
00458
00459
00460
00461
00462 void
00463 InitAuxiliaryProcess(void)
00464 {
00465 PGPROC *auxproc;
00466 int proctype;
00467
00468
00469
00470
00471
00472 if (ProcGlobal == NULL || AuxiliaryProcs == NULL)
00473 elog(PANIC, "proc header uninitialized");
00474
00475 if (MyProc != NULL)
00476 elog(ERROR, "you already exist");
00477
00478
00479
00480
00481
00482
00483 InitializeLatchSupport();
00484
00485
00486
00487
00488
00489
00490
00491
00492 SpinLockAcquire(ProcStructLock);
00493
00494 set_spins_per_delay(ProcGlobal->spins_per_delay);
00495
00496
00497
00498
00499 for (proctype = 0; proctype < NUM_AUXILIARY_PROCS; proctype++)
00500 {
00501 auxproc = &AuxiliaryProcs[proctype];
00502 if (auxproc->pid == 0)
00503 break;
00504 }
00505 if (proctype >= NUM_AUXILIARY_PROCS)
00506 {
00507 SpinLockRelease(ProcStructLock);
00508 elog(FATAL, "all AuxiliaryProcs are in use");
00509 }
00510
00511
00512
00513 ((volatile PGPROC *) auxproc)->pid = MyProcPid;
00514
00515 MyProc = auxproc;
00516 MyPgXact = &ProcGlobal->allPgXact[auxproc->pgprocno];
00517
00518 SpinLockRelease(ProcStructLock);
00519
00520
00521
00522
00523
00524 SHMQueueElemInit(&(MyProc->links));
00525 MyProc->waitStatus = STATUS_OK;
00526 MyProc->lxid = InvalidLocalTransactionId;
00527 MyProc->fpVXIDLock = false;
00528 MyProc->fpLocalTransactionId = InvalidLocalTransactionId;
00529 MyPgXact->xid = InvalidTransactionId;
00530 MyPgXact->xmin = InvalidTransactionId;
00531 MyProc->backendId = InvalidBackendId;
00532 MyProc->databaseId = InvalidOid;
00533 MyProc->roleId = InvalidOid;
00534 MyPgXact->delayChkpt = false;
00535 MyPgXact->vacuumFlags = 0;
00536 MyProc->lwWaiting = false;
00537 MyProc->lwWaitMode = 0;
00538 MyProc->lwWaitLink = NULL;
00539 MyProc->waitLock = NULL;
00540 MyProc->waitProcLock = NULL;
00541 #ifdef USE_ASSERT_CHECKING
00542 if (assert_enabled)
00543 {
00544 int i;
00545
00546
00547 for (i = 0; i < NUM_LOCK_PARTITIONS; i++)
00548 Assert(SHMQueueEmpty(&(MyProc->myProcLocks[i])));
00549 }
00550 #endif
00551
00552
00553
00554
00555
00556 OwnLatch(&MyProc->procLatch);
00557
00558
00559
00560
00561
00562
00563 PGSemaphoreReset(&MyProc->sem);
00564
00565
00566
00567
00568 on_shmem_exit(AuxiliaryProcKill, Int32GetDatum(proctype));
00569 }
00570
00571
00572
00573
00574
00575 void
00576 PublishStartupProcessInformation(void)
00577 {
00578
00579 volatile PROC_HDR *procglobal = ProcGlobal;
00580
00581 SpinLockAcquire(ProcStructLock);
00582
00583 procglobal->startupProc = MyProc;
00584 procglobal->startupProcPid = MyProcPid;
00585
00586 SpinLockRelease(ProcStructLock);
00587 }
00588
00589
00590
00591
00592
00593
00594
00595
00596 void
00597 SetStartupBufferPinWaitBufId(int bufid)
00598 {
00599
00600 volatile PROC_HDR *procglobal = ProcGlobal;
00601
00602 procglobal->startupBufferPinWaitBufId = bufid;
00603 }
00604
00605
00606
00607
00608 int
00609 GetStartupBufferPinWaitBufId(void)
00610 {
00611
00612 volatile PROC_HDR *procglobal = ProcGlobal;
00613
00614 return procglobal->startupBufferPinWaitBufId;
00615 }
00616
00617
00618
00619
00620
00621
00622 bool
00623 HaveNFreeProcs(int n)
00624 {
00625 PGPROC *proc;
00626
00627
00628 volatile PROC_HDR *procglobal = ProcGlobal;
00629
00630 SpinLockAcquire(ProcStructLock);
00631
00632 proc = procglobal->freeProcs;
00633
00634 while (n > 0 && proc != NULL)
00635 {
00636 proc = (PGPROC *) proc->links.next;
00637 n--;
00638 }
00639
00640 SpinLockRelease(ProcStructLock);
00641
00642 return (n <= 0);
00643 }
00644
00645
00646
00647
00648 bool
00649 IsWaitingForLock(void)
00650 {
00651 if (lockAwaited == NULL)
00652 return false;
00653
00654 return true;
00655 }
00656
00657
00658
00659
00660
00661
00662
00663
00664
00665 void
00666 LockErrorCleanup(void)
00667 {
00668 LWLockId partitionLock;
00669 DisableTimeoutParams timeouts[2];
00670
00671 AbortStrongLockAcquire();
00672
00673
00674 if (lockAwaited == NULL)
00675 return;
00676
00677
00678
00679
00680
00681
00682
00683
00684
00685 timeouts[0].id = DEADLOCK_TIMEOUT;
00686 timeouts[0].keep_indicator = false;
00687 timeouts[1].id = LOCK_TIMEOUT;
00688 timeouts[1].keep_indicator = true;
00689 disable_timeouts(timeouts, 2);
00690
00691
00692 partitionLock = LockHashPartitionLock(lockAwaited->hashcode);
00693 LWLockAcquire(partitionLock, LW_EXCLUSIVE);
00694
00695 if (MyProc->links.next != NULL)
00696 {
00697
00698 RemoveFromWaitQueue(MyProc, lockAwaited->hashcode);
00699 }
00700 else
00701 {
00702
00703
00704
00705
00706
00707
00708 if (MyProc->waitStatus == STATUS_OK)
00709 GrantAwaitedLock();
00710 }
00711
00712 lockAwaited = NULL;
00713
00714 LWLockRelease(partitionLock);
00715
00716
00717
00718
00719
00720
00721
00722
00723
00724
00725 }
00726
00727
00728
00729
00730
00731
00732
00733
00734
00735
00736
00737
00738
00739
00740
00741
00742
00743
00744 void
00745 ProcReleaseLocks(bool isCommit)
00746 {
00747 if (!MyProc)
00748 return;
00749
00750 LockErrorCleanup();
00751
00752 LockReleaseAll(DEFAULT_LOCKMETHOD, !isCommit);
00753
00754 LockReleaseAll(USER_LOCKMETHOD, false);
00755 }
00756
00757
00758
00759
00760
00761 static void
00762 RemoveProcFromArray(int code, Datum arg)
00763 {
00764 Assert(MyProc != NULL);
00765 ProcArrayRemove(MyProc, InvalidTransactionId);
00766 }
00767
00768
00769
00770
00771
00772 static void
00773 ProcKill(int code, Datum arg)
00774 {
00775
00776 volatile PROC_HDR *procglobal = ProcGlobal;
00777
00778 Assert(MyProc != NULL);
00779
00780
00781 SyncRepCleanupAtProcExit();
00782
00783 #ifdef USE_ASSERT_CHECKING
00784 if (assert_enabled)
00785 {
00786 int i;
00787
00788
00789 for (i = 0; i < NUM_LOCK_PARTITIONS; i++)
00790 Assert(SHMQueueEmpty(&(MyProc->myProcLocks[i])));
00791 }
00792 #endif
00793
00794
00795
00796
00797
00798
00799 LWLockReleaseAll();
00800
00801
00802 DisownLatch(&MyProc->procLatch);
00803
00804 SpinLockAcquire(ProcStructLock);
00805
00806
00807 if (IsAnyAutoVacuumProcess())
00808 {
00809 MyProc->links.next = (SHM_QUEUE *) procglobal->autovacFreeProcs;
00810 procglobal->autovacFreeProcs = MyProc;
00811 }
00812 else if (IsBackgroundWorker)
00813 {
00814 MyProc->links.next = (SHM_QUEUE *) procglobal->bgworkerFreeProcs;
00815 procglobal->bgworkerFreeProcs = MyProc;
00816 }
00817 else
00818 {
00819 MyProc->links.next = (SHM_QUEUE *) procglobal->freeProcs;
00820 procglobal->freeProcs = MyProc;
00821 }
00822
00823
00824 MyProc = NULL;
00825
00826
00827 procglobal->spins_per_delay = update_spins_per_delay(procglobal->spins_per_delay);
00828
00829 SpinLockRelease(ProcStructLock);
00830
00831
00832
00833
00834
00835
00836 if (IsUnderPostmaster && !IsAutoVacuumLauncherProcess())
00837 MarkPostmasterChildInactive();
00838
00839
00840 if (AutovacuumLauncherPid != 0)
00841 kill(AutovacuumLauncherPid, SIGUSR2);
00842 }
00843
00844
00845
00846
00847
00848
00849 static void
00850 AuxiliaryProcKill(int code, Datum arg)
00851 {
00852 int proctype = DatumGetInt32(arg);
00853 PGPROC *auxproc PG_USED_FOR_ASSERTS_ONLY;
00854
00855 Assert(proctype >= 0 && proctype < NUM_AUXILIARY_PROCS);
00856
00857 auxproc = &AuxiliaryProcs[proctype];
00858
00859 Assert(MyProc == auxproc);
00860
00861
00862 LWLockReleaseAll();
00863
00864
00865 DisownLatch(&MyProc->procLatch);
00866
00867 SpinLockAcquire(ProcStructLock);
00868
00869
00870 MyProc->pid = 0;
00871
00872
00873 MyProc = NULL;
00874
00875
00876 ProcGlobal->spins_per_delay = update_spins_per_delay(ProcGlobal->spins_per_delay);
00877
00878 SpinLockRelease(ProcStructLock);
00879 }
00880
00881
00882
00883
00884
00885
00886
00887
00888
00889
00890
00891
00892
00893 #ifdef NOT_USED
00894 PROC_QUEUE *
00895 ProcQueueAlloc(const char *name)
00896 {
00897 PROC_QUEUE *queue;
00898 bool found;
00899
00900 queue = (PROC_QUEUE *)
00901 ShmemInitStruct(name, sizeof(PROC_QUEUE), &found);
00902
00903 if (!found)
00904 ProcQueueInit(queue);
00905
00906 return queue;
00907 }
00908 #endif
00909
00910
00911
00912
00913 void
00914 ProcQueueInit(PROC_QUEUE *queue)
00915 {
00916 SHMQueueInit(&(queue->links));
00917 queue->size = 0;
00918 }
00919
00920
00921
00922
00923
00924
00925
00926
00927
00928
00929
00930
00931
00932
00933
00934
00935
00936
00937
00938
00939
00940 int
00941 ProcSleep(LOCALLOCK *locallock, LockMethod lockMethodTable)
00942 {
00943 LOCKMODE lockmode = locallock->tag.mode;
00944 LOCK *lock = locallock->lock;
00945 PROCLOCK *proclock = locallock->proclock;
00946 uint32 hashcode = locallock->hashcode;
00947 LWLockId partitionLock = LockHashPartitionLock(hashcode);
00948 PROC_QUEUE *waitQueue = &(lock->waitProcs);
00949 LOCKMASK myHeldLocks = MyProc->heldLocks;
00950 bool early_deadlock = false;
00951 bool allow_autovacuum_cancel = true;
00952 int myWaitStatus;
00953 PGPROC *proc;
00954 int i;
00955
00956
00957
00958
00959
00960
00961
00962
00963
00964
00965
00966
00967
00968
00969
00970
00971
00972
00973 if (myHeldLocks != 0)
00974 {
00975 LOCKMASK aheadRequests = 0;
00976
00977 proc = (PGPROC *) waitQueue->links.next;
00978 for (i = 0; i < waitQueue->size; i++)
00979 {
00980
00981 if (lockMethodTable->conflictTab[proc->waitLockMode] & myHeldLocks)
00982 {
00983
00984 if (lockMethodTable->conflictTab[lockmode] & proc->heldLocks)
00985 {
00986
00987
00988
00989
00990
00991
00992
00993 RememberSimpleDeadLock(MyProc, lockmode, lock, proc);
00994 early_deadlock = true;
00995 break;
00996 }
00997
00998 if ((lockMethodTable->conflictTab[lockmode] & aheadRequests) == 0 &&
00999 LockCheckConflicts(lockMethodTable,
01000 lockmode,
01001 lock,
01002 proclock,
01003 MyProc) == STATUS_OK)
01004 {
01005
01006 GrantLock(lock, proclock, lockmode);
01007 GrantAwaitedLock();
01008 return STATUS_OK;
01009 }
01010
01011 break;
01012 }
01013
01014 aheadRequests |= LOCKBIT_ON(proc->waitLockMode);
01015 proc = (PGPROC *) proc->links.next;
01016 }
01017
01018
01019
01020
01021
01022 }
01023 else
01024 {
01025
01026 proc = (PGPROC *) &(waitQueue->links);
01027 }
01028
01029
01030
01031
01032 SHMQueueInsertBefore(&(proc->links), &(MyProc->links));
01033 waitQueue->size++;
01034
01035 lock->waitMask |= LOCKBIT_ON(lockmode);
01036
01037
01038 MyProc->waitLock = lock;
01039 MyProc->waitProcLock = proclock;
01040 MyProc->waitLockMode = lockmode;
01041
01042 MyProc->waitStatus = STATUS_WAITING;
01043
01044
01045
01046
01047
01048
01049 if (early_deadlock)
01050 {
01051 RemoveFromWaitQueue(MyProc, hashcode);
01052 return STATUS_ERROR;
01053 }
01054
01055
01056 lockAwaited = locallock;
01057
01058
01059
01060
01061
01062
01063
01064
01065
01066 LWLockRelease(partitionLock);
01067
01068
01069
01070
01071
01072
01073
01074 if (RecoveryInProgress() && !InRecovery)
01075 CheckRecoveryConflictDeadlock();
01076
01077
01078 deadlock_state = DS_NOT_YET_CHECKED;
01079
01080
01081
01082
01083
01084
01085
01086
01087
01088
01089
01090
01091
01092 if (LockTimeout > 0)
01093 {
01094 EnableTimeoutParams timeouts[2];
01095
01096 timeouts[0].id = DEADLOCK_TIMEOUT;
01097 timeouts[0].type = TMPARAM_AFTER;
01098 timeouts[0].delay_ms = DeadlockTimeout;
01099 timeouts[1].id = LOCK_TIMEOUT;
01100 timeouts[1].type = TMPARAM_AFTER;
01101 timeouts[1].delay_ms = LockTimeout;
01102 enable_timeouts(timeouts, 2);
01103 }
01104 else
01105 enable_timeout_after(DEADLOCK_TIMEOUT, DeadlockTimeout);
01106
01107
01108
01109
01110
01111
01112
01113
01114
01115
01116
01117
01118
01119
01120
01121
01122
01123
01124 do
01125 {
01126 PGSemaphoreLock(&MyProc->sem, true);
01127
01128
01129
01130
01131
01132
01133 myWaitStatus = MyProc->waitStatus;
01134
01135
01136
01137
01138
01139 if (deadlock_state == DS_BLOCKED_BY_AUTOVACUUM && allow_autovacuum_cancel)
01140 {
01141 PGPROC *autovac = GetBlockingAutoVacuumPgproc();
01142 PGXACT *autovac_pgxact = &ProcGlobal->allPgXact[autovac->pgprocno];
01143
01144 LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
01145
01146
01147
01148
01149
01150 if ((autovac != NULL) &&
01151 (autovac_pgxact->vacuumFlags & PROC_IS_AUTOVACUUM) &&
01152 !(autovac_pgxact->vacuumFlags & PROC_VACUUM_FOR_WRAPAROUND))
01153 {
01154 int pid = autovac->pid;
01155 StringInfoData locktagbuf;
01156 StringInfoData logbuf;
01157
01158 initStringInfo(&locktagbuf);
01159 initStringInfo(&logbuf);
01160 DescribeLockTag(&locktagbuf, &lock->tag);
01161 appendStringInfo(&logbuf,
01162 _("Process %d waits for %s on %s."),
01163 MyProcPid,
01164 GetLockmodeName(lock->tag.locktag_lockmethodid,
01165 lockmode),
01166 locktagbuf.data);
01167
01168
01169 LWLockRelease(ProcArrayLock);
01170
01171 ereport(LOG,
01172 (errmsg("sending cancel to blocking autovacuum PID %d",
01173 pid),
01174 errdetail_log("%s", logbuf.data)));
01175
01176 pfree(logbuf.data);
01177 pfree(locktagbuf.data);
01178
01179
01180 if (kill(pid, SIGINT) < 0)
01181 {
01182
01183 ereport(WARNING,
01184 (errmsg("could not send signal to process %d: %m",
01185 pid)));
01186 }
01187 }
01188 else
01189 LWLockRelease(ProcArrayLock);
01190
01191
01192 allow_autovacuum_cancel = false;
01193 }
01194
01195
01196
01197
01198
01199 if (log_lock_waits && deadlock_state != DS_NOT_YET_CHECKED)
01200 {
01201 StringInfoData buf;
01202 const char *modename;
01203 long secs;
01204 int usecs;
01205 long msecs;
01206
01207 initStringInfo(&buf);
01208 DescribeLockTag(&buf, &locallock->tag.lock);
01209 modename = GetLockmodeName(locallock->tag.lock.locktag_lockmethodid,
01210 lockmode);
01211 TimestampDifference(get_timeout_start_time(DEADLOCK_TIMEOUT),
01212 GetCurrentTimestamp(),
01213 &secs, &usecs);
01214 msecs = secs * 1000 + usecs / 1000;
01215 usecs = usecs % 1000;
01216
01217 if (deadlock_state == DS_SOFT_DEADLOCK)
01218 ereport(LOG,
01219 (errmsg("process %d avoided deadlock for %s on %s by rearranging queue order after %ld.%03d ms",
01220 MyProcPid, modename, buf.data, msecs, usecs)));
01221 else if (deadlock_state == DS_HARD_DEADLOCK)
01222 {
01223
01224
01225
01226
01227
01228
01229
01230 ereport(LOG,
01231 (errmsg("process %d detected deadlock while waiting for %s on %s after %ld.%03d ms",
01232 MyProcPid, modename, buf.data, msecs, usecs)));
01233 }
01234
01235 if (myWaitStatus == STATUS_WAITING)
01236 ereport(LOG,
01237 (errmsg("process %d still waiting for %s on %s after %ld.%03d ms",
01238 MyProcPid, modename, buf.data, msecs, usecs)));
01239 else if (myWaitStatus == STATUS_OK)
01240 ereport(LOG,
01241 (errmsg("process %d acquired %s on %s after %ld.%03d ms",
01242 MyProcPid, modename, buf.data, msecs, usecs)));
01243 else
01244 {
01245 Assert(myWaitStatus == STATUS_ERROR);
01246
01247
01248
01249
01250
01251
01252
01253
01254
01255 if (deadlock_state != DS_HARD_DEADLOCK)
01256 ereport(LOG,
01257 (errmsg("process %d failed to acquire %s on %s after %ld.%03d ms",
01258 MyProcPid, modename, buf.data, msecs, usecs)));
01259 }
01260
01261
01262
01263
01264
01265 deadlock_state = DS_NO_DEADLOCK;
01266
01267 pfree(buf.data);
01268 }
01269 } while (myWaitStatus == STATUS_WAITING);
01270
01271
01272
01273
01274 if (LockTimeout > 0)
01275 {
01276 DisableTimeoutParams timeouts[2];
01277
01278 timeouts[0].id = DEADLOCK_TIMEOUT;
01279 timeouts[0].keep_indicator = false;
01280 timeouts[1].id = LOCK_TIMEOUT;
01281 timeouts[1].keep_indicator = false;
01282 disable_timeouts(timeouts, 2);
01283 }
01284 else
01285 disable_timeout(DEADLOCK_TIMEOUT, false);
01286
01287
01288
01289
01290
01291
01292 LWLockAcquire(partitionLock, LW_EXCLUSIVE);
01293
01294
01295
01296
01297 lockAwaited = NULL;
01298
01299
01300
01301
01302 if (MyProc->waitStatus == STATUS_OK)
01303 GrantAwaitedLock();
01304
01305
01306
01307
01308
01309 return MyProc->waitStatus;
01310 }
01311
01312
01313
01314
01315
01316
01317
01318
01319
01320
01321
01322
01323
01324
01325
01326 PGPROC *
01327 ProcWakeup(PGPROC *proc, int waitStatus)
01328 {
01329 PGPROC *retProc;
01330
01331
01332 if (proc->links.prev == NULL ||
01333 proc->links.next == NULL)
01334 return NULL;
01335 Assert(proc->waitStatus == STATUS_WAITING);
01336
01337
01338 retProc = (PGPROC *) proc->links.next;
01339
01340
01341 SHMQueueDelete(&(proc->links));
01342 (proc->waitLock->waitProcs.size)--;
01343
01344
01345 proc->waitLock = NULL;
01346 proc->waitProcLock = NULL;
01347 proc->waitStatus = waitStatus;
01348
01349
01350 PGSemaphoreUnlock(&proc->sem);
01351
01352 return retProc;
01353 }
01354
01355
01356
01357
01358
01359
01360
01361
01362 void
01363 ProcLockWakeup(LockMethod lockMethodTable, LOCK *lock)
01364 {
01365 PROC_QUEUE *waitQueue = &(lock->waitProcs);
01366 int queue_size = waitQueue->size;
01367 PGPROC *proc;
01368 LOCKMASK aheadRequests = 0;
01369
01370 Assert(queue_size >= 0);
01371
01372 if (queue_size == 0)
01373 return;
01374
01375 proc = (PGPROC *) waitQueue->links.next;
01376
01377 while (queue_size-- > 0)
01378 {
01379 LOCKMODE lockmode = proc->waitLockMode;
01380
01381
01382
01383
01384
01385 if ((lockMethodTable->conflictTab[lockmode] & aheadRequests) == 0 &&
01386 LockCheckConflicts(lockMethodTable,
01387 lockmode,
01388 lock,
01389 proc->waitProcLock,
01390 proc) == STATUS_OK)
01391 {
01392
01393 GrantLock(lock, proc->waitProcLock, lockmode);
01394 proc = ProcWakeup(proc, STATUS_OK);
01395
01396
01397
01398
01399
01400
01401 }
01402 else
01403 {
01404
01405
01406
01407 aheadRequests |= LOCKBIT_ON(lockmode);
01408 proc = (PGPROC *) proc->links.next;
01409 }
01410 }
01411
01412 Assert(waitQueue->size >= 0);
01413 }
01414
01415
01416
01417
01418
01419
01420
01421
01422
01423
01424
01425
01426
01427
01428 void
01429 CheckDeadLock(void)
01430 {
01431 int i;
01432
01433
01434
01435
01436
01437
01438
01439
01440
01441
01442
01443 for (i = 0; i < NUM_LOCK_PARTITIONS; i++)
01444 LWLockAcquire(FirstLockMgrLock + i, LW_EXCLUSIVE);
01445
01446
01447
01448
01449
01450
01451
01452
01453
01454
01455
01456
01457 if (MyProc->links.prev == NULL ||
01458 MyProc->links.next == NULL)
01459 goto check_done;
01460
01461 #ifdef LOCK_DEBUG
01462 if (Debug_deadlocks)
01463 DumpAllLocks();
01464 #endif
01465
01466
01467 deadlock_state = DeadLockCheck(MyProc);
01468
01469 if (deadlock_state == DS_HARD_DEADLOCK)
01470 {
01471
01472
01473
01474
01475
01476
01477
01478
01479
01480
01481
01482
01483 Assert(MyProc->waitLock != NULL);
01484 RemoveFromWaitQueue(MyProc, LockTagHashCode(&(MyProc->waitLock->tag)));
01485
01486
01487
01488
01489
01490 PGSemaphoreUnlock(&MyProc->sem);
01491
01492
01493
01494
01495
01496
01497
01498
01499
01500
01501
01502 }
01503 else if (log_lock_waits || deadlock_state == DS_BLOCKED_BY_AUTOVACUUM)
01504 {
01505
01506
01507
01508
01509
01510
01511
01512
01513
01514 PGSemaphoreUnlock(&MyProc->sem);
01515 }
01516
01517
01518
01519
01520
01521
01522
01523
01524 check_done:
01525 for (i = NUM_LOCK_PARTITIONS; --i >= 0;)
01526 LWLockRelease(FirstLockMgrLock + i);
01527 }
01528
01529
01530
01531
01532
01533
01534
01535
01536
01537
01538
01539
01540
01541 void
01542 ProcWaitForSignal(void)
01543 {
01544 PGSemaphoreLock(&MyProc->sem, true);
01545 }
01546
01547
01548
01549
01550 void
01551 ProcSendSignal(int pid)
01552 {
01553 PGPROC *proc = NULL;
01554
01555 if (RecoveryInProgress())
01556 {
01557
01558 volatile PROC_HDR *procglobal = ProcGlobal;
01559
01560 SpinLockAcquire(ProcStructLock);
01561
01562
01563
01564
01565
01566
01567
01568
01569
01570 if (pid == procglobal->startupProcPid)
01571 proc = procglobal->startupProc;
01572
01573 SpinLockRelease(ProcStructLock);
01574 }
01575
01576 if (proc == NULL)
01577 proc = BackendPidGetProc(pid);
01578
01579 if (proc != NULL)
01580 PGSemaphoreUnlock(&proc->sem);
01581 }