From 349f40b2c264cbbfe4c5c7ba783bce58483cefae Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Wed, 4 Jan 2006 21:06:32 +0000 Subject: [PATCH] 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. --- src/backend/bootstrap/bootstrap.c | 33 +++-- src/backend/postmaster/autovacuum.c | 18 ++- src/backend/postmaster/pgarch.c | 8 +- src/backend/postmaster/pgstat.c | 45 ++++-- src/backend/postmaster/postmaster.c | 145 ++++++++++++------ src/backend/postmaster/syslogger.c | 8 +- src/backend/storage/ipc/ipci.c | 16 +- src/backend/storage/ipc/shmem.c | 121 ++++++++------- src/backend/storage/lmgr/proc.c | 219 ++++++++++++++++------------ src/backend/tcop/postgres.c | 16 +- src/backend/utils/init/postinit.c | 19 ++- src/include/storage/lwlock.h | 3 +- src/include/storage/pg_shmem.h | 5 +- src/include/storage/proc.h | 12 +- src/include/storage/shmem.h | 5 +- 15 files changed, 414 insertions(+), 259 deletions(-) diff --git a/src/backend/bootstrap/bootstrap.c b/src/backend/bootstrap/bootstrap.c index 283ca24647..66cf4c4ce0 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 0049f4307c..c2b6ac1a29 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -10,7 +10,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/postmaster/autovacuum.c,v 1.8 2005/11/28 17:23:11 alvherre Exp $ + * $PostgreSQL: pgsql/src/backend/postmaster/autovacuum.c,v 1.9 2006/01/04 21:06:31 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -167,6 +167,9 @@ autovac_start(void) /* Close the postmaster's sockets */ ClosePostmasterPorts(false); + /* Lose the postmaster's on-exit routines */ + on_exit_reset(); + AutoVacMain(0, NULL); break; #endif @@ -230,9 +233,6 @@ AutoVacMain(int argc, char *argv[]) /* reset MyProcPid */ MyProcPid = getpid(); - /* Lose the postmaster's on-exit routines */ - on_exit_reset(); - /* Identify myself via ps */ init_ps_display("autovacuum process", "", ""); set_ps_display(""); @@ -268,6 +268,16 @@ AutoVacMain(int argc, char *argv[]) /* Early initialization */ BaseInit(); + /* + * Create a per-backend PGPROC struct in shared memory, except in + * the EXEC_BACKEND case where this was done in SubPostmasterMain. + * We must do this before we can use LWLocks (and in the EXEC_BACKEND + * case we already had to do some stuff with LWLocks). + */ +#ifndef EXEC_BACKEND + InitProcess(); +#endif + /* * If an exception is encountered, processing resumes here. * diff --git a/src/backend/postmaster/pgarch.c b/src/backend/postmaster/pgarch.c index 61019d7a5e..7b604b9f9f 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 a192b4e5c8..d4a07efce2 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 24212f1fff..187bfeb47e 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 */ + 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); diff --git a/src/backend/postmaster/syslogger.c b/src/backend/postmaster/syslogger.c index 805ea8087a..e27f2bf8bc 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 bfe8d52af3..e878462100 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 e6865563b3..21d136d6cf 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 34d80bfcee..605f8b5e68 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); + &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 */ diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c index 64fda97831..8991258523 100644 --- a/src/backend/tcop/postgres.c +++ b/src/backend/tcop/postgres.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/tcop/postgres.c,v 1.474 2005/12/31 16:50:44 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/tcop/postgres.c,v 1.475 2006/01/04 21:06:31 tgl Exp $ * * NOTES * this is the "main" module of the postgres backend and @@ -2860,7 +2860,6 @@ PostgresMain(int argc, char *argv[], const char *username) PG_SETMASK(&BlockSig); /* block everything except SIGQUIT */ - if (IsUnderPostmaster) { /* noninteractive case: nothing should be left after switches */ @@ -2933,6 +2932,19 @@ PostgresMain(int argc, char *argv[], const char *username) BuildFlatFiles(true); } + /* + * Create a per-backend PGPROC struct in shared memory, except in + * the EXEC_BACKEND case where this was done in SubPostmasterMain. + * We must do this before we can use LWLocks (and in the EXEC_BACKEND + * case we already had to do some stuff with LWLocks). + */ +#ifdef EXEC_BACKEND + if (!IsUnderPostmaster) + InitProcess(); +#else + InitProcess(); +#endif + /* * General initialization. * diff --git a/src/backend/utils/init/postinit.c b/src/backend/utils/init/postinit.c index b9b1f56dd0..580a2b4068 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 c318e60b57..ca384218a5 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 4dd91e8540..5978411761 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 2cfee41eff..abf99668f3 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 520f8eb3ad..141ecf17d9 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);