Ejemplo n.º 1
0
/*
 * ProcWakeup -- wake up a process by releasing its private___ semaphore.
 *
 *	 Also remove the process from the wait queue and set its links invalid.
 *	 RETURN: the next process in the wait queue.
 *
 * The appropriate lock partition lock must be held by caller.
 *
 * 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
 * to twiddle the lock's request counts too --- see RemoveFromWaitQueue.
 * Hence, in practice the waitStatus parameter must be STATUS_OK.
 */
PGPROC *
ProcWakeup(PGPROC *proc, int waitStatus)
{
	PGPROC	   *retProc;

	/* Proc should be sleeping ... */
	if (proc->links.prev == NULL ||
		proc->links.next == NULL)
		return NULL;
	Assert(proc->waitStatus == STATUS_WAITING);

	/* Save next process before we zap the list link */
	retProc = (PGPROC *) proc->links.next;

	/* Remove process from wait queue */
	SHMQueueDelete(&(proc->links));
	(proc->waitLock->waitProcs.size)--;

	/* Clean up process' state and pass it the ok/fail signal */
	proc->waitLock = NULL;
	proc->waitProcLock = NULL;
	proc->waitStatus = waitStatus;

	/* And awaken it */
	SetLatch(&proc->procLatch);

	return retProc;
}
Ejemplo n.º 2
0
/*
 * Acquire SyncRepLock and cancel any wait currently in progress.
 */
static void
SyncRepCancelWait(void)
{
	LWLockAcquire(SyncRepLock, LW_EXCLUSIVE);
	if (!SHMQueueIsDetached(&(MyProc->syncRepLinks)))
		SHMQueueDelete(&(MyProc->syncRepLinks));
	MyProc->syncRepState = SYNC_REP_NOT_WAITING;
	LWLockRelease(SyncRepLock);
}
Ejemplo n.º 3
0
void
SyncRepCleanupAtProcExit(void)
{
	if (!SHMQueueIsDetached(&(MyProc->syncRepLinks)))
	{
		LWLockAcquire(SyncRepLock, LW_EXCLUSIVE);
		SHMQueueDelete(&(MyProc->syncRepLinks));
		LWLockRelease(SyncRepLock);
	}
}
Ejemplo n.º 4
0
void
SyncRepCleanupAtProcExit(int code, Datum arg)
{
	if (!SHMQueueIsDetached(&(MyProc->syncRepLinks)))
	{
		LWLockAcquire(SyncRepLock, LW_EXCLUSIVE);
		SHMQueueDelete(&(MyProc->syncRepLinks));
		LWLockRelease(SyncRepLock);
	}

	DisownLatch(&MyProc->waitLatch);
}
Ejemplo n.º 5
0
/*
 * ProcKill() -- Destroy the per-proc data structure for
 *	this process. Release any of its held spin locks.
 */
static void
ProcKill(int exitStatus, int pid)
{
    PROC 		*proc;
    SHMEM_OFFSET	location;
    
    /* -------------------- 
     * If this is a FATAL exit the postmaster will have to kill all the
     * existing backends and reinitialize shared memory.  So all we don't 
     * need to do anything here.
     * --------------------
     */
    if (exitStatus != 0)
	return;
    
    if (! pid)
	{
	    pid = getpid();
	}
    
    ShmemPIDLookup(pid,&location);
    if (location == INVALID_OFFSET)
	return;
    
    proc = (PROC *) MAKE_PTR(location);
    
    if (proc != MyProc) {
	Assert( pid != getpid() );
    } else
	MyProc = NULL;
    
    /* ---------------
     * Assume one lock table.
     * ---------------
     */
    ProcReleaseSpins(proc);
    LockReleaseAll(1,&proc->lockQueue);
    
    /* ----------------
     * get off the wait queue
     * ----------------
     */
    LockLockTable();
    if (proc->links.next != INVALID_OFFSET) {
	Assert(proc->waitLock->waitProcs.size > 0);
	SHMQueueDelete(&(proc->links));
	--proc->waitLock->waitProcs.size;
    }
    SHMQueueElemInit(&(proc->links));
    UnlockLockTable();
    
    return;
}
Ejemplo n.º 6
0
/*
 * ProcWakeup -- wake up a process by releasing its private semaphore.
 *
 *   remove the process from the wait queue and set its links invalid.
 *   RETURN: the next process in the wait queue.
 */
