proc.c 31.1 KB
Newer Older
1 2
/*-------------------------------------------------------------------------
 *
3
 * proc.c
4
 *	  routines to manage per-process shared memory data structure
5
 *
6
 * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
B
Add:  
Bruce Momjian 已提交
7
 * Portions Copyright (c) 1994, Regents of the University of California
8 9 10
 *
 *
 * IDENTIFICATION
B
Bruce Momjian 已提交
11
 *	  $Header: /cvsroot/pgsql/src/backend/storage/lmgr/proc.c,v 1.110 2001/09/29 21:35:14 momjian Exp $
12 13 14 15 16
 *
 *-------------------------------------------------------------------------
 */
/*
 * Interface (a):
17
 *		ProcSleep(), ProcWakeup(),
18 19
 *		ProcQueueAlloc() -- create a shm queue for sleeping processes
 *		ProcQueueInit() -- create a queue without allocing memory
20 21 22 23 24 25 26 27
 *
 * Locking and waiting for buffers can cause the backend to be
 * put to sleep.  Whoever releases the lock, etc. wakes the
 * process up again (and gives it an error code so it knows
 * whether it was awoken on an error condition).
 *
 * Interface (b):
 *
28 29
 * ProcReleaseLocks -- frees the locks associated with current transaction
 *
30
 * ProcKill -- destroys the shared memory state (and locks)
31
 *		associated with the process.
32 33
 *
 * 5/15/91 -- removed the buffer pool based lock chain in favor
34 35 36 37 38 39
 *		of a shared memory lock chain.	The write-protection is
 *		more expensive if the lock chain is in the buffer pool.
 *		The only reason I kept the lock chain in the buffer pool
 *		in the first place was to allow the lock table to grow larger
 *		than available shared memory and that isn't going to work
 *		without a lot of unimplemented support anyway.
40 41
 *
 * 4/7/95 -- instead of allocating a set of 1 semaphore per process, we
42 43 44 45
 *		allocate a semaphore from a set of PROC_NSEMS_PER_SET semaphores
 *		shared among backends (we keep a few sets of semaphores around).
 *		This is so that we can support more backends. (system-wide semaphore
 *		sets run out pretty fast.)				  -ay 4/95
46
 */
47 48
#include "postgres.h"

49
#include <errno.h>
50 51
#include <sys/time.h>
#include <unistd.h>
52
#include <signal.h>
53
#include <sys/types.h>
M
Marc G. Fournier 已提交
54

55
#if defined(solaris_sparc) || defined(__CYGWIN__)
56 57 58 59
#include <sys/ipc.h>
#include <sys/sem.h>
#endif

60 61
#include "miscadmin.h"

62 63 64 65
#if defined(__darwin__)
#include "port/darwin/sem.h"
#endif

66
/* In Ultrix and QNX, sem.h must be included after ipc.h */
67
#ifdef HAVE_SYS_SEM_H
68
#include <sys/sem.h>
69
#endif
B
Bruce Momjian 已提交
70

71
#include "access/xact.h"
72
#include "storage/proc.h"
73
#include "storage/sinval.h"
74
#include "storage/spin.h"
75

76

B
Bruce Momjian 已提交
77
int			DeadlockTimeout = 1000;
M
 
Marc G. Fournier 已提交
78

79 80 81 82 83 84 85 86
PROC	   *MyProc = NULL;

/*
 * This spinlock protects the freelist of recycled PROC structures and the
 * bitmap of free semaphores.  We cannot use an LWLock because the LWLock
 * manager depends on already having a PROC and a wait semaphore!  But these
 * structures are touched relatively infrequently (only at backend startup
 * or shutdown) and not for very long, so a spinlock is okay.
87
 */
88
static slock_t *ProcStructLock = NULL;
89 90 91

static PROC_HDR *ProcGlobal = NULL;

92
static PROC *DummyProc = NULL;
93

94
static bool waitingForLock = false;
95
static bool waitingForSignal = false;
96 97

static void ProcKill(void);
98
static void DummyProcKill(void);
99 100
static void ProcGetNewSemIdAndNum(IpcSemaphoreId *semId, int *semNum);
static void ProcFreeSem(IpcSemaphoreId semId, int semNum);
101 102 103
static void ZeroProcSemaphore(PROC *proc);
static void ProcFreeAllSemaphores(void);

V
Vadim B. Mikheev 已提交
104

105 106
/*
 * InitProcGlobal -
107
 *	  initializes the global process table. We put it here so that
108
 *	  the postmaster can do this initialization. (ProcFreeAllSemaphores needs
109 110 111
 *	  to read this table on exiting the postmaster. If we have the first
 *	  backend do this, starting up and killing the postmaster without
 *	  starting any backends will be a problem.)
112 113 114 115 116 117 118 119 120 121 122
 *
 *	  We also allocate all the per-process semaphores we will need to support
 *	  the requested number of backends.  We used to allocate semaphores
 *	  only when backends were actually started up, but that is bad because
 *	  it lets Postgres fail under load --- a lot of Unix systems are
 *	  (mis)configured with small limits on the number of semaphores, and
 *	  running out when trying to start another backend is a common failure.
 *	  So, now we grab enough semaphores to support the desired max number
 *	  of backends immediately at initialization --- if the sysadmin has set
 *	  MaxBackends higher than his kernel will support, he'll find out sooner
 *	  rather than later.
123 124
 */
void
125
InitProcGlobal(int maxBackends)
126
{
127 128
	int			semMapEntries;
	Size		procGlobalSize;
129
	bool		found = false;
130

131 132 133 134
	/*
	 * Compute size for ProcGlobal structure.  Note we need one more sema
	 * besides those used for regular backends.
	 */
135
	Assert(maxBackends > 0);
136
	semMapEntries = PROC_SEM_MAP_ENTRIES(maxBackends+1);
137 138 139
	procGlobalSize = sizeof(PROC_HDR) + (semMapEntries-1) * sizeof(SEM_MAP_ENTRY);

	/* Create or attach to the ProcGlobal shared structure */
140
	ProcGlobal = (PROC_HDR *)
141
		ShmemInitStruct("Proc Header", procGlobalSize, &found);
142

143 144
	/* --------------------
	 * We're the first - initialize.
145 146
	 * XXX if found should ever be true, it is a sign of impending doom ...
	 * ought to complain if so?
147 148 149
	 * --------------------
	 */
	if (!found)
150
	{
151
		int			i;
152

153
		ProcGlobal->freeProcs = INVALID_OFFSET;
154 155 156
		ProcGlobal->semMapEntries = semMapEntries;

		for (i = 0; i < semMapEntries; i++)
157
		{
158 159
			ProcGlobal->procSemMap[i].procSemId = -1;
			ProcGlobal->procSemMap[i].freeSemMap = 0;
160
		}
161

B
Bruce Momjian 已提交
162 163
		/*
		 * Arrange to delete semas on exit --- set this up now so that we
B
Bruce Momjian 已提交
164 165 166 167
		 * will clean up if pre-allocation fails.  We use our own
		 * freeproc, rather than IpcSemaphoreCreate's removeOnExit option,
		 * because we don't want to fill up the on_shmem_exit list with a
		 * separate entry for each semaphore set.
168
		 */
169
		on_shmem_exit(ProcFreeAllSemaphores, 0);
170

B
Bruce Momjian 已提交
171
		/*
172
		 * Pre-create the semaphores.
173
		 */
174
		for (i = 0; i < semMapEntries; i++)
175
		{
B
Bruce Momjian 已提交
176
			IpcSemaphoreId semId;
177 178 179 180 181

			semId = IpcSemaphoreCreate(PROC_NSEMS_PER_SET,
									   IPCProtection,
									   1,
									   false);
182
			ProcGlobal->procSemMap[i].procSemId = semId;
183
		}
184 185 186 187 188 189 190 191 192 193 194 195 196 197 198

		/*
		 * Pre-allocate a PROC structure for dummy (checkpoint) processes,
		 * and reserve the last sema of the precreated semas for it.
		 */
		DummyProc = (PROC *) ShmemAlloc(sizeof(PROC));
		DummyProc->pid = 0;		/* marks DummyProc as not in use */
		i = semMapEntries-1;
		ProcGlobal->procSemMap[i].freeSemMap |= 1 << (PROC_NSEMS_PER_SET-1);
		DummyProc->sem.semId = ProcGlobal->procSemMap[i].procSemId;
		DummyProc->sem.semNum = PROC_NSEMS_PER_SET-1;

		/* Create ProcStructLock spinlock, too */
		ProcStructLock = (slock_t *) ShmemAlloc(sizeof(slock_t));
		SpinLockInit(ProcStructLock);
199 200 201
	}
}

202 203
/*
 * InitProcess -- create a per-process data structure for this backend
204 205
 */
void
206
InitProcess(void)
207
{
208 209 210 211 212 213 214 215 216 217 218
	SHMEM_OFFSET	myOffset;

	/*
	 * ProcGlobal should be set by a previous call to InitProcGlobal
	 * (if we are a backend, we inherit this by fork() from the postmaster).
	 */
	if (ProcGlobal == NULL)
		elog(STOP, "InitProcess: Proc Header uninitialized");

	if (MyProc != NULL)
		elog(ERROR, "InitProcess: you already exist");
219

220
	/*
221
	 * try to get a proc struct from the free list first
222
	 */
223
	SpinLockAcquire(ProcStructLock);
224 225 226 227

	myOffset = ProcGlobal->freeProcs;

	if (myOffset != INVALID_OFFSET)
228
	{
229 230
		MyProc = (PROC *) MAKE_PTR(myOffset);
		ProcGlobal->freeProcs = MyProc->links.next;
231
		SpinLockRelease(ProcStructLock);
232 233 234 235
	}
	else
	{
		/*
236
		 * have to allocate a new one.
237
		 */
238
		SpinLockRelease(ProcStructLock);
239
		MyProc = (PROC *) ShmemAlloc(sizeof(PROC));
240 241
		if (!MyProc)
			elog(FATAL, "cannot create new proc: out of memory");
242
	}
243

244
	/*
245
	 * Initialize all fields of MyProc.
246
	 */
247
	SHMQueueElemInit(&(MyProc->links));
248 249
	MyProc->sem.semId = -1;		/* no wait-semaphore acquired yet */
	MyProc->sem.semNum = -1;
250
	MyProc->errType = STATUS_OK;
251
	MyProc->xid = InvalidTransactionId;
252
	MyProc->xmin = InvalidTransactionId;
253 254
	MyProc->pid = MyProcPid;
	MyProc->databaseId = MyDatabaseId;
255
	MyProc->logRec.xrecoff = 0;
256 257 258
	MyProc->lwWaiting = false;
	MyProc->lwExclusive = false;
	MyProc->lwWaitLink = NULL;
259 260 261
	MyProc->waitLock = NULL;
	MyProc->waitHolder = NULL;
	SHMQueueInit(&(MyProc->procHolders));
262

263
	/*
264
	 * Arrange to clean up at backend exit.
265
	 */
266
	on_shmem_exit(ProcKill, 0);
267

268
	/*
269
	 * Set up a wait-semaphore for the proc.  (We rely on ProcKill to clean
270
	 * up MyProc if this fails.)
271 272 273
	 */
	if (IsUnderPostmaster)
		ProcGetNewSemIdAndNum(&MyProc->sem.semId, &MyProc->sem.semNum);
274 275

	/*
276
	 * We might be reusing a semaphore that belonged to a failed process.
277 278 279
	 * So be careful and reinitialize its value here.
	 */
	if (MyProc->sem.semId >= 0)
280 281
		ZeroProcSemaphore(MyProc);

282
	/*
B
Bruce Momjian 已提交
283 284
	 * Now that we have a PROC, we could try to acquire locks, so
	 * initialize the deadlock checker.
285 286
	 */
	InitDeadLockChecking();
287 288
}

289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347
/*
 * InitDummyProcess -- create a dummy per-process data structure
 *
 * This is called by checkpoint processes so that they will have a MyProc
 * value that's real enough to let them wait for LWLocks.  The PROC and
 * sema that are assigned are the extra ones created during InitProcGlobal.
 */
void
InitDummyProcess(void)
{
	/*
	 * ProcGlobal should be set by a previous call to InitProcGlobal
	 * (we inherit this by fork() from the postmaster).
	 */
	if (ProcGlobal == NULL || DummyProc == NULL)
		elog(STOP, "InitDummyProcess: Proc Header uninitialized");

	if (MyProc != NULL)
		elog(ERROR, "InitDummyProcess: you already exist");

	/*
	 * DummyProc should not presently be in use by anyone else
	 */
	if (DummyProc->pid != 0)
		elog(FATAL, "InitDummyProcess: DummyProc is in use by PID %d",
			 DummyProc->pid);
	MyProc = DummyProc;

	/*
	 * Initialize all fields of MyProc, except MyProc->sem which was
	 * set up by InitProcGlobal.
	 */
	MyProc->pid = MyProcPid;	/* marks DummyProc as in use by me */
	SHMQueueElemInit(&(MyProc->links));
	MyProc->errType = STATUS_OK;
	MyProc->xid = InvalidTransactionId;
	MyProc->xmin = InvalidTransactionId;
	MyProc->databaseId = MyDatabaseId;
	MyProc->logRec.xrecoff = 0;
	MyProc->lwWaiting = false;
	MyProc->lwExclusive = false;
	MyProc->lwWaitLink = NULL;
	MyProc->waitLock = NULL;
	MyProc->waitHolder = NULL;
	SHMQueueInit(&(MyProc->procHolders));

	/*
	 * Arrange to clean up at process exit.
	 */
	on_shmem_exit(DummyProcKill, 0);

	/*
	 * We might be reusing a semaphore that belonged to a failed process.
	 * So be careful and reinitialize its value here.
	 */
	if (MyProc->sem.semId >= 0)
		ZeroProcSemaphore(MyProc);
}

348 349 350 351 352 353
/*
 * Initialize the proc's wait-semaphore to count zero.
 */
static void
ZeroProcSemaphore(PROC *proc)
{
B
Bruce Momjian 已提交
354
	union semun semun;
355 356 357 358 359 360 361 362

	semun.val = 0;
	if (semctl(proc->sem.semId, proc->sem.semNum, SETVAL, semun) < 0)
	{
		fprintf(stderr, "ZeroProcSemaphore: semctl(id=%d,SETVAL) failed: %s\n",
				proc->sem.semId, strerror(errno));
		proc_exit(255);
	}
363 364
}

365 366 367
/*
 * Cancel any pending wait for lock, when aborting a transaction.
 *
368 369
 * Returns true if we had been waiting for a lock, else false.
 *
370 371 372 373
 * (Normally, this would only happen if we accept a cancel/die
 * interrupt while waiting; but an elog(ERROR) while waiting is
 * within the realm of possibility, too.)
 */
374
bool
375 376 377 378
LockWaitCancel(void)
{
	/* Nothing to do if we weren't waiting for a lock */
	if (!waitingForLock)
379 380
		return false;

381 382 383
	waitingForLock = false;

	/* Turn off the deadlock timer, if it's still running (see ProcSleep) */
384
	disable_sigalrm_interrupt();
385 386

	/* Unlink myself from the wait queue, if on it (might not be anymore!) */
387
	LWLockAcquire(LockMgrLock, LW_EXCLUSIVE);
388 389
	if (MyProc->links.next != INVALID_OFFSET)
		RemoveFromWaitQueue(MyProc);
390
	LWLockRelease(LockMgrLock);
H
Hiroshi Inoue 已提交
391

392 393 394
	/*
	 * Reset the proc wait semaphore to zero.  This is necessary in the
	 * scenario where someone else granted us the lock we wanted before we
B
Bruce Momjian 已提交
395 396 397 398 399
	 * were able to remove ourselves from the wait-list.  The semaphore
	 * will have been bumped to 1 by the would-be grantor, and since we
	 * are no longer going to wait on the sema, we have to force it back
	 * to zero. Otherwise, our next attempt to wait for a lock will fall
	 * through prematurely.
400 401
	 */
	ZeroProcSemaphore(MyProc);
402 403

	/*
B
Bruce Momjian 已提交
404 405
	 * Return true even if we were kicked off the lock before we were able
	 * to remove ourselves.
406 407
	 */
	return true;
H
Hiroshi Inoue 已提交
408
}
409

410

411
/*
412 413 414 415 416 417 418 419
 * ProcReleaseLocks() -- release locks associated with current transaction
 *			at transaction commit or abort
 *
 * At commit, we release only locks tagged with the current transaction's XID,
 * leaving those marked with XID 0 (ie, session locks) undisturbed.  At abort,
 * we release all locks including XID 0, because we need to clean up after
 * a failure.  This logic will need extension if we ever support nested
 * transactions.
420
 *
421
 * Note that user locks are not released in either case.
422 423
 */
void
424
ProcReleaseLocks(bool isCommit)
425
{
426 427
	if (!MyProc)
		return;
428 429 430
	/* If waiting, get off wait queue (should only be needed after error) */
	LockWaitCancel();
	/* Release locks */
431 432
	LockReleaseAll(DEFAULT_LOCKMETHOD, MyProc,
				   !isCommit, GetCurrentTransactionId());
433 434 435 436 437
}


/*
 * ProcKill() -- Destroy the per-proc data structure for
438
 *		this process. Release any of its held LW locks.
439 440
 */
static void
441
ProcKill(void)
442
{
443
	Assert(MyProc != NULL);
444

445 446 447 448 449
	/* Release any LW locks I am holding */
	LWLockReleaseAll();

	/* Abort any buffer I/O in progress */
	AbortBufferIO();
450

451 452
	/* Get off any wait queue I might be on */
	LockWaitCancel();
453

454
	/* Remove from the standard lock table */
455
	LockReleaseAll(DEFAULT_LOCKMETHOD, MyProc, true, InvalidTransactionId);
456

457 458
#ifdef USER_LOCKS
	/* Remove from the user lock table */
459
	LockReleaseAll(USER_LOCKMETHOD, MyProc, true, InvalidTransactionId);
460
#endif
461

462
	SpinLockAcquire(ProcStructLock);
463

464 465 466
	/* Free up my wait semaphore, if I got one */
	if (MyProc->sem.semId >= 0)
		ProcFreeSem(MyProc->sem.semId, MyProc->sem.semNum);
467 468 469 470 471

	/* Add PROC struct to freelist so space can be recycled in future */
	MyProc->links.next = ProcGlobal->freeProcs;
	ProcGlobal->freeProcs = MAKE_OFFSET(MyProc);

472
	/* PROC struct isn't mine anymore */
473
	MyProc = NULL;
474

475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500
	SpinLockRelease(ProcStructLock);
}

/*
 * DummyProcKill() -- Cut-down version of ProcKill for dummy (checkpoint)
 *		processes.  The PROC and sema are not released, only marked
 *		as not-in-use.
 */
static void
DummyProcKill(void)
{
	Assert(MyProc != NULL && MyProc == DummyProc);

	/* Release any LW locks I am holding */
	LWLockReleaseAll();

	/* Abort any buffer I/O in progress */
	AbortBufferIO();

	/* I can't be on regular lock queues, so needn't check */

	/* Mark DummyProc no longer in use */
	MyProc->pid = 0;

	/* PROC struct isn't mine anymore */
	MyProc = NULL;
501 502
}

503

504 505
/*
 * ProcQueue package: routines for putting processes to sleep
506
 *		and  waking them up
507 508 509 510 511 512 513 514
 */

/*
 * ProcQueueAlloc -- alloc/attach to a shared memory process queue
 *
 * Returns: a pointer to the queue or NULL
 * Side Effects: Initializes the queue if we allocated one
 */
515
#ifdef NOT_USED
516
PROC_QUEUE *
517 518
ProcQueueAlloc(char *name)
{
519 520
	bool		found;
	PROC_QUEUE *queue = (PROC_QUEUE *)
B
Bruce Momjian 已提交
521
	ShmemInitStruct(name, sizeof(PROC_QUEUE), &found);
522 523

	if (!queue)
524
		return NULL;
525 526
	if (!found)
		ProcQueueInit(queue);
527
	return queue;
528
}
529

530
#endif
531 532 533 534 535

/*
 * ProcQueueInit -- initialize a shared memory process queue
 */
void
536
ProcQueueInit(PROC_QUEUE *queue)
537
{
538 539
	SHMQueueInit(&(queue->links));
	queue->size = 0;
540 541 542 543 544 545
}


/*
 * ProcSleep -- put a process to sleep
 *
546 547
 * Caller must have set MyProc->heldLocks to reflect locks already held
 * on the lockable object by this process (under all XIDs).
548
 *
549
 * Locktable's masterLock must be held at entry, and will be held
550
 * at exit.
551
 *
552
 * Result: STATUS_OK if we acquired the lock, STATUS_ERROR if not (deadlock).
553
 *
554
 * ASSUME: that no one will fiddle with the queue until after
555
 *		we release the masterLock.
556 557
 *
 * NOTES: The process queue is now a priority queue for locking.
558 559 560
 *
 * P() on the semaphore should put us to sleep.  The process
 * semaphore is normally zero, so when we try to acquire it, we sleep.
561 562
 */
int
563
ProcSleep(LOCKMETHODTABLE *lockMethodTable,
564 565
		  LOCKMODE lockmode,
		  LOCK *lock,
B
Bruce Momjian 已提交
566
		  PROCLOCK *holder)
567
{
568
	LOCKMETHODCTL *lockctl = lockMethodTable->ctl;
569
	LWLockId	masterLock = lockctl->masterLock;
570 571
	PROC_QUEUE *waitQueue = &(lock->waitProcs);
	int			myHeldLocks = MyProc->heldLocks;
572
	bool		early_deadlock = false;
573 574
	PROC	   *proc;
	int			i;
575

576
	/*
577 578 579 580 581 582
	 * Determine where to add myself in the wait queue.
	 *
	 * Normally I should go at the end of the queue.  However, if I already
	 * hold locks that conflict with the request of any previous waiter,
	 * put myself in the queue just in front of the first such waiter.
	 * This is not a necessary step, since deadlock detection would move
583 584 585
	 * me to before that waiter anyway; but it's relatively cheap to
	 * detect such a conflict immediately, and avoid delaying till
	 * deadlock timeout.
586
	 *
587 588
	 * Special case: if I find I should go in front of some waiter, check to
	 * see if I conflict with already-held locks or the requests before
589 590
	 * that waiter.  If not, then just grant myself the requested lock
	 * immediately.  This is the same as the test for immediate grant in
591 592
	 * LockAcquire, except we are only considering the part of the wait
	 * queue before my insertion point.
593 594
	 */
	if (myHeldLocks != 0)
V
Vadim B. Mikheev 已提交
595
	{
596 597
		int			aheadRequests = 0;

598 599
		proc = (PROC *) MAKE_PTR(waitQueue->links.next);
		for (i = 0; i < waitQueue->size; i++)
V
Vadim B. Mikheev 已提交
600
		{
601 602
			/* Must he wait for me? */
			if (lockctl->conflictTab[proc->waitLockMode] & myHeldLocks)
V
Vadim B. Mikheev 已提交
603
			{
604 605 606
				/* Must I wait for him ? */
				if (lockctl->conflictTab[lockmode] & proc->heldLocks)
				{
607 608 609 610 611 612 613 614
					/*
					 * Yes, so we have a deadlock.  Easiest way to clean up
					 * correctly is to call RemoveFromWaitQueue(), but we
					 * can't do that until we are *on* the wait queue.
					 * So, set a flag to check below, and break out of loop.
					 */
					early_deadlock = true;
					break;
615
				}
616 617 618 619 620 621 622 623
				/* I must go before this waiter.  Check special case. */
				if ((lockctl->conflictTab[lockmode] & aheadRequests) == 0 &&
					LockCheckConflicts(lockMethodTable,
									   lockmode,
									   lock,
									   holder,
									   MyProc,
									   NULL) == STATUS_OK)
624
				{
625 626 627
					/* Skip the wait and just grant myself the lock. */
					GrantLock(lock, holder, lockmode);
					return STATUS_OK;
628 629
				}
				/* Break out of loop to put myself before him */
V
Vadim B. Mikheev 已提交
630
				break;
631
			}
632 633
			/* Nope, so advance to next waiter */
			aheadRequests |= (1 << proc->waitLockMode);
634
			proc = (PROC *) MAKE_PTR(proc->links.next);
V
Vadim B. Mikheev 已提交
635
		}
B
Bruce Momjian 已提交
636

637 638 639 640
		/*
		 * If we fall out of loop normally, proc points to waitQueue head,
		 * so we will insert at tail of queue as desired.
		 */
641 642 643 644 645
	}
	else
	{
		/* I hold no locks, so I can't push in front of anyone. */
		proc = (PROC *) &(waitQueue->links);
V
Vadim B. Mikheev 已提交
646
	}
647

648 649 650
	/*
	 * Insert self into queue, ahead of the given proc (or at tail of
	 * queue).
651
	 */
652
	SHMQueueInsertBefore(&(proc->links), &(MyProc->links));
B
Bruce Momjian 已提交
653
	waitQueue->size++;
654

655
	lock->waitMask |= (1 << lockmode);
656

657 658 659 660 661
	/* Set up wait information in PROC object, too */
	MyProc->waitLock = lock;
	MyProc->waitHolder = holder;
	MyProc->waitLockMode = lockmode;

662 663 664 665 666 667 668 669 670 671 672 673 674
	MyProc->errType = STATUS_OK; /* initialize result for success */

	/*
	 * If we detected deadlock, give up without waiting.  This must agree
	 * with HandleDeadLock's recovery code, except that we shouldn't release
	 * the semaphore since we haven't tried to lock it yet.
	 */
	if (early_deadlock)
	{
		RemoveFromWaitQueue(MyProc);
		MyProc->errType = STATUS_ERROR;
		return STATUS_ERROR;
	}
675

676 677 678
	/* mark that we are waiting for a lock */
	waitingForLock = true;

679
	/*
680
	 * Release the locktable's masterLock.
681
	 *
682 683 684 685
	 * NOTE: this may also cause us to exit critical-section state, possibly
	 * allowing a cancel/die interrupt to be accepted. This is OK because
	 * we have recorded the fact that we are waiting for a lock, and so
	 * LockWaitCancel will clean up if cancel/die happens.
686
	 */
687
	LWLockRelease(masterLock);
688

689
	/*
690 691 692 693 694 695 696
	 * Set timer so we can wake up after awhile and check for a deadlock.
	 * If a deadlock is detected, the handler releases the process's
	 * semaphore and sets MyProc->errType = STATUS_ERROR, allowing us to
	 * know that we must report failure rather than success.
	 *
	 * By delaying the check until we've waited for a bit, we can avoid
	 * running the rather expensive deadlock-check code in most cases.
697
	 */
698
	if (! enable_sigalrm_interrupt(DeadlockTimeout))
699
		elog(FATAL, "ProcSleep: Unable to set timer for process wakeup");
700

701
	/*
702
	 * If someone wakes us between LWLockRelease and IpcSemaphoreLock,
703 704 705 706 707
	 * IpcSemaphoreLock will not block.  The wakeup is "saved" by the
	 * semaphore implementation.  Note also that if HandleDeadLock is
	 * invoked but does not detect a deadlock, IpcSemaphoreLock() will
	 * continue to wait.  There used to be a loop here, but it was useless
	 * code...
708 709 710 711 712 713
	 *
	 * We pass interruptOK = true, which eliminates a window in which
	 * cancel/die interrupts would be held off undesirably.  This is a
	 * promise that we don't mind losing control to a cancel/die interrupt
	 * here.  We don't, because we have no state-change work to do after
	 * being granted the lock (the grantor did it all).
714
	 */
715
	IpcSemaphoreLock(MyProc->sem.semId, MyProc->sem.semNum, true);
716

717
	/*
718
	 * Disable the timer, if it's still running
B
Bruce Momjian 已提交
719
	 */
720
	if (! disable_sigalrm_interrupt())
721
		elog(FATAL, "ProcSleep: Unable to disable timer for process wakeup");
B
Bruce Momjian 已提交
722

723 724 725 726 727
	/*
	 * Now there is nothing for LockWaitCancel to do.
	 */
	waitingForLock = false;

728
	/*
729
	 * Re-acquire the locktable's masterLock.
730
	 */
731
	LWLockAcquire(masterLock, LW_EXCLUSIVE);
732

733 734 735 736
	/*
	 * We don't have to do anything else, because the awaker did all the
	 * necessary update of the lock table and MyProc.
	 */
737
	return MyProc->errType;
738 739 740 741 742 743
}


