proc.c 31.3 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
11
 *	  $Header: /cvsroot/pgsql/src/backend/storage/lmgr/proc.c,v 1.116 2001/11/08 20:37:52 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
#include <signal.h>
51 52
#include <unistd.h>
#include <sys/time.h>
M
Marc G. Fournier 已提交
53

54 55 56
#include "storage/ipc.h"
/* In Ultrix, sem.h and shm.h must be included AFTER ipc.h */
#ifdef HAVE_SYS_SEM_H
57 58 59
#include <sys/sem.h>
#endif

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

64
#include "miscadmin.h"
65
#include "access/xact.h"
66
#include "storage/proc.h"
67
#include "storage/sinval.h"
68
#include "storage/spin.h"
69

70

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

73 74 75 76 77 78 79 80
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.
81
 */
82
static slock_t *ProcStructLock = NULL;
83 84 85

static PROC_HDR *ProcGlobal = NULL;

86
static PROC *DummyProc = NULL;
87

88
static bool waitingForLock = false;
89
static bool waitingForSignal = false;
90 91

static void ProcKill(void);
92
static void DummyProcKill(void);
93 94
static void ProcGetNewSemIdAndNum(IpcSemaphoreId *semId, int *semNum);
static void ProcFreeSem(IpcSemaphoreId semId, int semNum);
95 96 97
static void ZeroProcSemaphore(PROC *proc);
static void ProcFreeAllSemaphores(void);

V
Vadim B. Mikheev 已提交
98

99 100
/*
 * InitProcGlobal -
101
 *	  initializes the global process table. We put it here so that
102
 *	  the postmaster can do this initialization. (ProcFreeAllSemaphores needs
103 104 105
 *	  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.)
106 107 108 109 110 111 112 113 114 115 116
 *
 *	  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.
117 118
 */
void
119
InitProcGlobal(int maxBackends)
120
{
121 122
	int			semMapEntries;
	Size		procGlobalSize;
123
	bool		found = false;
124

125 126
	/*
	 * Compute size for ProcGlobal structure.  Note we need one more sema
127
	 * besides those used for regular backends; this is accounted for in
128
	 * the PROC_SEM_MAP_ENTRIES macro.	(We do it that way so that other
129 130
	 * modules that use PROC_SEM_MAP_ENTRIES(maxBackends) to size data
	 * structures don't have to know about this explicitly.)
131
	 */
132
	Assert(maxBackends > 0);
133
	semMapEntries = PROC_SEM_MAP_ENTRIES(maxBackends);
134
	procGlobalSize = sizeof(PROC_HDR) + (semMapEntries - 1) *sizeof(SEM_MAP_ENTRY);
135 136

	/* Create or attach to the ProcGlobal shared structure */
137
	ProcGlobal = (PROC_HDR *)
138
		ShmemInitStruct("Proc Header", procGlobalSize, &found);
139

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

150
		ProcGlobal->freeProcs = INVALID_OFFSET;
151 152 153
		ProcGlobal->semMapEntries = semMapEntries;

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

B
Bruce Momjian 已提交
159 160
		/*
		 * Arrange to delete semas on exit --- set this up now so that we
B
Bruce Momjian 已提交
161 162 163 164
		 * 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.
165
		 */
166
		on_shmem_exit(ProcFreeAllSemaphores, 0);
167

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

			semId = IpcSemaphoreCreate(PROC_NSEMS_PER_SET,
									   IPCProtection,
									   1,
									   false);
179
			ProcGlobal->procSemMap[i].procSemId = semId;
180
		}
181 182 183 184 185 186 187

		/*
		 * 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 */
188 189
		i = semMapEntries - 1;
		ProcGlobal->procSemMap[i].freeSemMap |= 1 << (PROC_NSEMS_PER_SET - 1);
190
		DummyProc->sem.semId = ProcGlobal->procSemMap[i].procSemId;
191
		DummyProc->sem.semNum = PROC_NSEMS_PER_SET - 1;
192 193 194 195

		/* Create ProcStructLock spinlock, too */
		ProcStructLock = (slock_t *) ShmemAlloc(sizeof(slock_t));
		SpinLockInit(ProcStructLock);
