mirror of
https://git.postgresql.org/git/postgresql.git
synced 2024-12-15 08:20:16 +08:00
Remove the option to service interrupts during PGSemaphoreLock().
The remaining caller (lwlocks) doesn't need that facility, and we plan to remove ImmedidateInterruptOK entirely. That means that interrupts can't be serviced race-free and portably anyway, so there's little reason for keeping the feature. Reviewed-By: Heikki Linnakangas
This commit is contained in:
parent
6753333f55
commit
d06995710b
@ -236,22 +236,14 @@ PGSemaphoreReset(PGSemaphore sema)
|
|||||||
* Lock a semaphore (decrement count), blocking if count would be < 0
|
* Lock a semaphore (decrement count), blocking if count would be < 0
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
PGSemaphoreLock(PGSemaphore sema, bool interruptOK)
|
PGSemaphoreLock(PGSemaphore sema)
|
||||||
{
|
{
|
||||||
int errStatus;
|
int errStatus;
|
||||||
|
|
||||||
/*
|
/* See notes in sysv_sema.c's implementation of PGSemaphoreLock. */
|
||||||
* See notes in sysv_sema.c's implementation of PGSemaphoreLock. Just as
|
|
||||||
* that code does for semop(), we handle both the case where sem_wait()
|
|
||||||
* returns errno == EINTR after a signal, and the case where it just keeps
|
|
||||||
* waiting.
|
|
||||||
*/
|
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
ImmediateInterruptOK = interruptOK;
|
|
||||||
CHECK_FOR_INTERRUPTS();
|
|
||||||
errStatus = sem_wait(PG_SEM_REF(sema));
|
errStatus = sem_wait(PG_SEM_REF(sema));
|
||||||
ImmediateInterruptOK = false;
|
|
||||||
} while (errStatus < 0 && errno == EINTR);
|
} while (errStatus < 0 && errno == EINTR);
|
||||||
|
|
||||||
if (errStatus < 0)
|
if (errStatus < 0)
|
||||||
|
@ -364,7 +364,7 @@ PGSemaphoreReset(PGSemaphore sema)
|
|||||||
* Lock a semaphore (decrement count), blocking if count would be < 0
|
* Lock a semaphore (decrement count), blocking if count would be < 0
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
PGSemaphoreLock(PGSemaphore sema, bool interruptOK)
|
PGSemaphoreLock(PGSemaphore sema)
|
||||||
{
|
{
|
||||||
int errStatus;
|
int errStatus;
|
||||||
struct sembuf sops;
|
struct sembuf sops;
|
||||||
@ -378,48 +378,13 @@ PGSemaphoreLock(PGSemaphore sema, bool interruptOK)
|
|||||||
* from the operation prematurely because we were sent a signal. So we
|
* from the operation prematurely because we were sent a signal. So we
|
||||||
* try and lock the semaphore again.
|
* try and lock the semaphore again.
|
||||||
*
|
*
|
||||||
* Each time around the loop, we check for a cancel/die interrupt. On
|
* We used to check interrupts here, but that required servicing
|
||||||
* some platforms, if such an interrupt comes in while we are waiting, it
|
* interrupts directly from signal handlers. Which is hard to do safely
|
||||||
* will cause the semop() call to exit with errno == EINTR, allowing us to
|
* and portably.
|
||||||
* service the interrupt (if not in a critical section already) during the
|
|
||||||
* next loop iteration.
|
|
||||||
*
|
|
||||||
* Once we acquire the lock, we do NOT check for an interrupt before
|
|
||||||
* returning. The caller needs to be able to record ownership of the lock
|
|
||||||
* before any interrupt can be accepted.
|
|
||||||
*
|
|
||||||
* There is a window of a few instructions between CHECK_FOR_INTERRUPTS
|
|
||||||
* and entering the semop() call. If a cancel/die interrupt occurs in
|
|
||||||
* that window, we would fail to notice it until after we acquire the lock
|
|
||||||
* (or get another interrupt to escape the semop()). We can avoid this
|
|
||||||
* problem by temporarily setting ImmediateInterruptOK to true before we
|
|
||||||
* do CHECK_FOR_INTERRUPTS; then, a die() interrupt in this interval will
|
|
||||||
* execute directly. However, there is a huge pitfall: there is another
|
|
||||||
* window of a few instructions after the semop() before we are able to
|
|
||||||
* reset ImmediateInterruptOK. If an interrupt occurs then, we'll lose
|
|
||||||
* control, which means that the lock has been acquired but our caller did
|
|
||||||
* not get a chance to record the fact. Therefore, we only set
|
|
||||||
* ImmediateInterruptOK if the caller tells us it's OK to do so, ie, the
|
|
||||||
* caller does not need to record acquiring the lock. (This is currently
|
|
||||||
* true for lockmanager locks, since the process that granted us the lock
|
|
||||||
* did all the necessary state updates. It's not true for SysV semaphores
|
|
||||||
* used to implement LW locks or emulate spinlocks --- but the wait time
|
|
||||||
* for such locks should not be very long, anyway.)
|
|
||||||
*
|
|
||||||
* On some platforms, signals marked SA_RESTART (which is most, for us)
|
|
||||||
* will not interrupt the semop(); it will just keep waiting. Therefore
|
|
||||||
* it's necessary for cancel/die interrupts to be serviced directly by the
|
|
||||||
* signal handler. On these platforms the behavior is really the same
|
|
||||||
* whether the signal arrives just before the semop() begins, or while it
|
|
||||||
* is waiting. The loop on EINTR is thus important only for platforms
|
|
||||||
* without SA_RESTART.
|
|
||||||
*/
|
*/
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
ImmediateInterruptOK = interruptOK;
|
|
||||||
CHECK_FOR_INTERRUPTS();
|
|
||||||
errStatus = semop(sema->semId, &sops, 1);
|
errStatus = semop(sema->semId, &sops, 1);
|
||||||
ImmediateInterruptOK = false;
|
|
||||||
} while (errStatus < 0 && errno == EINTR);
|
} while (errStatus < 0 && errno == EINTR);
|
||||||
|
|
||||||
if (errStatus < 0)
|
if (errStatus < 0)
|
||||||
|
@ -116,13 +116,11 @@ PGSemaphoreReset(PGSemaphore sema)
|
|||||||
* Serve the interrupt if interruptOK is true.
|
* Serve the interrupt if interruptOK is true.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
PGSemaphoreLock(PGSemaphore sema, bool interruptOK)
|
PGSemaphoreLock(PGSemaphore sema)
|
||||||
{
|
{
|
||||||
HANDLE wh[2];
|
HANDLE wh[2];
|
||||||
bool done = false;
|
bool done = false;
|
||||||
|
|
||||||
ImmediateInterruptOK = interruptOK;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Note: pgwin32_signal_event should be first to ensure that it will be
|
* Note: pgwin32_signal_event should be first to ensure that it will be
|
||||||
* reported when multiple events are set. We want to guarantee that
|
* reported when multiple events are set. We want to guarantee that
|
||||||
@ -173,8 +171,6 @@ PGSemaphoreLock(PGSemaphore sema, bool interruptOK)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ImmediateInterruptOK = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -863,8 +863,7 @@ LWLockDequeueSelf(LWLock *lock)
|
|||||||
*/
|
*/
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
/* "false" means cannot accept cancel/die interrupt here. */
|
PGSemaphoreLock(&MyProc->sem);
|
||||||
PGSemaphoreLock(&MyProc->sem, false);
|
|
||||||
if (!MyProc->lwWaiting)
|
if (!MyProc->lwWaiting)
|
||||||
break;
|
break;
|
||||||
extraWaits++;
|
extraWaits++;
|
||||||
@ -1034,8 +1033,7 @@ LWLockAcquireCommon(LWLock *lock, LWLockMode mode, uint64 *valptr, uint64 val)
|
|||||||
|
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
/* "false" means cannot accept cancel/die interrupt here. */
|
PGSemaphoreLock(&proc->sem);
|
||||||
PGSemaphoreLock(&proc->sem, false);
|
|
||||||
if (!proc->lwWaiting)
|
if (!proc->lwWaiting)
|
||||||
break;
|
break;
|
||||||
extraWaits++;
|
extraWaits++;
|
||||||
@ -1195,8 +1193,7 @@ LWLockAcquireOrWait(LWLock *lock, LWLockMode mode)
|
|||||||
|
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
/* "false" means cannot accept cancel/die interrupt here. */
|
PGSemaphoreLock(&proc->sem);
|
||||||
PGSemaphoreLock(&proc->sem, false);
|
|
||||||
if (!proc->lwWaiting)
|
if (!proc->lwWaiting)
|
||||||
break;
|
break;
|
||||||
extraWaits++;
|
extraWaits++;
|
||||||
@ -1397,8 +1394,7 @@ LWLockWaitForVar(LWLock *lock, uint64 *valptr, uint64 oldval, uint64 *newval)
|
|||||||
|
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
/* "false" means cannot accept cancel/die interrupt here. */
|
PGSemaphoreLock(&proc->sem);
|
||||||
PGSemaphoreLock(&proc->sem, false);
|
|
||||||
if (!proc->lwWaiting)
|
if (!proc->lwWaiting)
|
||||||
break;
|
break;
|
||||||
extraWaits++;
|
extraWaits++;
|
||||||
|
@ -72,7 +72,7 @@ extern void PGSemaphoreCreate(PGSemaphore sema);
|
|||||||
extern void PGSemaphoreReset(PGSemaphore sema);
|
extern void PGSemaphoreReset(PGSemaphore sema);
|
||||||
|
|
||||||
/* Lock a semaphore (decrement count), blocking if count would be < 0 */
|
/* Lock a semaphore (decrement count), blocking if count would be < 0 */
|
||||||
extern void PGSemaphoreLock(PGSemaphore sema, bool interruptOK);
|
extern void PGSemaphoreLock(PGSemaphore sema);
|
||||||
|
|
||||||
/* Unlock a semaphore (increment count) */
|
/* Unlock a semaphore (increment count) */
|
||||||
extern void PGSemaphoreUnlock(PGSemaphore sema);
|
extern void PGSemaphoreUnlock(PGSemaphore sema);
|
||||||
|
Loading…
Reference in New Issue
Block a user