PROC *
ProcWakeup(PROC *proc, int errType)
{
    PROC *retProc;
    /* assume that spinlock has been acquired */
    
    if (proc->links.prev == INVALID_OFFSET ||
	proc->links.next == INVALID_OFFSET)
	return((PROC *) NULL);
    
    retProc = (PROC *) MAKE_PTR(proc->links.prev);
    
    /* you have to update waitLock->waitProcs.size yourself */
    SHMQueueDelete(&(proc->links));
    SHMQueueElemInit(&(proc->links));
    
    proc->errType = errType;
    
    IpcSemaphoreUnlock(proc->sem.semId, proc->sem.semNum, IpcExclusiveLock);
    
    return retProc;
}
Ejemplo n.º 7
0
/* --------------------
 * We only get to this routine if we got SIGALRM after DEADLOCK_TIMEOUT
 * while waiting for a lock to be released by some other process.  After
 * the one minute deadline we assume we have a deadlock and must abort
 * this transaction.  We must also indicate that I'm no longer waiting
 * on a lock so that other processes don't try to wake me up and screw 
 * up my semaphore.
 * --------------------
 */
void
HandleDeadLock(int sig)
{
    LOCK *lock;
    int size;
    
    LockLockTable();
    
    /* ---------------------
     * Check to see if we've been awoken by anyone in the interim.
     *
     * If we have we can return and resume our transaction -- happy day.
     * Before we are awoken the process releasing the lock grants it to
     * us so we know that we don't have to wait anymore.
     * 
     * Damn these names are LONG! -mer
     * ---------------------
     */
    if (IpcSemaphoreGetCount(MyProc->sem.semId, MyProc->sem.semNum) == 
	IpcSemaphoreDefaultStartValue) {
	UnlockLockTable();
	return;
    }
    
    /*
     * you would think this would be unnecessary, but...
     *
     * this also means we've been removed already.  in some ports
     * (e.g., sparc and aix) the semop(2) implementation is such that
     * we can actually end up in this handler after someone has removed
     * us from the queue and bopped the semaphore *but the test above
     * fails to detect the semaphore update* (presumably something weird
     * having to do with the order in which the semaphore wakeup signal
     * and SIGALRM get handled).
     */
    if (MyProc->links.prev == INVALID_OFFSET ||
	MyProc->links.next == INVALID_OFFSET) {
	UnlockLockTable();
	return;
    }
    
    lock = MyProc->waitLock;
    size = lock->waitProcs.size; /* so we can look at this in the core */
    
    /* ------------------------
     * Get this process off the lock's wait queue
     * ------------------------
     */
    Assert(lock->waitProcs.size > 0);
    --lock->waitProcs.size;
    SHMQueueDelete(&(MyProc->links));
    SHMQueueElemInit(&(MyProc->links));
    
    /* ------------------
     * Unlock my semaphore so that the count is right for next time.
     * I was awoken by a signal, not by someone unlocking my semaphore.
     * ------------------
     */
    IpcSemaphoreUnlock(MyProc->sem.semId, MyProc->sem.semNum, IpcExclusiveLock);
    
    /* -------------
     * Set MyProc->errType to STATUS_ERROR so that we abort after
     * returning from this handler.
     * -------------
     */
    MyProc->errType = STATUS_ERROR;
    
    /*
     * if this doesn't follow the IpcSemaphoreUnlock then we get lock
     * table corruption ("LockReplace: xid table corrupted") due to
     * race conditions.  i don't claim to understand this...
     */
    UnlockLockTable();
    
    elog(NOTICE, "Timeout -- possible deadlock");
    return;
}