196 197 198
	}
}

199 200
/*
 * InitProcess -- create a per-process data structure for this backend
201 202
 */
void
203
InitProcess(void)
204
{
205
	SHMEM_OFFSET myOffset;
206 207

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

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

217
	/*
218
	 * try to get a proc struct from the free list first
219
	 */
220
	SpinLockAcquire(ProcStructLock);
221 222 223 224

	myOffset = ProcGlobal->freeProcs;

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

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

260
	/*
261
	 * Arrange to clean up at backend exit.
262
	 */
263
	on_shmem_exit(ProcKill, 0);
264

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

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

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

286 287 288 289 290 291 292 293 294 295 296
/*
 * 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)
{
	/*
297 298
	 * ProcGlobal should be set by a previous call to InitProcGlobal (we
	 * inherit this by fork() from the postmaster).
299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314
	 */
	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;

	/*
315 316
	 * Initialize all fields of MyProc, except MyProc->sem which was set
	 * up by InitProcGlobal.
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
	 */
	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);
}

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

	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);
	}
360 361
}

362 363 364
/*
 * Cancel any pending wait for lock, when aborting a transaction.
 *
365 366
 * Returns true if we had been waiting for a lock, else false.
 *
367 368 369 370
 * (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.)
 */
371
bool
372 373 374 375
LockWaitCancel(void)
{
	/* Nothing to do if we weren't waiting for a lock */
	if (!waitingForLock)
376 377
		return false;

378 379 380
	waitingForLock = false;

	/* Turn off the deadlock timer, if it's still running (see ProcSleep) */
381
	disable_sigalrm_interrupt();
382 383

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

389 390 391
	/*
	 * 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 已提交
392 393 394 395 396
	 * 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.
397 398
	 */
	ZeroProcSemaphore(MyProc);
399 400

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

407

408
/*
409 410 411 412 413 414 415 416
 * 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.
417
 *
418
 * Note that user locks are not released in either case.
419 420
 */
void
421
ProcReleaseLocks(bool isCommit)
422
{
423 424
	if (!MyProc)
		return;
425 426 427
	/* If waiting, get off wait queue (should only be needed after error) */
	LockWaitCancel();
	/* Release locks */
428 429
	LockReleaseAll(DEFAULT_LOCKMETHOD, MyProc,
				   !isCommit, GetCurrentTransactionId());
430 431 432 433 434
}


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

442 443 444 445 446
	/* Release any LW locks I am holding */
	LWLockReleaseAll();

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

448 449
	/* Get off any wait queue I might be on */
	LockWaitCancel();
450

451
	/* Remove from the standard lock table */
452
	LockReleaseAll(DEFAULT_LOCKMETHOD, MyProc, true, InvalidTransactionId);
453

454 455
#ifdef USER_LOCKS
	/* Remove from the user lock table */
456
	LockReleaseAll(USER_LOCKMETHOD, MyProc, true, InvalidTransactionId);
457
#endif
458

459
	SpinLockAcquire(ProcStructLock);
460

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

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

469
	/* PROC struct isn't mine anymore */
470
	MyProc = NULL;
471

472 473 474 475 476
	SpinLockRelease(ProcStructLock);
}

/*
 * DummyProcKill() -- Cut-down version of ProcKill for dummy (checkpoint)
477
 *		processes.	The PROC and sema are not released, only marked
478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497
 *		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;
498 499
}

500

501 502
/*
 * ProcQueue package: routines for putting processes to sleep
503
 *		and  waking them up
504 505 506 507 508 509 510 511
 */

/*
 * 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
 */
512
#ifdef NOT_USED
513
PROC_QUEUE *
514 515
ProcQueueAlloc(char *name)
{
516 517
	bool		found;
	PROC_QUEUE *queue = (PROC_QUEUE *)
B
Bruce Momjian 已提交
518
	ShmemInitStruct(name, sizeof(PROC_QUEUE), &found);
519 520

	if (!queue)
521
		return NULL;
522 523
	if (!found)
		ProcQueueInit(queue);
524
	return queue;
525
}
526
#endif
527 528 529 530 531

/*
 * ProcQueueInit -- initialize a shared memory process queue
 */
void
532
ProcQueueInit(PROC_QUEUE *queue)
533
{
534 535
	SHMQueueInit(&(queue->links));
	queue->size = 0;
536 537 538 539 540 541
}


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

572
	/*
573 574 575 576 577 578
	 * 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
579 580 581
	 * me to before that waiter anyway; but it's relatively cheap to
	 * detect such a conflict immediately, and avoid delaying till
	 * deadlock timeout.
582
	 *
583 584
	 * 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
585 586
	 * that waiter.  If not, then just grant myself the requested lock
	 * immediately.  This is the same as the test for immediate grant in
587 588
	 * LockAcquire, except we are only considering the part of the wait
	 * queue before my insertion point.
589 590
	 */
	if (myHeldLocks != 0)
V
Vadim B. Mikheev 已提交
591
	{
592 593
		int			aheadRequests = 0;

594 595
		proc = (PROC *) MAKE_PTR(waitQueue->links.next);
		for (i = 0; i < waitQueue->size; i++)
V
Vadim B. Mikheev 已提交
596
		{
597 598
			/* Must he wait for me? */
			if (lockctl->conflictTab[proc->waitLockMode] & myHeldLocks)
V
Vadim B. Mikheev 已提交
599
			{
600 601 602
				/* Must I wait for him ? */
				if (lockctl->conflictTab[lockmode] & proc->heldLocks)
				{
603
					/*
604 605 606 607 608
					 * 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.
609 610 611
					 */
					early_deadlock = true;
					break;
612
				}
613 614 615 616 617 618 619 620
				/* I must go before this waiter.  Check special case. */
				if ((lockctl->conflictTab[lockmode] & aheadRequests) == 0 &&
					LockCheckConflicts(lockMethodTable,
									   lockmode,
									   lock,
									   holder,
									   MyProc,
									   NULL) == STATUS_OK)
621
				{
622 623 624
					/* Skip the wait and just grant myself the lock. */
					GrantLock(lock, holder, lockmode);
					return STATUS_OK;
625 626
				}
				/* Break out of loop to put myself before him */
V
Vadim B. Mikheev 已提交
627
				break;
628
			}
629 630
			/* Nope, so advance to next waiter */
			aheadRequests |= (1 << proc->waitLockMode);
631
			proc = (PROC *) MAKE_PTR(proc->links.next);
V
Vadim B. Mikheev 已提交
632
		}
B
Bruce Momjian 已提交
633

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

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

652
	lock->waitMask |= (1 << lockmode);
653

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

659
	MyProc->errType = STATUS_OK;	/* initialize result for success */
660 661 662

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

673 674 675
	/* mark that we are waiting for a lock */
	waitingForLock = true;

676
	/*
677
	 * Release the locktable's masterLock.
678
	 *
679 680 681 682
	 * 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.
683
	 */
684
	LWLockRelease(masterLock);
685

686
	/*
687 688 689 690 691 692 693
	 * 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.
694
	 */
695
	if (!enable_sigalrm_interrupt(DeadlockTimeout))
696
		elog(FATAL, "ProcSleep: Unable to set timer for process wakeup");
697

698
	/*
699
	 * If someone wakes us between LWLockRelease and IpcSemaphoreLock,
700 701 702 703 704
	 * 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...
705 706 707 708 709 710
	 *
	 * 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).
711
	 */
712
	IpcSemaphoreLock(MyProc->sem.semId, MyProc->sem.semNum, true);
713

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

720 721 722 723 724
	/*
	 * Now there is nothing for LockWaitCancel to do.
	 */
	waitingForLock = false;

725
	/*
726
	 * Re-acquire the locktable's masterLock.
727
	 */
728
	LWLockAcquire(masterLock, LW_EXCLUSIVE);
729

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


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

753
	/* assume that masterLock has been acquired */
754

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

760 761
	/* Save next process before we zap the list link */
	retProc = (PROC *) MAKE_PTR(proc->links.next);
762

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

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

772
	/* And awaken it */
773
	IpcSemaphoreUnlock(proc->sem.semId, proc->sem.semNum);
774 775

	return retProc;
776 777 778 779
}

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

792
	Assert(queue_size >= 0);
793

794 795
	if (queue_size == 0)
		return;
796

797
	proc = (PROC *) MAKE_PTR(waitQueue->links.next);
798

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

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

819
			/*
B
Bruce Momjian 已提交
820 821 822
			 * 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.
823
			 */
M
 
Marc G. Fournier 已提交
824
		}
825
		else
826
		{
B
Bruce Momjian 已提交
827 828 829 830
			/*
			 * Cannot wake this guy. Remember his request for later
			 * checks.
			 */
831
			aheadRequests |= (1 << lockmode);
832
			proc = (PROC *) MAKE_PTR(proc->links.next);
833
		}
M
 
Marc G. Fournier 已提交
834
	}
835 836

	Assert(waitQueue->size >= 0);
837 838 839
}

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

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

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

882
#ifdef LOCK_DEBUG
B
Bruce Momjian 已提交
883 884
	if (Debug_deadlocks)
		DumpAllLocks();
885 886
#endif

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

895
	/*
896 897 898
	 * Oops.  We have a deadlock.
	 *
	 * Get this process out of wait state.
899
	 */
900 901
	RemoveFromWaitQueue(MyProc);

902 903 904
	/*
	 * Set MyProc->errType to STATUS_ERROR so that ProcSleep will report
	 * an error after we return from this signal handler.
905 906
	 */
	MyProc->errType = STATUS_ERROR;
907

908 909 910
	/*
	 * Unlock my semaphore so that the interrupted ProcSleep() call can
	 * finish.
911
	 */
912
	IpcSemaphoreUnlock(MyProc->sem.semId, MyProc->sem.semNum);
913

914 915 916 917 918 919 920 921 922
	/*
	 * 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.
923
	 */
924
	LWLockRelease(LockMgrLock);
925
	errno = save_errno;
926 927 928
}


929 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
/*
 * 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)
{
965
	PROC	   *proc = BackendIdGetProc(procId);
966 967 968 969 970 971

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


972 973 974 975 976 977 978 979 980
/*****************************************************************************
 * SIGALRM interrupt support
 *
 * Maybe these should be in pqsignal.c?
 *****************************************************************************/

/*
 * Enable the SIGALRM interrupt to fire after the specified delay
 *
981
 * Delay is given in milliseconds.	Caller should be sure a SIGALRM
982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001
 * 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;

1002
	time_interval = delayms * 1000;		/* usecs */
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
	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;
}


1035
/*****************************************************************************
1036
 *
1037 1038 1039
 *****************************************************************************/

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

1052
	SpinLockAcquire(ProcStructLock);
1053

1054
	for (i = 0; i < semMapEntries; i++)
1055
	{
1056 1057
		int			mask = 1;
		int			j;
1058

1059
		if (procSemMap[i].freeSemMap == fullmask)
1060
			continue;			/* this set is fully allocated */
1061
		if (procSemMap[i].procSemId < 0)
1062
			continue;			/* this set hasn't been initialized */
1063 1064 1065

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

1071
				*semId = procSemMap[i].procSemId;
1072
				*semNum = j;
1073 1074 1075

				SpinLockRelease(ProcStructLock);

1076 1077 1078 1079
				return;
			}
			mask <<= 1;
		}
1080 1081
	}

1082 1083
	SpinLockRelease(ProcStructLock);

1084
	/*
1085 1086 1087 1088 1089
	 * 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.)
1090 1091
	 */
	elog(FATAL, "Sorry, too many clients already");
1092 1093 1094 1095
}

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

1107
	mask = ~(1 << semNum);
1108

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

/*
 * ProcFreeAllSemaphores -
1123 1124 1125
 *	  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.
1126
 */
1127
static void
1128
ProcFreeAllSemaphores(void)
1129
{
1130
	int			i;
1131

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