示例#1
0
/*
 * ProcLockWakeup -- routine for waking up processes when a lock is
 *		released (or a prior waiter is aborted).  Scan all waiters
 *		for lock, waken any that are no longer blocked.
 *
 * The appropriate lock partition lock must be held by caller.
 */
void
ProcLockWakeup(LockMethod lockMethodTable, LOCK *lock)
{
	PROC_QUEUE *waitQueue = &(lock->waitProcs);
	int			queue_size = waitQueue->size;
	PGPROC	   *proc;
	LOCKMASK	aheadRequests = 0;

	Assert(queue_size >= 0);

	if (queue_size == 0)
		return;

	proc = (PGPROC *) waitQueue->links.next;

	while (queue_size-- > 0)
	{
		LOCKMODE	lockmode = proc->waitLockMode;

		/*
		 * Waken if (a) doesn't conflict with requests of earlier waiters, and
		 * (b) doesn't conflict with already-held locks.
		 */
		if ((lockMethodTable->conflictTab[lockmode] & aheadRequests) == 0 &&
			LockCheckConflicts(lockMethodTable,
							   lockmode,
							   lock,
							   proc->waitProcLock,
							   proc) == STATUS_OK)
		{
			/* OK to waken */
			GrantLock(lock, proc->waitProcLock, lockmode);
			proc = ProcWakeup(proc, STATUS_OK);

			/*
			 * ProcWakeup removes proc from the lock's waiting process queue
			 * and returns the next proc in chain; don't use proc's next-link,
			 * because it's been cleared.
			 */
		}
		else
		{
			/*
			 * Cannot wake this guy. Remember his request for later checks.
			 */
			aheadRequests |= LOCKBIT_ON(lockmode);
			proc = (PGPROC *) proc->links.next;
		}
	}

	Assert(waitQueue->size >= 0);
}
示例#2
0
/*
 * ProcLockWakeup -- routine for waking up processes when a lock is
 * 	released.
 */
int
ProcLockWakeup(PROC_QUEUE *queue, char *ltable, char *lock)
{
    PROC	*proc;
    int	count;
    
    if (! queue->size)
	return(STATUS_NOT_FOUND);
    
    proc = (PROC *) MAKE_PTR(queue->links.prev);
    count = 0;
    while ((LockResolveConflicts ((LOCKTAB *) ltable,
				  (LOCK *) lock,
				  proc->token,
				  proc->xid) == STATUS_OK))
	{
	    /* there was a waiting process, grant it the lock before waking it
	     * up.  This will prevent another process from seizing the lock
	     * between the time we release the lock master (spinlock) and
	     * the time that the awoken process begins executing again.
	     */
	    GrantLock((LOCK *) lock, proc->token);
	    queue->size--;
	    
	    /*
	     * ProcWakeup removes proc from the lock waiting process queue and
	     * returns the next proc in chain.  If a writer just dropped
	     * its lock and there are several waiting readers, wake them all up.
	     */
	    proc = ProcWakeup(proc, NO_ERROR);
	    
	    count++;
	    if (!proc || queue->size == 0)
		break;
	}
    
    if (count)
	return(STATUS_OK);
    else
	/* Something is still blocking us.  May have deadlocked. */
	return(STATUS_NOT_FOUND);
}