/*
 * ProcWakeup -- wake up a process by releasing its private semaphore.
 *
744
 *	 Also remove the process from the wait queue and set its links invalid.
745
 *	 RETURN: the next process in the wait queue.
746 747 748 749
 *
 * 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.
750
 */
B
Bruce Momjian 已提交
751
PROC *
752
ProcWakeup(PROC *proc, int errType)
753
{
754
	PROC	   *retProc;
755

756
	/* assume that masterLock has been acquired */
757

758
	/* Proc should be sleeping ... */
759 760
	if (proc->links.prev == INVALID_OFFSET ||
		proc->links.next == INVALID_OFFSET)
761
		return (PROC *) NULL;
762

763 764
	/* Save next process before we zap the list link */
	retProc = (PROC *) MAKE_PTR(proc->links.next);
765

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

770 771 772
	/* Clean up process' state and pass it the ok/fail signal */
	proc->waitLock = NULL;
	proc->waitHolder = NULL;
773 774
	proc->errType = errType;

775
	/* And awaken it */
776
	IpcSemaphoreUnlock(proc->sem.semId, proc->sem.semNum);
777 778

	return retProc;
779 780 781 782
}

/*
 * ProcLockWakeup -- routine for waking up processes when a lock is
783 784
 *		released (or a prior waiter is aborted).  Scan all waiters
 *		for lock, waken any that are no longer blocked.
785
 */
