diff options
Diffstat (limited to 'src/backend/storage/lmgr/lmgr.c')
-rw-r--r-- | src/backend/storage/lmgr/lmgr.c | 67 |
1 files changed, 67 insertions, 0 deletions
diff --git a/src/backend/storage/lmgr/lmgr.c b/src/backend/storage/lmgr/lmgr.c index 2b7a1db3eba..a978172796d 100644 --- a/src/backend/storage/lmgr/lmgr.c +++ b/src/backend/storage/lmgr/lmgr.c @@ -534,6 +534,73 @@ ConditionalXactLockTableWait(TransactionId xid) } /* + * WaitForLockersMultiple + * Wait until no transaction holds locks that conflict with the given + * locktags at the given lockmode. + * + * To do this, obtain the current list of lockers, and wait on their VXIDs + * until they are finished. + * + * Note we don't try to acquire the locks on the given locktags, only the VXIDs + * of its lock holders; if somebody grabs a conflicting lock on the objects + * after we obtained our initial list of lockers, we will not wait for them. + */ +void +WaitForLockersMultiple(List *locktags, LOCKMODE lockmode) +{ + List *holders = NIL; + ListCell *lc; + + /* Done if no locks to wait for */ + if (list_length(locktags) == 0) + return; + + /* Collect the transactions we need to wait on */ + foreach(lc, locktags) + { + LOCKTAG *locktag = lfirst(lc); + + holders = lappend(holders, GetLockConflicts(locktag, lockmode)); + } + + /* + * Note: GetLockConflicts() never reports our own xid, hence we need not + * check for that. Also, prepared xacts are not reported, which is fine + * since they certainly aren't going to do anything anymore. + */ + + /* Finally wait for each such transaction to complete */ + foreach(lc, holders) + { + VirtualTransactionId *lockholders = lfirst(lc); + + while (VirtualTransactionIdIsValid(*lockholders)) + { + VirtualXactLock(*lockholders, true); + lockholders++; + } + } + + list_free_deep(holders); +} + +/* + * WaitForLockers + * + * Same as WaitForLockersMultiple, for a single lock tag. + */ +void +WaitForLockers(LOCKTAG heaplocktag, LOCKMODE lockmode) +{ + List *l; + + l = list_make1(&heaplocktag); + WaitForLockersMultiple(l, lockmode); + list_free(l); +} + + +/* * LockDatabaseObject * * Obtain a lock on a general object of the current database. Don't use |