00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014 #ifndef LOCK_H_
00015 #define LOCK_H_
00016
00017 #include "storage/backendid.h"
00018 #include "storage/lwlock.h"
00019 #include "storage/shmem.h"
00020
00021
00022
00023 typedef struct PGPROC PGPROC;
00024
00025 typedef struct PROC_QUEUE
00026 {
00027 SHM_QUEUE links;
00028 int size;
00029 } PROC_QUEUE;
00030
00031
00032 extern int max_locks_per_xact;
00033
00034 #ifdef LOCK_DEBUG
00035 extern int Trace_lock_oidmin;
00036 extern bool Trace_locks;
00037 extern bool Trace_userlocks;
00038 extern int Trace_lock_table;
00039 extern bool Debug_deadlocks;
00040 #endif
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058 typedef struct
00059 {
00060 BackendId backendId;
00061 LocalTransactionId localTransactionId;
00062
00063 } VirtualTransactionId;
00064
00065 #define InvalidLocalTransactionId 0
00066 #define LocalTransactionIdIsValid(lxid) ((lxid) != InvalidLocalTransactionId)
00067 #define VirtualTransactionIdIsValid(vxid) \
00068 (((vxid).backendId != InvalidBackendId) && \
00069 LocalTransactionIdIsValid((vxid).localTransactionId))
00070 #define VirtualTransactionIdEquals(vxid1, vxid2) \
00071 ((vxid1).backendId == (vxid2).backendId && \
00072 (vxid1).localTransactionId == (vxid2).localTransactionId)
00073 #define SetInvalidVirtualTransactionId(vxid) \
00074 ((vxid).backendId = InvalidBackendId, \
00075 (vxid).localTransactionId = InvalidLocalTransactionId)
00076 #define GET_VXID_FROM_PGPROC(vxid, proc) \
00077 ((vxid).backendId = (proc).backendId, \
00078 (vxid).localTransactionId = (proc).lxid)
00079
00080
00081
00082
00083
00084
00085
00086 typedef int LOCKMASK;
00087 typedef int LOCKMODE;
00088
00089
00090 #define MAX_LOCKMODES 10
00091
00092 #define LOCKBIT_ON(lockmode) (1 << (lockmode))
00093 #define LOCKBIT_OFF(lockmode) (~(1 << (lockmode)))
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116 typedef struct LockMethodData
00117 {
00118 int numLockModes;
00119 const LOCKMASK *conflictTab;
00120 const char *const * lockModeNames;
00121 const bool *trace_flag;
00122 } LockMethodData;
00123
00124 typedef const LockMethodData *LockMethod;
00125
00126
00127
00128
00129
00130 typedef uint16 LOCKMETHODID;
00131
00132
00133 #define DEFAULT_LOCKMETHOD 1
00134 #define USER_LOCKMETHOD 2
00135
00136
00137
00138
00139
00140
00141
00142 #define NoLock 0
00143
00144 #define AccessShareLock 1
00145 #define RowShareLock 2
00146 #define RowExclusiveLock 3
00147 #define ShareUpdateExclusiveLock 4
00148
00149 #define ShareLock 5
00150 #define ShareRowExclusiveLock 6
00151
00152 #define ExclusiveLock 7
00153
00154 #define AccessExclusiveLock 8
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165 typedef enum LockTagType
00166 {
00167 LOCKTAG_RELATION,
00168
00169 LOCKTAG_RELATION_EXTEND,
00170
00171 LOCKTAG_PAGE,
00172
00173 LOCKTAG_TUPLE,
00174
00175 LOCKTAG_TRANSACTION,
00176
00177 LOCKTAG_VIRTUALTRANSACTION,
00178
00179 LOCKTAG_OBJECT,
00180
00181
00182
00183
00184
00185
00186
00187 LOCKTAG_USERLOCK,
00188 LOCKTAG_ADVISORY
00189 } LockTagType;
00190
00191 #define LOCKTAG_LAST_TYPE LOCKTAG_ADVISORY
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201 typedef struct LOCKTAG
00202 {
00203 uint32 locktag_field1;
00204 uint32 locktag_field2;
00205 uint32 locktag_field3;
00206 uint16 locktag_field4;
00207 uint8 locktag_type;
00208 uint8 locktag_lockmethodid;
00209 } LOCKTAG;
00210
00211
00212
00213
00214
00215
00216 #define SET_LOCKTAG_RELATION(locktag,dboid,reloid) \
00217 ((locktag).locktag_field1 = (dboid), \
00218 (locktag).locktag_field2 = (reloid), \
00219 (locktag).locktag_field3 = 0, \
00220 (locktag).locktag_field4 = 0, \
00221 (locktag).locktag_type = LOCKTAG_RELATION, \
00222 (locktag).locktag_lockmethodid = DEFAULT_LOCKMETHOD)
00223
00224 #define SET_LOCKTAG_RELATION_EXTEND(locktag,dboid,reloid) \
00225 ((locktag).locktag_field1 = (dboid), \
00226 (locktag).locktag_field2 = (reloid), \
00227 (locktag).locktag_field3 = 0, \
00228 (locktag).locktag_field4 = 0, \
00229 (locktag).locktag_type = LOCKTAG_RELATION_EXTEND, \
00230 (locktag).locktag_lockmethodid = DEFAULT_LOCKMETHOD)
00231
00232 #define SET_LOCKTAG_PAGE(locktag,dboid,reloid,blocknum) \
00233 ((locktag).locktag_field1 = (dboid), \
00234 (locktag).locktag_field2 = (reloid), \
00235 (locktag).locktag_field3 = (blocknum), \
00236 (locktag).locktag_field4 = 0, \
00237 (locktag).locktag_type = LOCKTAG_PAGE, \
00238 (locktag).locktag_lockmethodid = DEFAULT_LOCKMETHOD)
00239
00240 #define SET_LOCKTAG_TUPLE(locktag,dboid,reloid,blocknum,offnum) \
00241 ((locktag).locktag_field1 = (dboid), \
00242 (locktag).locktag_field2 = (reloid), \
00243 (locktag).locktag_field3 = (blocknum), \
00244 (locktag).locktag_field4 = (offnum), \
00245 (locktag).locktag_type = LOCKTAG_TUPLE, \
00246 (locktag).locktag_lockmethodid = DEFAULT_LOCKMETHOD)
00247
00248 #define SET_LOCKTAG_TRANSACTION(locktag,xid) \
00249 ((locktag).locktag_field1 = (xid), \
00250 (locktag).locktag_field2 = 0, \
00251 (locktag).locktag_field3 = 0, \
00252 (locktag).locktag_field4 = 0, \
00253 (locktag).locktag_type = LOCKTAG_TRANSACTION, \
00254 (locktag).locktag_lockmethodid = DEFAULT_LOCKMETHOD)
00255
00256 #define SET_LOCKTAG_VIRTUALTRANSACTION(locktag,vxid) \
00257 ((locktag).locktag_field1 = (vxid).backendId, \
00258 (locktag).locktag_field2 = (vxid).localTransactionId, \
00259 (locktag).locktag_field3 = 0, \
00260 (locktag).locktag_field4 = 0, \
00261 (locktag).locktag_type = LOCKTAG_VIRTUALTRANSACTION, \
00262 (locktag).locktag_lockmethodid = DEFAULT_LOCKMETHOD)
00263
00264 #define SET_LOCKTAG_OBJECT(locktag,dboid,classoid,objoid,objsubid) \
00265 ((locktag).locktag_field1 = (dboid), \
00266 (locktag).locktag_field2 = (classoid), \
00267 (locktag).locktag_field3 = (objoid), \
00268 (locktag).locktag_field4 = (objsubid), \
00269 (locktag).locktag_type = LOCKTAG_OBJECT, \
00270 (locktag).locktag_lockmethodid = DEFAULT_LOCKMETHOD)
00271
00272 #define SET_LOCKTAG_ADVISORY(locktag,id1,id2,id3,id4) \
00273 ((locktag).locktag_field1 = (id1), \
00274 (locktag).locktag_field2 = (id2), \
00275 (locktag).locktag_field3 = (id3), \
00276 (locktag).locktag_field4 = (id4), \
00277 (locktag).locktag_type = LOCKTAG_ADVISORY, \
00278 (locktag).locktag_lockmethodid = USER_LOCKMETHOD)
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296
00297
00298
00299 typedef struct LOCK
00300 {
00301
00302 LOCKTAG tag;
00303
00304
00305 LOCKMASK grantMask;
00306 LOCKMASK waitMask;
00307 SHM_QUEUE procLocks;
00308 PROC_QUEUE waitProcs;
00309 int requested[MAX_LOCKMODES];
00310 int nRequested;
00311 int granted[MAX_LOCKMODES];
00312 int nGranted;
00313 } LOCK;
00314
00315 #define LOCK_LOCKMETHOD(lock) ((LOCKMETHODID) (lock).tag.locktag_lockmethodid)
00316
00317
00318
00319
00320
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347
00348
00349
00350
00351
00352 typedef struct PROCLOCKTAG
00353 {
00354
00355 LOCK *myLock;
00356 PGPROC *myProc;
00357 } PROCLOCKTAG;
00358
00359 typedef struct PROCLOCK
00360 {
00361
00362 PROCLOCKTAG tag;
00363
00364
00365 LOCKMASK holdMask;
00366 LOCKMASK releaseMask;
00367 SHM_QUEUE lockLink;
00368 SHM_QUEUE procLink;
00369 } PROCLOCK;
00370
00371 #define PROCLOCK_LOCKMETHOD(proclock) \
00372 LOCK_LOCKMETHOD(*((proclock).tag.myLock))
00373
00374
00375
00376
00377
00378
00379
00380
00381
00382
00383 typedef struct LOCALLOCKTAG
00384 {
00385 LOCKTAG lock;
00386 LOCKMODE mode;
00387 } LOCALLOCKTAG;
00388
00389 typedef struct LOCALLOCKOWNER
00390 {
00391
00392
00393
00394
00395
00396
00397 struct ResourceOwnerData *owner;
00398 int64 nLocks;
00399 } LOCALLOCKOWNER;
00400
00401 typedef struct LOCALLOCK
00402 {
00403
00404 LOCALLOCKTAG tag;
00405
00406
00407 LOCK *lock;
00408 PROCLOCK *proclock;
00409 uint32 hashcode;
00410 int64 nLocks;
00411 int numLockOwners;
00412 int maxLockOwners;
00413 bool holdsStrongLockCount;
00414 LOCALLOCKOWNER *lockOwners;
00415 } LOCALLOCK;
00416
00417 #define LOCALLOCK_LOCKMETHOD(llock) ((llock).tag.lock.locktag_lockmethodid)
00418
00419
00420
00421
00422
00423
00424
00425 typedef struct LockInstanceData
00426 {
00427 LOCKTAG locktag;
00428 LOCKMASK holdMask;
00429 LOCKMODE waitLockMode;
00430 BackendId backend;
00431 LocalTransactionId lxid;
00432 int pid;
00433 bool fastpath;
00434 } LockInstanceData;
00435
00436 typedef struct LockData
00437 {
00438 int nelements;
00439 LockInstanceData *locks;
00440 } LockData;
00441
00442
00443
00444 typedef enum
00445 {
00446 LOCKACQUIRE_NOT_AVAIL,
00447 LOCKACQUIRE_OK,
00448 LOCKACQUIRE_ALREADY_HELD
00449 } LockAcquireResult;
00450
00451
00452 typedef enum
00453 {
00454 DS_NOT_YET_CHECKED,
00455 DS_NO_DEADLOCK,
00456 DS_SOFT_DEADLOCK,
00457 DS_HARD_DEADLOCK,
00458 DS_BLOCKED_BY_AUTOVACUUM
00459
00460 } DeadLockState;
00461
00462
00463
00464
00465
00466
00467
00468
00469 #define LockHashPartition(hashcode) \
00470 ((hashcode) % NUM_LOCK_PARTITIONS)
00471 #define LockHashPartitionLock(hashcode) \
00472 ((LWLockId) (FirstLockMgrLock + LockHashPartition(hashcode)))
00473
00474
00475
00476
00477
00478 extern void InitLocks(void);
00479 extern LockMethod GetLocksMethodTable(const LOCK *lock);
00480 extern uint32 LockTagHashCode(const LOCKTAG *locktag);
00481 extern bool DoLockModesConflict(LOCKMODE mode1, LOCKMODE mode2);
00482 extern LockAcquireResult LockAcquire(const LOCKTAG *locktag,
00483 LOCKMODE lockmode,
00484 bool sessionLock,
00485 bool dontWait);
00486 extern LockAcquireResult LockAcquireExtended(const LOCKTAG *locktag,
00487 LOCKMODE lockmode,
00488 bool sessionLock,
00489 bool dontWait,
00490 bool report_memory_error);
00491 extern void AbortStrongLockAcquire(void);
00492 extern bool LockRelease(const LOCKTAG *locktag,
00493 LOCKMODE lockmode, bool sessionLock);
00494 extern void LockReleaseAll(LOCKMETHODID lockmethodid, bool allLocks);
00495 extern void LockReleaseSession(LOCKMETHODID lockmethodid);
00496 extern void LockReleaseCurrentOwner(LOCALLOCK **locallocks, int nlocks);
00497 extern void LockReassignCurrentOwner(LOCALLOCK **locallocks, int nlocks);
00498 extern bool LockHasWaiters(const LOCKTAG *locktag,
00499 LOCKMODE lockmode, bool sessionLock);
00500 extern VirtualTransactionId *GetLockConflicts(const LOCKTAG *locktag,
00501 LOCKMODE lockmode);
00502 extern void AtPrepare_Locks(void);
00503 extern void PostPrepare_Locks(TransactionId xid);
00504 extern int LockCheckConflicts(LockMethod lockMethodTable,
00505 LOCKMODE lockmode,
00506 LOCK *lock, PROCLOCK *proclock, PGPROC *proc);
00507 extern void GrantLock(LOCK *lock, PROCLOCK *proclock, LOCKMODE lockmode);
00508 extern void GrantAwaitedLock(void);
00509 extern void RemoveFromWaitQueue(PGPROC *proc, uint32 hashcode);
00510 extern Size LockShmemSize(void);
00511 extern LockData *GetLockStatusData(void);
00512
00513 extern void ReportLockTableError(bool report);
00514
00515 typedef struct xl_standby_lock
00516 {
00517 TransactionId xid;
00518 Oid dbOid;
00519 Oid relOid;
00520 } xl_standby_lock;
00521
00522 extern xl_standby_lock *GetRunningTransactionLocks(int *nlocks);
00523 extern const char *GetLockmodeName(LOCKMETHODID lockmethodid, LOCKMODE mode);
00524
00525 extern void lock_twophase_recover(TransactionId xid, uint16 info,
00526 void *recdata, uint32 len);
00527 extern void lock_twophase_postcommit(TransactionId xid, uint16 info,
00528 void *recdata, uint32 len);
00529 extern void lock_twophase_postabort(TransactionId xid, uint16 info,
00530 void *recdata, uint32 len);
00531 extern void lock_twophase_standby_recover(TransactionId xid, uint16 info,
00532 void *recdata, uint32 len);
00533
00534 extern DeadLockState DeadLockCheck(PGPROC *proc);
00535 extern PGPROC *GetBlockingAutoVacuumPgproc(void);
00536 extern void DeadLockReport(void) __attribute__((noreturn));
00537 extern void RememberSimpleDeadLock(PGPROC *proc1,
00538 LOCKMODE lockmode,
00539 LOCK *lock,
00540 PGPROC *proc2);
00541 extern void InitDeadLockChecking(void);
00542
00543 #ifdef LOCK_DEBUG
00544 extern void DumpLocks(PGPROC *proc);
00545 extern void DumpAllLocks(void);
00546 #endif
00547
00548
00549 extern void VirtualXactLockTableInsert(VirtualTransactionId vxid);
00550 extern void VirtualXactLockTableCleanup(void);
00551 extern bool VirtualXactLock(VirtualTransactionId vxid, bool wait);
00552
00553 #endif