786 787
void
ProcLockWakeup(LOCKMETHODTABLE *lockMethodTable, LOCK *lock)
788
{
789 790 791
	LOCKMETHODCTL *lockctl = lockMethodTable->ctl;
	PROC_QUEUE *waitQueue = &(lock->waitProcs);
	int			queue_size = waitQueue->size;
792
	PROC	   *proc;
793
	int			aheadRequests = 0;
M
 
Marc G. Fournier 已提交
794

795
	Assert(queue_size >= 0);
796

797 798
	if (queue_size == 0)
		return;
799

800
	proc = (PROC *) MAKE_PTR(waitQueue->links.next);
801

802 803
	while (queue_size-- > 0)
	{
B
Bruce Momjian 已提交
804
		LOCKMODE	lockmode = proc->waitLockMode;
M
 
Marc G. Fournier 已提交
805 806

		/*
807 808
		 * Waken if (a) doesn't conflict with requests of earlier waiters,
		 * and (b) doesn't conflict with already-held locks.
M
 
Marc G. Fournier 已提交
809
		 */
810
		if ((lockctl->conflictTab[lockmode] & aheadRequests) == 0 &&
811 812 813 814 815 816
			LockCheckConflicts(lockMethodTable,
							   lockmode,
							   lock,
							   proc->waitHolder,
							   proc,
							   NULL) == STATUS_OK)
M
 
Marc G. Fournier 已提交
817
		{
818 819 820
			/* OK to waken */
			GrantLock(lock, proc->waitHolder, lockmode);
			proc = ProcWakeup(proc, STATUS_OK);
B
Bruce Momjian 已提交
821

822
			/*
B
Bruce Momjian 已提交
823 824 825
			 * 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.
826
			 */
M
 
Marc G. Fournier 已提交
827
		}
828
		else
829
		{
B
Bruce Momjian 已提交
830 831 832 833 834

			/*
			 * Cannot wake this guy. Remember his request for later
			 * checks.
			 */
835
			aheadRequests |= (1 << lockmode);
836
			proc = (PROC *) MAKE_PTR(proc->links.next);
837
		}
M
 
Marc G. Fournier 已提交
838
	}
839 840

	Assert(waitQueue->size >= 0);
841 842 843
}

/* --------------------
844
 * We only get to this routine if we got SIGALRM after DeadlockTimeout
845 846 847 848
 * 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.
849 850
 * --------------------
 */
851
void
852
HandleDeadLock(SIGNAL_ARGS)
853
{
854
	int			save_errno = errno;
855

856
	/*
B
Bruce Momjian 已提交
857 858
	 * Acquire locktable lock.	Note that the SIGALRM interrupt had better
	 * not be enabled anywhere that this process itself holds the
859 860
	 * locktable lock, else this will wait forever.  Also note that
	 * LWLockAcquire creates a critical section, so that this
B
Bruce Momjian 已提交
861
	 * routine cannot be interrupted by cancel/die interrupts.
862
	 */
863
	LWLockAcquire(LockMgrLock, LW_EXCLUSIVE);
864

865
	/*
866 867 868
	 * 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.
869 870
	 * Before we are awoken the process releasing the lock grants it to us
	 * so we know that we don't have to wait anymore.
871
	 *
872
	 * We check by looking to see if we've been unlinked from the wait queue.
873 874 875 876
	 * 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.
	 *
877 878 879 880
	 */
	if (MyProc->links.prev == INVALID_OFFSET ||
		MyProc->links.next == INVALID_OFFSET)
	{
881
		LWLockRelease(LockMgrLock);
882
		errno = save_errno;
883 884 885
		return;
	}

886
#ifdef LOCK_DEBUG
B
Bruce Momjian 已提交
887 888
	if (Debug_deadlocks)
		DumpAllLocks();
889 890
#endif

891
	if (!DeadLockCheck(MyProc))
B
Bruce Momjian 已提交
892
	{
893
		/* No deadlock, so keep waiting */
894
		LWLockRelease(LockMgrLock);
895
		errno = save_errno;
B
Bruce Momjian 已提交
896 897 898
		return;
	}

899
	/*
900 901 902
	 * Oops.  We have a deadlock.
	 *
	 * Get this process out of wait state.
903
	 */
904 905
	RemoveFromWaitQueue(MyProc);

906 907 908
	/*
	 * Set MyProc->errType to STATUS_ERROR so that ProcSleep will report
	 * an error after we return from this signal handler.
909 910
	 */
	MyProc->errType = STATUS_ERROR;
911

912 913 914
	/*
	 * Unlock my semaphore so that the interrupted ProcSleep() call can
	 * finish.
915
	 */
916
	IpcSemaphoreUnlock(MyProc->sem.semId, MyProc->sem.semNum);
917

918 919 920 921 922 923 924 925 926
	/*
	 * 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.
927
	 */
928
	LWLockRelease(LockMgrLock);
929
	errno = save_errno;
930 931 932
}


933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975
/*
 * 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.
 */
