|
|
@ -383,7 +383,7 @@ InitProcess(void) |
|
|
|
* initialized by InitProcGlobal. |
|
|
|
* initialized by InitProcGlobal. |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
SHMQueueElemInit(&(MyProc->links)); |
|
|
|
SHMQueueElemInit(&(MyProc->links)); |
|
|
|
MyProc->waitStatus = STATUS_OK; |
|
|
|
MyProc->waitStatus = PROC_WAIT_STATUS_OK; |
|
|
|
MyProc->lxid = InvalidLocalTransactionId; |
|
|
|
MyProc->lxid = InvalidLocalTransactionId; |
|
|
|
MyProc->fpVXIDLock = false; |
|
|
|
MyProc->fpVXIDLock = false; |
|
|
|
MyProc->fpLocalTransactionId = InvalidLocalTransactionId; |
|
|
|
MyProc->fpLocalTransactionId = InvalidLocalTransactionId; |
|
|
@ -567,7 +567,7 @@ InitAuxiliaryProcess(void) |
|
|
|
* initialized by InitProcGlobal. |
|
|
|
* initialized by InitProcGlobal. |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
SHMQueueElemInit(&(MyProc->links)); |
|
|
|
SHMQueueElemInit(&(MyProc->links)); |
|
|
|
MyProc->waitStatus = STATUS_OK; |
|
|
|
MyProc->waitStatus = PROC_WAIT_STATUS_OK; |
|
|
|
MyProc->lxid = InvalidLocalTransactionId; |
|
|
|
MyProc->lxid = InvalidLocalTransactionId; |
|
|
|
MyProc->fpVXIDLock = false; |
|
|
|
MyProc->fpVXIDLock = false; |
|
|
|
MyProc->fpLocalTransactionId = InvalidLocalTransactionId; |
|
|
|
MyProc->fpLocalTransactionId = InvalidLocalTransactionId; |
|
|
@ -755,7 +755,7 @@ LockErrorCleanup(void) |
|
|
|
* did grant us the lock, we'd better remember it in our local lock |
|
|
|
* did grant us the lock, we'd better remember it in our local lock |
|
|
|
* table. |
|
|
|
* table. |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
if (MyProc->waitStatus == STATUS_OK) |
|
|
|
if (MyProc->waitStatus == PROC_WAIT_STATUS_OK) |
|
|
|
GrantAwaitedLock(); |
|
|
|
GrantAwaitedLock(); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
@ -1051,14 +1051,14 @@ ProcQueueInit(PROC_QUEUE *queue) |
|
|
|
* The lock table's partition lock must be held at entry, and will be held |
|
|
|
* The lock table's partition lock must be held at entry, and will be held |
|
|
|
* at exit. |
|
|
|
* at exit. |
|
|
|
* |
|
|
|
* |
|
|
|
* Result: STATUS_OK if we acquired the lock, STATUS_ERROR if not (deadlock). |
|
|
|
* Result: PROC_WAIT_STATUS_OK if we acquired the lock, PROC_WAIT_STATUS_ERROR if not (deadlock). |
|
|
|
* |
|
|
|
* |
|
|
|
* ASSUME: that no one will fiddle with the queue until after |
|
|
|
* ASSUME: that no one will fiddle with the queue until after |
|
|
|
* we release the partition lock. |
|
|
|
* we release the partition lock. |
|
|
|
* |
|
|
|
* |
|
|
|
* NOTES: The process queue is now a priority queue for locking. |
|
|
|
* NOTES: The process queue is now a priority queue for locking. |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
int |
|
|
|
ProcWaitStatus |
|
|
|
ProcSleep(LOCALLOCK *locallock, LockMethod lockMethodTable) |
|
|
|
ProcSleep(LOCALLOCK *locallock, LockMethod lockMethodTable) |
|
|
|
{ |
|
|
|
{ |
|
|
|
LOCKMODE lockmode = locallock->tag.mode; |
|
|
|
LOCKMODE lockmode = locallock->tag.mode; |
|
|
@ -1070,7 +1070,7 @@ ProcSleep(LOCALLOCK *locallock, LockMethod lockMethodTable) |
|
|
|
LOCKMASK myHeldLocks = MyProc->heldLocks; |
|
|
|
LOCKMASK myHeldLocks = MyProc->heldLocks; |
|
|
|
bool early_deadlock = false; |
|
|
|
bool early_deadlock = false; |
|
|
|
bool allow_autovacuum_cancel = true; |
|
|
|
bool allow_autovacuum_cancel = true; |
|
|
|
int myWaitStatus; |
|
|
|
ProcWaitStatus myWaitStatus; |
|
|
|
PGPROC *proc; |
|
|
|
PGPROC *proc; |
|
|
|
PGPROC *leader = MyProc->lockGroupLeader; |
|
|
|
PGPROC *leader = MyProc->lockGroupLeader; |
|
|
|
int i; |
|
|
|
int i; |
|
|
@ -1161,7 +1161,7 @@ ProcSleep(LOCALLOCK *locallock, LockMethod lockMethodTable) |
|
|
|
/* Skip the wait and just grant myself the lock. */ |
|
|
|
/* Skip the wait and just grant myself the lock. */ |
|
|
|
GrantLock(lock, proclock, lockmode); |
|
|
|
GrantLock(lock, proclock, lockmode); |
|
|
|
GrantAwaitedLock(); |
|
|
|
GrantAwaitedLock(); |
|
|
|
return STATUS_OK; |
|
|
|
return PROC_WAIT_STATUS_OK; |
|
|
|
} |
|
|
|
} |
|
|
|
/* Break out of loop to put myself before him */ |
|
|
|
/* Break out of loop to put myself before him */ |
|
|
|
break; |
|
|
|
break; |
|
|
@ -1195,7 +1195,7 @@ ProcSleep(LOCALLOCK *locallock, LockMethod lockMethodTable) |
|
|
|
MyProc->waitProcLock = proclock; |
|
|
|
MyProc->waitProcLock = proclock; |
|
|
|
MyProc->waitLockMode = lockmode; |
|
|
|
MyProc->waitLockMode = lockmode; |
|
|
|
|
|
|
|
|
|
|
|
MyProc->waitStatus = STATUS_WAITING; |
|
|
|
MyProc->waitStatus = PROC_WAIT_STATUS_WAITING; |
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
/*
|
|
|
|
* If we detected deadlock, give up without waiting. This must agree with |
|
|
|
* If we detected deadlock, give up without waiting. This must agree with |
|
|
@ -1204,7 +1204,7 @@ ProcSleep(LOCALLOCK *locallock, LockMethod lockMethodTable) |
|
|
|
if (early_deadlock) |
|
|
|
if (early_deadlock) |
|
|
|
{ |
|
|
|
{ |
|
|
|
RemoveFromWaitQueue(MyProc, hashcode); |
|
|
|
RemoveFromWaitQueue(MyProc, hashcode); |
|
|
|
return STATUS_ERROR; |
|
|
|
return PROC_WAIT_STATUS_ERROR; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/* mark that we are waiting for a lock */ |
|
|
|
/* mark that we are waiting for a lock */ |
|
|
@ -1236,7 +1236,7 @@ ProcSleep(LOCALLOCK *locallock, LockMethod lockMethodTable) |
|
|
|
/*
|
|
|
|
/*
|
|
|
|
* Set timer so we can wake up after awhile and check for a deadlock. If a |
|
|
|
* Set timer so we can wake up after awhile and check for a deadlock. If a |
|
|
|
* deadlock is detected, the handler sets MyProc->waitStatus = |
|
|
|
* deadlock is detected, the handler sets MyProc->waitStatus = |
|
|
|
* STATUS_ERROR, allowing us to know that we must report failure rather |
|
|
|
* PROC_WAIT_STATUS_ERROR, allowing us to know that we must report failure rather |
|
|
|
* than success. |
|
|
|
* than success. |
|
|
|
* |
|
|
|
* |
|
|
|
* By delaying the check until we've waited for a bit, we can avoid |
|
|
|
* By delaying the check until we've waited for a bit, we can avoid |
|
|
@ -1302,11 +1302,11 @@ ProcSleep(LOCALLOCK *locallock, LockMethod lockMethodTable) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
/*
|
|
|
|
* waitStatus could change from STATUS_WAITING to something else |
|
|
|
* waitStatus could change from PROC_WAIT_STATUS_WAITING to something else |
|
|
|
* asynchronously. Read it just once per loop to prevent surprising |
|
|
|
* asynchronously. Read it just once per loop to prevent surprising |
|
|
|
* behavior (such as missing log messages). |
|
|
|
* behavior (such as missing log messages). |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
myWaitStatus = *((volatile int *) &MyProc->waitStatus); |
|
|
|
myWaitStatus = *((volatile ProcWaitStatus *) &MyProc->waitStatus); |
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
/*
|
|
|
|
* If we are not deadlocked, but are waiting on an autovacuum-induced |
|
|
|
* If we are not deadlocked, but are waiting on an autovacuum-induced |
|
|
@ -1487,24 +1487,24 @@ ProcSleep(LOCALLOCK *locallock, LockMethod lockMethodTable) |
|
|
|
lockHoldersNum, lock_holders_sbuf.data, lock_waiters_sbuf.data)))); |
|
|
|
lockHoldersNum, lock_holders_sbuf.data, lock_waiters_sbuf.data)))); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (myWaitStatus == STATUS_WAITING) |
|
|
|
if (myWaitStatus == PROC_WAIT_STATUS_WAITING) |
|
|
|
ereport(LOG, |
|
|
|
ereport(LOG, |
|
|
|
(errmsg("process %d still waiting for %s on %s after %ld.%03d ms", |
|
|
|
(errmsg("process %d still waiting for %s on %s after %ld.%03d ms", |
|
|
|
MyProcPid, modename, buf.data, msecs, usecs), |
|
|
|
MyProcPid, modename, buf.data, msecs, usecs), |
|
|
|
(errdetail_log_plural("Process holding the lock: %s. Wait queue: %s.", |
|
|
|
(errdetail_log_plural("Process holding the lock: %s. Wait queue: %s.", |
|
|
|
"Processes holding the lock: %s. Wait queue: %s.", |
|
|
|
"Processes holding the lock: %s. Wait queue: %s.", |
|
|
|
lockHoldersNum, lock_holders_sbuf.data, lock_waiters_sbuf.data)))); |
|
|
|
lockHoldersNum, lock_holders_sbuf.data, lock_waiters_sbuf.data)))); |
|
|
|
else if (myWaitStatus == STATUS_OK) |
|
|
|
else if (myWaitStatus == PROC_WAIT_STATUS_OK) |
|
|
|
ereport(LOG, |
|
|
|
ereport(LOG, |
|
|
|
(errmsg("process %d acquired %s on %s after %ld.%03d ms", |
|
|
|
(errmsg("process %d acquired %s on %s after %ld.%03d ms", |
|
|
|
MyProcPid, modename, buf.data, msecs, usecs))); |
|
|
|
MyProcPid, modename, buf.data, msecs, usecs))); |
|
|
|
else |
|
|
|
else |
|
|
|
{ |
|
|
|
{ |
|
|
|
Assert(myWaitStatus == STATUS_ERROR); |
|
|
|
Assert(myWaitStatus == PROC_WAIT_STATUS_ERROR); |
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
/*
|
|
|
|
* Currently, the deadlock checker always kicks its own |
|
|
|
* Currently, the deadlock checker always kicks its own |
|
|
|
* process, which means that we'll only see STATUS_ERROR when |
|
|
|
* process, which means that we'll only see PROC_WAIT_STATUS_ERROR when |
|
|
|
* deadlock_state == DS_HARD_DEADLOCK, and there's no need to |
|
|
|
* deadlock_state == DS_HARD_DEADLOCK, and there's no need to |
|
|
|
* print redundant messages. But for completeness and |
|
|
|
* print redundant messages. But for completeness and |
|
|
|
* future-proofing, print a message if it looks like someone |
|
|
|
* future-proofing, print a message if it looks like someone |
|
|
@ -1529,7 +1529,7 @@ ProcSleep(LOCALLOCK *locallock, LockMethod lockMethodTable) |
|
|
|
pfree(lock_holders_sbuf.data); |
|
|
|
pfree(lock_holders_sbuf.data); |
|
|
|
pfree(lock_waiters_sbuf.data); |
|
|
|
pfree(lock_waiters_sbuf.data); |
|
|
|
} |
|
|
|
} |
|
|
|
} while (myWaitStatus == STATUS_WAITING); |
|
|
|
} while (myWaitStatus == PROC_WAIT_STATUS_WAITING); |
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
/*
|
|
|
|
* Disable the timers, if they are still running. As in LockErrorCleanup, |
|
|
|
* Disable the timers, if they are still running. As in LockErrorCleanup, |
|
|
@ -1568,7 +1568,7 @@ ProcSleep(LOCALLOCK *locallock, LockMethod lockMethodTable) |
|
|
|
/*
|
|
|
|
/*
|
|
|
|
* If we got the lock, be sure to remember it in the locallock table. |
|
|
|
* If we got the lock, be sure to remember it in the locallock table. |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
if (MyProc->waitStatus == STATUS_OK) |
|
|
|
if (MyProc->waitStatus == PROC_WAIT_STATUS_OK) |
|
|
|
GrantAwaitedLock(); |
|
|
|
GrantAwaitedLock(); |
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
/*
|
|
|
@ -1590,10 +1590,10 @@ ProcSleep(LOCALLOCK *locallock, LockMethod lockMethodTable) |
|
|
|
* XXX: presently, this code is only used for the "success" case, and only |
|
|
|
* XXX: presently, this code is only used for the "success" case, and only |
|
|
|
* works correctly for that case. To clean up in failure case, would need |
|
|
|
* works correctly for that case. To clean up in failure case, would need |
|
|
|
* to twiddle the lock's request counts too --- see RemoveFromWaitQueue. |
|
|
|
* to twiddle the lock's request counts too --- see RemoveFromWaitQueue. |
|
|
|
* Hence, in practice the waitStatus parameter must be STATUS_OK. |
|
|
|
* Hence, in practice the waitStatus parameter must be PROC_WAIT_STATUS_OK. |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
PGPROC * |
|
|
|
PGPROC * |
|
|
|
ProcWakeup(PGPROC *proc, int waitStatus) |
|
|
|
ProcWakeup(PGPROC *proc, ProcWaitStatus waitStatus) |
|
|
|
{ |
|
|
|
{ |
|
|
|
PGPROC *retProc; |
|
|
|
PGPROC *retProc; |
|
|
|
|
|
|
|
|
|
|
@ -1601,7 +1601,7 @@ ProcWakeup(PGPROC *proc, int waitStatus) |
|
|
|
if (proc->links.prev == NULL || |
|
|
|
if (proc->links.prev == NULL || |
|
|
|
proc->links.next == NULL) |
|
|
|
proc->links.next == NULL) |
|
|
|
return NULL; |
|
|
|
return NULL; |
|
|
|
Assert(proc->waitStatus == STATUS_WAITING); |
|
|
|
Assert(proc->waitStatus == PROC_WAIT_STATUS_WAITING); |
|
|
|
|
|
|
|
|
|
|
|
/* Save next process before we zap the list link */ |
|
|
|
/* Save next process before we zap the list link */ |
|
|
|
retProc = (PGPROC *) proc->links.next; |
|
|
|
retProc = (PGPROC *) proc->links.next; |
|
|
@ -1657,7 +1657,7 @@ ProcLockWakeup(LockMethod lockMethodTable, LOCK *lock) |
|
|
|
{ |
|
|
|
{ |
|
|
|
/* OK to waken */ |
|
|
|
/* OK to waken */ |
|
|
|
GrantLock(lock, proc->waitProcLock, lockmode); |
|
|
|
GrantLock(lock, proc->waitProcLock, lockmode); |
|
|
|
proc = ProcWakeup(proc, STATUS_OK); |
|
|
|
proc = ProcWakeup(proc, PROC_WAIT_STATUS_OK); |
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
/*
|
|
|
|
* ProcWakeup removes proc from the lock's waiting process queue |
|
|
|
* ProcWakeup removes proc from the lock's waiting process queue |
|
|
@ -1737,7 +1737,7 @@ CheckDeadLock(void) |
|
|
|
* preserve the flexibility to kill some other transaction than the |
|
|
|
* preserve the flexibility to kill some other transaction than the |
|
|
|
* one detecting the deadlock.) |
|
|
|
* one detecting the deadlock.) |
|
|
|
* |
|
|
|
* |
|
|
|
* RemoveFromWaitQueue sets MyProc->waitStatus to STATUS_ERROR, so |
|
|
|
* RemoveFromWaitQueue sets MyProc->waitStatus to PROC_WAIT_STATUS_ERROR, so |
|
|
|
* ProcSleep will report an error after we return from the signal |
|
|
|
* ProcSleep will report an error after we return from the signal |
|
|
|
* handler. |
|
|
|
* handler. |
|
|
|
*/ |
|
|
|
*/ |
|
|
|