| 1 | /*------------------------------------------------------------------------- |
| 2 | * |
| 3 | * lock.h |
| 4 | * POSTGRES low-level lock mechanism |
| 5 | * |
| 6 | * |
| 7 | * Portions Copyright (c) 1996-2019, PostgreSQL Global Development Group |
| 8 | * Portions Copyright (c) 1994, Regents of the University of California |
| 9 | * |
| 10 | * src/include/storage/lock.h |
| 11 | * |
| 12 | *------------------------------------------------------------------------- |
| 13 | */ |
| 14 | #ifndef LOCK_H_ |
| 15 | #define LOCK_H_ |
| 16 | |
| 17 | #ifdef FRONTEND |
| 18 | #error "lock.h may not be included from frontend code" |
| 19 | #endif |
| 20 | |
| 21 | #include "storage/lockdefs.h" |
| 22 | #include "storage/backendid.h" |
| 23 | #include "storage/lwlock.h" |
| 24 | #include "storage/shmem.h" |
| 25 | |
| 26 | |
| 27 | /* struct PGPROC is declared in proc.h, but must forward-reference it */ |
| 28 | typedef struct PGPROC PGPROC; |
| 29 | |
| 30 | typedef struct PROC_QUEUE |
| 31 | { |
| 32 | SHM_QUEUE links; /* head of list of PGPROC objects */ |
| 33 | int size; /* number of entries in list */ |
| 34 | } PROC_QUEUE; |
| 35 | |
| 36 | /* GUC variables */ |
| 37 | extern int max_locks_per_xact; |
| 38 | |
| 39 | #ifdef LOCK_DEBUG |
| 40 | extern int Trace_lock_oidmin; |
| 41 | extern bool Trace_locks; |
| 42 | extern bool Trace_userlocks; |
| 43 | extern int Trace_lock_table; |
| 44 | extern bool Debug_deadlocks; |
| 45 | #endif /* LOCK_DEBUG */ |
| 46 | |
| 47 | |
| 48 | /* |
| 49 | * Top-level transactions are identified by VirtualTransactionIDs comprising |
| 50 | * the BackendId of the backend running the xact, plus a locally-assigned |
| 51 | * LocalTransactionId. These are guaranteed unique over the short term, |
| 52 | * but will be reused after a database restart; hence they should never |
| 53 | * be stored on disk. |
| 54 | * |
| 55 | * Note that struct VirtualTransactionId can not be assumed to be atomically |
| 56 | * assignable as a whole. However, type LocalTransactionId is assumed to |
| 57 | * be atomically assignable, and the backend ID doesn't change often enough |
| 58 | * to be a problem, so we can fetch or assign the two fields separately. |
| 59 | * We deliberately refrain from using the struct within PGPROC, to prevent |
| 60 | * coding errors from trying to use struct assignment with it; instead use |
| 61 | * GET_VXID_FROM_PGPROC(). |
| 62 | */ |
| 63 | typedef struct |
| 64 | { |
| 65 | BackendId backendId; /* determined at backend startup */ |
| 66 | LocalTransactionId localTransactionId; /* backend-local transaction id */ |
| 67 | } VirtualTransactionId; |
| 68 | |
| 69 | #define InvalidLocalTransactionId 0 |
| 70 | #define LocalTransactionIdIsValid(lxid) ((lxid) != InvalidLocalTransactionId) |
| 71 | #define VirtualTransactionIdIsValid(vxid) \ |
| 72 | (((vxid).backendId != InvalidBackendId) && \ |
| 73 | LocalTransactionIdIsValid((vxid).localTransactionId)) |
| 74 | #define VirtualTransactionIdEquals(vxid1, vxid2) \ |
| 75 | ((vxid1).backendId == (vxid2).backendId && \ |
| 76 | (vxid1).localTransactionId == (vxid2).localTransactionId) |
| 77 | #define SetInvalidVirtualTransactionId(vxid) \ |
| 78 | ((vxid).backendId = InvalidBackendId, \ |
| 79 | (vxid).localTransactionId = InvalidLocalTransactionId) |
| 80 | #define GET_VXID_FROM_PGPROC(vxid, proc) \ |
| 81 | ((vxid).backendId = (proc).backendId, \ |
| 82 | (vxid).localTransactionId = (proc).lxid) |
| 83 | |
| 84 | /* MAX_LOCKMODES cannot be larger than the # of bits in LOCKMASK */ |
| 85 | #define MAX_LOCKMODES 10 |
| 86 | |
| 87 | #define LOCKBIT_ON(lockmode) (1 << (lockmode)) |
| 88 | #define LOCKBIT_OFF(lockmode) (~(1 << (lockmode))) |
| 89 | |
| 90 | |
| 91 | /* |
| 92 | * This data structure defines the locking semantics associated with a |
| 93 | * "lock method". The semantics specify the meaning of each lock mode |
| 94 | * (by defining which lock modes it conflicts with). |
| 95 | * All of this data is constant and is kept in const tables. |
| 96 | * |
| 97 | * numLockModes -- number of lock modes (READ,WRITE,etc) that |
| 98 | * are defined in this lock method. Must be less than MAX_LOCKMODES. |
| 99 | * |
| 100 | * conflictTab -- this is an array of bitmasks showing lock |
| 101 | * mode conflicts. conflictTab[i] is a mask with the j-th bit |
| 102 | * turned on if lock modes i and j conflict. Lock modes are |
| 103 | * numbered 1..numLockModes; conflictTab[0] is unused. |
| 104 | * |
| 105 | * lockModeNames -- ID strings for debug printouts. |
| 106 | * |
| 107 | * trace_flag -- pointer to GUC trace flag for this lock method. (The |
| 108 | * GUC variable is not constant, but we use "const" here to denote that |
| 109 | * it can't be changed through this reference.) |
| 110 | */ |
| 111 | typedef struct LockMethodData |
| 112 | { |
| 113 | int numLockModes; |
| 114 | const LOCKMASK *conflictTab; |
| 115 | const char *const *lockModeNames; |
| 116 | const bool *trace_flag; |
| 117 | } LockMethodData; |
| 118 | |
| 119 | typedef const LockMethodData *LockMethod; |
| 120 | |
| 121 | /* |
| 122 | * Lock methods are identified by LOCKMETHODID. (Despite the declaration as |
| 123 | * uint16, we are constrained to 256 lockmethods by the layout of LOCKTAG.) |
| 124 | */ |
| 125 | typedef uint16 LOCKMETHODID; |
| 126 | |
| 127 | /* These identify the known lock methods */ |
| 128 | #define DEFAULT_LOCKMETHOD 1 |
| 129 | #define USER_LOCKMETHOD 2 |
| 130 | |
| 131 | /* |
| 132 | * LOCKTAG is the key information needed to look up a LOCK item in the |
| 133 | * lock hashtable. A LOCKTAG value uniquely identifies a lockable object. |
| 134 | * |
| 135 | * The LockTagType enum defines the different kinds of objects we can lock. |
| 136 | * We can handle up to 256 different LockTagTypes. |
| 137 | */ |
| 138 | typedef enum LockTagType |
| 139 | { |
| 140 | LOCKTAG_RELATION, /* whole relation */ |
| 141 | LOCKTAG_RELATION_EXTEND, /* the right to extend a relation */ |
| 142 | LOCKTAG_PAGE, /* one page of a relation */ |
| 143 | LOCKTAG_TUPLE, /* one physical tuple */ |
| 144 | LOCKTAG_TRANSACTION, /* transaction (for waiting for xact done) */ |
| 145 | LOCKTAG_VIRTUALTRANSACTION, /* virtual transaction (ditto) */ |
| 146 | LOCKTAG_SPECULATIVE_TOKEN, /* speculative insertion Xid and token */ |
| 147 | LOCKTAG_OBJECT, /* non-relation database object */ |
| 148 | LOCKTAG_USERLOCK, /* reserved for old contrib/userlock code */ |
| 149 | LOCKTAG_ADVISORY /* advisory user locks */ |
| 150 | } LockTagType; |
| 151 | |
| 152 | #define LOCKTAG_LAST_TYPE LOCKTAG_ADVISORY |
| 153 | |
| 154 | extern const char *const LockTagTypeNames[]; |
| 155 | |
| 156 | /* |
| 157 | * The LOCKTAG struct is defined with malice aforethought to fit into 16 |
| 158 | * bytes with no padding. Note that this would need adjustment if we were |
| 159 | * to widen Oid, BlockNumber, or TransactionId to more than 32 bits. |
| 160 | * |
| 161 | * We include lockmethodid in the locktag so that a single hash table in |
| 162 | * shared memory can store locks of different lockmethods. |
| 163 | */ |
| 164 | typedef struct LOCKTAG |
| 165 | { |
| 166 | uint32 locktag_field1; /* a 32-bit ID field */ |
| 167 | uint32 locktag_field2; /* a 32-bit ID field */ |
| 168 | uint32 locktag_field3; /* a 32-bit ID field */ |
| 169 | uint16 locktag_field4; /* a 16-bit ID field */ |
| 170 | uint8 locktag_type; /* see enum LockTagType */ |
| 171 | uint8 locktag_lockmethodid; /* lockmethod indicator */ |
| 172 | } LOCKTAG; |
| 173 | |
| 174 | /* |
| 175 | * These macros define how we map logical IDs of lockable objects into |
| 176 | * the physical fields of LOCKTAG. Use these to set up LOCKTAG values, |
| 177 | * rather than accessing the fields directly. Note multiple eval of target! |
| 178 | */ |
| 179 | |
| 180 | /* ID info for a relation is DB OID + REL OID; DB OID = 0 if shared */ |
| 181 | #define SET_LOCKTAG_RELATION(locktag,dboid,reloid) \ |
| 182 | ((locktag).locktag_field1 = (dboid), \ |
| 183 | (locktag).locktag_field2 = (reloid), \ |
| 184 | (locktag).locktag_field3 = 0, \ |
| 185 | (locktag).locktag_field4 = 0, \ |
| 186 | (locktag).locktag_type = LOCKTAG_RELATION, \ |
| 187 | (locktag).locktag_lockmethodid = DEFAULT_LOCKMETHOD) |
| 188 | |
| 189 | /* same ID info as RELATION */ |
| 190 | #define SET_LOCKTAG_RELATION_EXTEND(locktag,dboid,reloid) \ |
| 191 | ((locktag).locktag_field1 = (dboid), \ |
| 192 | (locktag).locktag_field2 = (reloid), \ |
| 193 | (locktag).locktag_field3 = 0, \ |
| 194 | (locktag).locktag_field4 = 0, \ |
| 195 | (locktag).locktag_type = LOCKTAG_RELATION_EXTEND, \ |
| 196 | (locktag).locktag_lockmethodid = DEFAULT_LOCKMETHOD) |
| 197 | |
| 198 | /* ID info for a page is RELATION info + BlockNumber */ |
| 199 | #define SET_LOCKTAG_PAGE(locktag,dboid,reloid,blocknum) \ |
| 200 | ((locktag).locktag_field1 = (dboid), \ |
| 201 | (locktag).locktag_field2 = (reloid), \ |
| 202 | (locktag).locktag_field3 = (blocknum), \ |
| 203 | (locktag).locktag_field4 = 0, \ |
| 204 | (locktag).locktag_type = LOCKTAG_PAGE, \ |
| 205 | (locktag).locktag_lockmethodid = DEFAULT_LOCKMETHOD) |
| 206 | |
| 207 | /* ID info for a tuple is PAGE info + OffsetNumber */ |
| 208 | #define SET_LOCKTAG_TUPLE(locktag,dboid,reloid,blocknum,offnum) \ |
| 209 | ((locktag).locktag_field1 = (dboid), \ |
| 210 | (locktag).locktag_field2 = (reloid), \ |
| 211 | (locktag).locktag_field3 = (blocknum), \ |
| 212 | (locktag).locktag_field4 = (offnum), \ |
| 213 | (locktag).locktag_type = LOCKTAG_TUPLE, \ |
| 214 | (locktag).locktag_lockmethodid = DEFAULT_LOCKMETHOD) |
| 215 | |
| 216 | /* ID info for a transaction is its TransactionId */ |
| 217 | #define SET_LOCKTAG_TRANSACTION(locktag,xid) \ |
| 218 | ((locktag).locktag_field1 = (xid), \ |
| 219 | (locktag).locktag_field2 = 0, \ |
| 220 | (locktag).locktag_field3 = 0, \ |
| 221 | (locktag).locktag_field4 = 0, \ |
| 222 | (locktag).locktag_type = LOCKTAG_TRANSACTION, \ |
| 223 | (locktag).locktag_lockmethodid = DEFAULT_LOCKMETHOD) |
| 224 | |
| 225 | /* ID info for a virtual transaction is its VirtualTransactionId */ |
| 226 | #define SET_LOCKTAG_VIRTUALTRANSACTION(locktag,vxid) \ |
| 227 | ((locktag).locktag_field1 = (vxid).backendId, \ |
| 228 | (locktag).locktag_field2 = (vxid).localTransactionId, \ |
| 229 | (locktag).locktag_field3 = 0, \ |
| 230 | (locktag).locktag_field4 = 0, \ |
| 231 | (locktag).locktag_type = LOCKTAG_VIRTUALTRANSACTION, \ |
| 232 | (locktag).locktag_lockmethodid = DEFAULT_LOCKMETHOD) |
| 233 | |
| 234 | /* |
| 235 | * ID info for a speculative insert is TRANSACTION info + |
| 236 | * its speculative insert counter. |
| 237 | */ |
| 238 | #define SET_LOCKTAG_SPECULATIVE_INSERTION(locktag,xid,token) \ |
| 239 | ((locktag).locktag_field1 = (xid), \ |
| 240 | (locktag).locktag_field2 = (token), \ |
| 241 | (locktag).locktag_field3 = 0, \ |
| 242 | (locktag).locktag_field4 = 0, \ |
| 243 | (locktag).locktag_type = LOCKTAG_SPECULATIVE_TOKEN, \ |
| 244 | (locktag).locktag_lockmethodid = DEFAULT_LOCKMETHOD) |
| 245 | |
| 246 | /* |
| 247 | * ID info for an object is DB OID + CLASS OID + OBJECT OID + SUBID |
| 248 | * |
| 249 | * Note: object ID has same representation as in pg_depend and |
| 250 | * pg_description, but notice that we are constraining SUBID to 16 bits. |
| 251 | * Also, we use DB OID = 0 for shared objects such as tablespaces. |
| 252 | */ |
| 253 | #define SET_LOCKTAG_OBJECT(locktag,dboid,classoid,objoid,objsubid) \ |
| 254 | ((locktag).locktag_field1 = (dboid), \ |
| 255 | (locktag).locktag_field2 = (classoid), \ |
| 256 | (locktag).locktag_field3 = (objoid), \ |
| 257 | (locktag).locktag_field4 = (objsubid), \ |
| 258 | (locktag).locktag_type = LOCKTAG_OBJECT, \ |
| 259 | (locktag).locktag_lockmethodid = DEFAULT_LOCKMETHOD) |
| 260 | |
| 261 | #define SET_LOCKTAG_ADVISORY(locktag,id1,id2,id3,id4) \ |
| 262 | ((locktag).locktag_field1 = (id1), \ |
| 263 | (locktag).locktag_field2 = (id2), \ |
| 264 | (locktag).locktag_field3 = (id3), \ |
| 265 | (locktag).locktag_field4 = (id4), \ |
| 266 | (locktag).locktag_type = LOCKTAG_ADVISORY, \ |
| 267 | (locktag).locktag_lockmethodid = USER_LOCKMETHOD) |
| 268 | |
| 269 | |
| 270 | /* |
| 271 | * Per-locked-object lock information: |
| 272 | * |
| 273 | * tag -- uniquely identifies the object being locked |
| 274 | * grantMask -- bitmask for all lock types currently granted on this object. |
| 275 | * waitMask -- bitmask for all lock types currently awaited on this object. |
| 276 | * procLocks -- list of PROCLOCK objects for this lock. |
| 277 | * waitProcs -- queue of processes waiting for this lock. |
| 278 | * requested -- count of each lock type currently requested on the lock |
| 279 | * (includes requests already granted!!). |
| 280 | * nRequested -- total requested locks of all types. |
| 281 | * granted -- count of each lock type currently granted on the lock. |
| 282 | * nGranted -- total granted locks of all types. |
| 283 | * |
| 284 | * Note: these counts count 1 for each backend. Internally to a backend, |
| 285 | * there may be multiple grabs on a particular lock, but this is not reflected |
| 286 | * into shared memory. |
| 287 | */ |
| 288 | typedef struct LOCK |
| 289 | { |
| 290 | /* hash key */ |
| 291 | LOCKTAG tag; /* unique identifier of lockable object */ |
| 292 | |
| 293 | /* data */ |
| 294 | LOCKMASK grantMask; /* bitmask for lock types already granted */ |
| 295 | LOCKMASK waitMask; /* bitmask for lock types awaited */ |
| 296 | SHM_QUEUE procLocks; /* list of PROCLOCK objects assoc. with lock */ |
| 297 | PROC_QUEUE waitProcs; /* list of PGPROC objects waiting on lock */ |
| 298 | int requested[MAX_LOCKMODES]; /* counts of requested locks */ |
| 299 | int nRequested; /* total of requested[] array */ |
| 300 | int granted[MAX_LOCKMODES]; /* counts of granted locks */ |
| 301 | int nGranted; /* total of granted[] array */ |
| 302 | } LOCK; |
| 303 | |
| 304 | #define LOCK_LOCKMETHOD(lock) ((LOCKMETHODID) (lock).tag.locktag_lockmethodid) |
| 305 | |
| 306 | |
| 307 | /* |
| 308 | * We may have several different backends holding or awaiting locks |
| 309 | * on the same lockable object. We need to store some per-holder/waiter |
| 310 | * information for each such holder (or would-be holder). This is kept in |
| 311 | * a PROCLOCK struct. |
| 312 | * |
| 313 | * PROCLOCKTAG is the key information needed to look up a PROCLOCK item in the |
| 314 | * proclock hashtable. A PROCLOCKTAG value uniquely identifies the combination |
| 315 | * of a lockable object and a holder/waiter for that object. (We can use |
| 316 | * pointers here because the PROCLOCKTAG need only be unique for the lifespan |
| 317 | * of the PROCLOCK, and it will never outlive the lock or the proc.) |
| 318 | * |
| 319 | * Internally to a backend, it is possible for the same lock to be held |
| 320 | * for different purposes: the backend tracks transaction locks separately |
| 321 | * from session locks. However, this is not reflected in the shared-memory |
| 322 | * state: we only track which backend(s) hold the lock. This is OK since a |
| 323 | * backend can never block itself. |
| 324 | * |
| 325 | * The holdMask field shows the already-granted locks represented by this |
| 326 | * proclock. Note that there will be a proclock object, possibly with |
| 327 | * zero holdMask, for any lock that the process is currently waiting on. |
| 328 | * Otherwise, proclock objects whose holdMasks are zero are recycled |
| 329 | * as soon as convenient. |
| 330 | * |
| 331 | * releaseMask is workspace for LockReleaseAll(): it shows the locks due |
| 332 | * to be released during the current call. This must only be examined or |
| 333 | * set by the backend owning the PROCLOCK. |
| 334 | * |
| 335 | * Each PROCLOCK object is linked into lists for both the associated LOCK |
| 336 | * object and the owning PGPROC object. Note that the PROCLOCK is entered |
| 337 | * into these lists as soon as it is created, even if no lock has yet been |
| 338 | * granted. A PGPROC that is waiting for a lock to be granted will also be |
| 339 | * linked into the lock's waitProcs queue. |
| 340 | */ |
| 341 | typedef struct PROCLOCKTAG |
| 342 | { |
| 343 | /* NB: we assume this struct contains no padding! */ |
| 344 | LOCK *myLock; /* link to per-lockable-object information */ |
| 345 | PGPROC *myProc; /* link to PGPROC of owning backend */ |
| 346 | } PROCLOCKTAG; |
| 347 | |
| 348 | typedef struct PROCLOCK |
| 349 | { |
| 350 | /* tag */ |
| 351 | PROCLOCKTAG tag; /* unique identifier of proclock object */ |
| 352 | |
| 353 | /* data */ |
| 354 | PGPROC *groupLeader; /* proc's lock group leader, or proc itself */ |
| 355 | LOCKMASK holdMask; /* bitmask for lock types currently held */ |
| 356 | LOCKMASK releaseMask; /* bitmask for lock types to be released */ |
| 357 | SHM_QUEUE lockLink; /* list link in LOCK's list of proclocks */ |
| 358 | SHM_QUEUE procLink; /* list link in PGPROC's list of proclocks */ |
| 359 | } PROCLOCK; |
| 360 | |
| 361 | #define PROCLOCK_LOCKMETHOD(proclock) \ |
| 362 | LOCK_LOCKMETHOD(*((proclock).tag.myLock)) |
| 363 | |
| 364 | /* |
| 365 | * Each backend also maintains a local hash table with information about each |
| 366 | * lock it is currently interested in. In particular the local table counts |
| 367 | * the number of times that lock has been acquired. This allows multiple |
| 368 | * requests for the same lock to be executed without additional accesses to |
| 369 | * shared memory. We also track the number of lock acquisitions per |
| 370 | * ResourceOwner, so that we can release just those locks belonging to a |
| 371 | * particular ResourceOwner. |
| 372 | * |
| 373 | * When holding a lock taken "normally", the lock and proclock fields always |
| 374 | * point to the associated objects in shared memory. However, if we acquired |
| 375 | * the lock via the fast-path mechanism, the lock and proclock fields are set |
| 376 | * to NULL, since there probably aren't any such objects in shared memory. |
| 377 | * (If the lock later gets promoted to normal representation, we may eventually |
| 378 | * update our locallock's lock/proclock fields after finding the shared |
| 379 | * objects.) |
| 380 | * |
| 381 | * Caution: a locallock object can be left over from a failed lock acquisition |
| 382 | * attempt. In this case its lock/proclock fields are untrustworthy, since |
| 383 | * the shared lock object is neither held nor awaited, and hence is available |
| 384 | * to be reclaimed. If nLocks > 0 then these pointers must either be valid or |
| 385 | * NULL, but when nLocks == 0 they should be considered garbage. |
| 386 | */ |
| 387 | typedef struct LOCALLOCKTAG |
| 388 | { |
| 389 | LOCKTAG lock; /* identifies the lockable object */ |
| 390 | LOCKMODE mode; /* lock mode for this table entry */ |
| 391 | } LOCALLOCKTAG; |
| 392 | |
| 393 | typedef struct LOCALLOCKOWNER |
| 394 | { |
| 395 | /* |
| 396 | * Note: if owner is NULL then the lock is held on behalf of the session; |
| 397 | * otherwise it is held on behalf of my current transaction. |
| 398 | * |
| 399 | * Must use a forward struct reference to avoid circularity. |
| 400 | */ |
| 401 | struct ResourceOwnerData *owner; |
| 402 | int64 nLocks; /* # of times held by this owner */ |
| 403 | } LOCALLOCKOWNER; |
| 404 | |
| 405 | typedef struct LOCALLOCK |
| 406 | { |
| 407 | /* tag */ |
| 408 | LOCALLOCKTAG tag; /* unique identifier of locallock entry */ |
| 409 | |
| 410 | /* data */ |
| 411 | uint32 hashcode; /* copy of LOCKTAG's hash value */ |
| 412 | LOCK *lock; /* associated LOCK object, if any */ |
| 413 | PROCLOCK *proclock; /* associated PROCLOCK object, if any */ |
| 414 | int64 nLocks; /* total number of times lock is held */ |
| 415 | int numLockOwners; /* # of relevant ResourceOwners */ |
| 416 | int maxLockOwners; /* allocated size of array */ |
| 417 | LOCALLOCKOWNER *lockOwners; /* dynamically resizable array */ |
| 418 | bool holdsStrongLockCount; /* bumped FastPathStrongRelationLocks */ |
| 419 | bool lockCleared; /* we read all sinval msgs for lock */ |
| 420 | } LOCALLOCK; |
| 421 | |
| 422 | #define LOCALLOCK_LOCKMETHOD(llock) ((llock).tag.lock.locktag_lockmethodid) |
| 423 | |
| 424 | |
| 425 | /* |
| 426 | * These structures hold information passed from lmgr internals to the lock |
| 427 | * listing user-level functions (in lockfuncs.c). |
| 428 | */ |
| 429 | |
| 430 | typedef struct LockInstanceData |
| 431 | { |
| 432 | LOCKTAG locktag; /* tag for locked object */ |
| 433 | LOCKMASK holdMask; /* locks held by this PGPROC */ |
| 434 | LOCKMODE waitLockMode; /* lock awaited by this PGPROC, if any */ |
| 435 | BackendId backend; /* backend ID of this PGPROC */ |
| 436 | LocalTransactionId lxid; /* local transaction ID of this PGPROC */ |
| 437 | int pid; /* pid of this PGPROC */ |
| 438 | int leaderPid; /* pid of group leader; = pid if no group */ |
| 439 | bool fastpath; /* taken via fastpath? */ |
| 440 | } LockInstanceData; |
| 441 | |
| 442 | typedef struct LockData |
| 443 | { |
| 444 | int nelements; /* The length of the array */ |
| 445 | LockInstanceData *locks; /* Array of per-PROCLOCK information */ |
| 446 | } LockData; |
| 447 | |
| 448 | typedef struct BlockedProcData |
| 449 | { |
| 450 | int pid; /* pid of a blocked PGPROC */ |
| 451 | /* Per-PROCLOCK information about PROCLOCKs of the lock the pid awaits */ |
| 452 | /* (these fields refer to indexes in BlockedProcsData.locks[]) */ |
| 453 | int first_lock; /* index of first relevant LockInstanceData */ |
| 454 | int num_locks; /* number of relevant LockInstanceDatas */ |
| 455 | /* PIDs of PGPROCs that are ahead of "pid" in the lock's wait queue */ |
| 456 | /* (these fields refer to indexes in BlockedProcsData.waiter_pids[]) */ |
| 457 | int first_waiter; /* index of first preceding waiter */ |
| 458 | int num_waiters; /* number of preceding waiters */ |
| 459 | } BlockedProcData; |
| 460 | |
| 461 | typedef struct BlockedProcsData |
| 462 | { |
| 463 | BlockedProcData *procs; /* Array of per-blocked-proc information */ |
| 464 | LockInstanceData *locks; /* Array of per-PROCLOCK information */ |
| 465 | int *waiter_pids; /* Array of PIDs of other blocked PGPROCs */ |
| 466 | int nprocs; /* # of valid entries in procs[] array */ |
| 467 | int maxprocs; /* Allocated length of procs[] array */ |
| 468 | int nlocks; /* # of valid entries in locks[] array */ |
| 469 | int maxlocks; /* Allocated length of locks[] array */ |
| 470 | int npids; /* # of valid entries in waiter_pids[] array */ |
| 471 | int maxpids; /* Allocated length of waiter_pids[] array */ |
| 472 | } BlockedProcsData; |
| 473 | |
| 474 | |
| 475 | /* Result codes for LockAcquire() */ |
| 476 | typedef enum |
| 477 | { |
| 478 | LOCKACQUIRE_NOT_AVAIL, /* lock not available, and dontWait=true */ |
| 479 | LOCKACQUIRE_OK, /* lock successfully acquired */ |
| 480 | LOCKACQUIRE_ALREADY_HELD, /* incremented count for lock already held */ |
| 481 | LOCKACQUIRE_ALREADY_CLEAR /* incremented count for lock already clear */ |
| 482 | } LockAcquireResult; |
| 483 | |
| 484 | /* Deadlock states identified by DeadLockCheck() */ |
| 485 | typedef enum |
| 486 | { |
| 487 | DS_NOT_YET_CHECKED, /* no deadlock check has run yet */ |
| 488 | DS_NO_DEADLOCK, /* no deadlock detected */ |
| 489 | DS_SOFT_DEADLOCK, /* deadlock avoided by queue rearrangement */ |
| 490 | DS_HARD_DEADLOCK, /* deadlock, no way out but ERROR */ |
| 491 | DS_BLOCKED_BY_AUTOVACUUM /* no deadlock; queue blocked by autovacuum |
| 492 | * worker */ |
| 493 | } DeadLockState; |
| 494 | |
| 495 | /* |
| 496 | * The lockmgr's shared hash tables are partitioned to reduce contention. |
| 497 | * To determine which partition a given locktag belongs to, compute the tag's |
| 498 | * hash code with LockTagHashCode(), then apply one of these macros. |
| 499 | * NB: NUM_LOCK_PARTITIONS must be a power of 2! |
| 500 | */ |
| 501 | #define LockHashPartition(hashcode) \ |
| 502 | ((hashcode) % NUM_LOCK_PARTITIONS) |
| 503 | #define LockHashPartitionLock(hashcode) \ |
| 504 | (&MainLWLockArray[LOCK_MANAGER_LWLOCK_OFFSET + \ |
| 505 | LockHashPartition(hashcode)].lock) |
| 506 | #define LockHashPartitionLockByIndex(i) \ |
| 507 | (&MainLWLockArray[LOCK_MANAGER_LWLOCK_OFFSET + (i)].lock) |
| 508 | |
| 509 | /* |
| 510 | * The deadlock detector needs to be able to access lockGroupLeader and |
| 511 | * related fields in the PGPROC, so we arrange for those fields to be protected |
| 512 | * by one of the lock hash partition locks. Since the deadlock detector |
| 513 | * acquires all such locks anyway, this makes it safe for it to access these |
| 514 | * fields without doing anything extra. To avoid contention as much as |
| 515 | * possible, we map different PGPROCs to different partition locks. The lock |
| 516 | * used for a given lock group is determined by the group leader's pgprocno. |
| 517 | */ |
| 518 | #define LockHashPartitionLockByProc(leader_pgproc) \ |
| 519 | LockHashPartitionLock((leader_pgproc)->pgprocno) |
| 520 | |
| 521 | /* |
| 522 | * function prototypes |
| 523 | */ |
| 524 | extern void InitLocks(void); |
| 525 | extern LockMethod GetLocksMethodTable(const LOCK *lock); |
| 526 | extern LockMethod GetLockTagsMethodTable(const LOCKTAG *locktag); |
| 527 | extern uint32 LockTagHashCode(const LOCKTAG *locktag); |
| 528 | extern bool DoLockModesConflict(LOCKMODE mode1, LOCKMODE mode2); |
| 529 | extern LockAcquireResult LockAcquire(const LOCKTAG *locktag, |
| 530 | LOCKMODE lockmode, |
| 531 | bool sessionLock, |
| 532 | bool dontWait); |
| 533 | extern LockAcquireResult LockAcquireExtended(const LOCKTAG *locktag, |
| 534 | LOCKMODE lockmode, |
| 535 | bool sessionLock, |
| 536 | bool dontWait, |
| 537 | bool reportMemoryError, |
| 538 | LOCALLOCK **locallockp); |
| 539 | extern void AbortStrongLockAcquire(void); |
| 540 | extern void MarkLockClear(LOCALLOCK *locallock); |
| 541 | extern bool LockRelease(const LOCKTAG *locktag, |
| 542 | LOCKMODE lockmode, bool sessionLock); |
| 543 | extern void LockReleaseAll(LOCKMETHODID lockmethodid, bool allLocks); |
| 544 | extern void LockReleaseSession(LOCKMETHODID lockmethodid); |
| 545 | extern void LockReleaseCurrentOwner(LOCALLOCK **locallocks, int nlocks); |
| 546 | extern void LockReassignCurrentOwner(LOCALLOCK **locallocks, int nlocks); |
| 547 | extern bool LockHeldByMe(const LOCKTAG *locktag, LOCKMODE lockmode); |
| 548 | extern bool LockHasWaiters(const LOCKTAG *locktag, |
| 549 | LOCKMODE lockmode, bool sessionLock); |
| 550 | extern VirtualTransactionId *GetLockConflicts(const LOCKTAG *locktag, |
| 551 | LOCKMODE lockmode, int *countp); |
| 552 | extern void AtPrepare_Locks(void); |
| 553 | extern void PostPrepare_Locks(TransactionId xid); |
| 554 | extern int LockCheckConflicts(LockMethod lockMethodTable, |
| 555 | LOCKMODE lockmode, |
| 556 | LOCK *lock, PROCLOCK *proclock); |
| 557 | extern void GrantLock(LOCK *lock, PROCLOCK *proclock, LOCKMODE lockmode); |
| 558 | extern void GrantAwaitedLock(void); |
| 559 | extern void RemoveFromWaitQueue(PGPROC *proc, uint32 hashcode); |
| 560 | extern Size LockShmemSize(void); |
| 561 | extern LockData *GetLockStatusData(void); |
| 562 | extern BlockedProcsData *GetBlockerStatusData(int blocked_pid); |
| 563 | |
| 564 | extern xl_standby_lock *GetRunningTransactionLocks(int *nlocks); |
| 565 | extern const char *GetLockmodeName(LOCKMETHODID lockmethodid, LOCKMODE mode); |
| 566 | |
| 567 | extern void lock_twophase_recover(TransactionId xid, uint16 info, |
| 568 | void *recdata, uint32 len); |
| 569 | extern void lock_twophase_postcommit(TransactionId xid, uint16 info, |
| 570 | void *recdata, uint32 len); |
| 571 | extern void lock_twophase_postabort(TransactionId xid, uint16 info, |
| 572 | void *recdata, uint32 len); |
| 573 | extern void lock_twophase_standby_recover(TransactionId xid, uint16 info, |
| 574 | void *recdata, uint32 len); |
| 575 | |
| 576 | extern DeadLockState DeadLockCheck(PGPROC *proc); |
| 577 | extern PGPROC *GetBlockingAutoVacuumPgproc(void); |
| 578 | extern void DeadLockReport(void) pg_attribute_noreturn(); |
| 579 | extern void RememberSimpleDeadLock(PGPROC *proc1, |
| 580 | LOCKMODE lockmode, |
| 581 | LOCK *lock, |
| 582 | PGPROC *proc2); |
| 583 | extern void InitDeadLockChecking(void); |
| 584 | |
| 585 | extern int LockWaiterCount(const LOCKTAG *locktag); |
| 586 | |
| 587 | #ifdef LOCK_DEBUG |
| 588 | extern void DumpLocks(PGPROC *proc); |
| 589 | extern void DumpAllLocks(void); |
| 590 | #endif |
| 591 | |
| 592 | /* Lock a VXID (used to wait for a transaction to finish) */ |
| 593 | extern void VirtualXactLockTableInsert(VirtualTransactionId vxid); |
| 594 | extern void VirtualXactLockTableCleanup(void); |
| 595 | extern bool VirtualXactLock(VirtualTransactionId vxid, bool wait); |
| 596 | |
| 597 | #endif /* LOCK_H */ |
| 598 | |