⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 proc.c

📁 PostgreSQL7.4.6 for Linux
💻 C
📖 第 1 页 / 共 3 页
字号:
			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 |= (1 << lockmode);			proc = (PGPROC *) MAKE_PTR(proc->links.next);		}	}	Assert(waitQueue->size >= 0);}/* -------------------- * We only get to this routine if we got SIGALRM after DeadlockTimeout * while waiting for a lock to be released by some other process.  Look * to see if there's a deadlock; if not, just return and continue waiting. * If we have a real deadlock, remove ourselves from the lock's wait queue * and signal an error to ProcSleep. * -------------------- */static voidCheckDeadLock(void){	/*	 * Acquire locktable lock.	Note that the deadlock check interrupt had	 * better not be enabled anywhere that this process itself holds the	 * locktable lock, else this will wait forever.  Also note that	 * LWLockAcquire creates a critical section, so that this routine	 * cannot be interrupted by cancel/die interrupts.	 */	LWLockAcquire(LockMgrLock, LW_EXCLUSIVE);	/*	 * 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.	 *	 * We check by looking to see if we've been unlinked from the wait queue.	 * This is quicker than checking our semaphore's state, since no	 * kernel call is needed, and it is safe because we hold the locktable	 * lock.	 */	if (MyProc->links.prev == INVALID_OFFSET ||		MyProc->links.next == INVALID_OFFSET)	{		LWLockRelease(LockMgrLock);		return;	}#ifdef LOCK_DEBUG	if (Debug_deadlocks)		DumpAllLocks();#endif	if (!DeadLockCheck(MyProc))	{		/* No deadlock, so keep waiting */		LWLockRelease(LockMgrLock);		return;	}	/*	 * Oops.  We have a deadlock.	 *	 * Get this process out of wait state.	 */	RemoveFromWaitQueue(MyProc);	/*	 * Set MyProc->errType to STATUS_ERROR so that ProcSleep will report	 * an error after we return from the signal handler.	 */	MyProc->errType = STATUS_ERROR;	/*	 * Unlock my semaphore so that the interrupted ProcSleep() call can	 * finish.	 */	PGSemaphoreUnlock(&MyProc->sem);	/*	 * We're done here.  Transaction abort caused by the error that	 * ProcSleep will raise will cause any other locks we hold to be	 * released, thus allowing other processes to wake up; we don't need	 * to do that here. NOTE: an exception is that releasing locks we hold	 * doesn't consider the possibility of waiters that were blocked	 * behind us on the lock we just failed to get, and might now be	 * wakable because we're not in front of them anymore.  However,	 * RemoveFromWaitQueue took care of waking up any such processes.	 */	LWLockRelease(LockMgrLock);}/* * ProcWaitForSignal - wait for a signal from another backend. * * This can share the semaphore normally used for waiting for locks, * since a backend could never be waiting for a lock and a signal at * the same time.  As with locks, it's OK if the signal arrives just * before we actually reach the waiting state. */voidProcWaitForSignal(void){	waitingForSignal = true;	PGSemaphoreLock(&MyProc->sem, true);	waitingForSignal = false;}/* * ProcCancelWaitForSignal - clean up an aborted wait for signal * * We need this in case the signal arrived after we aborted waiting, * or if it arrived but we never reached ProcWaitForSignal() at all. * Caller should call this after resetting the signal request status. */voidProcCancelWaitForSignal(void){	PGSemaphoreReset(&MyProc->sem);	waitingForSignal = false;}/* * ProcSendSignal - send a signal to a backend identified by BackendId */voidProcSendSignal(BackendId procId){	PGPROC	   *proc = BackendIdGetProc(procId);	if (proc != NULL)		PGSemaphoreUnlock(&proc->sem);}/***************************************************************************** * SIGALRM interrupt support * * Maybe these should be in pqsignal.c? *****************************************************************************//* * Enable the SIGALRM interrupt to fire after the specified delay * * Delay is given in milliseconds.	Caller should be sure a SIGALRM * signal handler is installed before this is called. * * This code properly handles nesting of deadlock timeout alarms within * statement timeout alarms. * * Returns TRUE if okay, FALSE on failure. */boolenable_sig_alarm(int delayms, bool is_statement_timeout){#ifdef WIN32#warning add Win32 timer#else	struct timeval fin_time;#ifndef __BEOS__	struct itimerval timeval;#else	bigtime_t	time_interval;#endif	/* Compute target timeout time if we will need it */	if (is_statement_timeout || statement_timeout_active)	{		gettimeofday(&fin_time, NULL);		fin_time.tv_sec += delayms / 1000;		fin_time.tv_usec += (delayms % 1000) * 1000;		if (fin_time.tv_usec >= 1000000)		{			fin_time.tv_sec++;			fin_time.tv_usec -= 1000000;		}	}	if (is_statement_timeout)	{		/* Begin statement-level timeout */		Assert(!deadlock_timeout_active);		statement_fin_time = fin_time;		statement_timeout_active = true;	}	else if (statement_timeout_active)	{		/*		 * Begin deadlock timeout with statement-level timeout active		 *		 * Here, we want to interrupt at the closer of the two timeout times.		 * If fin_time >= statement_fin_time then we need not touch the		 * existing timer setting; else set up to interrupt at the		 * deadlock timeout time.		 *		 * NOTE: in this case it is possible that this routine will be		 * interrupted by the previously-set timer alarm.  This is okay		 * because the signal handler will do only what it should do		 * according to the state variables.  The deadlock checker may get		 * run earlier than normal, but that does no harm.		 */		deadlock_timeout_active = true;		if (fin_time.tv_sec > statement_fin_time.tv_sec ||			(fin_time.tv_sec == statement_fin_time.tv_sec &&			 fin_time.tv_usec >= statement_fin_time.tv_usec))			return true;	}	else	{		/* Begin deadlock timeout with no statement-level timeout */		deadlock_timeout_active = true;	}	/* If we reach here, okay to set the timer interrupt */#ifndef __BEOS__	MemSet(&timeval, 0, sizeof(struct itimerval));	timeval.it_value.tv_sec = delayms / 1000;	timeval.it_value.tv_usec = (delayms % 1000) * 1000;	if (setitimer(ITIMER_REAL, &timeval, NULL))		return false;#else	/* BeOS doesn't have setitimer, but has set_alarm */	time_interval = delayms * 1000;		/* usecs */	if (set_alarm(time_interval, B_ONE_SHOT_RELATIVE_ALARM) < 0)		return false;#endif#endif	return true;}/* * Cancel the SIGALRM timer, either for a deadlock timeout or a statement * timeout.  If a deadlock timeout is canceled, any active statement timeout * remains in force. * * Returns TRUE if okay, FALSE on failure. */booldisable_sig_alarm(bool is_statement_timeout){#ifdef WIN32#warning add Win32 timer#else	/*	 * Always disable the interrupt if it is active; this avoids being	 * interrupted by the signal handler and thereby possibly getting	 * confused.	 *	 * We will re-enable the interrupt if necessary in CheckStatementTimeout.	 */	if (statement_timeout_active || deadlock_timeout_active)	{#ifndef __BEOS__		struct itimerval timeval;		MemSet(&timeval, 0, sizeof(struct itimerval));		if (setitimer(ITIMER_REAL, &timeval, NULL))		{			statement_timeout_active = deadlock_timeout_active = false;			return false;		}#else		/* BeOS doesn't have setitimer, but has set_alarm */		if (set_alarm(B_INFINITE_TIMEOUT, B_PERIODIC_ALARM) < 0)		{			statement_timeout_active = deadlock_timeout_active = false;			return false;		}#endif	}	/* Always cancel deadlock timeout, in case this is error cleanup */	deadlock_timeout_active = false;	/* Cancel or reschedule statement timeout */	if (is_statement_timeout)		statement_timeout_active = false;	else if (statement_timeout_active)	{		if (!CheckStatementTimeout())			return false;	}#endif	return true;}/* * Check for statement timeout.  If the timeout time has come, * trigger a query-cancel interrupt; if not, reschedule the SIGALRM * interrupt to occur at the right time. * * Returns true if okay, false if failed to set the interrupt. */static boolCheckStatementTimeout(void){	struct timeval now;	if (!statement_timeout_active)		return true;			/* do nothing if not active */	gettimeofday(&now, NULL);	if (now.tv_sec > statement_fin_time.tv_sec ||		(now.tv_sec == statement_fin_time.tv_sec &&		 now.tv_usec >= statement_fin_time.tv_usec))	{		/* Time to die */		statement_timeout_active = false;		kill(MyProcPid, SIGINT);	}	else	{		/* Not time yet, so (re)schedule the interrupt */#ifdef WIN32#warning add win32 timer#else#ifndef __BEOS__		struct itimerval timeval;		MemSet(&timeval, 0, sizeof(struct itimerval));		timeval.it_value.tv_sec = statement_fin_time.tv_sec - now.tv_sec;		timeval.it_value.tv_usec = statement_fin_time.tv_usec - now.tv_usec;		if (timeval.it_value.tv_usec < 0)		{			timeval.it_value.tv_sec--;			timeval.it_value.tv_usec += 1000000;		}		if (setitimer(ITIMER_REAL, &timeval, NULL))			return false;#else		/* BeOS doesn't have setitimer, but has set_alarm */		bigtime_t	time_interval;		time_interval =			(statement_fin_time.tv_sec - now.tv_sec) * 1000000 +			(statement_fin_time.tv_usec - now.tv_usec);		if (set_alarm(time_interval, B_ONE_SHOT_RELATIVE_ALARM) < 0)			return false;#endif#endif	}	return true;}/* * Signal handler for SIGALRM * * Process deadlock check and/or statement timeout check, as needed. * To avoid various edge cases, we must be careful to do nothing * when there is nothing to be done.  We also need to be able to * reschedule the timer interrupt if called before end of statement. */voidhandle_sig_alarm(SIGNAL_ARGS){	int			save_errno = errno;	if (deadlock_timeout_active)	{		deadlock_timeout_active = false;		CheckDeadLock();	}	if (statement_timeout_active)		(void) CheckStatementTimeout();	errno = save_errno;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -