diff --git a/src/backend/bootstrap/bootstrap.c b/src/backend/bootstrap/bootstrap.c
index 283ca246473260f1b3466f2e1e6280d4e5d918a5..66cf4c4ce0ac20645b29851530bae666fd000734 100644
--- a/src/backend/bootstrap/bootstrap.c
+++ b/src/backend/bootstrap/bootstrap.c
@@ -8,7 +8,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/bootstrap/bootstrap.c,v 1.209 2005/11/22 18:17:07 momjian Exp $
+ *	  $PostgreSQL: pgsql/src/backend/bootstrap/bootstrap.c,v 1.210 2006/01/04 21:06:30 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -381,22 +381,19 @@ BootstrapMain(int argc, char *argv[])
 	BaseInit();
 
 	/*
-	 * We aren't going to do the full InitPostgres pushups, but there are a
-	 * couple of things that need to get lit up even in a dummy process.
+	 * When we are a dummy process, we aren't going to do the full
+	 * InitPostgres pushups, but there are a couple of things that need
+	 * to get lit up even in a dummy process.
 	 */
 	if (IsUnderPostmaster)
 	{
-		/* set up proc.c to get use of LWLocks */
-		switch (xlogop)
-		{
-			case BS_XLOG_BGWRITER:
-				InitDummyProcess(DUMMY_PROC_BGWRITER);
-				break;
-
-			default:
-				InitDummyProcess(DUMMY_PROC_DEFAULT);
-				break;
-		}
+		/*
+		 * Create a PGPROC so we can use LWLocks.  In the EXEC_BACKEND case,
+		 * this was already done by SubPostmasterMain().
+		 */
+#ifndef EXEC_BACKEND
+		InitDummyProcess();
+#endif
 
 		/* finish setting up bufmgr.c */
 		InitBufferPoolBackend();
@@ -437,11 +434,17 @@ BootstrapMain(int argc, char *argv[])
 			proc_exit(1);
 	}
 
+	/*
+	 * We must be getting invoked for bootstrap mode
+	 */
+	Assert(!IsUnderPostmaster);
+
 	SetProcessingMode(BootstrapProcessing);
 
 	/*
-	 * backend initialization
+	 * Do backend-like initialization for bootstrap mode
 	 */
+	InitProcess();
 	(void) InitPostgres(dbname, NULL);
 
 	/*
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index 0049f4307cdf68bd4aa1be244ee6f2464ace2bac..c2b6ac1a2988d496f725ccba3e95ae93bc77c5a2 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -10,7 +10,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/postmaster/autovacuum.c,v 1.8 2005/11/28 17:23:11 alvherre Exp $
+ *	  $PostgreSQL: pgsql/src/backend/postmaster/autovacuum.c,v 1.9 2006/01/04 21:06:31 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -167,6 +167,9 @@ autovac_start(void)
 			/* Close the postmaster's sockets */
 			ClosePostmasterPorts(false);
 
+			/* Lose the postmaster's on-exit routines */
+			on_exit_reset();
+
 			AutoVacMain(0, NULL);
 			break;
 #endif
@@ -230,9 +233,6 @@ AutoVacMain(int argc, char *argv[])
 	/* reset MyProcPid */
 	MyProcPid = getpid();
 
-	/* Lose the postmaster's on-exit routines */
-	on_exit_reset();
-
 	/* Identify myself via ps */
 	init_ps_display("autovacuum process", "", "");
 	set_ps_display("");
@@ -268,6 +268,16 @@ AutoVacMain(int argc, char *argv[])
 	/* Early initialization */
 	BaseInit();
 
+	/*
+	 * Create a per-backend PGPROC struct in shared memory, except in
+	 * the EXEC_BACKEND case where this was done in SubPostmasterMain.
+	 * We must do this before we can use LWLocks (and in the EXEC_BACKEND
+	 * case we already had to do some stuff with LWLocks).
+	 */
+#ifndef EXEC_BACKEND
+	InitProcess();
+#endif
+
 	/*
 	 * If an exception is encountered, processing resumes here.
 	 *
diff --git a/src/backend/postmaster/pgarch.c b/src/backend/postmaster/pgarch.c
index 61019d7a5e3b405c8a6ffdca490887d458e49eea..7b604b9f9f993d57c40c8cd04f3abcedface372d 100644
--- a/src/backend/postmaster/pgarch.c
+++ b/src/backend/postmaster/pgarch.c
@@ -19,7 +19,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/postmaster/pgarch.c,v 1.18 2005/10/15 02:49:23 momjian Exp $
+ *	  $PostgreSQL: pgsql/src/backend/postmaster/pgarch.c,v 1.19 2006/01/04 21:06:31 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -158,6 +158,9 @@ pgarch_start(void)
 			/* Close the postmaster's sockets */
 			ClosePostmasterPorts(false);
 
+			/* Lose the postmaster's on-exit routines */
+			on_exit_reset();
+
 			/* Drop our connection to postmaster's shared memory, as well */
 			PGSharedMemoryDetach();
 
@@ -219,9 +222,6 @@ PgArchiverMain(int argc, char *argv[])
 
 	MyProcPid = getpid();		/* reset MyProcPid */
 
-	/* Lose the postmaster's on-exit routines */
-	on_exit_reset();
-
 	/*
 	 * Ignore all signals usually bound to some action in the postmaster,
 	 * except for SIGHUP, SIGUSR1 and SIGQUIT.
diff --git a/src/backend/postmaster/pgstat.c b/src/backend/postmaster/pgstat.c
index a192b4e5c878beccdd4473f2e31163c527c077bc..d4a07efce2f0de60dcd2d0cdd99d2c81b2ccd425 100644
--- a/src/backend/postmaster/pgstat.c
+++ b/src/backend/postmaster/pgstat.c
@@ -13,7 +13,7 @@
  *
  *	Copyright (c) 2001-2005, PostgreSQL Global Development Group
  *
- *	$PostgreSQL: pgsql/src/backend/postmaster/pgstat.c,v 1.118 2006/01/03 19:54:08 momjian Exp $
+ *	$PostgreSQL: pgsql/src/backend/postmaster/pgstat.c,v 1.119 2006/01/04 21:06:31 tgl Exp $
  * ----------
  */
 #include "postgres.h"
@@ -147,6 +147,7 @@ static int	pgStatNumBackends = 0;
 
 static volatile bool	need_statwrite;
 
+
 /* ----------
  * Local function forward declarations
  * ----------
@@ -608,6 +609,9 @@ pgstat_start(void)
 			/* Close the postmaster's sockets */
 			ClosePostmasterPorts(false);
 
+			/* Lose the postmaster's on-exit routines */
+			on_exit_reset();
+
 			/* Drop our connection to postmaster's shared memory, as well */
 			PGSharedMemoryDetach();
 
@@ -1465,9 +1469,6 @@ PgstatBufferMain(int argc, char *argv[])
 
 	MyProcPid = getpid();		/* reset MyProcPid */
 
-	/* Lose the postmaster's on-exit routines */
-	on_exit_reset();
-
 	/*
 	 * Ignore all signals usually bound to some action in the postmaster,
 	 * except for SIGCHLD and SIGQUIT --- see pgstat_recvbuffer.
@@ -1551,10 +1552,10 @@ PgstatCollectorMain(int argc, char *argv[])
 	fd_set		rfds;
 	int			readPipe;
 	int			len = 0;
-	struct itimerval timeval;
+	struct itimerval timeout;
 	HASHCTL		hash_ctl;
 	bool		need_timer = false;
-	
+
 	MyProcPid = getpid();		/* reset MyProcPid */
 
 	/*
@@ -1597,11 +1598,15 @@ PgstatCollectorMain(int argc, char *argv[])
 	init_ps_display("stats collector process", "", "");
 	set_ps_display("");
 
+	/*
+	 * Arrange to write the initial status file right away
+	 */
 	need_statwrite = true;
 
