示例#1
0
/*
 * PGSemaphoreCreate
 *
 * Allocate a PGSemaphore structure with initial count 1
 */
PGSemaphore
PGSemaphoreCreate(void)
{
	PGSemaphore sema;
	sem_t	   *newsem;

	/* Can't do this in a backend, because static state is postmaster's */
	Assert(!IsUnderPostmaster);

	if (numSems >= maxSems)
		elog(PANIC, "too many semaphores created");

#ifdef USE_NAMED_POSIX_SEMAPHORES
	newsem = PosixSemaphoreCreate();
	/* Remember new sema for ReleaseSemaphores */
	mySemPointers[numSems] = newsem;
	sema = (PGSemaphore) newsem;
#else
	sema = &sharedSemas[numSems];
	newsem = PG_SEM_REF(sema);
	PosixSemaphoreCreate(newsem);
#endif

	numSems++;

	return sema;
}
示例#2
0
/*
 * PGSemaphoreTryLock
 *
 * Lock a semaphore only if able to do so without blocking
 */
bool
PGSemaphoreTryLock(PGSemaphore sema)
{
	int			errStatus;

	/*
	 * Note: if errStatus is -1 and errno == EINTR then it means we returned
	 * from the operation prematurely because we were sent a signal.  So we
	 * try and lock the semaphore again.
	 */
	do
	{
		errStatus = sem_trywait(PG_SEM_REF(sema));
	} while (errStatus < 0 && errno == EINTR);

	if (errStatus < 0)
	{
		if (errno == EAGAIN || errno == EDEADLK)
			return false;		/* failed to lock it */
		/* Otherwise we got trouble */
		elog(FATAL, "sem_trywait failed: %m");
	}

	return true;
}
示例#3
0
/*
 * PGSemaphoreLock
 *
 * Lock a semaphore (decrement count), blocking if count would be < 0
 */
void
PGSemaphoreLock(PGSemaphore sema)
{
	int			errStatus;

	/* See notes in sysv_sema.c's implementation of PGSemaphoreLock. */
	do
	{
		errStatus = sem_wait(PG_SEM_REF(sema));
	} while (errStatus < 0 && errno == EINTR);

	if (errStatus < 0)
		elog(FATAL, "sem_wait failed: %m");
}
示例#4
0
/*
 * PGSemaphoreLock
 *
 * Lock a semaphore (decrement count), blocking if count would be < 0
 */
void
PGSemaphoreLock(PGSemaphore sema, bool interruptOK)
{
	int			errStatus;

	/*
	 * Note: if errStatus is -1 and errno == EINTR then it means we
	 * returned from the operation prematurely because we were sent a
	 * signal.	So we try and lock the semaphore again.
	 *
	 * Each time around the loop, we check for a cancel/die interrupt. We
	 * assume that if such an interrupt comes in while we are waiting, it
	 * will cause the sem_wait() call to exit with errno == EINTR, so that
	 * we will be able to service the interrupt (if not in a critical
	 * section already).
	 *
	 * 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 sem_wait() 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 sem_wait()).  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
	 * sem_wait() 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 Posix semaphores used to
	 * implement LW locks or emulate spinlocks --- but the wait time for
	 * such locks should not be very long, anyway.)
	 */
	do
	{
		ImmediateInterruptOK = interruptOK;
		CHECK_FOR_INTERRUPTS();
		errStatus = sem_wait(PG_SEM_REF(sema));
		ImmediateInterruptOK = false;
	} while (errStatus < 0 && errno == EINTR);

	if (errStatus < 0)
		elog(FATAL, "sem_wait failed: %m");
}
示例#5
0
文件: posix_sema.c 项目: AnLingm/gpdb
/*
 * PGSemaphoreLockInterruptable
 *
 * Lock a semaphore (decrement count), blocking if count would be < 0.
 * Return true if the lock obtained or false if an interrupt occurred.
 */
bool
PGSemaphoreLockInterruptable(PGSemaphore sema)
{
	int			errStatus;

	errStatus = sem_wait(PG_SEM_REF(sema));
	if (errStatus < 0)
	{
		if (errno == EINTR)
			return false;
		elog(FATAL, "sem_wait failed: %m");
	}

	return true;
}
示例#6
0
/*
 * Release semaphores at shutdown or shmem reinitialization
 *
 * (called as an on_shmem_exit callback, hence funny argument list)
 */
static void
ReleaseSemaphores(int status, Datum arg)
{
	int			i;

#ifdef USE_NAMED_POSIX_SEMAPHORES
	for (i = 0; i < numSems; i++)
		PosixSemaphoreKill(mySemPointers[i]);
	free(mySemPointers);
#endif

#ifdef USE_UNNAMED_POSIX_SEMAPHORES
	for (i = 0; i < numSems; i++)
		PosixSemaphoreKill(PG_SEM_REF(sharedSemas + i));
#endif
}
示例#7
0
/*
 * PGSemaphoreUnlock
 *
 * Unlock a semaphore (increment count)
 */
void
PGSemaphoreUnlock(PGSemaphore sema)
{
	int			errStatus;

	/*
	 * Note: if errStatus is -1 and errno == EINTR then it means we returned
	 * from the operation prematurely because we were sent a signal.  So we
	 * try and unlock the semaphore again. Not clear this can really happen,
	 * but might as well cope.
	 */
	do
	{
		errStatus = sem_post(PG_SEM_REF(sema));
	} while (errStatus < 0 && errno == EINTR);

	if (errStatus < 0)
		elog(FATAL, "sem_post failed: %m");
}
示例#8
0
/*
 * PGSemaphoreReset
 *
 * Reset a previously-initialized PGSemaphore to have count 0
 */
void
PGSemaphoreReset(PGSemaphore sema)
{
	/*
	 * There's no direct API for this in POSIX, so we have to ratchet the
	 * semaphore down to 0 with repeated trywait's.
	 */
	for (;;)
	{
		if (sem_trywait(PG_SEM_REF(sema)) < 0)
		{
			if (errno == EAGAIN || errno == EDEADLK)
				break;			/* got it down to 0 */
			if (errno == EINTR)
				continue;		/* can this happen? */
			elog(FATAL, "sem_trywait failed: %m");
		}
	}
}
示例#9
0
/*
 * PGSemaphoreLock
 *
 * Lock a semaphore (decrement count), blocking if count would be < 0
 */
void
PGSemaphoreLock(PGSemaphore sema, bool interruptOK)
{
	int			errStatus;

	/*
	 * 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
	{
		ImmediateInterruptOK = interruptOK;
		CHECK_FOR_INTERRUPTS();
		errStatus = sem_wait(PG_SEM_REF(sema));
		ImmediateInterruptOK = false;
	} while (errStatus < 0 && errno == EINTR);

	if (errStatus < 0)
		elog(FATAL, "sem_wait failed: %m");
}