void
ProcWaitForSignal(void)
{
	waitingForSignal = true;
	IpcSemaphoreLock(MyProc->sem.semId, MyProc->sem.semNum, 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.
 */
void
ProcCancelWaitForSignal(void)
{
	ZeroProcSemaphore(MyProc);
	waitingForSignal = false;
}

/*
 * ProcSendSignal - send a signal to a backend identified by BackendId
 */
void
ProcSendSignal(BackendId procId)
{
	PROC   *proc = BackendIdGetProc(procId);

	if (proc != NULL)
		IpcSemaphoreUnlock(proc->sem.semId, proc->sem.semNum);
}


976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038
/*****************************************************************************
 * 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.
 *
 * Returns TRUE if okay, FALSE on failure.
 */
bool
enable_sigalrm_interrupt(int delayms)
{
#ifndef __BEOS__
	struct itimerval timeval,
				dummy;

	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, &dummy))
		return false;
#else
	/* BeOS doesn't have setitimer, but has set_alarm */
	bigtime_t	time_interval;

	time_interval = delayms * 1000;	/* usecs */
	if (set_alarm(time_interval, B_ONE_SHOT_RELATIVE_ALARM) < 0)
		return false;
#endif

	return true;
}

/*
 * Disable the SIGALRM interrupt, if it has not yet fired
 *
 * Returns TRUE if okay, FALSE on failure.
 */
bool
disable_sigalrm_interrupt(void)
{
#ifndef __BEOS__
	struct itimerval timeval,
				dummy;

	MemSet(&timeval, 0, sizeof(struct itimerval));
	if (setitimer(ITIMER_REAL, &timeval, &dummy))
		return false;
#else
	/* BeOS doesn't have setitimer, but has set_alarm */
	if (set_alarm(B_INFINITE_TIMEOUT, B_PERIODIC_ALARM) < 0)
		return false;
#endif

	return true;
}


1039
/*****************************************************************************
1040
 *
1041 1042 1043
 *****************************************************************************/

/*
1044
 * ProcGetNewSemIdAndNum -
1045
 *	  scan the free semaphore bitmap and allocate a single semaphore from
1046
 *	  a semaphore set.
1047 1048
 */
static void
1049
ProcGetNewSemIdAndNum(IpcSemaphoreId *semId, int *semNum)
1050
{
1051
	int			i;
1052 1053
	int			semMapEntries = ProcGlobal->semMapEntries;
	SEM_MAP_ENTRY  *procSemMap = ProcGlobal->procSemMap;
1054
	int32		fullmask = (1 << PROC_NSEMS_PER_SET) - 1;
1055

1056
	SpinLockAcquire(ProcStructLock);
1057

1058
	for (i = 0; i < semMapEntries; i++)
1059
	{
1060 1061
		int			mask = 1;
		int			j;
1062

1063
		if (procSemMap[i].freeSemMap == fullmask)
1064
			continue;			/* this set is fully allocated */
1065
		if (procSemMap[i].procSemId < 0)
1066
			continue;			/* this set hasn't been initialized */
1067 1068 1069

		for (j = 0; j < PROC_NSEMS_PER_SET; j++)
		{
1070
			if ((procSemMap[i].freeSemMap & mask) == 0)
1071
			{
1072
				/* A free semaphore found. Mark it as allocated. */
1073
				procSemMap[i].freeSemMap |= mask;
1074

1075
				*semId = procSemMap[i].procSemId;
1076
				*semNum = j;
1077 1078 1079

				SpinLockRelease(ProcStructLock);

1080 1081 1082 1083
				return;
			}
			mask <<= 1;
		}
1084 1085
	}

1086 1087
	SpinLockRelease(ProcStructLock);

1088 1089 1090 1091 1092 1093 1094
	/*
	 * If we reach here, all the semaphores are in use.  This is one of the
	 * possible places to detect "too many backends", so give the standard
	 * error message.  (Whether we detect it here or in sinval.c depends on
	 * whether MaxBackends is a multiple of PROC_NSEMS_PER_SET.)
	 */
	elog(FATAL, "Sorry, too many clients already");
1095 1096 1097 1098
}

/*
 * ProcFreeSem -
1099
 *	  free up our semaphore in the semaphore set.
1100 1101
 *
 * Caller is assumed to hold ProcStructLock.
1102 1103
 */
static void
1104
ProcFreeSem(IpcSemaphoreId semId, int semNum)
1105
{
1106
	int32		mask;
1107
	int			i;
1108
	int			semMapEntries = ProcGlobal->semMapEntries;
1109

1110
	mask = ~(1 << semNum);
1111

1112
	for (i = 0; i < semMapEntries; i++)
1113
	{
1114
		if (ProcGlobal->procSemMap[i].procSemId == semId)
1115
		{
1116
			ProcGlobal->procSemMap[i].freeSemMap &= mask;
1117 1118 1119
			return;
		}
	}
1120
	/* can't elog here!!! */
1121
	fprintf(stderr, "ProcFreeSem: no ProcGlobal entry for semId %d\n", semId);
1122 1123 1124 1125
}

/*
 * ProcFreeAllSemaphores -
1126 1127 1128
 *	  called at shmem_exit time, ie when exiting the postmaster or
 *	  destroying shared state for a failed set of backends.
 *	  Free up all the semaphores allocated to the lmgrs of the backends.
1129
 */
1130
static void
1131
ProcFreeAllSemaphores(void)
1132
{
1133
	int			i;
1134

1135
	for (i = 0; i < ProcGlobal->semMapEntries; i++)
1136
	{
1137 1138
		if (ProcGlobal->procSemMap[i].procSemId >= 0)
			IpcSemaphoreKill(ProcGlobal->procSemMap[i].procSemId);
1139
	}
1140
}