-	MemSet(&timeval, 0, sizeof(struct itimerval));
-	timeval.it_value.tv_sec = PGSTAT_STAT_INTERVAL / 1000;
-	timeval.it_value.tv_usec = PGSTAT_STAT_INTERVAL % 1000;
+	/* Preset the delay between status file writes */
+	MemSet(&timeout, 0, sizeof(struct itimerval));
+	timeout.it_value.tv_sec = PGSTAT_STAT_INTERVAL / 1000;
+	timeout.it_value.tv_usec = PGSTAT_STAT_INTERVAL % 1000;
 
 	/*
 	 * Read in an existing statistics stats file or initialize the stats to
@@ -1634,6 +1639,12 @@ PgstatCollectorMain(int argc, char *argv[])
 	 */
 	for (;;)
 	{
+		/*
+		 * If time to write the stats file, do so.  Note that the alarm
+		 * interrupt isn't re-enabled immediately, but only after we next
+		 * receive a stats message; so no cycles are wasted when there is
+		 * nothing going on.
+		 */
 		if (need_statwrite)
 		{
 			pgstat_write_statsfile();
@@ -1776,11 +1787,16 @@ PgstatCollectorMain(int argc, char *argv[])
 			 */
 			pgStatNumMessages++;
 
+			/*
+			 * If this is the first message after we wrote the stats file the
+			 * last time, enable the alarm interrupt to make it be written
+			 * again later.
+			 */
 			if (need_timer)
 			{
-				if (setitimer(ITIMER_REAL, &timeval, NULL))
+				if (setitimer(ITIMER_REAL, &timeout, NULL))
 					ereport(ERROR,
-						  (errmsg("unable to set statistics collector timer: %m")));
+						  (errmsg("could not set statistics collector timer: %m")));
 				need_timer = false;
 			}
 		}
@@ -1806,6 +1822,7 @@ PgstatCollectorMain(int argc, char *argv[])
 }
 
 
+/* SIGALRM signal handler for collector process */
 static void
 force_statwrite(SIGNAL_ARGS)
 {
@@ -1913,8 +1930,10 @@ pgstat_recvbuffer(void)
 		/*
 		 * Wait for some work to do; but not for more than 10 seconds. (This
 		 * determines how quickly we will shut down after an ungraceful
-		 * postmaster termination; so it needn't be very fast.)  struct timeout
-		 * is modified by some operating systems.
+		 * postmaster termination; so it needn't be very fast.)
+		 *
+		 * struct timeout is modified by select() on some operating systems,
+		 * so re-fill it each time.
 		 */
 		timeout.tv_sec = 10;
 		timeout.tv_usec = 0;
diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c
index 24212f1ffffa4d597a83f18b9c86bd8added4d53..187bfeb47ec317c79c3260933ef7de63fe69a079 100644
--- a/src/backend/postmaster/postmaster.c
+++ b/src/backend/postmaster/postmaster.c
@@ -37,7 +37,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/postmaster/postmaster.c,v 1.476 2005/11/22 18:17:18 momjian Exp $
+ *	  $PostgreSQL: pgsql/src/backend/postmaster/postmaster.c,v 1.477 2006/01/04 21:06:31 tgl Exp $
  *
  * NOTES
  *
@@ -262,6 +262,7 @@ static void CleanupBackend(int pid, int exitstatus);
 static void HandleChildCrash(int pid, int exitstatus, const char *procname);
 static void LogChildExit(int lev, const char *procname,
 			 int pid, int exitstatus);
+static void BackendInitialize(Port *port);
 static int	BackendRun(Port *port);
 static void ExitPostmaster(int status);
 static void usage(const char *);
@@ -324,12 +325,12 @@ typedef struct
 	unsigned long UsedShmemSegID;
 	void	   *UsedShmemSegAddr;
 	slock_t    *ShmemLock;
-	slock_t    *ShmemIndexLock;
 	VariableCache ShmemVariableCache;
-	void	   *ShmemIndexAlloc;
 	Backend    *ShmemBackendArray;
 	LWLock	   *LWLockArray;
 	slock_t    *ProcStructLock;
+	PROC_HDR   *ProcGlobal;
+	PGPROC	   *DummyProcs;
 	InheritableSocket pgStatSock;
 	InheritableSocket pgStatPipe0;
 	InheritableSocket pgStatPipe1;
@@ -2496,6 +2497,26 @@ BackendStartup(Port *port)
 	if (pid == 0)				/* child */
 	{
 		free(bn);
+
+		/*
+		 * Let's clean up ourselves as the postmaster child, and close the
+		 * postmaster's listen sockets.  (In EXEC_BACKEND case this is all
+		 * done in SubPostmasterMain.)
+		 */
+		IsUnderPostmaster = true;	/* we are a postmaster subprocess now */
+
+		MyProcPid = getpid();		/* reset MyProcPid */
+
+		/* We don't want the postmaster's proc_exit() handlers */
+		on_exit_reset();
+
+		/* Close the postmaster's sockets */
+		ClosePostmasterPorts(false);
+
+		/* Perform additional initialization and client authentication */
+		BackendInitialize(port);
+
+		/* And run the backend */
 		proc_exit(BackendRun(port));
 	}
 #endif   /* EXEC_BACKEND */
@@ -2589,47 +2610,26 @@ split_opts(char **argv, int *argcp, char *s)
 
 
 /*
- * BackendRun -- perform authentication, and if successful,
- *				set up the backend's argument list and invoke PostgresMain()
+ * BackendInitialize -- initialize an interactive (postmaster-child)
+ *				backend process, and perform client authentication.
  *
- * returns:
- *		Shouldn't return at all.
- *		If PostgresMain() fails, return status.
+ * returns: nothing.  Will not return at all if there's any failure.
+ *
+ * Note: this code does not depend on having any access to shared memory.
+ * In the EXEC_BACKEND case, we are physically attached to shared memory
+ * but have not yet set up most of our local pointers to shmem structures.
  */
-static int
-BackendRun(Port *port)
+static void
+BackendInitialize(Port *port)
 {
 	int			status;
 	char		remote_host[NI_MAXHOST];
 	char		remote_port[NI_MAXSERV];
 	char		remote_ps_data[NI_MAXHOST];
-	char	  **av;
-	int			maxac;
-	int			ac;
-	char		protobuf[32];
-	int			i;
-
-	IsUnderPostmaster = true;	/* we are a postmaster subprocess now */
-
-	/*
-	 * Let's clean up ourselves as the postmaster child, and close the
-	 * postmaster's listen sockets
-	 */
-	ClosePostmasterPorts(false);
-
-	/* We don't want the postmaster's proc_exit() handlers */
-	on_exit_reset();
-
-	/*
-	 * Signal handlers setting is moved to tcop/postgres...
-	 */
 
 	/* Save port etc. for ps status */
 	MyProcPort = port;
 
-	/* Reset MyProcPid to new backend's pid */
-	MyProcPid = getpid();
-
 	/*
 	 * PreAuthDelay is a debugging aid for investigating problems in the
 	 * authentication cycle: it can be set in postgresql.conf to allow time to
@@ -2698,7 +2698,7 @@ BackendRun(Port *port)
 						remote_port)));
 
 	/*
-	 * save remote_host and remote_port in port stucture
+	 * save remote_host and remote_port in port structure
 	 */
 	port->remote_host = strdup(remote_host);
 	port->remote_port = strdup(remote_port);
@@ -2766,6 +2766,24 @@ BackendRun(Port *port)
 		ereport(LOG,
 				(errmsg("connection authorized: user=%s database=%s",
 						port->user_name, port->database_name)));
+}
+
+
+/*
+ * BackendRun -- set up the backend's argument list and invoke PostgresMain()
+ *
+ * returns:
+ *		Shouldn't return at all.
+ *		If PostgresMain() fails, return status.
+ */
+static int
+BackendRun(Port *port)
+{
+	char	  **av;
+	int			maxac;
+	int			ac;
+	char		protobuf[32];
+	int			i;
 
 	/*
 	 * Don't want backend to be able to see the postmaster random number
@@ -3184,6 +3202,9 @@ SubPostmasterMain(int argc, char *argv[])
 
 	MyProcPid = getpid();		/* reset MyProcPid */
 
+	/* Lose the postmaster's on-exit routines (really a no-op) */
+	on_exit_reset();
+
 	/* In EXEC_BACKEND case we will not have inherited these settings */
 	IsPostmasterEnvironment = true;
 	whereToSendOutput = DestNone;
@@ -3229,23 +3250,43 @@ SubPostmasterMain(int argc, char *argv[])
 	/* Run backend or appropriate child */
 	if (strcmp(argv[1], "-forkbackend") == 0)
 	{
-		/* BackendRun will close sockets */
-
-		/* Attach process to shared data structures */
-		CreateSharedMemoryAndSemaphores(false, 0);
+		Assert(argc == 3);		/* shouldn't be any more args */
 
-#ifdef USE_SSL
+		/* Close the postmaster's sockets */
+		ClosePostmasterPorts(false);
 
 		/*
 		 * Need to reinitialize the SSL library in the backend, since the
 		 * context structures contain function pointers and cannot be passed
 		 * through the parameter file.
 		 */
+#ifdef USE_SSL
 		if (EnableSSL)
 			secure_initialize();
 #endif
 
-		Assert(argc == 3);		/* shouldn't be any more args */
+		/*
+		 * Perform additional initialization and client authentication.
+		 *
+		 * We want to do this before InitProcess() for a couple of reasons:
+		 * 1. so that we aren't eating up a PGPROC slot while waiting on the 
+		 * client.
+		 * 2. so that if InitProcess() fails due to being out of PGPROC slots,
+		 * we have already initialized libpq and are able to report the error
+		 * to the client.
+		 */
+		BackendInitialize(&port);
+
+		/* Restore basic shared memory pointers */
+		InitShmemAccess(UsedShmemSegAddr);
+
+		/* Need a PGPROC to run CreateSharedMemoryAndSemaphores */
+		InitProcess();
+
+		/* Attach process to shared data structures */
+		CreateSharedMemoryAndSemaphores(false, 0);
+
+		/* And run the backend */
 		proc_exit(BackendRun(&port));
 	}
 	if (strcmp(argv[1], "-forkboot") == 0)
@@ -3253,6 +3294,12 @@ SubPostmasterMain(int argc, char *argv[])
 		/* Close the postmaster's sockets */
 		ClosePostmasterPorts(false);
 
+		/* Restore basic shared memory pointers */
+		InitShmemAccess(UsedShmemSegAddr);
+
+		/* Need a PGPROC to run CreateSharedMemoryAndSemaphores */
+		InitDummyProcess();
+
 		/* Attach process to shared data structures */
 		CreateSharedMemoryAndSemaphores(false, 0);
 
@@ -3264,6 +3311,12 @@ SubPostmasterMain(int argc, char *argv[])
 		/* Close the postmaster's sockets */
 		ClosePostmasterPorts(false);
 
+		/* Restore basic shared memory pointers */
+		InitShmemAccess(UsedShmemSegAddr);
+
+		/* Need a PGPROC to run CreateSharedMemoryAndSemaphores */
+		InitProcess();
+
 		/* Attach process to shared data structures */
 		CreateSharedMemoryAndSemaphores(false, 0);
 
@@ -3630,10 +3683,10 @@ CreateOptsFile(int argc, char *argv[], char *fullprogname)
  * functions
  */
 extern slock_t *ShmemLock;
-extern slock_t *ShmemIndexLock;
-extern void *ShmemIndexAlloc;
 extern LWLock *LWLockArray;
 extern slock_t *ProcStructLock;
+extern PROC_HDR *ProcGlobal;
+extern PGPROC *DummyProcs;
 extern int	pgStatSock;
 extern int	pgStatPipe[2];
 
@@ -3671,13 +3724,13 @@ save_backend_variables(BackendParameters * param, Port *port,
 	param->UsedShmemSegAddr = UsedShmemSegAddr;
 
 	param->ShmemLock = ShmemLock;
-	param->ShmemIndexLock = ShmemIndexLock;
 	param->ShmemVariableCache = ShmemVariableCache;
-	param->ShmemIndexAlloc = ShmemIndexAlloc;
 	param->ShmemBackendArray = ShmemBackendArray;
 
 	param->LWLockArray = LWLockArray;
 	param->ProcStructLock = ProcStructLock;
+	param->ProcGlobal = ProcGlobal;
+	param->DummyProcs = DummyProcs;
 	write_inheritable_socket(&param->pgStatSock, pgStatSock, childPid);
 	write_inheritable_socket(&param->pgStatPipe0, pgStatPipe[0], childPid);
 	write_inheritable_socket(&param->pgStatPipe1, pgStatPipe[1], childPid);
@@ -3876,13 +3929,13 @@ restore_backend_variables(BackendParameters * param, Port *port)
 	UsedShmemSegAddr = param->UsedShmemSegAddr;
 
 	ShmemLock = param->ShmemLock;
-	ShmemIndexLock = param->ShmemIndexLock;
 	ShmemVariableCache = param->ShmemVariableCache;
-	ShmemIndexAlloc = param->ShmemIndexAlloc;
 	ShmemBackendArray = param->ShmemBackendArray;
 
 	LWLockArray = param->LWLockArray;
 	ProcStructLock = param->ProcStructLock;
+	ProcGlobal = param->ProcGlobal;
+	DummyProcs = param->DummyProcs;
 	read_inheritable_socket(&pgStatSock, &param->pgStatSock);
 	read_inheritable_socket(&pgStatPipe[0], &param->pgStatPipe0);
 	read_inheritable_socket(&pgStatPipe[1], &param->pgStatPipe1);
diff --git a/src/backend/postmaster/syslogger.c b/src/backend/postmaster/syslogger.c
index 805ea8087a3d0f958b1b76ed4da4335d397b43fa..e27f2bf8bc6ad69efe78018f42f678468ee649c5 100644
--- a/src/backend/postmaster/syslogger.c
+++ b/src/backend/postmaster/syslogger.c
@@ -18,7 +18,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/postmaster/syslogger.c,v 1.21 2005/11/22 18:17:18 momjian Exp $
+ *	  $PostgreSQL: pgsql/src/backend/postmaster/syslogger.c,v 1.22 2006/01/04 21:06:31 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -135,9 +135,6 @@ SysLoggerMain(int argc, char *argv[])
 
 	MyProcPid = getpid();		/* reset MyProcPid */
 
-	/* Lose the postmaster's on-exit routines */
-	on_exit_reset();
-
 #ifdef EXEC_BACKEND
 	syslogger_parseArgs(argc, argv);
 #endif   /* EXEC_BACKEND */
@@ -460,6 +457,9 @@ SysLogger_Start(void)
 			/* Close the postmaster's sockets */
 			ClosePostmasterPorts(true);
 
+			/* Lose the postmaster's on-exit routines */
+			on_exit_reset();
+
 			/* Drop our connection to postmaster's shared memory, as well */
 			PGSharedMemoryDetach();
 
diff --git a/src/backend/storage/ipc/ipci.c b/src/backend/storage/ipc/ipci.c
index bfe8d52af3028c77c18a49e3dfba2202f6069982..e878462100e9f15950749abbc2c5f2c088e60568 100644
--- a/src/backend/storage/ipc/ipci.c
+++ b/src/backend/storage/ipc/ipci.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/storage/ipc/ipci.c,v 1.80 2005/12/09 01:22:03 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/storage/ipc/ipci.c,v 1.81 2006/01/04 21:06:31 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -57,10 +57,9 @@
 void
 CreateSharedMemoryAndSemaphores(bool makePrivate, int port)
 {
-	PGShmemHeader *seghdr = NULL;
-
 	if (!IsUnderPostmaster)
 	{
+		PGShmemHeader *seghdr;
 		Size		size;
 		int			numSemas;
 
@@ -104,6 +103,8 @@ CreateSharedMemoryAndSemaphores(bool makePrivate, int port)
 		 */
 		seghdr = PGSharedMemoryCreate(size, makePrivate, port);
 
+		InitShmemAccess(seghdr);
+
 		/*
 		 * Create semaphores
 		 */
@@ -120,18 +121,16 @@ CreateSharedMemoryAndSemaphores(bool makePrivate, int port)
 		 */
 #ifdef EXEC_BACKEND
 		Assert(!makePrivate);
-		Assert(UsedShmemSegAddr != NULL);
-		seghdr = UsedShmemSegAddr;
 #else
 		elog(PANIC, "should be attached to shared memory already");
 #endif
 	}
 
-
 	/*
 	 * Set up shared memory allocation mechanism
 	 */
-	InitShmemAllocation(seghdr, !IsUnderPostmaster);
+	if (!IsUnderPostmaster)
+		InitShmemAllocation();
 
 	/*
 	 * Now initialize LWLocks, which do shared memory allocation and are
@@ -163,7 +162,8 @@ CreateSharedMemoryAndSemaphores(bool makePrivate, int port)
 	/*
 	 * Set up process table
 	 */
-	InitProcGlobal();
+	if (!IsUnderPostmaster)
+		InitProcGlobal();
 	CreateSharedProcArray();
 
 	/*
diff --git a/src/backend/storage/ipc/shmem.c b/src/backend/storage/ipc/shmem.c
index e6865563b398a84d002b53ec275e062f2da72e35..21d136d6cf01f5182b4b4de6baa0a03302bb6d0d 100644
--- a/src/backend/storage/ipc/shmem.c
+++ b/src/backend/storage/ipc/shmem.c
@@ -8,25 +8,26 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/storage/ipc/shmem.c,v 1.89 2005/12/29 18:08:05 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/storage/ipc/shmem.c,v 1.90 2006/01/04 21:06:31 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
 /*
  * POSTGRES processes share one or more regions of shared memory.
  * The shared memory is created by a postmaster and is inherited
- * by each backend via fork().	The routines in this file are used for
- * allocating and binding to shared memory data structures.
+ * by each backend via fork() (or, in some ports, via other OS-specific
+ * methods).  The routines in this file are used for allocating and
+ * binding to shared memory data structures.
  *
  * NOTES:
  *		(a) There are three kinds of shared memory data structures
  *	available to POSTGRES: fixed-size structures, queues and hash
  *	tables.  Fixed-size structures contain things like global variables
- *	for a module and should never be allocated after the process
+ *	for a module and should never be allocated after the shared memory
  *	initialization phase.  Hash tables have a fixed maximum size, but
  *	their actual size can vary dynamically.  When entries are added
  *	to the table, more space is allocated.	Queues link data structures
- *	that have been allocated either as fixed size structures or as hash
+ *	that have been allocated either within fixed-size structures or as hash
  *	buckets.  Each shared data structure has a string name to identify
  *	it (assigned in the module that declares it).
  *
@@ -46,7 +47,14 @@
  *	of shared memory in a lot of different places (and changing
  *	things during development), this is important.
  *
- *		(c) memory allocation model: shared memory can never be
+ *		(c) In standard Unix-ish environments, individual backends do not
+ *	need to re-establish their local pointers into shared memory, because
+ *	they inherit correct values of those variables via fork() from the
+ *	postmaster.  However, this does not work in the EXEC_BACKEND case.
+ *	In ports using EXEC_BACKEND, new backends have to set up their local
+ *	pointers using the method described in (b) above.
+
+ *		(d) memory allocation model: shared memory can never be
  *	freed, once allocated.	 Each hash table has its own free list,
  *	so hash buckets can be reused when an item is deleted.	However,
  *	if one hash table grows very large and then shrinks, its space
@@ -75,58 +83,59 @@ static SHMEM_OFFSET ShmemEnd;	/* end+1 address of shared memory */
 slock_t    *ShmemLock;			/* spinlock for shared memory and LWLock
 								 * allocation */
 
-NON_EXEC_STATIC slock_t *ShmemIndexLock;		/* spinlock for ShmemIndex */
-
-NON_EXEC_STATIC void *ShmemIndexAlloc = NULL;	/* Memory actually allocated
-												 * for ShmemIndex */
-
 static HTAB *ShmemIndex = NULL; /* primary index hashtable for shmem */
 
 
 /*
- *	InitShmemAllocation() --- set up shared-memory allocation.
+ *	InitShmemAccess() --- set up basic pointers to shared memory.
  *
  * Note: the argument should be declared "PGShmemHeader *seghdr",
  * but we use void to avoid having to include ipc.h in shmem.h.
  */
 void
-InitShmemAllocation(void *seghdr, bool init)
+InitShmemAccess(void *seghdr)
 {
 	PGShmemHeader *shmhdr = (PGShmemHeader *) seghdr;
 
-	/* Set up basic pointers to shared memory */
 	ShmemSegHdr = shmhdr;
 	ShmemBase = (SHMEM_OFFSET) shmhdr;
 	ShmemEnd = ShmemBase + shmhdr->totalsize;
+}
 
-	if (init)
-	{
-		/*
-		 * Initialize the spinlocks used by ShmemAlloc/ShmemInitStruct. We
-		 * have to do the space allocation the hard way, since ShmemAlloc
-		 * can't be called yet.
-		 */
-		ShmemLock = (slock_t *) (((char *) shmhdr) + shmhdr->freeoffset);
-		shmhdr->freeoffset += MAXALIGN(sizeof(slock_t));
-		Assert(shmhdr->freeoffset <= shmhdr->totalsize);
+/*
+ *	InitShmemAllocation() --- set up shared-memory space allocation.
+ *
+ * This should be called only in the postmaster or a standalone backend.
+ */
+void
+InitShmemAllocation(void)
+{
+	PGShmemHeader *shmhdr = ShmemSegHdr;
 
-		ShmemIndexLock = (slock_t *) (((char *) shmhdr) + shmhdr->freeoffset);
-		shmhdr->freeoffset += MAXALIGN(sizeof(slock_t));
-		Assert(shmhdr->freeoffset <= shmhdr->totalsize);
+	Assert(shmhdr != NULL);
 
-		SpinLockInit(ShmemLock);
-		SpinLockInit(ShmemIndexLock);
+	/*
+	 * Initialize the spinlock used by ShmemAlloc.  We have to do the
+	 * space allocation the hard way, since obviously ShmemAlloc can't
+	 * be called yet.
+	 */
+	ShmemLock = (slock_t *) (((char *) shmhdr) + shmhdr->freeoffset);
+	shmhdr->freeoffset += MAXALIGN(sizeof(slock_t));
+	Assert(shmhdr->freeoffset <= shmhdr->totalsize);
 
-		/* ShmemIndex can't be set up yet (need LWLocks first) */
-		ShmemIndex = (HTAB *) NULL;
+	SpinLockInit(ShmemLock);
 
-		/*
-		 * Initialize ShmemVariableCache for transaction manager.
-		 */
-		ShmemVariableCache = (VariableCache)
-			ShmemAlloc(sizeof(*ShmemVariableCache));
-		memset(ShmemVariableCache, 0, sizeof(*ShmemVariableCache));
-	}
+	/* ShmemIndex can't be set up yet (need LWLocks first) */
+	shmhdr->indexoffset = 0;
+	ShmemIndex = (HTAB *) NULL;
+
+	/*
+	 * Initialize ShmemVariableCache for transaction manager.
+	 * (This doesn't really belong here, but not worth moving.)
+	 */
+	ShmemVariableCache = (VariableCache)
+		ShmemAlloc(sizeof(*ShmemVariableCache));
+	memset(ShmemVariableCache, 0, sizeof(*ShmemVariableCache));
 }
 
 /*
@@ -194,7 +203,7 @@ ShmemIsValid(unsigned long addr)
 }
 
 /*
- *	InitShmemIndex() --- set up shmem index table.
+ *	InitShmemIndex() --- set up or attach to shmem index table.
  */
 void
 InitShmemIndex(void)
@@ -239,15 +248,14 @@ InitShmemIndex(void)
 
 		result->location = MAKE_OFFSET(ShmemIndex->hctl);
 		result->size = SHMEM_INDEX_SIZE;
-
 	}
 
 	/* now release the lock acquired in ShmemInitStruct */
-	SpinLockRelease(ShmemIndexLock);
+	LWLockRelease(ShmemIndexLock);
 }
 
 /*
- * ShmemInitHash -- Create/Attach to and initialize
+ * ShmemInitHash -- Create and initialize, or attach to, a
  *		shared memory hash table.
  *
  * We assume caller is doing some kind of synchronization
@@ -290,8 +298,8 @@ ShmemInitHash(const char *name, /* table string name for shmem index */
 							   &found);
 
 	/*
-	 * shmem index is corrupted.	Let someone else give the error message
-	 * since they have more information
+	 * If fail, shmem index is corrupted.  Let caller give the error message
+	 * since it has more information
 	 */
 	if (location == NULL)
 		return NULL;
@@ -315,8 +323,8 @@ ShmemInitHash(const char *name, /* table string name for shmem index */
  *		memory.
  *
  *	This is called during initialization to find or allocate
- *		a data structure in shared memory.	If no other processes
- *		have created the structure, this routine allocates space
+ *		a data structure in shared memory.	If no other process
+ *		has created the structure, this routine allocates space
  *		for it.  If it exists already, a pointer to the existing
  *		table is returned.
  *
@@ -334,15 +342,18 @@ ShmemInitStruct(const char *name, Size size, bool *foundPtr)
 	strncpy(item.key, name, SHMEM_INDEX_KEYSIZE);
 	item.location = BAD_LOCATION;
 
-	SpinLockAcquire(ShmemIndexLock);
+	LWLockAcquire(ShmemIndexLock, LW_EXCLUSIVE);
 
 	if (!ShmemIndex)
 	{
+		PGShmemHeader *shmemseghdr = ShmemSegHdr;
+
 		Assert(strcmp(name, "ShmemIndex") == 0);
 		if (IsUnderPostmaster)
 		{
 			/* Must be initializing a (non-standalone) backend */
-			Assert(ShmemIndexAlloc);
+			Assert(shmemseghdr->indexoffset != 0);
+			structPtr = (void *) MAKE_PTR(shmemseghdr->indexoffset);
 			*foundPtr = TRUE;
 		}
 		else
@@ -354,10 +365,12 @@ ShmemInitStruct(const char *name, Size size, bool *foundPtr)
 			 * Notice that the ShmemIndexLock is held until the shmem index
 			 * has been completely initialized.
 			 */
+			Assert(shmemseghdr->indexoffset == 0);
+			structPtr = ShmemAlloc(size);
+			shmemseghdr->indexoffset = MAKE_OFFSET(structPtr);
 			*foundPtr = FALSE;
-			ShmemIndexAlloc = ShmemAlloc(size);
 		}
-		return ShmemIndexAlloc;
+		return structPtr;
 	}
 
 	/* look it up in the shmem index */
@@ -366,7 +379,7 @@ ShmemInitStruct(const char *name, Size size, bool *foundPtr)
 
 	if (!result)
 	{
-		SpinLockRelease(ShmemIndexLock);
+		LWLockRelease(ShmemIndexLock);
 		ereport(ERROR,
 				(errcode(ERRCODE_OUT_OF_MEMORY),
 				 errmsg("out of shared memory")));
@@ -381,7 +394,7 @@ ShmemInitStruct(const char *name, Size size, bool *foundPtr)
 		 */
 		if (result->size != size)
 		{
-			SpinLockRelease(ShmemIndexLock);
+			LWLockRelease(ShmemIndexLock);
 
 			elog(WARNING, "ShmemIndex entry size is wrong");
 			/* let caller print its message too */
@@ -398,7 +411,7 @@ ShmemInitStruct(const char *name, Size size, bool *foundPtr)
 			/* out of memory */
 			Assert(ShmemIndex);
 			hash_search(ShmemIndex, (void *) &item, HASH_REMOVE, NULL);
-			SpinLockRelease(ShmemIndexLock);
+			LWLockRelease(ShmemIndexLock);
 
 			ereport(WARNING,
 					(errcode(ERRCODE_OUT_OF_MEMORY),
@@ -411,7 +424,7 @@ ShmemInitStruct(const char *name, Size size, bool *foundPtr)
 	}
 	Assert(ShmemIsValid((unsigned long) structPtr));
 
-	SpinLockRelease(ShmemIndexLock);
+	LWLockRelease(ShmemIndexLock);
 	return structPtr;
 }
 
diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c
index 34d80bfceeacf8ea4e5007831964dab095e8440b..605f8b5e68bc6d3d4f31a3af31b20bdb94c87b5d 100644
--- a/src/backend/storage/lmgr/proc.c
+++ b/src/backend/storage/lmgr/proc.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/storage/lmgr/proc.c,v 1.170 2005/12/11 21:02:18 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/storage/lmgr/proc.c,v 1.171 2006/01/04 21:06:31 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -61,8 +61,8 @@ PGPROC	   *MyProc = NULL;
 NON_EXEC_STATIC slock_t *ProcStructLock = NULL;
 
 /* Pointers to shared-memory structures */
-static PROC_HDR *ProcGlobal = NULL;
-static PGPROC *DummyProcs = NULL;
+NON_EXEC_STATIC PROC_HDR *ProcGlobal = NULL;
+NON_EXEC_STATIC PGPROC *DummyProcs = NULL;
 
 /* If we are waiting for a lock, this points to the associated LOCALLOCK */
 static LOCALLOCK *lockAwaited = NULL;
@@ -76,6 +76,7 @@ volatile bool cancel_from_timeout = false;
 static struct timeval statement_fin_time;
 
 
+static void RemoveProcFromArray(int code, Datum arg);
 static void ProcKill(int code, Datum arg);
 static void DummyProcKill(int code, Datum arg);
 static bool CheckStatementTimeout(void);
@@ -113,7 +114,8 @@ ProcGlobalSemas(void)
 
 /*
  * InitProcGlobal -
- *	  Initialize the global process table during postmaster startup.
+ *	  Initialize the global process table during postmaster or standalone
+ *	  backend startup.
  *
  *	  We also create all the per-process semaphores we will need to support
  *	  the requested number of backends.  We used to allocate semaphores
@@ -129,69 +131,65 @@ ProcGlobalSemas(void)
  *	  Another reason for creating semaphores here is that the semaphore
  *	  implementation typically requires us to create semaphores in the
  *	  postmaster, not in backends.
+ *
+ * Note: this is NOT called by individual backends under a postmaster,
+ * not even in the EXEC_BACKEND case.  The ProcGlobal and DummyProcs
+ * pointers must be propagated specially for EXEC_BACKEND operation.
  */
 void
 InitProcGlobal(void)
 {
-	bool		foundProcGlobal,
-				foundDummy;
+	PGPROC	   *procs;
+	int			i;
+	bool		found;
 
-	/* Create or attach to the ProcGlobal shared structure */
+	/* Create the ProcGlobal shared structure */
 	ProcGlobal = (PROC_HDR *)
-		ShmemInitStruct("Proc Header", sizeof(PROC_HDR), &foundProcGlobal);
+		ShmemInitStruct("Proc Header", sizeof(PROC_HDR), &found);
+	Assert(!found);
 
 	/*
-	 * Create or attach to the PGPROC structures for dummy (bgwriter)
-	 * processes, too.	These do not get linked into the freeProcs list.
+	 * Create the PGPROC structures for dummy (bgwriter) processes, too.
+	 * These do not get linked into the freeProcs list.
 	 */
 	DummyProcs = (PGPROC *)
 		ShmemInitStruct("DummyProcs", NUM_DUMMY_PROCS * sizeof(PGPROC),
-						&foundDummy);
-
-	if (foundProcGlobal || foundDummy)
-	{
-		/* both should be present or neither */
-		Assert(foundProcGlobal && foundDummy);
-	}
-	else
-	{
-		/*
-		 * We're the first - initialize.
-		 */
-		PGPROC	   *procs;
-		int			i;
-
-		ProcGlobal->freeProcs = INVALID_OFFSET;
+						&found);
+	Assert(!found);
 
-		ProcGlobal->spins_per_delay = DEFAULT_SPINS_PER_DELAY;
+	/*
+	 * Initialize the data structures.
+	 */
+	ProcGlobal->freeProcs = INVALID_OFFSET;
 
-		/*
-		 * Pre-create the PGPROC structures and create a semaphore for each.
-		 */
-		procs = (PGPROC *) ShmemAlloc(MaxBackends * sizeof(PGPROC));
-		if (!procs)
-			ereport(FATAL,
-					(errcode(ERRCODE_OUT_OF_MEMORY),
-					 errmsg("out of shared memory")));
-		MemSet(procs, 0, MaxBackends * sizeof(PGPROC));
-		for (i = 0; i < MaxBackends; i++)
-		{
-			PGSemaphoreCreate(&(procs[i].sem));
-			procs[i].links.next = ProcGlobal->freeProcs;
-			ProcGlobal->freeProcs = MAKE_OFFSET(&procs[i]);
-		}
+	ProcGlobal->spins_per_delay = DEFAULT_SPINS_PER_DELAY;
 
-		MemSet(DummyProcs, 0, NUM_DUMMY_PROCS * sizeof(PGPROC));
-		for (i = 0; i < NUM_DUMMY_PROCS; i++)
-		{
-			DummyProcs[i].pid = 0;		/* marks dummy proc as not in use */
-			PGSemaphoreCreate(&(DummyProcs[i].sem));
-		}
+	/*
+	 * Pre-create the PGPROC structures and create a semaphore for each.
+	 */
+	procs = (PGPROC *) ShmemAlloc(MaxBackends * sizeof(PGPROC));
+	if (!procs)
+		ereport(FATAL,
+				(errcode(ERRCODE_OUT_OF_MEMORY),
+				 errmsg("out of shared memory")));
+	MemSet(procs, 0, MaxBackends * sizeof(PGPROC));
+	for (i = 0; i < MaxBackends; i++)
+	{
+		PGSemaphoreCreate(&(procs[i].sem));
+		procs[i].links.next = ProcGlobal->freeProcs;
+		ProcGlobal->freeProcs = MAKE_OFFSET(&procs[i]);
+	}
 
-		/* Create ProcStructLock spinlock, too */
-		ProcStructLock = (slock_t *) ShmemAlloc(sizeof(slock_t));
-		SpinLockInit(ProcStructLock);
+	MemSet(DummyProcs, 0, NUM_DUMMY_PROCS * sizeof(PGPROC));
+	for (i = 0; i < NUM_DUMMY_PROCS; i++)
+	{
+		DummyProcs[i].pid = 0;		/* marks dummy proc as not in use */
+		PGSemaphoreCreate(&(DummyProcs[i].sem));
 	}
+
+	/* Create ProcStructLock spinlock, too */
+	ProcStructLock = (slock_t *) ShmemAlloc(sizeof(slock_t));
+	SpinLockInit(ProcStructLock);
 }
 
 /*
@@ -206,8 +204,8 @@ InitProcess(void)
 	int			i;
 
 	/*
-	 * ProcGlobal should be set by a previous call to InitProcGlobal (if we
-	 * are a backend, we inherit this by fork() from the postmaster).
+	 * ProcGlobal should be set up already (if we are a backend, we inherit
+	 * this by fork() or EXEC_BACKEND mechanism from the postmaster).
 	 */
 	if (procglobal == NULL)
 		elog(PANIC, "proc header uninitialized");
@@ -256,8 +254,8 @@ InitProcess(void)
 	MyProc->xid = InvalidTransactionId;
 	MyProc->xmin = InvalidTransactionId;
 	MyProc->pid = MyProcPid;
-	MyProc->databaseId = MyDatabaseId;
-	/* Will be set properly after the session role id is determined */
+	/* databaseId and roleId will be filled in later */
+	MyProc->databaseId = InvalidOid;
 	MyProc->roleId = InvalidOid;
 	MyProc->lwWaiting = false;
 	MyProc->lwExclusive = false;
@@ -268,21 +266,16 @@ InitProcess(void)
 		SHMQueueInit(&(MyProc->myProcLocks[i]));
 
 	/*
-	 * Add our PGPROC to the PGPROC array in shared memory.
+	 * We might be reusing a semaphore that belonged to a failed process. So
+	 * be careful and reinitialize its value here.
 	 */
-	ProcArrayAdd(MyProc);
+	PGSemaphoreReset(&MyProc->sem);
 
 	/*
 	 * Arrange to clean up at backend exit.
 	 */
 	on_shmem_exit(ProcKill, 0);
 
-	/*
-	 * We might be reusing a semaphore that belonged to a failed process. So
-	 * be careful and reinitialize its value here.
-	 */
-	PGSemaphoreReset(&MyProc->sem);
-
 	/*
 	 * Now that we have a PGPROC, we could try to acquire locks, so initialize
 	 * the deadlock checker.
@@ -290,26 +283,59 @@ InitProcess(void)
 	InitDeadLockChecking();
 }
 
+/*
+ * InitProcessPhase2 -- make MyProc visible in the shared ProcArray.
+ *
+ * This is separate from InitProcess because we can't acquire LWLocks until
+ * we've created a PGPROC, but in the EXEC_BACKEND case there is a good deal
+ * of stuff to be done before this step that will require LWLock access.
+ */
+void
+InitProcessPhase2(void)
+{
+	Assert(MyProc != NULL);
+
+	/*
+	 * We should now know what database we're in, so advertise that.  (We
+	 * need not do any locking here, since no other backend can yet see
+	 * our PGPROC.)
+	 */
+	Assert(OidIsValid(MyDatabaseId));
+	MyProc->databaseId = MyDatabaseId;
+
+	/*
+	 * Add our PGPROC to the PGPROC array in shared memory.
+	 */
+	ProcArrayAdd(MyProc);
+
+	/*
+	 * Arrange to clean that up at backend exit.
+	 */
+	on_shmem_exit(RemoveProcFromArray, 0);
+}
+
 /*
  * InitDummyProcess -- create a dummy per-process data structure
  *
  * This is called by bgwriter and similar processes so that they will have a
  * MyProc value that's real enough to let them wait for LWLocks.  The PGPROC
- * and sema that are assigned are the extra ones created during
+ * and sema that are assigned are one of the extra ones created during
  * InitProcGlobal.
  *
  * Dummy processes are presently not expected to wait for real (lockmgr)
- * locks, nor to participate in sinval messaging.
+ * locks, so we need not set up the deadlock checker.  They are never added
+ * to the ProcArray or the sinval messaging mechanism, either.
  */
 void
-InitDummyProcess(int proctype)
+InitDummyProcess(void)
 {
 	PGPROC	   *dummyproc;
+	int			proctype;
 	int			i;
 
 	/*
-	 * ProcGlobal should be set by a previous call to InitProcGlobal (we
-	 * inherit this by fork() from the postmaster).
+	 * ProcGlobal should be set up already (if we are a backend, we inherit
+	 * this by fork() or EXEC_BACKEND mechanism from the postmaster).
 	 */
 	if (ProcGlobal == NULL || DummyProcs == NULL)
 		elog(PANIC, "proc header uninitialized");
@@ -317,11 +343,9 @@ InitDummyProcess(int proctype)
 	if (MyProc != NULL)
 		elog(ERROR, "you already exist");
 
-	Assert(proctype >= 0 && proctype < NUM_DUMMY_PROCS);
-
 	/*
-	 * Just for paranoia's sake, we use the ProcStructLock to protect
-	 * assignment and releasing of DummyProcs entries.
+	 * We use the ProcStructLock to protect assignment and releasing of
+	 * DummyProcs entries.
 	 *
 	 * While we are holding the ProcStructLock, also copy the current shared
 	 * estimate of spins_per_delay to local storage.
@@ -330,32 +354,38 @@ InitDummyProcess(int proctype)
 
 	set_spins_per_delay(ProcGlobal->spins_per_delay);
 
-	dummyproc = &DummyProcs[proctype];
-
 	/*
-	 * dummyproc should not presently be in use by anyone else
+	 * Find a free dummyproc ... *big* trouble if there isn't one ...
 	 */
-	if (dummyproc->pid != 0)
+	for (proctype = 0; proctype < NUM_DUMMY_PROCS; proctype++)
+	{
+		dummyproc = &DummyProcs[proctype];
+		if (dummyproc->pid == 0)
+			break;
+	}
+	if (proctype >= NUM_DUMMY_PROCS)
 	{
 		SpinLockRelease(ProcStructLock);
-		elog(FATAL, "DummyProc[%d] is in use by PID %d",
-			 proctype, dummyproc->pid);
+		elog(FATAL, "all DummyProcs are in use");
 	}
-	MyProc = dummyproc;
 
-	MyProc->pid = MyProcPid;	/* marks dummy proc as in use by me */
+	/* Mark dummy proc as in use by me */
+	/* use volatile pointer to prevent code rearrangement */
+	((volatile PGPROC *) dummyproc)->pid = MyProcPid;
+
+	MyProc = dummyproc;
 
 	SpinLockRelease(ProcStructLock);
 
 	/*
-	 * Initialize all fields of MyProc, except MyProc->sem which was set up by
-	 * InitProcGlobal.
+	 * Initialize all fields of MyProc, except for the semaphore which was
+	 * prepared for us by InitProcGlobal.
 	 */
 	SHMQueueElemInit(&(MyProc->links));
 	MyProc->waitStatus = STATUS_OK;
 	MyProc->xid = InvalidTransactionId;
 	MyProc->xmin = InvalidTransactionId;
-	MyProc->databaseId = MyDatabaseId;
+	MyProc->databaseId = InvalidOid;
 	MyProc->roleId = InvalidOid;
 	MyProc->lwWaiting = false;
 	MyProc->lwExclusive = false;
@@ -365,16 +395,16 @@ InitDummyProcess(int proctype)
 	for (i = 0; i < NUM_LOCK_PARTITIONS; i++)
 		SHMQueueInit(&(MyProc->myProcLocks[i]));
 
-	/*
-	 * Arrange to clean up at process exit.
-	 */
-	on_shmem_exit(DummyProcKill, Int32GetDatum(proctype));
-
 	/*
 	 * We might be reusing a semaphore that belonged to a failed process. So
 	 * be careful and reinitialize its value here.
 	 */
 	PGSemaphoreReset(&MyProc->sem);
+
+	/*
+	 * Arrange to clean up at process exit.
+	 */
+	on_shmem_exit(DummyProcKill, Int32GetDatum(proctype));
 }
 
 /*
@@ -501,6 +531,16 @@ ProcReleaseLocks(bool isCommit)
 }
 
 
+/*
+ * RemoveProcFromArray() -- Remove this process from the shared ProcArray.
+ */
+static void
+RemoveProcFromArray(int code, Datum arg)
+{
+	Assert(MyProc != NULL);
+	ProcArrayRemove(MyProc);
+}
+
 /*
  * ProcKill() -- Destroy the per-proc data structure for
  *		this process. Release any of its held LW locks.
@@ -520,9 +560,6 @@ ProcKill(int code, Datum arg)
 	 */
 	LWLockReleaseAll();
 
-	/* Remove our PGPROC from the PGPROC array in shared memory */
-	ProcArrayRemove(MyProc);
-
 	SpinLockAcquire(ProcStructLock);
 
 	/* Return PGPROC structure (and semaphore) to freelist */
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 64fda9783163aacfb6a322ed3fa951dacd3541d3..8991258523b5e13f9190d3c8629080a447b64daf 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/tcop/postgres.c,v 1.474 2005/12/31 16:50:44 momjian Exp $
+ *	  $PostgreSQL: pgsql/src/backend/tcop/postgres.c,v 1.475 2006/01/04 21:06:31 tgl Exp $
  *
  * NOTES
  *	  this is the "main" module of the postgres backend and
@@ -2860,7 +2860,6 @@ PostgresMain(int argc, char *argv[], const char *username)
 
 	PG_SETMASK(&BlockSig);		/* block everything except SIGQUIT */
 
-
 	if (IsUnderPostmaster)
 	{
 		/* noninteractive case: nothing should be left after switches */
@@ -2933,6 +2932,19 @@ PostgresMain(int argc, char *argv[], const char *username)
 		BuildFlatFiles(true);
 	}
 
+	/*
+	 * Create a per-backend PGPROC struct in shared memory, except in
+	 * the EXEC_BACKEND case where this was done in SubPostmasterMain.
+	 * We must do this before we can use LWLocks (and in the EXEC_BACKEND
+	 * case we already had to do some stuff with LWLocks).
+	 */
+#ifdef EXEC_BACKEND
+	if (!IsUnderPostmaster)
+		InitProcess();
+#else
+	InitProcess();
+#endif
+
 	/*
 	 * General initialization.
 	 *
diff --git a/src/backend/utils/init/postinit.c b/src/backend/utils/init/postinit.c
index b9b1f56dd08456aa5e53c899205c03e14c0ca316..580a2b4068b76628f2a725d994e3123641988c15 100644
--- a/src/backend/utils/init/postinit.c
+++ b/src/backend/utils/init/postinit.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/utils/init/postinit.c,v 1.159 2005/11/22 18:17:26 momjian Exp $
+ *	  $PostgreSQL: pgsql/src/backend/utils/init/postinit.c,v 1.160 2006/01/04 21:06:32 tgl Exp $
  *
  *
  *-------------------------------------------------------------------------
@@ -311,6 +311,9 @@ BaseInit(void)
  * can only be tested inside a transaction, so we want to do it during
  * the startup transaction rather than doing a separate one in postgres.c.)
  *
+ * As of PostgreSQL 8.2, we expect InitProcess() was already called, so we
+ * already have a PGPROC struct ... but it's not filled in yet.
+ *
  * Note:
  *		Be very careful with the order of calls in the InitPostgres function.
  * --------------------------------
@@ -383,17 +386,17 @@ InitPostgres(const char *dbname, const char *username)
 	 */
 
 	/*
-	 * Set up my per-backend PGPROC struct in shared memory.	(We need to
-	 * know MyDatabaseId before we can do this, since it's entered into the
-	 * PGPROC struct.)
+	 * Finish filling in the PGPROC struct, and add it to the ProcArray.
+	 * (We need to know MyDatabaseId before we can do this, since it's entered
+	 * into the PGPROC struct.)
+	 *
+	 * Once I have done this, I am visible to other backends!
 	 */
-	InitProcess();
+	InitProcessPhase2();
 
 	/*
 	 * Initialize my entry in the shared-invalidation manager's array of
-	 * per-backend data.  (Formerly this came before InitProcess, but now it
-	 * must happen after, because it uses MyProc.)	Once I have done this, I
-	 * am visible to other backends!
+	 * per-backend data.
 	 *
 	 * Sets up MyBackendId, a unique backend identifier.
 	 */
diff --git a/src/include/storage/lwlock.h b/src/include/storage/lwlock.h
index c318e60b5771fbeb35845dad0d0eea98226278f4..ca384218a50cb5f8716f3c302ee3fabaab55f4a0 100644
--- a/src/include/storage/lwlock.h
+++ b/src/include/storage/lwlock.h
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/storage/lwlock.h,v 1.24 2005/12/11 21:02:18 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/storage/lwlock.h,v 1.25 2006/01/04 21:06:32 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -27,6 +27,7 @@ typedef enum LWLockId
 {
 	BufMappingLock,
 	BufFreelistLock,
+	ShmemIndexLock,
 	OidGenLock,
 	XidGenLock,
 	ProcArrayLock,
diff --git a/src/include/storage/pg_shmem.h b/src/include/storage/pg_shmem.h
index 4dd91e8540f7260d8fb639b0a13445b3c99ea3ab..59784117614a2dd5c61c68337349a4c0e8156478 100644
--- a/src/include/storage/pg_shmem.h
+++ b/src/include/storage/pg_shmem.h
@@ -17,7 +17,7 @@
  * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/storage/pg_shmem.h,v 1.16 2005/10/15 02:49:46 momjian Exp $
+ * $PostgreSQL: pgsql/src/include/storage/pg_shmem.h,v 1.17 2006/01/04 21:06:32 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -27,10 +27,11 @@
 typedef struct PGShmemHeader	/* standard header for all Postgres shmem */
 {
 	int32		magic;			/* magic # to identify Postgres segments */
-#define PGShmemMagic  679834893
+#define PGShmemMagic  679834894
 	pid_t		creatorPID;		/* PID of creating process */
 	Size		totalsize;		/* total size of segment */
 	Size		freeoffset;		/* offset to first free space */
+	Size		indexoffset;	/* offset to ShmemIndex table */
 #ifndef WIN32					/* Windows doesn't have useful inode#s */
 	dev_t		device;			/* device data directory is on */
 	ino_t		inode;			/* inode number of data directory */
diff --git a/src/include/storage/proc.h b/src/include/storage/proc.h
index 2cfee41eff91e85f6767aa8098402e36ea69148a..abf99668f349475d380d15a54ec421cacfbf4ca4 100644
--- a/src/include/storage/proc.h
+++ b/src/include/storage/proc.h
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/storage/proc.h,v 1.85 2005/12/11 21:02:18 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/storage/proc.h,v 1.86 2006/01/04 21:06:32 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -114,9 +114,10 @@ typedef struct PROC_HDR
 	int			spins_per_delay;
 } PROC_HDR;
 
-
-#define DUMMY_PROC_DEFAULT	0
-#define DUMMY_PROC_BGWRITER 1
+/*
+ * We set aside some extra PGPROC structures for "dummy" processes,
+ * ie things that aren't full-fledged backends but need shmem access.
+ */
 #define NUM_DUMMY_PROCS		2
 
 
@@ -134,7 +135,8 @@ extern int	ProcGlobalSemas(void);
 extern Size ProcGlobalShmemSize(void);
 extern void InitProcGlobal(void);
 extern void InitProcess(void);
-extern void InitDummyProcess(int proctype);
+extern void InitProcessPhase2(void);
+extern void InitDummyProcess(void);
 extern bool HaveNFreeProcs(int n);
 extern void ProcReleaseLocks(bool isCommit);
 
diff --git a/src/include/storage/shmem.h b/src/include/storage/shmem.h
index 520f8eb3adff930c30de33a0c680f47e7ed38adf..141ecf17d9006f523d065f02342fc889a91cff47 100644
--- a/src/include/storage/shmem.h
+++ b/src/include/storage/shmem.h
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/storage/shmem.h,v 1.45 2005/08/20 23:26:35 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/storage/shmem.h,v 1.46 2006/01/04 21:06:32 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -61,7 +61,8 @@ typedef struct SHM_QUEUE
 } SHM_QUEUE;
 
 /* shmem.c */
-extern void InitShmemAllocation(void *seghdr, bool init);
+extern void InitShmemAccess(void *seghdr);
+extern void InitShmemAllocation(void);
 extern void *ShmemAlloc(Size size);
 extern bool ShmemIsValid(unsigned long addr);
 extern void InitShmemIndex(void);