PostgreSQL Source Code: src/backend/storage/lmgr/lock.c Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
31
32#include <signal.h>
34
50
51
52
55
56#define NLOCKENTS() \
57 mul_size(max_locks_per_xact, add_size(MaxBackends, max_prepared_xacts))
58
59
60
61
62
63
64
66 0,
67
68
70
71
73
74
77
78
82
83
87
88
92
93
98
99
104
105};
106
107
109{
110 "INVALID",
111 "AccessShareLock",
112 "RowShareLock",
113 "RowExclusiveLock",
114 "ShareUpdateExclusiveLock",
115 "ShareLock",
116 "ShareRowExclusiveLock",
117 "ExclusiveLock",
118 "AccessExclusiveLock"
119};
120
121#ifndef LOCK_DEBUG
123#endif
124
129#ifdef LOCK_DEBUG
130 &Trace_locks
131#else
133#endif
134};
135
140#ifdef LOCK_DEBUG
141 &Trace_userlocks
142#else
144#endif
145};
146
147
148
149
151 NULL,
154};
155
156
157
159{
163
164
165
166
167
168
169
170
171
172
173
174
175
177
178
179
180
181
182
183
184
185
186
187
188
189
190
192
193
194
195
196
197
198
199
200
201
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217#define FAST_PATH_REL_GROUP(rel) \
218 (((uint64) (rel) * 49157) & (FastPathLockGroupsPerBackend - 1))
219
220
221
222
223
224#define FAST_PATH_SLOT(group, index) \
225 (AssertMacro((uint32) (group) < FastPathLockGroupsPerBackend), \
226 AssertMacro((uint32) (index) < FP_LOCK_SLOTS_PER_GROUP), \
227 ((group) * FP_LOCK_SLOTS_PER_GROUP + (index)))
228
229
230
231
232
233#define FAST_PATH_GROUP(index) \
234 (AssertMacro((uint32) (index) < FastPathLockSlotsPerBackend()), \
235 ((index) / FP_LOCK_SLOTS_PER_GROUP))
236#define FAST_PATH_INDEX(index) \
237 (AssertMacro((uint32) (index) < FastPathLockSlotsPerBackend()), \
238 ((index) % FP_LOCK_SLOTS_PER_GROUP))
239
240
241#define FAST_PATH_BITS_PER_SLOT 3
242#define FAST_PATH_LOCKNUMBER_OFFSET 1
243#define FAST_PATH_MASK ((1 << FAST_PATH_BITS_PER_SLOT) - 1)
244#define FAST_PATH_BITS(proc, n) (proc)->fpLockBits[FAST_PATH_GROUP(n)]
245#define FAST_PATH_GET_BITS(proc, n) \
246 ((FAST_PATH_BITS(proc, n) >> (FAST_PATH_BITS_PER_SLOT * FAST_PATH_INDEX(n))) & FAST_PATH_MASK)
247#define FAST_PATH_BIT_POSITION(n, l) \
248 (AssertMacro((l) >= FAST_PATH_LOCKNUMBER_OFFSET), \
249 AssertMacro((l) < FAST_PATH_BITS_PER_SLOT+FAST_PATH_LOCKNUMBER_OFFSET), \
250 AssertMacro((n) < FastPathLockSlotsPerBackend()), \
251 ((l) - FAST_PATH_LOCKNUMBER_OFFSET + FAST_PATH_BITS_PER_SLOT * (FAST_PATH_INDEX(n))))
252#define FAST_PATH_SET_LOCKMODE(proc, n, l) \
253 FAST_PATH_BITS(proc, n) |= UINT64CONST(1) << FAST_PATH_BIT_POSITION(n, l)
254#define FAST_PATH_CLEAR_LOCKMODE(proc, n, l) \
255 FAST_PATH_BITS(proc, n) &= ~(UINT64CONST(1) << FAST_PATH_BIT_POSITION(n, l))
256#define FAST_PATH_CHECK_LOCKMODE(proc, n, l) \
257 (FAST_PATH_BITS(proc, n) & (UINT64CONST(1) << FAST_PATH_BIT_POSITION(n, l)))
258
259
260
261
262
263
264
265
266
267#define EligibleForRelationFastPath(locktag, mode) \
268 ((locktag)->locktag_lockmethodid == DEFAULT_LOCKMETHOD && \
269 (locktag)->locktag_type == LOCKTAG_RELATION && \
270 (locktag)->locktag_field1 == MyDatabaseId && \
271 MyDatabaseId != InvalidOid && \
272 (mode) < ShareUpdateExclusiveLock)
273#define ConflictsWithRelationFastPath(locktag, mode) \
274 ((locktag)->locktag_lockmethodid == DEFAULT_LOCKMETHOD && \
275 (locktag)->locktag_type == LOCKTAG_RELATION && \
276 (locktag)->locktag_field1 != InvalidOid && \
277 (mode) > ShareUpdateExclusiveLock)
278
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300#define FAST_PATH_STRONG_LOCK_HASH_BITS 10
301#define FAST_PATH_STRONG_LOCK_HASH_PARTITIONS \
302 (1 << FAST_PATH_STRONG_LOCK_HASH_BITS)
303#define FastPathStrongLockHashPartition(hashcode) \
304 ((hashcode) % FAST_PATH_STRONG_LOCK_HASH_PARTITIONS)
305
306typedef struct
307{
311
313
314
315
316
317
318
319
320
324
325
326
330
331
332#ifdef LOCK_DEBUG
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
352bool Trace_locks = false;
353bool Trace_userlocks = false;
354int Trace_lock_table = 0;
355bool Debug_deadlocks = false;
356
357
358inline static bool
359LOCK_DEBUG_ENABLED(const LOCKTAG *tag)
360{
361 return
364 || (Trace_lock_table &&
366}
367
368
369inline static void
371{
372 if (LOCK_DEBUG_ENABLED(&lock->tag))
374 "%s: lock(%p) id(%u,%u,%u,%u,%u,%u) grantMask(%x) "
375 "req(%d,%d,%d,%d,%d,%d,%d)=%d "
376 "grant(%d,%d,%d,%d,%d,%d,%d)=%d wait(%d) type(%s)",
377 where, lock,
390}
391
392
393inline static void
395{
396 if (LOCK_DEBUG_ENABLED(&proclockP->tag.myLock->tag))
398 "%s: proclock(%p) lock(%p) method(%u) proc(%p) hold(%x)",
399 where, proclockP, proclockP->tag.myLock,
402}
403#else
404
405#define LOCK_PRINT(where, lock, type) ((void) 0)
406#define PROCLOCK_PRINT(where, proclockP) ((void) 0)
407#endif
408
409
424 bool wakeupNeeded);
427 bool decrement_strong_lock_count);
430
431
432
433
434
435
436
437
438
439
440
441
442void
444{
446 long init_table_size,
447 max_table_size;
448 bool found;
449
450
451
452
453
455 init_table_size = max_table_size / 2;
456
457
458
459
460
464
466 init_table_size,
467 max_table_size,
468 &info,
470
471
472 max_table_size *= 2;
473 init_table_size *= 2;
474
475
476
477
478
483
485 init_table_size,
486 max_table_size,
487 &info,
489
490
491
492
496 if (!found)
498}
499
500
501
502
503void
505{
506
507
508
509
511
514
516 16,
517 &info,
519}
520
521
522
523
524
527{
529
532}
533
534
535
536
539{
541
544}
545
546
547
548
549
550
551
552
553
554
557{
559}
560
561
562
563
564
565
566
567
568
569
570
571
574{
578
580
581
583
584
585
586
587
588
589
590
593
594 return lockhash;
595}
596
597
598
599
600
601
602
605{
606 uint32 lockhash = hashcode;
608
609
610
611
614
615 return lockhash;
616}
617
618
619
620
621bool
623{
625
627 return true;
628
629 return false;
630}
631
632
633
634
635
636
637
638
639
640
641bool
643 LOCKMODE lockmode, bool orstronger)
644{
647
648
649
650
651 MemSet(&localtag, 0, sizeof(localtag));
652 localtag.lock = *locktag;
653 localtag.mode = lockmode;
654
656 &localtag,
658
659 if (locallock && locallock->nLocks > 0)
660 return true;
661
662 if (orstronger)
663 {
665
666 for (slockmode = lockmode + 1;
668 slockmode++)
669 {
671 return true;
672 }
673 }
674
675 return false;
676}
677
678#ifdef USE_ASSERT_CHECKING
679
680
681
682
684GetLockMethodLocalHash(void)
685{
687}
688#endif
689
690
691
692
693
694bool
696{
703 LWLock *partitionLock;
704 bool hasWaiters = false;
705
707 elog(ERROR, "unrecognized lock method: %d", lockmethodid);
708 lockMethodTable = LockMethods[lockmethodid];
709 if (lockmode <= 0 || lockmode > lockMethodTable->numLockModes)
710 elog(ERROR, "unrecognized lock mode: %d", lockmode);
711
712#ifdef LOCK_DEBUG
713 if (LOCK_DEBUG_ENABLED(locktag))
714 elog(LOG, "LockHasWaiters: lock [%u,%u] %s",
717#endif
718
719
720
721
722 MemSet(&localtag, 0, sizeof(localtag));
723 localtag.lock = *locktag;
724 localtag.mode = lockmode;
725
727 &localtag,
729
730
731
732
733 if (!locallock || locallock->nLocks <= 0)
734 {
735 elog(WARNING, "you don't own a lock of type %s",
737 return false;
738 }
739
740
741
742
744
746
747
748
749
750
751
752 lock = locallock->lock;
753 LOCK_PRINT("LockHasWaiters: found", lock, lockmode);
754 proclock = locallock->proclock;
756
757
758
759
760
762 {
763 PROCLOCK_PRINT("LockHasWaiters: WRONGTYPE", proclock);
765 elog(WARNING, "you don't own a lock of type %s",
768 return false;
769 }
770
771
772
773
775 hasWaiters = true;
776
778
779 return hasWaiters;
780}
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
810 bool sessionLock,
811 bool dontWait)
812{
814 true, NULL, false);
815}
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
837 bool sessionLock,
838 bool dontWait,
839 bool reportMemoryError,
841 bool logLockFailure)
842{
849 bool found;
852 LWLock *partitionLock;
853 bool found_conflict;
855 bool log_lock = false;
856
858 elog(ERROR, "unrecognized lock method: %d", lockmethodid);
859 lockMethodTable = LockMethods[lockmethodid];
860 if (lockmode <= 0 || lockmode > lockMethodTable->numLockModes)
861 elog(ERROR, "unrecognized lock mode: %d", lockmode);
862
868 (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
869 errmsg("cannot acquire lock mode %s on database objects while recovery is in progress",
871 errhint("Only RowExclusiveLock or less can be acquired on database objects during recovery.")));
872
873#ifdef LOCK_DEBUG
874 if (LOCK_DEBUG_ENABLED(locktag))
875 elog(LOG, "LockAcquire: lock [%u,%u] %s",
878#endif
879
880
881 if (sessionLock)
882 owner = NULL;
883 else
885
886
887
888
889 MemSet(&localtag, 0, sizeof(localtag));
890 localtag.lock = *locktag;
891 localtag.mode = lockmode;
892
894 &localtag,
896
897
898
899
900 if (!found)
901 {
902 locallock->lock = NULL;
905 locallock->nLocks = 0;
910 locallock->lockOwners = NULL;
914 }
915 else
916 {
917
919 {
921
926 }
927 }
928 hashcode = locallock->hashcode;
929
930 if (locallockp)
931 *locallockp = locallock;
932
933
934
935
936
937
938
939 if (locallock->nLocks > 0)
940 {
944 else
946 }
947
948
949
950
951
952
953 Assert(!IsRelationExtensionLockHeld);
954
955
956
957
958
959
960
961
962
963
964
965
966
971 {
973 log_lock = true;
974 }
975
976
977
978
979
980
981
982
983
984
985
988 {
990 bool acquired;
991
992
993
994
995
996
997
1000 acquired = false;
1001 else
1003 lockmode);
1005 if (acquired)
1006 {
1007
1008
1009
1010
1011
1012 locallock->lock = NULL;
1016 }
1017 }
1018
1019
1020
1021
1022
1023
1024
1026 {
1028
1031 hashcode))
1032 {
1034 if (locallock->nLocks == 0)
1036 if (locallockp)
1037 *locallockp = NULL;
1038 if (reportMemoryError)
1040 (errcode(ERRCODE_OUT_OF_MEMORY),
1041 errmsg("out of shared memory"),
1042 errhint("You might need to increase \"%s\".", "max_locks_per_transaction")));
1043 else
1045 }
1046 }
1047
1048
1049
1050
1051
1052
1054
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1067 hashcode, lockmode);
1068 if (!proclock)
1069 {
1072 if (locallock->nLocks == 0)
1074 if (locallockp)
1075 *locallockp = NULL;
1076 if (reportMemoryError)
1078 (errcode(ERRCODE_OUT_OF_MEMORY),
1079 errmsg("out of shared memory"),
1080 errhint("You might need to increase \"%s\".", "max_locks_per_transaction")));
1081 else
1083 }
1084 locallock->proclock = proclock;
1086 locallock->lock = lock;
1087
1088
1089
1090
1091
1092
1094 found_conflict = true;
1095 else
1097 lock, proclock);
1098
1099 if (!found_conflict)
1100 {
1101
1102 GrantLock(lock, proclock, lockmode);
1104 }
1105 else
1106 {
1107
1108
1109
1110
1111
1112 waitResult = JoinWaitQueue(locallock, lockMethodTable, dontWait);
1113 }
1114
1116 {
1117
1118
1119
1120
1121
1122
1123
1124
1126
1127 if (proclock->holdMask == 0)
1128 {
1129 uint32 proclock_hashcode;
1130
1132 hashcode);
1136 &(proclock->tag),
1137 proclock_hashcode,
1139 NULL))
1140 elog(PANIC, "proclock table corrupted");
1141 }
1142 else
1143 PROCLOCK_PRINT("LockAcquire: did not join wait queue", proclock);
1146 LOCK_PRINT("LockAcquire: did not join wait queue",
1147 lock, lockmode);
1149 (lock->requested[lockmode] >= 0));
1152 if (locallock->nLocks == 0)
1154
1155 if (dontWait)
1156 {
1157
1158
1159
1160
1161
1162 if (logLockFailure)
1163 {
1165 lock_waiters_sbuf,
1166 lock_holders_sbuf;
1167 const char *modename;
1168 int lockHoldersNum = 0;
1169
1173
1176 lockmode);
1177
1178
1181 &lock_waiters_sbuf, &lockHoldersNum);
1183
1185 (errmsg("process %d could not obtain %s on %s",
1188 "Process holding the lock: %s, Wait queue: %s.",
1189 "Processes holding the lock: %s, Wait queue: %s.",
1190 lockHoldersNum,
1191 lock_holders_sbuf.data,
1192 lock_waiters_sbuf.data)));
1193
1197 }
1198 if (locallockp)
1199 *locallockp = NULL;
1201 }
1202 else
1203 {
1205
1206 }
1207 }
1208
1209
1210
1211
1212
1214 {
1216 PROCLOCK_PRINT("LockAcquire: sleeping on lock", proclock);
1217 LOCK_PRINT("LockAcquire: sleeping on lock", lock, lockmode);
1219
1220 waitResult = WaitOnLock(locallock, owner);
1221
1222
1223
1224
1225
1226
1227
1229 {
1230
1231
1232
1233
1236
1237 }
1238 }
1239 else
1242
1243
1246
1247
1248
1249
1250
1252
1253
1254
1255
1256
1257 if (log_lock)
1258 {
1259
1260
1261
1262
1263
1266 }
1267
1269}
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1284{
1288 uint32 proclock_hashcode;
1289 bool found;
1290
1291
1292
1293
1295 locktag,
1296 hashcode,
1298 &found);
1299 if (!lock)
1300 return NULL;
1301
1302
1303
1304
1305 if (!found)
1306 {
1315 LOCK_PRINT("LockAcquire: new", lock, lockmode);
1316 }
1317 else
1318 {
1319 LOCK_PRINT("LockAcquire: found", lock, lockmode);
1323 }
1324
1325
1326
1327
1328 proclocktag.myLock = lock;
1329 proclocktag.myProc = proc;
1330
1331 proclock_hashcode = ProcLockHashCode(&proclocktag, hashcode);
1332
1333
1334
1335
1337 &proclocktag,
1338 proclock_hashcode,
1340 &found);
1341 if (!proclock)
1342 {
1343
1345 {
1346
1347
1348
1349
1350
1351
1354 &(lock->tag),
1355 hashcode,
1357 NULL))
1358 elog(PANIC, "lock table corrupted");
1359 }
1360 return NULL;
1361 }
1362
1363
1364
1365
1366 if (!found)
1367 {
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1384
1388 }
1389 else
1390 {
1393
1394#ifdef CHECK_DEADLOCK_RISK
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410 {
1411 int i;
1412
1414 {
1416 {
1417 if (i >= (int) lockmode)
1418 break;
1419 elog(LOG, "deadlock risk: raising lock level"
1420 " from %s to %s on object %u/%u/%u",
1425 break;
1426 }
1427 }
1428 }
1429#endif
1430 }
1431
1432
1433
1434
1435
1436
1440
1441
1442
1443
1444
1446 elog(ERROR, "lock %s on object %u/%u/%u is already held",
1450
1451 return proclock;
1452}
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462static inline void
1464{
1465#ifdef USE_ASSERT_CHECKING
1467 IsRelationExtensionLockHeld = acquired;
1468#endif
1469}
1470
1471
1472
1473
1474static void
1476{
1477 int i;
1478
1480 {
1483 }
1488
1490 {
1491 uint32 fasthashcode;
1492
1494
1500 }
1501
1503 &(locallock->tag),
1505 elog(WARNING, "locallock table corrupted");
1506
1507
1508
1509
1511}
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527bool
1532{
1533 int numLockModes = lockMethodTable->numLockModes;
1535 int conflictMask = lockMethodTable->conflictTab[lockmode];
1537 int totalConflictsRemaining = 0;
1539 int i;
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550 if (!(conflictMask & lock->grantMask))
1551 {
1552 PROCLOCK_PRINT("LockCheckConflicts: no conflict", proclock);
1553 return false;
1554 }
1555
1556
1557
1558
1559
1560
1561 myLocks = proclock->holdMask;
1562 for (i = 1; i <= numLockModes; i++)
1563 {
1564 if ((conflictMask & LOCKBIT_ON(i)) == 0)
1565 {
1566 conflictsRemaining[i] = 0;
1567 continue;
1568 }
1569 conflictsRemaining[i] = lock->granted[i];
1571 --conflictsRemaining[i];
1572 totalConflictsRemaining += conflictsRemaining[i];
1573 }
1574
1575
1576 if (totalConflictsRemaining == 0)
1577 {
1578 PROCLOCK_PRINT("LockCheckConflicts: resolved (simple)", proclock);
1579 return false;
1580 }
1581
1582
1584 {
1586 PROCLOCK_PRINT("LockCheckConflicts: conflicting (simple)",
1587 proclock);
1588 return true;
1589 }
1590
1591
1592
1593
1595 {
1596 PROCLOCK_PRINT("LockCheckConflicts: conflicting (group)",
1597 proclock);
1598 return true;
1599 }
1600
1601
1602
1603
1604
1605
1606
1607
1608
1610 {
1613
1614 if (proclock != otherproclock &&
1616 (otherproclock->holdMask & conflictMask) != 0)
1617 {
1618 int intersectMask = otherproclock->holdMask & conflictMask;
1619
1620 for (i = 1; i <= numLockModes; i++)
1621 {
1622 if ((intersectMask & LOCKBIT_ON(i)) != 0)
1623 {
1624 if (conflictsRemaining[i] <= 0)
1625 elog(PANIC, "proclocks held do not match lock");
1626 conflictsRemaining[i]--;
1627 totalConflictsRemaining--;
1628 }
1629 }
1630
1631 if (totalConflictsRemaining == 0)
1632 {
1633 PROCLOCK_PRINT("LockCheckConflicts: resolved (group)",
1634 proclock);
1635 return false;
1636 }
1637 }
1638 }
1639
1640
1641 PROCLOCK_PRINT("LockCheckConflicts: conflicting (group)", proclock);
1642 return true;
1643}
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656void
1658{
1660 lock->granted[lockmode]++;
1665 LOCK_PRINT("GrantLock", lock, lockmode);
1668}
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679static bool
1682{
1683 bool wakeupNeeded = false;
1684
1688
1689
1690
1691
1695 lock->granted[lockmode]--;
1696
1697 if (lock->granted[lockmode] == 0)
1698 {
1699
1701 }
1702
1703 LOCK_PRINT("UnGrantLock: updated", lock, lockmode);
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1715 wakeupNeeded = true;
1716
1717
1718
1719
1722
1723 return wakeupNeeded;
1724}
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736static void
1739 bool wakeupNeeded)
1740{
1741
1742
1743
1744
1745 if (proclock->holdMask == 0)
1746 {
1747 uint32 proclock_hashcode;
1748
1754 &(proclock->tag),
1755 proclock_hashcode,
1757 NULL))
1758 elog(PANIC, "proclock table corrupted");
1759 }
1760
1762 {
1763
1764
1765
1766
1767 LOCK_PRINT("CleanUpLock: deleting", lock, 0);
1770 &(lock->tag),
1771 hashcode,
1773 NULL))
1774 elog(PANIC, "lock table corrupted");
1775 }
1776 else if (wakeupNeeded)
1777 {
1778
1780 }
1781}
1782
1783
1784
1785
1786
1787
1788
1789
1790static void
1792{
1794 int i;
1795
1797
1798 locallock->nLocks++;
1799
1801 {
1802 if (lockOwners[i].owner == owner)
1803 {
1805 return;
1806 }
1807 }
1808 lockOwners[i].owner = owner;
1809 lockOwners[i].nLocks = 1;
1811 if (owner != NULL)
1813
1814
1816}
1817
1818
1819
1820
1821
1822static void
1824{
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1842}
1843
1844
1845
1846
1847
1848static void
1850{
1852}
1853
1854
1855
1856
1857
1858void
1860{
1861 uint32 fasthashcode;
1863
1864 if (locallock == NULL)
1865 return;
1866
1875}
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887void
1889{
1891}
1892
1893
1894
1895
1898{
1900}
1901
1902
1903
1904
1905void
1907{
1909}
1910
1911
1912
1913
1914
1915
1916
1917
1918void
1920{
1923}
1924
1925
1926
1927
1928
1929
1932{
1934
1941
1942
1944
1945
1946
1947
1948
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1970 {
1972 }
1974 {
1975
1976
1977
1979
1980
1982 }
1984
1985
1986
1987
1989
1990
1992
1999
2000 return result;
2001}
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013void
2015{
2020
2021
2027
2028
2030
2031
2036 waitLock->requested[lockmode]--;
2037
2038 if (waitLock->granted[lockmode] == waitLock->requested[lockmode])
2040
2041
2045
2046
2047
2048
2049
2050
2051
2052
2055 true);
2056}
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069bool
2071{
2078 LWLock *partitionLock;
2079 bool wakeupNeeded;
2080
2082 elog(ERROR, "unrecognized lock method: %d", lockmethodid);
2083 lockMethodTable = LockMethods[lockmethodid];
2084 if (lockmode <= 0 || lockmode > lockMethodTable->numLockModes)
2085 elog(ERROR, "unrecognized lock mode: %d", lockmode);
2086
2087#ifdef LOCK_DEBUG
2088 if (LOCK_DEBUG_ENABLED(locktag))
2089 elog(LOG, "LockRelease: lock [%u,%u] %s",
2092#endif
2093
2094
2095
2096
2097 MemSet(&localtag, 0, sizeof(localtag));
2098 localtag.lock = *locktag;
2099 localtag.mode = lockmode;
2100
2102 &localtag,
2104
2105
2106
2107
2108 if (!locallock || locallock->nLocks <= 0)
2109 {
2110 elog(WARNING, "you don't own a lock of type %s",
2112 return false;
2113 }
2114
2115
2116
2117
2118 {
2121 int i;
2122
2123
2124 if (sessionLock)
2125 owner = NULL;
2126 else
2128
2130 {
2131 if (lockOwners[i].owner == owner)
2132 {
2133 Assert(lockOwners[i].nLocks > 0);
2134 if (--lockOwners[i].nLocks == 0)
2135 {
2136 if (owner != NULL)
2138
2140 if (i < locallock->numLockOwners)
2141 lockOwners[i] = lockOwners[locallock->numLockOwners];
2142 }
2143 break;
2144 }
2145 }
2146 if (i < 0)
2147 {
2148
2149 elog(WARNING, "you don't own a lock of type %s",
2151 return false;
2152 }
2153 }
2154
2155
2156
2157
2158
2159 locallock->nLocks--;
2160
2161 if (locallock->nLocks > 0)
2162 return true;
2163
2164
2165
2166
2167
2168
2169
2170
2172
2173
2176 {
2177 bool released;
2178
2179
2180
2181
2182
2185 lockmode);
2187 if (released)
2188 {
2190 return true;
2191 }
2192 }
2193
2194
2195
2196
2198
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209 lock = locallock->lock;
2210 if (!lock)
2211 {
2213
2216 locktag,
2219 NULL);
2220 if (!lock)
2221 elog(ERROR, "failed to re-find shared lock object");
2222 locallock->lock = lock;
2223
2224 proclocktag.myLock = lock;
2227 &proclocktag,
2229 NULL);
2231 elog(ERROR, "failed to re-find shared proclock object");
2232 }
2233 LOCK_PRINT("LockRelease: found", lock, lockmode);
2234 proclock = locallock->proclock;
2236
2237
2238
2239
2240
2242 {
2245 elog(WARNING, "you don't own a lock of type %s",
2248 return false;
2249 }
2250
2251
2252
2253
2254 wakeupNeeded = UnGrantLock(lock, lockmode, proclock, lockMethodTable);
2255
2257 lockMethodTable, locallock->hashcode,
2258 wakeupNeeded);
2259
2261
2263 return true;
2264}
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274void
2276{
2279 int i,
2280 numLockModes;
2283 int partition;
2284 bool have_fast_path_lwlock = false;
2285
2287 elog(ERROR, "unrecognized lock method: %d", lockmethodid);
2288 lockMethodTable = LockMethods[lockmethodid];
2289
2290#ifdef LOCK_DEBUG
2292 elog(LOG, "LockReleaseAll: lockmethod=%d", lockmethodid);
2293#endif
2294
2295
2296
2297
2298
2299
2300
2303
2304 numLockModes = lockMethodTable->numLockModes;
2305
2306
2307
2308
2309
2310
2311
2312
2313
2315
2317 {
2318
2319
2320
2321
2322 if (locallock->nLocks == 0)
2323 {
2325 continue;
2326 }
2327
2328
2330 continue;
2331
2332
2333
2334
2335
2336
2337 if (!allLocks)
2338 {
2340
2341
2343 {
2344 if (lockOwners[i].owner == NULL)
2345 lockOwners[0] = lockOwners[i];
2346 else
2348 }
2349
2351 lockOwners[0].owner == NULL &&
2352 lockOwners[0].nLocks > 0)
2353 {
2354
2357
2358 continue;
2359 }
2360 else
2362 }
2363
2364#ifdef USE_ASSERT_CHECKING
2365
2366
2367
2368
2369
2371 elog(WARNING, "tuple lock held at commit");
2372#endif
2373
2374
2375
2376
2377
2378 if (locallock->proclock == NULL || locallock->lock == NULL)
2379 {
2381 Oid relid;
2382
2383
2385 elog(PANIC, "locallock table corrupted");
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395 if (!have_fast_path_lwlock)
2396 {
2398 have_fast_path_lwlock = true;
2399 }
2400
2401
2404 {
2406 continue;
2407 }
2408
2409
2410
2411
2412
2413
2415 have_fast_path_lwlock = false;
2416
2417
2418
2419
2420
2421
2422
2423
2425 &locallock->tag.lock, lockmode, false);
2427 continue;
2428 }
2429
2430
2431 if (locallock->nLocks > 0)
2433
2434
2436 }
2437
2438
2439 if (have_fast_path_lwlock)
2441
2442
2443
2444
2446 {
2447 LWLock *partitionLock;
2450
2452
2453
2454
2455
2456
2457
2458
2459
2460
2461
2462
2463
2464
2465
2466
2467
2468
2469
2470
2471
2473 continue;
2474
2476
2478 {
2480 bool wakeupNeeded = false;
2481
2483
2485
2486
2488 continue;
2489
2490
2491
2492
2493
2494 if (allLocks)
2496 else
2498
2499
2500
2501
2502
2504 continue;
2505
2507 LOCK_PRINT("LockReleaseAll", lock, 0);
2512
2513
2514
2515
2516 for (i = 1; i <= numLockModes; i++)
2517 {
2519 wakeupNeeded |= UnGrantLock(lock, i, proclock,
2520 lockMethodTable);
2521 }
2524 LOCK_PRINT("LockReleaseAll: updated", lock, 0);
2525
2527
2528
2530 lockMethodTable,
2532 wakeupNeeded);
2533 }
2534
2536 }
2537
2538#ifdef LOCK_DEBUG
2540 elog(LOG, "LockReleaseAll done");
2541#endif
2542}
2543
2544
2545
2546
2547
2548void
2550{
2553
2555 elog(ERROR, "unrecognized lock method: %d", lockmethodid);
2556
2558
2560 {
2561
2563 continue;
2564
2566 }
2567}
2568
2569
2570
2571
2572
2573
2574
2575
2576
2577
2578void
2580{
2581 if (locallocks == NULL)
2582 {
2585
2587
2590 }
2591 else
2592 {
2593 int i;
2594
2595 for (i = nlocks - 1; i >= 0; i--)
2597 }
2598}
2599
2600
2601
2602
2603
2604
2605
2606
2607
2608
2609
2610
2611
2612
2613static void
2615{
2618 int i;
2619
2620
2621 if (sessionLock)
2622 owner = NULL;
2623 else
2625
2626
2629 {
2630 if (lockOwners[i].owner == owner)
2631 {
2632 Assert(lockOwners[i].nLocks > 0);
2633 if (lockOwners[i].nLocks < locallock->nLocks)
2634 {
2635
2636
2637
2638
2640
2642 if (owner != NULL)
2644 if (i < locallock->numLockOwners)
2645 lockOwners[i] = lockOwners[locallock->numLockOwners];
2646 }
2647 else
2648 {
2649 Assert(lockOwners[i].nLocks == locallock->nLocks);
2650
2651 lockOwners[i].nLocks = 1;
2652 locallock->nLocks = 1;
2655 sessionLock))
2656 elog(WARNING, "ReleaseLockIfHeld: failed??");
2657 }
2658 break;
2659 }
2660 }
2661}
2662
2663
2664
2665
2666
2667
2668
2669
2670
2671
2672
2673void
2675{
2677
2678 Assert(parent != NULL);
2679
2680 if (locallocks == NULL)
2681 {
2684
2686
2689 }
2690 else
2691 {
2692 int i;
2693
2694 for (i = nlocks - 1; i >= 0; i--)
2696 }
2697}
2698
2699
2700
2701
2702
2703static void
2705{
2707 int i;
2708 int ic = -1;
2709 int ip = -1;
2710
2711
2712
2713
2714
2717 {
2719 ic = i;
2720 else if (lockOwners[i].owner == parent)
2721 ip = i;
2722 }
2723
2724 if (ic < 0)
2725 return;
2726
2727 if (ip < 0)
2728 {
2729
2730 lockOwners[ic].owner = parent;
2732 }
2733 else
2734 {
2735
2736 lockOwners[ip].nLocks += lockOwners[ic].nLocks;
2737
2739 if (ic < locallock->numLockOwners)
2740 lockOwners[ic] = lockOwners[locallock->numLockOwners];
2741 }
2743}
2744
2745
2746
2747
2748
2749static bool
2751{
2754
2755
2757
2758
2760 {
2761
2763
2765 unused_slot = f;
2767 {
2770 return true;
2771 }
2772 }
2773
2774
2776 {
2780 return true;
2781 }
2782
2783
2784 return false;
2785}
2786
2787
2788
2789
2790
2791
2792static bool
2794{
2796 bool result = false;
2797
2798
2800
2803 {
2804
2806
2809 {
2812 result = true;
2813
2814 }
2817 }
2818 return result;
2819}
2820
2821
2822
2823
2824
2825
2826
2827
2828static bool
2831{
2835
2836
2838
2839
2840
2841
2842
2843
2844
2846 {
2849
2851
2852
2853
2854
2855
2856
2857
2858
2859
2860
2861
2862
2863
2864
2865
2866
2867
2868
2871 {
2873 continue;
2874 }
2875
2877 {
2879
2880
2882
2883
2885 continue;
2886
2887
2891 ++lockmode)
2892 {
2894
2896 continue;
2898 hashcode, lockmode);
2899 if (!proclock)
2900 {
2903 return false;
2904 }
2907 }
2909
2910
2911 break;
2912 }
2914 }
2915 return true;
2916}
2917
2918
2919
2920
2921
2922
2923
2924
2927{
2934 group;
2935
2936
2938
2940
2942 {
2944
2945
2947
2948
2950 continue;
2951
2952
2953 lockmode = locallock->tag.mode;
2955 break;
2956
2957
2959
2961 locallock->hashcode, lockmode);
2962 if (!proclock)
2963 {
2967 (errcode(ERRCODE_OUT_OF_MEMORY),
2968 errmsg("out of shared memory"),
2969 errhint("You might need to increase \"%s\".", "max_locks_per_transaction")));
2970 }
2973
2975
2976
2977 break;
2978 }
2979
2981
2982
2983 if (proclock == NULL)
2984 {
2987 uint32 proclock_hashcode;
2988
2990
2992 locktag,
2995 NULL);
2996 if (!lock)
2997 elog(ERROR, "failed to re-find shared lock object");
2998
2999 proclocktag.myLock = lock;
3001
3005 &proclocktag,
3006 proclock_hashcode,
3008 NULL);
3009 if (!proclock)
3010 elog(ERROR, "failed to re-find shared proclock object");
3012 }
3013
3014 return proclock;
3015}
3016
3017
3018
3019
3020
3021
3022
3023
3024
3025
3026
3027
3028
3029
3030
3031
3032
3033
3034
3035
3038{
3047 LWLock *partitionLock;
3048 int count = 0;
3049 int fast_count = 0;
3050
3052 elog(ERROR, "unrecognized lock method: %d", lockmethodid);
3053 lockMethodTable = LockMethods[lockmethodid];
3054 if (lockmode <= 0 || lockmode > lockMethodTable->numLockModes)
3055 elog(ERROR, "unrecognized lock mode: %d", lockmode);
3056
3057
3058
3059
3060
3061
3063 {
3064 if (vxids == NULL)
3069 }
3070 else
3074
3075
3078 conflictMask = lockMethodTable->conflictTab[lockmode];
3079
3080
3081
3082
3083
3084
3086 {
3087 int i;
3090
3091
3093
3094
3095
3096
3097
3098
3099
3100
3101
3102
3103
3105 {
3108
3109
3111 continue;
3112
3114
3115
3116
3117
3118
3119
3120
3121
3122
3123
3124
3127 {
3129 continue;
3130 }
3131
3133 {
3135
3136
3138
3139
3140 if (relid != proc->fpRelId[f])
3141 continue;
3143 if (!lockmask)
3144 continue;
3146
3147
3148
3149
3150
3151 if ((lockmask & conflictMask) == 0)
3152 break;
3153
3154
3156
3158 vxids[count++] = vxid;
3159
3160
3161
3162 break;
3163 }
3164
3166 }
3167 }
3168
3169
3170 fast_count = count;
3171
3172
3173
3174
3176
3178 locktag,
3179 hashcode,
3181 NULL);
3182 if (!lock)
3183 {
3184
3185
3186
3187
3191 if (countp)
3192 *countp = count;
3193 return vxids;
3194 }
3195
3196
3197
3198
3200 {
3202
3203 if (conflictMask & proclock->holdMask)
3204 {
3206
3207
3209 {
3211
3213
3215 {
3216 int i;
3217
3218
3219 for (i = 0; i < fast_count; ++i)
3221 break;
3222 if (i >= fast_count)
3223 vxids[count++] = vxid;
3224 }
3225
3226 }
3227 }
3228 }
3229
3231
3233 elog(PANIC, "too many conflicting locks found");
3234
3237 if (countp)
3238 *countp = count;
3239 return vxids;
3240}
3241
3242
3243
3244
3245
3246
3247
3248
3249
3250
3251
3252
3253static void
3256 bool decrement_strong_lock_count)
3257{
3262 uint32 proclock_hashcode;
3263 LWLock *partitionLock;
3264 bool wakeupNeeded;
3265
3268
3270
3271
3272
3273
3275 locktag,
3276 hashcode,
3278 NULL);
3279 if (!lock)
3280 elog(PANIC, "failed to re-find shared lock object");
3281
3282
3283
3284
3285 proclocktag.myLock = lock;
3286 proclocktag.myProc = proc;
3287
3288 proclock_hashcode = ProcLockHashCode(&proclocktag, hashcode);
3289
3291 &proclocktag,
3292 proclock_hashcode,
3294 NULL);
3295 if (!proclock)
3296 elog(PANIC, "failed to re-find shared proclock object");
3297
3298
3299
3300
3301
3303 {
3304 PROCLOCK_PRINT("lock_twophase_postcommit: WRONGTYPE", proclock);
3306 elog(WARNING, "you don't own a lock of type %s",
3308 return;
3309 }
3310
3311
3312
3313
3314 wakeupNeeded = UnGrantLock(lock, lockmode, proclock, lockMethodTable);
3315
3317 lockMethodTable, hashcode,
3318 wakeupNeeded);
3319
3321
3322
3323
3324
3325 if (decrement_strong_lock_count
3327 {
3329
3334 }
3335}
3336
3337
3338
3339
3340
3341
3342
3343
3344
3345
3346
3347
3348
3349
3350
3351
3352
3353
3354
3355
3356
3357static void
3359{
3360 typedef struct
3361 {
3362 LOCKTAG lock;
3363 bool sessLock;
3364 bool xactLock;
3365 } PerLockTagEntry;
3366
3368 HTAB *lockhtab;
3371
3372
3374 hash_ctl.entrysize = sizeof(PerLockTagEntry);
3376
3377 lockhtab = hash_create("CheckForSessionAndXactLocks table",
3378 256,
3379 &hash_ctl,
3381
3382
3384
3386 {
3388 PerLockTagEntry *hentry;
3389 bool found;
3390 int i;
3391
3392
3393
3394
3395
3397 continue;
3398
3399
3400 if (locallock->nLocks <= 0)
3401 continue;
3402
3403
3404 hentry = (PerLockTagEntry *) hash_search(lockhtab,
3407 if (!found)
3408 hentry->sessLock = hentry->xactLock = false;
3409
3410
3412 {
3413 if (lockOwners[i].owner == NULL)
3414 hentry->sessLock = true;
3415 else
3416 hentry->xactLock = true;
3417 }
3418
3419
3420
3421
3422
3423 if (hentry->sessLock && hentry->xactLock)
3425 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3426 errmsg("cannot PREPARE while holding both session-level and transaction-level locks on the same object")));
3427 }
3428
3429
3431}
3432
3433
3434
3435
3436
3437
3438
3439
3440
3441
3442
3443
3444
3445void
3447{
3450
3451
3453
3454
3456
3458 {
3461 bool haveSessionLock;
3462 bool haveXactLock;
3463 int i;
3464
3465
3466
3467
3468
3470 continue;
3471
3472
3473 if (locallock->nLocks <= 0)
3474 continue;
3475
3476
3477 haveSessionLock = haveXactLock = false;
3479 {
3480 if (lockOwners[i].owner == NULL)
3481 haveSessionLock = true;
3482 else
3483 haveXactLock = true;
3484 }
3485
3486
3487 if (!haveXactLock)
3488 continue;
3489
3490
3491 if (haveSessionLock)
3493 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3494 errmsg("cannot PREPARE while holding both session-level and transaction-level locks on the same object")));
3495
3496
3497
3498
3499
3500
3501
3502 if (locallock->proclock == NULL)
3503 {
3506 }
3507
3508
3509
3510
3511
3512
3514
3515
3516
3517
3520
3523 }
3524}
3525
3526
3527
3528
3529
3530
3531
3532
3533
3534
3535
3536
3537
3538
3539
3540
3541void
3543{
3550 int partition;
3551
3552
3555
3556
3558
3559
3560
3561
3562
3563
3564
3565
3566
3567
3569
3571 {
3573 bool haveSessionLock;
3574 bool haveXactLock;
3575 int i;
3576
3577 if (locallock->proclock == NULL || locallock->lock == NULL)
3578 {
3579
3580
3581
3582
3585 continue;
3586 }
3587
3588
3590 continue;
3591
3592
3593 haveSessionLock = haveXactLock = false;
3595 {
3596 if (lockOwners[i].owner == NULL)
3597 haveSessionLock = true;
3598 else
3599 haveXactLock = true;
3600 }
3601
3602
3603 if (!haveXactLock)
3604 continue;
3605
3606
3607 if (haveSessionLock)
3609 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3610 errmsg("cannot PREPARE while holding both session-level and transaction-level locks on the same object")));
3611
3612
3613 if (locallock->nLocks > 0)
3615
3616
3618 }
3619
3620
3621
3622
3624 {
3625 LWLock *partitionLock;
3628
3630
3631
3632
3633
3634
3635
3636
3637
3638
3640 continue;
3641
3643
3645 {
3647
3649
3651
3652
3654 continue;
3655
3657 LOCK_PRINT("PostPrepare_Locks", lock, 0);
3662
3663
3665 continue;
3666
3667
3669 elog(PANIC, "we seem to have dropped a bit somewhere");
3670
3671
3672
3673
3674
3675
3676
3677
3678
3679
3680
3681
3682
3683
3685
3686
3687
3688
3689 proclocktag.myLock = lock;
3690 proclocktag.myProc = newproc;
3691
3692
3693
3694
3695
3698
3699
3700
3701
3702
3703
3705 proclock,
3706 &proclocktag))
3707 elog(PANIC, "duplicate entry found while reassigning a prepared transaction's locks");
3708
3709
3711
3712 PROCLOCK_PRINT("PostPrepare_Locks: updated", proclock);
3713 }
3714
3716 }
3717
3719}
3720
3721
3722
3723
3724
3727{
3728 Size size = 0;
3729 long max_table_size;
3730
3731
3734
3735
3736 max_table_size *= 2;
3738
3739
3740
3741
3742 size = add_size(size, size / 10);
3743
3744 return size;
3745}
3746
3747
3748
3749
3750
3751
3752
3753
3754
3755
3756
3757
3758
3759
3760
3761
3764{
3768 int els;
3769 int el;
3770 int i;
3771
3773
3774
3776 el = 0;
3778
3779
3780
3781
3782
3783
3784
3785
3786
3787
3788
3789
3790
3792 {
3794
3795
3796 if (proc->pid == 0)
3797 continue;
3798
3800
3802 {
3803
3805 continue;
3806
3808 {
3812
3813
3814 if (!lockbits)
3815 continue;
3816
3817 if (el >= els)
3818 {
3822 }
3823
3824 instance = &data->locks[el];
3831 instance->pid = proc->pid;
3834
3835
3836
3837
3838
3840
3841 el++;
3842 }
3843 }
3844
3846 {
3849
3850 if (el >= els)
3851 {
3855 }
3856
3859
3860 instance = &data->locks[el];
3866 instance->pid = proc->pid;
3870
3871 el++;
3872 }
3873
3875 }
3876
3877
3878
3879
3880
3881
3882
3883
3884
3885
3886
3887
3888
3889
3892
3893
3895 if (data->nelements > els)
3896 {
3897 els = data->nelements;
3900 }
3901
3902
3904
3906 {
3910
3915 else
3919 instance->pid = proc->pid;
3923
3924 el++;
3925 }
3926
3927
3928
3929
3930
3931
3932
3933
3936
3938
3939 return data;
3940}
3941
3942
3943
3944
3945
3946
3947
3948
3949
3950
3951
3952
3953
3954
3955
3956
3957
3958
3959
3960
3961
3962
3963
3964
3967{
3970 int i;
3971
3973
3974
3975
3976
3977
3978
3979
3980 data->nprocs = data->nlocks = data->npids = 0;
3984 data->waiter_pids = (int *) palloc(sizeof(int) * data->maxpids);
3985
3986
3987
3988
3989
3990
3991
3992
3993
3994
3995
3996
3998
4000
4001
4002 if (proc != NULL)
4003 {
4004
4005
4006
4007
4010
4012 {
4013
4015 }
4016 else
4017 {
4018
4020
4022 {
4024
4027 }
4028 }
4029
4030
4031
4032
4035
4037 }
4038
4040
4041 return data;
4042}
4043
4044
4045static void
4047{
4053 int queue_size;
4054
4055
4056 if (theLock == NULL)
4057 return;
4058
4059
4060 bproc = &data->procs[data->nprocs++];
4061 bproc->pid = blocked_proc->pid;
4064
4065
4066
4067
4068
4069
4070
4072 {
4078
4079 if (data->nlocks >= data->maxlocks)
4080 {
4084 }
4085
4086 instance = &data->locks[data->nlocks];
4091 else
4095 instance->pid = proc->pid;
4098 data->nlocks++;
4099 }
4100
4101
4102 waitQueue = &(theLock->waitProcs);
4104
4105 if (queue_size > data->maxpids - data->npids)
4106 {
4108 data->npids + queue_size);
4110 sizeof(int) * data->maxpids);
4111 }
4112
4113
4115 {
4117
4118 if (queued_proc == blocked_proc)
4119 break;
4120 data->waiter_pids[data->npids++] = queued_proc->pid;
4122 }
4123
4126}
4127
4128
4129
4130
4131
4132
4133
4134
4135
4136
4137
4138
4139
4142{
4146 int i;
4148 int els;
4149
4150
4151
4152
4153
4154
4157
4158
4160
4161
4162
4163
4164
4166
4167
4169
4170
4171
4172
4173
4174
4175
4176
4179 {
4180
4183 {
4187
4188
4189
4190
4191
4192
4193
4195 continue;
4196
4197 accessExclusiveLocks[index].xid = xid;
4200
4202 }
4203 }
4204
4206
4207
4208
4209
4210
4211
4212
4213
4216
4217 *nlocks = index;
4218 return accessExclusiveLocks;
4219}
4220
4221
4222const char *
4224{
4228}
4229
4230#ifdef LOCK_DEBUG
4231
4232
4233
4234
4235
4236void
4237DumpLocks(PGPROC *proc)
4238{
4239 int i;
4240
4241 if (proc == NULL)
4242 return;
4243
4246
4248 {
4251
4253 {
4256
4260 }
4261 }
4262}
4263
4264
4265
4266
4267
4268
4269void
4270DumpAllLocks(void)
4271{
4276
4278
4281
4283
4285 {
4287
4289 if (lock)
4290 LOCK_PRINT("DumpAllLocks", lock, 0);
4291 else
4292 elog(LOG, "DumpAllLocks: proclock->tag.myLock = NULL");
4293 }
4294}
4295#endif
4296
4297
4298
4299
4300
4301
4302
4303
4304
4305
4306
4307
4308
4309
4310
4311
4312
4313
4314
4315
4316
4317
4318
4319
4320
4321
4322
4323
4324
4325
4326void
4329{
4338 bool found;
4340 uint32 proclock_hashcode;
4341 int partition;
4342 LWLock *partitionLock;
4344
4346 locktag = &rec->locktag;
4349
4351 elog(ERROR, "unrecognized lock method: %d", lockmethodid);
4352 lockMethodTable = LockMethods[lockmethodid];
4353
4357
4359
4360
4361
4362
4364 locktag,
4365 hashcode,
4367 &found);
4368 if (!lock)
4369 {
4372 (errcode(ERRCODE_OUT_OF_MEMORY),
4373 errmsg("out of shared memory"),
4374 errhint("You might need to increase \"%s\".", "max_locks_per_transaction")));
4375 }
4376
4377
4378
4379
4380 if (!found)
4381 {
4390 LOCK_PRINT("lock_twophase_recover: new", lock, lockmode);
4391 }
4392 else
4393 {
4394 LOCK_PRINT("lock_twophase_recover: found", lock, lockmode);
4398 }
4399
4400
4401
4402
4403 proclocktag.myLock = lock;
4404 proclocktag.myProc = proc;
4405
4406 proclock_hashcode = ProcLockHashCode(&proclocktag, hashcode);
4407
4408
4409
4410
4412 &proclocktag,
4413 proclock_hashcode,
4415 &found);
4416 if (!proclock)
4417 {
4418
4420 {
4421
4422
4423
4424
4425
4426
4429 &(lock->tag),
4430 hashcode,
4432 NULL))
4433 elog(PANIC, "lock table corrupted");
4434 }
4437 (errcode(ERRCODE_OUT_OF_MEMORY),
4438 errmsg("out of shared memory"),
4439 errhint("You might need to increase \"%s\".", "max_locks_per_transaction")));
4440 }
4441
4442
4443
4444
4445 if (!found)
4446 {
4451
4455 PROCLOCK_PRINT("lock_twophase_recover: new", proclock);
4456 }
4457 else
4458 {
4459 PROCLOCK_PRINT("lock_twophase_recover: found", proclock);
4461 }
4462
4463
4464
4465
4466
4470
4471
4472
4473
4475 elog(ERROR, "lock %s on object %u/%u/%u is already held",
4479
4480
4481
4482
4483
4484
4485 GrantLock(lock, proclock, lockmode);
4486
4487
4488
4489
4490
4492 {
4494
4498 }
4499
4501}
4502
4503
4504
4505
4506
4507void
4510{
4515
4517 locktag = &rec->locktag;
4520
4522 elog(ERROR, "unrecognized lock method: %d", lockmethodid);
4523
4526 {
4530 }
4531}
4532
4533
4534
4535
4536
4537
4538
4539void
4542{
4548
4550 locktag = &rec->locktag;
4552
4554 elog(ERROR, "unrecognized lock method: %d", lockmethodid);
4555 lockMethodTable = LockMethods[lockmethodid];
4556
4558}
4559
4560
4561
4562
4563
4564
4565void
4568{
4570}
4571
4572
4573
4574
4575
4576
4577
4578
4579
4580
4581
4582
4583
4584
4585
4586
4587
4588
4589void
4591{
4593
4595
4599
4602
4604}
4605
4606
4607
4608
4609
4610
4611
4612void
4614{
4615 bool fastpath;
4617
4619
4620
4621
4622
4624
4629
4631
4632
4633
4634
4635
4637 {
4640
4644
4647 }
4648}
4649
4650
4651
4652
4653
4654
4655
4656
4657
4658
4659
4660
4661static bool
4664{
4665 bool more = false;
4666
4667
4669 return true;
4670
4671 do
4672 {
4675
4676
4677 if (more)
4678 {
4680 more = false;
4681 }
4682
4683
4687 {
4689 return true;
4690 }
4691
4692
4696 return false;
4698 } while (more);
4699
4700 return true;
4701}
4702
4703
4704
4705
4706
4707
4708
4709
4710
4711
4712bool
4714{
4718
4720
4722
4724
4726
4727
4728
4729
4730
4731
4732
4733
4734
4736 if (proc == NULL)
4738
4739
4740
4741
4742
4743
4745
4748 {
4749
4752 }
4753
4754
4755
4756
4757
4758 if (!wait)
4759 {
4761 return false;
4762 }
4763
4764
4765
4766
4767
4768
4770 {
4773 LWLock *partitionLock;
4774
4776
4779
4782 if (!proclock)
4783 {
4787 (errcode(ERRCODE_OUT_OF_MEMORY),
4788 errmsg("out of shared memory"),
4789 errhint("You might need to increase \"%s\".", "max_locks_per_transaction")));
4790 }
4792
4794
4796 }
4797
4798
4799
4800
4801
4802
4803
4804
4805
4806 xid = proc->xid;
4807
4808
4810
4811
4813
4816}
4817
4818
4819
4820
4821
4822
4823int
4825{
4828 bool found;
4830 LWLock *partitionLock;
4831 int waiters = 0;
4832
4834 elog(ERROR, "unrecognized lock method: %d", lockmethodid);
4835
4839
4841 locktag,
4842 hashcode,
4844 &found);
4845 if (found)
4846 {
4847 Assert(lock != NULL);
4849 }
4851
4852 return waiters;
4853}
static uint64 pg_atomic_read_u64(volatile pg_atomic_uint64 *ptr)
uint32 LocalTransactionId
#define MemSet(start, val, len)
void DeadLockReport(void)
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
void hash_destroy(HTAB *hashp)
void * hash_search_with_hash_value(HTAB *hashp, const void *keyPtr, uint32 hashvalue, HASHACTION action, bool *foundPtr)
void * hash_seq_search(HASH_SEQ_STATUS *status)
long hash_get_num_entries(HTAB *hashp)
Size hash_estimate_size(long num_entries, Size entrysize)
HTAB * hash_create(const char *tabname, long nelem, const HASHCTL *info, int flags)
bool hash_update_hash_key(HTAB *hashp, void *existingEntry, const void *newKeyPtr)
uint32 get_hash_value(HTAB *hashp, const void *keyPtr)
void hash_seq_init(HASH_SEQ_STATUS *status, HTAB *hashp)
int errhint(const char *fmt,...)
int errcode(int sqlerrcode)
int errdetail_log_plural(const char *fmt_singular, const char *fmt_plural, unsigned long n,...)
int errmsg(const char *fmt,...)
#define ereport(elevel,...)
Assert(PointerIsAligned(start, uint64))
#define dlist_foreach(iter, lhead)
static void dlist_init(dlist_head *head)
static void dlist_delete(dlist_node *node)
static uint32 dclist_count(const dclist_head *head)
static bool dclist_is_empty(const dclist_head *head)
#define dlist_foreach_modify(iter, lhead)
static bool dlist_is_empty(const dlist_head *head)
static void dlist_push_tail(dlist_head *head, dlist_node *node)
static void dclist_delete_from_thoroughly(dclist_head *head, dlist_node *node)
static void dclist_init(dclist_head *head)
#define dlist_container(type, membername, ptr)
#define dclist_foreach(iter, lhead)
void DescribeLockTag(StringInfo buf, const LOCKTAG *tag)
static bool XactLockForVirtualXact(VirtualTransactionId vxid, TransactionId xid, bool wait)
LockAcquireResult LockAcquire(const LOCKTAG *locktag, LOCKMODE lockmode, bool sessionLock, bool dontWait)
static LOCALLOCK * awaitedLock
static void RemoveLocalLock(LOCALLOCK *locallock)
static void LockReassignOwner(LOCALLOCK *locallock, ResourceOwner parent)
bool LockHeldByMe(const LOCKTAG *locktag, LOCKMODE lockmode, bool orstronger)
static const char *const lock_mode_names[]
#define LOCK_PRINT(where, lock, type)
bool DoLockModesConflict(LOCKMODE mode1, LOCKMODE mode2)
static PROCLOCK * SetupLockInTable(LockMethod lockMethodTable, PGPROC *proc, const LOCKTAG *locktag, uint32 hashcode, LOCKMODE lockmode)
static PROCLOCK * FastPathGetRelationLockEntry(LOCALLOCK *locallock)
void VirtualXactLockTableInsert(VirtualTransactionId vxid)
#define FastPathStrongLockHashPartition(hashcode)
static uint32 ProcLockHashCode(const PROCLOCKTAG *proclocktag, uint32 hashcode)
#define FAST_PATH_CHECK_LOCKMODE(proc, n, l)
void GrantAwaitedLock(void)
int LockWaiterCount(const LOCKTAG *locktag)
void AtPrepare_Locks(void)
bool LockRelease(const LOCKTAG *locktag, LOCKMODE lockmode, bool sessionLock)
void lock_twophase_postcommit(TransactionId xid, uint16 info, void *recdata, uint32 len)
#define FAST_PATH_LOCKNUMBER_OFFSET
Size LockManagerShmemSize(void)
#define FAST_PATH_REL_GROUP(rel)
void InitLockManagerAccess(void)
void GrantLock(LOCK *lock, PROCLOCK *proclock, LOCKMODE lockmode)
void VirtualXactLockTableCleanup(void)
bool VirtualXactLock(VirtualTransactionId vxid, bool wait)
VirtualTransactionId * GetLockConflicts(const LOCKTAG *locktag, LOCKMODE lockmode, int *countp)
static volatile FastPathStrongRelationLockData * FastPathStrongRelationLocks
void RemoveFromWaitQueue(PGPROC *proc, uint32 hashcode)
LockAcquireResult LockAcquireExtended(const LOCKTAG *locktag, LOCKMODE lockmode, bool sessionLock, bool dontWait, bool reportMemoryError, LOCALLOCK **locallockp, bool logLockFailure)
void LockReleaseAll(LOCKMETHODID lockmethodid, bool allLocks)
#define FAST_PATH_SLOT(group, index)
static void CheckAndSetLockHeld(LOCALLOCK *locallock, bool acquired)
#define ConflictsWithRelationFastPath(locktag, mode)
void ResetAwaitedLock(void)
static bool FastPathTransferRelationLocks(LockMethod lockMethodTable, const LOCKTAG *locktag, uint32 hashcode)
static HTAB * LockMethodLocalHash
void LockReassignCurrentOwner(LOCALLOCK **locallocks, int nlocks)
static bool UnGrantLock(LOCK *lock, LOCKMODE lockmode, PROCLOCK *proclock, LockMethod lockMethodTable)
#define FAST_PATH_SET_LOCKMODE(proc, n, l)
#define PROCLOCK_PRINT(where, proclockP)
static void CleanUpLock(LOCK *lock, PROCLOCK *proclock, LockMethod lockMethodTable, uint32 hashcode, bool wakeupNeeded)
static uint32 proclock_hash(const void *key, Size keysize)
static bool FastPathUnGrantRelationLock(Oid relid, LOCKMODE lockmode)
void AbortStrongLockAcquire(void)
static bool FastPathGrantRelationLock(Oid relid, LOCKMODE lockmode)
static int FastPathLocalUseCounts[FP_LOCK_GROUPS_PER_BACKEND_MAX]
static HTAB * LockMethodLockHash
static ResourceOwner awaitedOwner
BlockedProcsData * GetBlockerStatusData(int blocked_pid)
void LockManagerShmemInit(void)
void lock_twophase_postabort(TransactionId xid, uint16 info, void *recdata, uint32 len)
static ProcWaitStatus WaitOnLock(LOCALLOCK *locallock, ResourceOwner owner)
bool LockHasWaiters(const LOCKTAG *locktag, LOCKMODE lockmode, bool sessionLock)
const char * GetLockmodeName(LOCKMETHODID lockmethodid, LOCKMODE mode)
static void GetSingleProcBlockerStatusData(PGPROC *blocked_proc, BlockedProcsData *data)
#define FAST_PATH_CLEAR_LOCKMODE(proc, n, l)
static const LockMethod LockMethods[]
void lock_twophase_standby_recover(TransactionId xid, uint16 info, void *recdata, uint32 len)
void LockReleaseCurrentOwner(LOCALLOCK **locallocks, int nlocks)
LOCALLOCK * GetAwaitedLock(void)
void lock_twophase_recover(TransactionId xid, uint16 info, void *recdata, uint32 len)
void LockReleaseSession(LOCKMETHODID lockmethodid)
void MarkLockClear(LOCALLOCK *locallock)
LockData * GetLockStatusData(void)
static bool IsRelationExtensionLockHeld PG_USED_FOR_ASSERTS_ONLY
static const LockMethodData default_lockmethod
#define FAST_PATH_GET_BITS(proc, n)
static LOCALLOCK * StrongLockInProgress
#define FAST_PATH_BITS_PER_SLOT
static const LockMethodData user_lockmethod
int FastPathLockGroupsPerBackend
#define EligibleForRelationFastPath(locktag, mode)
uint32 LockTagHashCode(const LOCKTAG *locktag)
static void BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode)
bool LockCheckConflicts(LockMethod lockMethodTable, LOCKMODE lockmode, LOCK *lock, PROCLOCK *proclock)
static void GrantLockLocal(LOCALLOCK *locallock, ResourceOwner owner)
static const LOCKMASK LockConflicts[]
static void ReleaseLockIfHeld(LOCALLOCK *locallock, bool sessionLock)
LockMethod GetLocksMethodTable(const LOCK *lock)
static void FinishStrongLockAcquire(void)
#define FAST_PATH_STRONG_LOCK_HASH_PARTITIONS
void PostPrepare_Locks(TransactionId xid)
xl_standby_lock * GetRunningTransactionLocks(int *nlocks)
static void LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, LOCKTAG *locktag, LOCKMODE lockmode, bool decrement_strong_lock_count)
static void CheckForSessionAndXactLocks(void)
static HTAB * LockMethodProcLockHash
struct TwoPhaseLockRecord TwoPhaseLockRecord
LockMethod GetLockTagsMethodTable(const LOCKTAG *locktag)
#define DEFAULT_LOCKMETHOD
struct LOCALLOCK LOCALLOCK
#define LOCK_LOCKTAG(lock)
#define SET_LOCKTAG_VIRTUALTRANSACTION(locktag, vxid)
@ LOCKTAG_RELATION_EXTEND
@ LOCKTAG_VIRTUALTRANSACTION
#define VirtualTransactionIdIsValid(vxid)
#define LockHashPartitionLock(hashcode)
#define GET_VXID_FROM_PGPROC(vxid_dst, proc)
#define LOCK_LOCKMETHOD(lock)
#define LOCKBIT_OFF(lockmode)
#define LOCALLOCK_LOCKMETHOD(llock)
#define InvalidLocalTransactionId
#define SET_LOCKTAG_TRANSACTION(locktag, xid)
#define SET_LOCKTAG_RELATION(locktag, dboid, reloid)
struct PROCLOCKTAG PROCLOCKTAG
#define LOCKBIT_ON(lockmode)
#define LocalTransactionIdIsValid(lxid)
#define LOCALLOCK_LOCKTAG(llock)
#define LockHashPartition(hashcode)
#define VirtualTransactionIdEquals(vxid1, vxid2)
struct LOCALLOCKTAG LOCALLOCKTAG
#define PROCLOCK_LOCKMETHOD(proclock)
#define LockHashPartitionLockByIndex(i)
@ LOCKACQUIRE_ALREADY_CLEAR
@ LOCKACQUIRE_ALREADY_HELD
#define VirtualTransactionIdIsRecoveredPreparedXact(vxid)
#define AccessExclusiveLock
#define ShareRowExclusiveLock
#define ShareUpdateExclusiveLock
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
void LWLockRelease(LWLock *lock)
#define NUM_LOCK_PARTITIONS
#define LOG2_NUM_LOCK_PARTITIONS
void * MemoryContextAlloc(MemoryContext context, Size size)
void * repalloc(void *pointer, Size size)
void pfree(void *pointer)
void * palloc0(Size size)
MemoryContext TopMemoryContext
MemoryContext CurrentMemoryContext
#define START_CRIT_SECTION()
#define END_CRIT_SECTION()
static PgChecksumMode mode
static Datum PointerGetDatum(const void *X)
#define FP_LOCK_GROUPS_PER_BACKEND_MAX
#define FastPathLockSlotsPerBackend()
#define FP_LOCK_SLOTS_PER_GROUP
@ PROC_WAIT_STATUS_WAITING
PGPROC * BackendPidGetProcWithLock(int pid)
PGPROC * ProcNumberGetProc(ProcNumber procNumber)
#define INVALID_PROC_NUMBER
void set_ps_display_remove_suffix(void)
void set_ps_display_suffix(const char *suffix)
void ResourceOwnerRememberLock(ResourceOwner owner, LOCALLOCK *locallock)
ResourceOwner ResourceOwnerGetParent(ResourceOwner owner)
ResourceOwner CurrentResourceOwner
void ResourceOwnerForgetLock(ResourceOwner owner, LOCALLOCK *locallock)
HTAB * ShmemInitHash(const char *name, long init_size, long max_size, HASHCTL *infoP, int hash_flags)
Size add_size(Size s1, Size s2)
void * ShmemInitStruct(const char *name, Size size, bool *foundPtr)
#define SpinLockInit(lock)
#define SpinLockRelease(lock)
#define SpinLockAcquire(lock)
ProcWaitStatus JoinWaitQueue(LOCALLOCK *locallock, LockMethod lockMethodTable, bool dontWait)
void GetLockHoldersAndWaiters(LOCALLOCK *locallock, StringInfo lock_holders_sbuf, StringInfo lock_waiters_sbuf, int *lockHoldersNum)
ProcWaitStatus ProcSleep(LOCALLOCK *locallock)
void ProcLockWakeup(LockMethod lockMethodTable, LOCK *lock)
void LogAccessExclusiveLockPrepare(void)
void StandbyAcquireAccessExclusiveLock(TransactionId xid, Oid dbOid, Oid relOid)
void LogAccessExclusiveLock(Oid dbOid, Oid relOid)
void initStringInfo(StringInfo str)
uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]
struct ResourceOwnerData * owner
LOCALLOCKOWNER * lockOwners
bool holdsStrongLockCount
uint8 locktag_lockmethodid
int requested[MAX_LOCKMODES]
int granted[MAX_LOCKMODES]
VirtualTransactionId vxid
const LOCKMASK * conflictTab
const char *const * lockModeNames
dlist_head lockGroupMembers
pg_atomic_uint64 waitStart
LocalTransactionId fpLocalTransactionId
dlist_head myProcLocks[NUM_LOCK_PARTITIONS]
ProcWaitStatus waitStatus
LocalTransactionId localTransactionId
#define InvalidTransactionId
#define FirstNormalObjectId
#define TransactionIdIsValid(xid)
void RegisterTwoPhaseRecord(TwoPhaseRmgrId rmid, uint16 info, const void *data, uint32 len)
TransactionId TwoPhaseGetXidByVirtualXID(VirtualTransactionId vxid, bool *have_more)
PGPROC * TwoPhaseGetDummyProc(TransactionId xid, bool lock_held)
#define TWOPHASE_RM_LOCK_ID
bool RecoveryInProgress(void)
#define XLogStandbyInfoActive()
static struct link * links