mirror of
https://github.com/postgres/postgres.git
synced 2025-07-30 00:03:00 -04:00
Compare commits
3 Commits
7a7c8c98a6
...
5f6ec27a64
Author | SHA1 | Date | |
---|---|---|---|
|
5f6ec27a64 | ||
|
28215a32b5 | ||
|
d8f6ab5f66 |
@ -482,7 +482,7 @@ MarkAsPreparingGuts(GlobalTransaction gxact, TransactionId xid, const char *gid,
|
|||||||
proc->roleId = owner;
|
proc->roleId = owner;
|
||||||
proc->tempNamespaceId = InvalidOid;
|
proc->tempNamespaceId = InvalidOid;
|
||||||
proc->isBackgroundWorker = false;
|
proc->isBackgroundWorker = false;
|
||||||
proc->lwWaiting = false;
|
proc->lwWaiting = LW_WS_NOT_WAITING;
|
||||||
proc->lwWaitMode = 0;
|
proc->lwWaitMode = 0;
|
||||||
proc->waitLock = NULL;
|
proc->waitLock = NULL;
|
||||||
proc->waitProcLock = NULL;
|
proc->waitProcLock = NULL;
|
||||||
|
@ -298,6 +298,7 @@ pgwin32_socket(int af, int type, int protocol)
|
|||||||
if (ioctlsocket(s, FIONBIO, &on))
|
if (ioctlsocket(s, FIONBIO, &on))
|
||||||
{
|
{
|
||||||
TranslateSocketError();
|
TranslateSocketError();
|
||||||
|
closesocket(s);
|
||||||
return INVALID_SOCKET;
|
return INVALID_SOCKET;
|
||||||
}
|
}
|
||||||
errno = 0;
|
errno = 0;
|
||||||
|
@ -993,6 +993,15 @@ LWLockWakeup(LWLock *lock)
|
|||||||
wokeup_somebody = true;
|
wokeup_somebody = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Signal that the process isn't on the wait list anymore. This allows
|
||||||
|
* LWLockDequeueSelf() to remove itself of the waitlist with a
|
||||||
|
* proclist_delete(), rather than having to check if it has been
|
||||||
|
* removed from the list.
|
||||||
|
*/
|
||||||
|
Assert(waiter->lwWaiting == LW_WS_WAITING);
|
||||||
|
waiter->lwWaiting = LW_WS_PENDING_WAKEUP;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Once we've woken up an exclusive lock, there's no point in waking
|
* Once we've woken up an exclusive lock, there's no point in waking
|
||||||
* up anybody else.
|
* up anybody else.
|
||||||
@ -1050,7 +1059,7 @@ LWLockWakeup(LWLock *lock)
|
|||||||
* another lock.
|
* another lock.
|
||||||
*/
|
*/
|
||||||
pg_write_barrier();
|
pg_write_barrier();
|
||||||
waiter->lwWaiting = false;
|
waiter->lwWaiting = LW_WS_NOT_WAITING;
|
||||||
PGSemaphoreUnlock(waiter->sem);
|
PGSemaphoreUnlock(waiter->sem);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1071,7 +1080,7 @@ LWLockQueueSelf(LWLock *lock, LWLockMode mode)
|
|||||||
if (MyProc == NULL)
|
if (MyProc == NULL)
|
||||||
elog(PANIC, "cannot wait without a PGPROC structure");
|
elog(PANIC, "cannot wait without a PGPROC structure");
|
||||||
|
|
||||||
if (MyProc->lwWaiting)
|
if (MyProc->lwWaiting != LW_WS_NOT_WAITING)
|
||||||
elog(PANIC, "queueing for lock while waiting on another one");
|
elog(PANIC, "queueing for lock while waiting on another one");
|
||||||
|
|
||||||
LWLockWaitListLock(lock);
|
LWLockWaitListLock(lock);
|
||||||
@ -1079,7 +1088,7 @@ LWLockQueueSelf(LWLock *lock, LWLockMode mode)
|
|||||||
/* setting the flag is protected by the spinlock */
|
/* setting the flag is protected by the spinlock */
|
||||||
pg_atomic_fetch_or_u32(&lock->state, LW_FLAG_HAS_WAITERS);
|
pg_atomic_fetch_or_u32(&lock->state, LW_FLAG_HAS_WAITERS);
|
||||||
|
|
||||||
MyProc->lwWaiting = true;
|
MyProc->lwWaiting = LW_WS_WAITING;
|
||||||
MyProc->lwWaitMode = mode;
|
MyProc->lwWaitMode = mode;
|
||||||
|
|
||||||
/* LW_WAIT_UNTIL_FREE waiters are always at the front of the queue */
|
/* LW_WAIT_UNTIL_FREE waiters are always at the front of the queue */
|
||||||
@ -1107,8 +1116,7 @@ LWLockQueueSelf(LWLock *lock, LWLockMode mode)
|
|||||||
static void
|
static void
|
||||||
LWLockDequeueSelf(LWLock *lock)
|
LWLockDequeueSelf(LWLock *lock)
|
||||||
{
|
{
|
||||||
bool found = false;
|
bool on_waitlist;
|
||||||
proclist_mutable_iter iter;
|
|
||||||
|
|
||||||
#ifdef LWLOCK_STATS
|
#ifdef LWLOCK_STATS
|
||||||
lwlock_stats *lwstats;
|
lwlock_stats *lwstats;
|
||||||
@ -1121,18 +1129,13 @@ LWLockDequeueSelf(LWLock *lock)
|
|||||||
LWLockWaitListLock(lock);
|
LWLockWaitListLock(lock);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Can't just remove ourselves from the list, but we need to iterate over
|
* Remove ourselves from the waitlist, unless we've already been
|
||||||
* all entries as somebody else could have dequeued us.
|
* removed. The removal happens with the wait list lock held, so there's
|
||||||
|
* no race in this check.
|
||||||
*/
|
*/
|
||||||
proclist_foreach_modify(iter, &lock->waiters, lwWaitLink)
|
on_waitlist = MyProc->lwWaiting == LW_WS_WAITING;
|
||||||
{
|
if (on_waitlist)
|
||||||
if (iter.cur == MyProc->pgprocno)
|
proclist_delete(&lock->waiters, MyProc->pgprocno, lwWaitLink);
|
||||||
{
|
|
||||||
found = true;
|
|
||||||
proclist_delete(&lock->waiters, iter.cur, lwWaitLink);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (proclist_is_empty(&lock->waiters) &&
|
if (proclist_is_empty(&lock->waiters) &&
|
||||||
(pg_atomic_read_u32(&lock->state) & LW_FLAG_HAS_WAITERS) != 0)
|
(pg_atomic_read_u32(&lock->state) & LW_FLAG_HAS_WAITERS) != 0)
|
||||||
@ -1144,8 +1147,8 @@ LWLockDequeueSelf(LWLock *lock)
|
|||||||
LWLockWaitListUnlock(lock);
|
LWLockWaitListUnlock(lock);
|
||||||
|
|
||||||
/* clear waiting state again, nice for debugging */
|
/* clear waiting state again, nice for debugging */
|
||||||
if (found)
|
if (on_waitlist)
|
||||||
MyProc->lwWaiting = false;
|
MyProc->lwWaiting = LW_WS_NOT_WAITING;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
int extraWaits = 0;
|
int extraWaits = 0;
|
||||||
@ -1169,7 +1172,7 @@ LWLockDequeueSelf(LWLock *lock)
|
|||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
PGSemaphoreLock(MyProc->sem);
|
PGSemaphoreLock(MyProc->sem);
|
||||||
if (!MyProc->lwWaiting)
|
if (MyProc->lwWaiting == LW_WS_NOT_WAITING)
|
||||||
break;
|
break;
|
||||||
extraWaits++;
|
extraWaits++;
|
||||||
}
|
}
|
||||||
@ -1320,7 +1323,7 @@ LWLockAcquire(LWLock *lock, LWLockMode mode)
|
|||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
PGSemaphoreLock(proc->sem);
|
PGSemaphoreLock(proc->sem);
|
||||||
if (!proc->lwWaiting)
|
if (proc->lwWaiting == LW_WS_NOT_WAITING)
|
||||||
break;
|
break;
|
||||||
extraWaits++;
|
extraWaits++;
|
||||||
}
|
}
|
||||||
@ -1485,7 +1488,7 @@ LWLockAcquireOrWait(LWLock *lock, LWLockMode mode)
|
|||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
PGSemaphoreLock(proc->sem);
|
PGSemaphoreLock(proc->sem);
|
||||||
if (!proc->lwWaiting)
|
if (proc->lwWaiting == LW_WS_NOT_WAITING)
|
||||||
break;
|
break;
|
||||||
extraWaits++;
|
extraWaits++;
|
||||||
}
|
}
|
||||||
@ -1701,7 +1704,7 @@ LWLockWaitForVar(LWLock *lock, uint64 *valptr, uint64 oldval, uint64 *newval)
|
|||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
PGSemaphoreLock(proc->sem);
|
PGSemaphoreLock(proc->sem);
|
||||||
if (!proc->lwWaiting)
|
if (proc->lwWaiting == LW_WS_NOT_WAITING)
|
||||||
break;
|
break;
|
||||||
extraWaits++;
|
extraWaits++;
|
||||||
}
|
}
|
||||||
@ -1779,6 +1782,10 @@ LWLockUpdateVar(LWLock *lock, uint64 *valptr, uint64 val)
|
|||||||
|
|
||||||
proclist_delete(&lock->waiters, iter.cur, lwWaitLink);
|
proclist_delete(&lock->waiters, iter.cur, lwWaitLink);
|
||||||
proclist_push_tail(&wakeup, iter.cur, lwWaitLink);
|
proclist_push_tail(&wakeup, iter.cur, lwWaitLink);
|
||||||
|
|
||||||
|
/* see LWLockWakeup() */
|
||||||
|
Assert(waiter->lwWaiting == LW_WS_WAITING);
|
||||||
|
waiter->lwWaiting = LW_WS_PENDING_WAKEUP;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* We are done updating shared state of the lock itself. */
|
/* We are done updating shared state of the lock itself. */
|
||||||
@ -1794,7 +1801,7 @@ LWLockUpdateVar(LWLock *lock, uint64 *valptr, uint64 val)
|
|||||||
proclist_delete(&wakeup, iter.cur, lwWaitLink);
|
proclist_delete(&wakeup, iter.cur, lwWaitLink);
|
||||||
/* check comment in LWLockWakeup() about this barrier */
|
/* check comment in LWLockWakeup() about this barrier */
|
||||||
pg_write_barrier();
|
pg_write_barrier();
|
||||||
waiter->lwWaiting = false;
|
waiter->lwWaiting = LW_WS_NOT_WAITING;
|
||||||
PGSemaphoreUnlock(waiter->sem);
|
PGSemaphoreUnlock(waiter->sem);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -400,7 +400,7 @@ InitProcess(void)
|
|||||||
/* NB -- autovac launcher intentionally does not set IS_AUTOVACUUM */
|
/* NB -- autovac launcher intentionally does not set IS_AUTOVACUUM */
|
||||||
if (IsAutoVacuumWorkerProcess())
|
if (IsAutoVacuumWorkerProcess())
|
||||||
MyProc->statusFlags |= PROC_IS_AUTOVACUUM;
|
MyProc->statusFlags |= PROC_IS_AUTOVACUUM;
|
||||||
MyProc->lwWaiting = false;
|
MyProc->lwWaiting = LW_WS_NOT_WAITING;
|
||||||
MyProc->lwWaitMode = 0;
|
MyProc->lwWaitMode = 0;
|
||||||
MyProc->waitLock = NULL;
|
MyProc->waitLock = NULL;
|
||||||
MyProc->waitProcLock = NULL;
|
MyProc->waitProcLock = NULL;
|
||||||
@ -583,7 +583,7 @@ InitAuxiliaryProcess(void)
|
|||||||
MyProc->delayChkpt = false;
|
MyProc->delayChkpt = false;
|
||||||
MyProc->delayChkptEnd = false;
|
MyProc->delayChkptEnd = false;
|
||||||
MyProc->statusFlags = 0;
|
MyProc->statusFlags = 0;
|
||||||
MyProc->lwWaiting = false;
|
MyProc->lwWaiting = LW_WS_NOT_WAITING;
|
||||||
MyProc->lwWaitMode = 0;
|
MyProc->lwWaitMode = 0;
|
||||||
MyProc->waitLock = NULL;
|
MyProc->waitLock = NULL;
|
||||||
MyProc->waitProcLock = NULL;
|
MyProc->waitProcLock = NULL;
|
||||||
|
@ -263,9 +263,9 @@ pgstat_beinit(void)
|
|||||||
* Assign the MyBEEntry for an auxiliary process. Since it doesn't
|
* Assign the MyBEEntry for an auxiliary process. Since it doesn't
|
||||||
* have a BackendId, the slot is statically allocated based on the
|
* have a BackendId, the slot is statically allocated based on the
|
||||||
* auxiliary process type (MyAuxProcType). Backends use slots indexed
|
* auxiliary process type (MyAuxProcType). Backends use slots indexed
|
||||||
* in the range from 1 to MaxBackends (inclusive), so we use
|
* in the range from 0 to MaxBackends (exclusive), so we use
|
||||||
* MaxBackends + AuxBackendType + 1 as the index of the slot for an
|
* MaxBackends + AuxProcType as the index of the slot for an auxiliary
|
||||||
* auxiliary process.
|
* process.
|
||||||
*/
|
*/
|
||||||
MyBEEntry = &BackendStatusArray[MaxBackends + MyAuxProcType];
|
MyBEEntry = &BackendStatusArray[MaxBackends + MyAuxProcType];
|
||||||
}
|
}
|
||||||
|
@ -23,6 +23,14 @@
|
|||||||
|
|
||||||
struct PGPROC;
|
struct PGPROC;
|
||||||
|
|
||||||
|
/* what state of the wait process is a backend in */
|
||||||
|
typedef enum LWLockWaitState
|
||||||
|
{
|
||||||
|
LW_WS_NOT_WAITING, /* not currently waiting / woken up */
|
||||||
|
LW_WS_WAITING, /* currently waiting */
|
||||||
|
LW_WS_PENDING_WAKEUP /* removed from waitlist, but not yet signalled */
|
||||||
|
} LWLockWaitState;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Code outside of lwlock.c should not manipulate the contents of this
|
* Code outside of lwlock.c should not manipulate the contents of this
|
||||||
* structure directly, but we have to declare it here to allow LWLocks to be
|
* structure directly, but we have to declare it here to allow LWLocks to be
|
||||||
|
@ -180,7 +180,7 @@ struct PGPROC
|
|||||||
bool recoveryConflictPending;
|
bool recoveryConflictPending;
|
||||||
|
|
||||||
/* Info about LWLock the process is currently waiting for, if any. */
|
/* Info about LWLock the process is currently waiting for, if any. */
|
||||||
bool lwWaiting; /* true if waiting for an LW lock */
|
uint8 lwWaiting; /* see LWLockWaitState */
|
||||||
uint8 lwWaitMode; /* lwlock mode being waited for */
|
uint8 lwWaitMode; /* lwlock mode being waited for */
|
||||||
proclist_node lwWaitLink; /* position in LW lock wait list */
|
proclist_node lwWaitLink; /* position in LW lock wait list */
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user