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