aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/backend/bootstrap/bootstrap.c33
-rw-r--r--src/backend/postmaster/autovacuum.c18
-rw-r--r--src/backend/postmaster/pgarch.c8
-rw-r--r--src/backend/postmaster/pgstat.c45
-rw-r--r--src/backend/postmaster/postmaster.c145
-rw-r--r--src/backend/postmaster/syslogger.c8
-rw-r--r--src/backend/storage/ipc/ipci.c16
-rw-r--r--src/backend/storage/ipc/shmem.c121
-rw-r--r--src/backend/storage/lmgr/proc.c219
-rw-r--r--src/backend/tcop/postgres.c16
-rw-r--r--src/backend/utils/init/postinit.c19
-rw-r--r--src/include/storage/lwlock.h3
-rw-r--r--src/include/storage/pg_shmem.h5
-rw-r--r--src/include/storage/proc.h12
-rw-r--r--src/include/storage/shmem.h5
15 files changed, 414 insertions, 259 deletions
diff --git a/src/backend/bootstrap/bootstrap.c b/src/backend/bootstrap/bootstrap.c
index 283ca246473..66cf4c4ce0a 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 0049f4307cd..c2b6ac1a298 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("");
@@ -269,6 +269,16 @@ AutoVacMain(int argc, char *argv[])
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.
*
* See notes in postgres.c about the design of this coding.
diff --git a/src/backend/postmaster/pgarch.c b/src/backend/postmaster/pgarch.c
index 61019d7a5e3..7b604b9f9f9 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 a192b4e5c87..d4a07efce2f 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 24212f1ffff..187bfeb47ec 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 805ea8087a3..e27f2bf8bc6 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 bfe8d52af30..e878462100e 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 e6865563b39..21d136d6cf0 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 34d80bfceea..605f8b5e68b 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,9 +266,10 @@ 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.
@@ -278,12 +277,6 @@ InitProcess(void)
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.
*/
@@ -291,25 +284,58 @@ InitProcess(void)
}
/*
+ * 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;
@@ -366,15 +396,15 @@ InitDummyProcess(int proctype)
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));
}
/*
@@ -502,6 +532,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 64fda978316..8991258523b 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 */
@@ -2934,6 +2933,19 @@ PostgresMain(int argc, char *argv[], const char *username)
}
/*
+ * 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.
*
* NOTE: if you are tempted to add code in this vicinity, consider putting
diff --git a/src/backend/utils/init/postinit.c b/src/backend/utils/init/postinit.c
index b9b1f56dd08..580a2b4068b 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 c318e60b577..ca384218a50 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 4dd91e8540f..59784117614 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 2cfee41eff9..abf99668f34 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 520f8eb3adf..141ecf17d90 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);