1
0
mirror of https://github.com/postgres/postgres.git synced 2025-07-15 19:21:59 +03:00

Change the autovacuum launcher to use WaitLatch instead of a poll loop.

In pursuit of this (and with the expectation that WaitLatch will be needed
in more places), convert the latch field that was already added to PGPROC
for sync rep into a generic latch that is activated for all PGPROC-owning
processes, and change many of the standard backend signal handlers to set
that latch when a signal happens.  This will allow WaitLatch callers to be
wakened properly by these signals.

In passing, fix a whole bunch of signal handlers that had been hacked to do
things that might change errno, without adding the necessary save/restore
logic for errno.  Also make some minor fixes in unix_latch.c, and clean
up bizarre and unsafe scheme for disowning the process's latch.  Much of
this has to be back-patched into 9.1.

Peter Geoghegan, with additional work by Tom
This commit is contained in:
Tom Lane
2011-08-10 12:20:30 -04:00
parent 1f1b70a7cf
commit 4dab3d5ae1
11 changed files with 186 additions and 77 deletions

View File

@ -196,9 +196,11 @@ InitProcGlobal(void)
for (i = 0; i < TotalProcs; i++)
{
/* Common initialization for all PGPROCs, regardless of type. */
/* Set up per-PGPROC semaphore, latch, and backendLock */
PGSemaphoreCreate(&(procs[i].sem));
InitSharedLatch(&(procs[i].procLatch));
procs[i].backendLock = LWLockAssign();
InitSharedLatch(&procs[i].waitLatch);
/*
* Newly created PGPROCs for normal backends or for autovacuum must
@ -300,8 +302,8 @@ InitProcess(void)
MarkPostmasterChildActive();
/*
* Initialize all fields of MyProc, except for the semaphore which was
* prepared for us by InitProcGlobal.
* Initialize all fields of MyProc, except for the semaphore and latch,
* which were prepared for us by InitProcGlobal.
*/
SHMQueueElemInit(&(MyProc->links));
MyProc->waitStatus = STATUS_OK;
@ -327,12 +329,17 @@ InitProcess(void)
SHMQueueInit(&(MyProc->myProcLocks[i]));
MyProc->recoveryConflictPending = false;
/* Initialise for sync rep */
/* Initialize fields for sync rep */
MyProc->waitLSN.xlogid = 0;
MyProc->waitLSN.xrecoff = 0;
MyProc->syncRepState = SYNC_REP_NOT_WAITING;
SHMQueueElemInit(&(MyProc->syncRepLinks));
OwnLatch(&MyProc->waitLatch);
/*
* Acquire ownership of the PGPROC's latch, so that we can use WaitLatch.
* Note that there's no particular need to do ResetLatch here.
*/
OwnLatch(&MyProc->procLatch);
/*
* We might be reusing a semaphore that belonged to a failed process. So
@ -373,7 +380,6 @@ InitProcessPhase2(void)
/*
* Arrange to clean that up at backend exit.
*/
on_shmem_exit(SyncRepCleanupAtProcExit, 0);
on_shmem_exit(RemoveProcFromArray, 0);
}
@ -448,8 +454,8 @@ InitAuxiliaryProcess(void)
SpinLockRelease(ProcStructLock);
/*
* Initialize all fields of MyProc, except for the semaphore which was
* prepared for us by InitProcGlobal.
* Initialize all fields of MyProc, except for the semaphore and latch,
* which were prepared for us by InitProcGlobal.
*/
SHMQueueElemInit(&(MyProc->links));
MyProc->waitStatus = STATUS_OK;
@ -469,6 +475,12 @@ InitAuxiliaryProcess(void)
for (i = 0; i < NUM_LOCK_PARTITIONS; i++)
SHMQueueInit(&(MyProc->myProcLocks[i]));
/*
* Acquire ownership of the PGPROC's latch, so that we can use WaitLatch.
* Note that there's no particular need to do ResetLatch here.
*/
OwnLatch(&MyProc->procLatch);
/*
* We might be reusing a semaphore that belonged to a failed process. So
* be careful and reinitialize its value here. (This is not strictly
@ -671,6 +683,9 @@ ProcKill(int code, Datum arg)
Assert(MyProc != NULL);
/* Make sure we're out of the sync rep lists */
SyncRepCleanupAtProcExit();
/*
* Release any LW locks I am holding. There really shouldn't be any, but
* it's cheap to check again before we cut the knees off the LWLock
@ -678,6 +693,9 @@ ProcKill(int code, Datum arg)
*/
LWLockReleaseAll();
/* Release ownership of the process's latch, too */
DisownLatch(&MyProc->procLatch);
SpinLockAcquire(ProcStructLock);
/* Return PGPROC structure (and semaphore) to appropriate freelist */
@ -733,6 +751,9 @@ AuxiliaryProcKill(int code, Datum arg)
/* Release any LW locks I am holding (see notes above) */
LWLockReleaseAll();
/* Release ownership of the process's latch, too */
DisownLatch(&MyProc->procLatch);
SpinLockAcquire(ProcStructLock);
/* Mark auxiliary proc no longer in use */
@ -1610,6 +1631,10 @@ handle_sig_alarm(SIGNAL_ARGS)
{
int save_errno = errno;
/* SIGALRM is cause for waking anything waiting on the process latch */
if (MyProc)
SetLatch(&MyProc->procLatch);
if (deadlock_timeout_active)
{
deadlock_timeout_active = false;