Rearrange backend startup sequence so that ShmemIndexLock can become
an LWLock instead of a spinlock. This hardly matters on Unix machines but should improve startup performance on Windows (or any port using EXEC_BACKEND). Per previous discussion.
This commit is contained in:
parent
e0078ea22d
commit
349f40b2c2
|
@ -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);
|
||||
|
||||
/*
|
||||
|
|
|
@ -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.
|
||||
*
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 */
|
||||
Assert(argc == 3); /* shouldn't be any more args */
|
||||
|
||||
/* Attach process to shared data structures */
|
||||
CreateSharedMemoryAndSemaphores(false, 0);
|
||||
|
||||
#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(¶m->pgStatSock, pgStatSock, childPid);
|
||||
write_inheritable_socket(¶m->pgStatPipe0, pgStatPipe[0], childPid);
|
||||
write_inheritable_socket(¶m->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, ¶m->pgStatSock);
|
||||
read_inheritable_socket(&pgStatPipe[0], ¶m->pgStatPipe0);
|
||||
read_inheritable_socket(&pgStatPipe[1], ¶m->pgStatPipe1);
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
||||
/*
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
&found);
|
||||
Assert(!found);
|
||||
|
||||
if (foundProcGlobal || foundDummy)
|
||||
/*
|
||||
* Initialize the data structures.
|
||||
*/
|
||||
ProcGlobal->freeProcs = INVALID_OFFSET;
|
||||
|
||||
ProcGlobal->spins_per_delay = DEFAULT_SPINS_PER_DELAY;
|
||||
|
||||
/*
|
||||
* 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++)
|
||||
{
|
||||
/* both should be present or neither */
|
||||
Assert(foundProcGlobal && foundDummy);
|
||||
PGSemaphoreCreate(&(procs[i].sem));
|
||||
procs[i].links.next = ProcGlobal->freeProcs;
|
||||
ProcGlobal->freeProcs = MAKE_OFFSET(&procs[i]);
|
||||
}
|
||||
else
|
||||
|
||||
MemSet(DummyProcs, 0, NUM_DUMMY_PROCS * sizeof(PGPROC));
|
||||
for (i = 0; i < NUM_DUMMY_PROCS; i++)
|
||||
{
|
||||
/*
|
||||
* We're the first - initialize.
|
||||
*/
|
||||
PGPROC *procs;
|
||||
int i;
|
||||
|
||||
ProcGlobal->freeProcs = INVALID_OFFSET;
|
||||
|
||||
ProcGlobal->spins_per_delay = DEFAULT_SPINS_PER_DELAY;
|
||||
|
||||
/*
|
||||
* 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]);
|
||||
}
|
||||
|
||||
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);
|
||||
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 */
|
||||
|
|
|
@ -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.
|
||||
*
|
||||
|
|
|
@ -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.
|
||||
*/
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue