mirror of
https://git.postgresql.org/git/postgresql.git
synced 2025-02-23 19:39:53 +08:00
This patch is the next step towards (re)allowing fork/exec.
Claudio Natoli
This commit is contained in:
parent
1ee0ddf91d
commit
d75b2ec4eb
@ -7,7 +7,7 @@
|
||||
* Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $PostgreSQL: pgsql/src/backend/access/transam/xlog.c,v 1.128 2003/12/14 00:34:47 neilc Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/access/transam/xlog.c,v 1.129 2003/12/20 17:31:20 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -166,7 +166,7 @@ XLogRecPtr ProcLastRecEnd = {0, 0};
|
||||
* to update from XLogCtl->Insert.RedoRecPtr if we hold the info_lck;
|
||||
* see GetRedoRecPtr.
|
||||
*/
|
||||
static XLogRecPtr RedoRecPtr;
|
||||
NON_EXEC_STATIC XLogRecPtr RedoRecPtr;
|
||||
|
||||
/*----------
|
||||
* Shared-memory data structures for XLOG control
|
||||
@ -231,12 +231,6 @@ typedef struct XLogwrtRqst
|
||||
XLogRecPtr Flush; /* last byte + 1 to flush */
|
||||
} XLogwrtRqst;
|
||||
|
||||
typedef struct XLogwrtResult
|
||||
{
|
||||
XLogRecPtr Write; /* last byte + 1 written out */
|
||||
XLogRecPtr Flush; /* last byte + 1 flushed */
|
||||
} XLogwrtResult;
|
||||
|
||||
/*
|
||||
* Shared state data for XLogInsert.
|
||||
*/
|
||||
@ -404,7 +398,7 @@ static char ControlFilePath[MAXPGPATH];
|
||||
* Private, possibly out-of-date copy of shared LogwrtResult.
|
||||
* See discussion above.
|
||||
*/
|
||||
static XLogwrtResult LogwrtResult = {{0, 0}, {0, 0}};
|
||||
NON_EXEC_STATIC XLogwrtResult LogwrtResult = {{0, 0}, {0, 0}};
|
||||
|
||||
/*
|
||||
* openLogFile is -1 or a kernel FD for an open log file segment.
|
||||
@ -2398,7 +2392,7 @@ XLOGShmemSize(void)
|
||||
void
|
||||
XLOGShmemInit(void)
|
||||
{
|
||||
bool found;
|
||||
bool foundXLog, foundCFile;
|
||||
|
||||
/* this must agree with space requested by XLOGShmemSize() */
|
||||
if (XLOGbuffers < MinXLOGbuffers)
|
||||
@ -2409,11 +2403,16 @@ XLOGShmemInit(void)
|
||||
MAXALIGN(sizeof(XLogCtlData) +
|
||||
sizeof(XLogRecPtr) * XLOGbuffers)
|
||||
+ BLCKSZ * XLOGbuffers,
|
||||
&found);
|
||||
Assert(!found);
|
||||
&foundXLog);
|
||||
ControlFile = (ControlFileData *)
|
||||
ShmemInitStruct("Control File", sizeof(ControlFileData), &found);
|
||||
Assert(!found);
|
||||
ShmemInitStruct("Control File", sizeof(ControlFileData), &foundCFile);
|
||||
|
||||
if (foundXLog || foundCFile)
|
||||
{
|
||||
/* both should be present or neither */
|
||||
Assert(foundXLog && foundCFile);
|
||||
return;
|
||||
}
|
||||
|
||||
memset(XLogCtl, 0, sizeof(XLogCtlData));
|
||||
|
||||
|
@ -8,7 +8,7 @@
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/bootstrap/bootstrap.c,v 1.170 2003/12/12 18:45:08 petere Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/bootstrap/bootstrap.c,v 1.171 2003/12/20 17:31:21 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -347,9 +347,10 @@ BootstrapMain(int argc, char *argv[])
|
||||
if (!dbname || argc != optind)
|
||||
usage();
|
||||
|
||||
|
||||
if (IsUnderPostmaster && ExecBackend && MyProc /* ordinary backend */ )
|
||||
#ifdef EXEC_BACKEND
|
||||
if (IsUnderPostmaster && MyProc /* ordinary backend */ )
|
||||
AttachSharedMemoryAndSemaphores();
|
||||
#endif
|
||||
|
||||
if (!IsUnderPostmaster /* when exec || ExecBackend */ )
|
||||
{
|
||||
|
@ -13,7 +13,7 @@
|
||||
*
|
||||
* Copyright (c) 2001-2003, PostgreSQL Global Development Group
|
||||
*
|
||||
* $PostgreSQL: pgsql/src/backend/postmaster/pgstat.c,v 1.48 2003/11/29 19:51:55 pgsql Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/postmaster/pgstat.c,v 1.49 2003/12/20 17:31:21 momjian Exp $
|
||||
* ----------
|
||||
*/
|
||||
#include "postgres.h"
|
||||
@ -71,7 +71,7 @@ bool pgstat_is_running = false;
|
||||
* Local data
|
||||
* ----------
|
||||
*/
|
||||
static int pgStatSock = -1;
|
||||
NON_EXEC_STATIC int pgStatSock = -1;
|
||||
static int pgStatPipe[2];
|
||||
static struct sockaddr_storage pgStatAddr;
|
||||
static int pgStatPmPipe[2] = {-1, -1};
|
||||
|
@ -37,7 +37,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/postmaster/postmaster.c,v 1.351 2003/12/01 22:15:37 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/postmaster/postmaster.c,v 1.352 2003/12/20 17:31:21 momjian Exp $
|
||||
*
|
||||
* NOTES
|
||||
*
|
||||
@ -273,6 +273,7 @@ static void dummy_handler(SIGNAL_ARGS);
|
||||
static void CleanupProc(int pid, int exitstatus);
|
||||
static void LogChildExit(int lev, const char *procname,
|
||||
int pid, int exitstatus);
|
||||
NON_EXEC_STATIC bool BackendInit(Port *port);
|
||||
static int BackendFork(Port *port);
|
||||
static void ExitPostmaster(int status);
|
||||
static void usage(const char *);
|
||||
@ -282,10 +283,6 @@ static int ProcessStartupPacket(Port *port, bool SSLdone);
|
||||
static void processCancelRequest(Port *port, void *pkt);
|
||||
static int initMasks(fd_set *rmask);
|
||||
static void report_fork_failure_to_client(Port *port, int errnum);
|
||||
enum CAC_state
|
||||
{
|
||||
CAC_OK, CAC_STARTUP, CAC_SHUTDOWN, CAC_RECOVERY, CAC_TOOMANY
|
||||
};
|
||||
static enum CAC_state canAcceptConnections(void);
|
||||
static long PostmasterRandom(void);
|
||||
static void RandomSalt(char *cryptSalt, char *md5Salt);
|
||||
@ -298,6 +295,11 @@ postmaster_error(const char *fmt,...)
|
||||
/* This lets gcc check the format string for consistency. */
|
||||
__attribute__((format(printf, 1, 2)));
|
||||
|
||||
#ifdef EXEC_BACKEND
|
||||
static void
|
||||
write_backend_variables(pid_t pid, Port *port);
|
||||
#endif
|
||||
|
||||
#define StartupDataBase() SSDataBase(BS_XLOG_STARTUP)
|
||||
#define CheckPointDataBase() SSDataBase(BS_XLOG_CHECKPOINT)
|
||||
#define StartBackgroundWriter() SSDataBase(BS_XLOG_BGWRITER)
|
||||
@ -1185,7 +1187,6 @@ initMasks(fd_set *rmask)
|
||||
static int
|
||||
ProcessStartupPacket(Port *port, bool SSLdone)
|
||||
{
|
||||
enum CAC_state cac;
|
||||
int32 len;
|
||||
void *buf;
|
||||
ProtocolVersion proto;
|
||||
@ -1244,7 +1245,11 @@ ProcessStartupPacket(Port *port, bool SSLdone)
|
||||
|
||||
if (proto == CANCEL_REQUEST_CODE)
|
||||
{
|
||||
#ifdef EXEC_BACKEND
|
||||
abort(); /* FIXME: [fork/exec] Whoops. Not handled... yet */
|
||||
#else
|
||||
processCancelRequest(port, buf);
|
||||
#endif
|
||||
return 127; /* XXX */
|
||||
}
|
||||
|
||||
@ -1435,9 +1440,7 @@ ProcessStartupPacket(Port *port, bool SSLdone)
|
||||
* so now instead of wasting cycles on an authentication exchange.
|
||||
* (This also allows a pg_ping utility to be written.)
|
||||
*/
|
||||
cac = canAcceptConnections();
|
||||
|
||||
switch (cac)
|
||||
switch (port->canAcceptConnections)
|
||||
{
|
||||
case CAC_STARTUP:
|
||||
ereport(FATAL,
|
||||
@ -1499,8 +1502,10 @@ processCancelRequest(Port *port, void *pkt)
|
||||
backendPID)));
|
||||
return;
|
||||
}
|
||||
else if (ExecBackend)
|
||||
#ifdef EXEC_BACKEND
|
||||
else
|
||||
AttachSharedMemoryAndSemaphores();
|
||||
#endif
|
||||
|
||||
/* See if we have a matching backend */
|
||||
|
||||
@ -2341,40 +2346,25 @@ split_opts(char **argv, int *argcp, char *s)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* BackendFork -- perform authentication, and if successful, set up the
|
||||
* backend's argument list and invoke backend main().
|
||||
*
|
||||
* This used to perform an execv() but we no longer exec the backend;
|
||||
* it's the same executable as the postmaster.
|
||||
* BackendInit/Fork -- perform authentication [BackendInit], and if successful,
|
||||
* set up the backend's argument list [BackendFork] and invoke
|
||||
* backend main() [or exec in EXEC_BACKEND case]
|
||||
*
|
||||
* returns:
|
||||
* Shouldn't return at all.
|
||||
* If PostgresMain() fails, return status.
|
||||
*/
|
||||
static int
|
||||
BackendFork(Port *port)
|
||||
NON_EXEC_STATIC bool
|
||||
BackendInit(Port *port)
|
||||
{
|
||||
char **av;
|
||||
int maxac;
|
||||
int ac;
|
||||
char debugbuf[32];
|
||||
char protobuf[32];
|
||||
|
||||
#ifdef EXEC_BACKEND
|
||||
char pbuf[NAMEDATALEN + 256];
|
||||
#endif
|
||||
int i;
|
||||
int status;
|
||||
struct timeval now;
|
||||
struct timezone tz;
|
||||
char remote_host[NI_MAXHOST];
|
||||
char remote_port[NI_MAXSERV];
|
||||
|
||||
/*
|
||||
* Let's clean up ourselves as the postmaster child
|
||||
*/
|
||||
|
||||
IsUnderPostmaster = true; /* we are a postmaster subprocess now */
|
||||
|
||||
ClientAuthInProgress = true; /* limit visibility of log messages */
|
||||
@ -2386,9 +2376,6 @@ BackendFork(Port *port)
|
||||
* Signal handlers setting is moved to tcop/postgres...
|
||||
*/
|
||||
|
||||
/* Close the postmaster's other sockets */
|
||||
ClosePostmasterPorts(true);
|
||||
|
||||
/* Save port etc. for ps status */
|
||||
MyProcPort = port;
|
||||
|
||||
@ -2444,16 +2431,6 @@ BackendFork(Port *port)
|
||||
StrNCpy(remote_host, tmphost, sizeof(remote_host));
|
||||
}
|
||||
|
||||
/*
|
||||
* PreAuthDelay is a debugging aid for investigating problems in the
|
||||
* authentication cycle: it can be set in postgresql.conf to allow
|
||||
* time to attach to the newly-forked backend with a debugger. (See
|
||||
* also the -W backend switch, which we allow clients to pass through
|
||||
* PGOPTIONS, but it is not honored until after authentication.)
|
||||
*/
|
||||
if (PreAuthDelay > 0)
|
||||
sleep(PreAuthDelay);
|
||||
|
||||
/*
|
||||
* Ready to begin client interaction. We will give up and exit(0)
|
||||
* after a time delay, so that a broken client can't hog a connection
|
||||
@ -2469,7 +2446,7 @@ BackendFork(Port *port)
|
||||
status = ProcessStartupPacket(port, false);
|
||||
|
||||
if (status != STATUS_OK)
|
||||
return 0; /* cancel request processed, or error */
|
||||
return false; /* cancel request processed, or error */
|
||||
|
||||
/*
|
||||
* Now that we have the user and database name, we can set the process
|
||||
@ -2506,6 +2483,50 @@ BackendFork(Port *port)
|
||||
gettimeofday(&now, &tz);
|
||||
srandom((unsigned int) now.tv_usec);
|
||||
|
||||
#ifdef EXEC_BACKEND
|
||||
ClientAuthInProgress = false; /* client_min_messages is active
|
||||
* now */
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
BackendFork(Port *port)
|
||||
{
|
||||
char **av;
|
||||
int maxac;
|
||||
int ac;
|
||||
char debugbuf[32];
|
||||
#ifndef EXEC_BACKEND
|
||||
char protobuf[32];
|
||||
#endif
|
||||
int i;
|
||||
char tmpExtraOptions[MAXPGPATH];
|
||||
|
||||
/*
|
||||
* Let's clean up ourselves as the postmaster child, and
|
||||
* close the postmaster's other sockets
|
||||
*/
|
||||
ClosePostmasterPorts(true);
|
||||
|
||||
/*
|
||||
* PreAuthDelay is a debugging aid for investigating problems in the
|
||||
* authentication cycle: it can be set in postgresql.conf to allow
|
||||
* time to attach to the newly-forked backend with a debugger. (See
|
||||
* also the -W backend switch, which we allow clients to pass through
|
||||
* PGOPTIONS, but it is not honored until after authentication.)
|
||||
*/
|
||||
if (PreAuthDelay > 0)
|
||||
sleep(PreAuthDelay);
|
||||
|
||||
port->canAcceptConnections = canAcceptConnections();
|
||||
|
||||
#ifndef EXEC_BACKEND
|
||||
if (!BackendInit(port))
|
||||
return -1;
|
||||
#endif
|
||||
|
||||
/* ----------------
|
||||
* Now, build the argv vector that will be given to PostgresMain.
|
||||
*
|
||||
@ -2540,30 +2561,38 @@ BackendFork(Port *port)
|
||||
|
||||
/*
|
||||
* Pass any backend switches specified with -o in the postmaster's own
|
||||
* command line. We assume these are secure. (It's OK to mangle
|
||||
* ExtraOptions since we are now in the child process; this won't
|
||||
* change the postmaster's copy.)
|
||||
* command line. We assume these are secure.
|
||||
* [Note: now makes a copy to protect against future fork/exec changes]
|
||||
*/
|
||||
split_opts(av, &ac, ExtraOptions);
|
||||
strcpy(tmpExtraOptions,ExtraOptions);
|
||||
split_opts(av, &ac, tmpExtraOptions);
|
||||
|
||||
#ifndef EXEC_BACKEND
|
||||
/* Tell the backend what protocol the frontend is using. */
|
||||
snprintf(protobuf, sizeof(protobuf), "-v%u", port->proto);
|
||||
av[ac++] = protobuf;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Tell the backend it is being called from the postmaster, and which
|
||||
* database to use. -p marks the end of secure switches.
|
||||
*/
|
||||
av[ac++] = "-p";
|
||||
#ifdef EXEC_BACKEND
|
||||
Assert(UsedShmemSegID != 0 && UsedShmemSegAddr != NULL);
|
||||
/* database name at the end because it might contain commas */
|
||||
snprintf(pbuf, sizeof(pbuf), "%d,%d,%lu,%p,%s",
|
||||
port->sock, canAcceptConnections(),
|
||||
UsedShmemSegID, UsedShmemSegAddr,
|
||||
port->database_name);
|
||||
av[ac++] = pbuf;
|
||||
write_backend_variables(getpid(),port);
|
||||
|
||||
/* pass data dir before end of secure switches (-p) */
|
||||
av[ac++] = "-D";
|
||||
av[ac++] = DataDir;
|
||||
|
||||
/*
|
||||
* This is totally bogus. We need to pass an arg to -p, but we'll
|
||||
* actually get the dbname by ProcessStartupPacket in the exec'd
|
||||
* process
|
||||
*/
|
||||
av[ac++] = "-p";
|
||||
av[ac++] = "FORK_EXEC";
|
||||
#else
|
||||
av[ac++] = "-p";
|
||||
av[ac++] = port->database_name;
|
||||
#endif
|
||||
|
||||
@ -2571,6 +2600,10 @@ BackendFork(Port *port)
|
||||
* Pass the (insecure) option switches from the connection request.
|
||||
* (It's OK to mangle port->cmdline_options now.)
|
||||
*/
|
||||
/* FIXME: [fork/exec] Hmmm.. we won't see these until after we BackendInit.
|
||||
* Should we add code to BackendInit to add these (somehow!) into
|
||||
* the PostgresMain argument list in the EXEC_BACKEND case?
|
||||
*/
|
||||
if (port->cmdline_options)
|
||||
split_opts(av, &ac, port->cmdline_options);
|
||||
|
||||
@ -2594,17 +2627,21 @@ BackendFork(Port *port)
|
||||
*/
|
||||
ereport(DEBUG3,
|
||||
(errmsg_internal("%s child[%d]: starting with (",
|
||||
progname, MyProcPid)));
|
||||
progname, getpid())));
|
||||
for (i = 0; i < ac; ++i)
|
||||
ereport(DEBUG3,
|
||||
(errmsg_internal("\t%s", av[i])));
|
||||
ereport(DEBUG3,
|
||||
(errmsg_internal(")")));
|
||||
|
||||
#ifdef EXEC_BACKEND
|
||||
return execv(pg_pathname,av);
|
||||
#else
|
||||
ClientAuthInProgress = false; /* client_min_messages is active
|
||||
* now */
|
||||
|
||||
return (PostgresMain(ac, av, port->user_name));
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
@ -3051,3 +3088,136 @@ postmaster_error(const char *fmt,...)
|
||||
va_end(ap);
|
||||
fprintf(stderr, "\n");
|
||||
}
|
||||
|
||||
|
||||
#ifdef EXEC_BACKEND
|
||||
|
||||
/*
|
||||
* The following need to be available to the read/write_backend_variables
|
||||
* functions
|
||||
*/
|
||||
extern XLogRecPtr RedoRecPtr;
|
||||
extern XLogwrtResult LogwrtResult;
|
||||
extern slock_t *ShmemLock;
|
||||
extern slock_t *ShmemIndexLock;
|
||||
extern void *ShmemIndexAlloc;
|
||||
typedef struct LWLock LWLock;
|
||||
extern LWLock *LWLockArray;
|
||||
extern slock_t *ProcStructLock;
|
||||
extern int pgStatSock;
|
||||
|
||||
#define write_var(var,fp) fwrite((void*)&(var),sizeof(var),1,fp)
|
||||
#define read_var(var,fp) fread((void*)&(var),sizeof(var),1,fp);
|
||||
#define get_tmp_backend_file_name(buf,id) \
|
||||
do { \
|
||||
Assert(DataDir); \
|
||||
sprintf((buf), \
|
||||
"%s/%s/%s.backend_var.%d", \
|
||||
DataDir, \
|
||||
PG_TEMP_FILES_DIR, \
|
||||
PG_TEMP_FILE_PREFIX, \
|
||||
(id)); \
|
||||
} while (0)
|
||||
|
||||
static void
|
||||
write_backend_variables(pid_t pid, Port *port)
|
||||
{
|
||||
char filename[MAXPGPATH];
|
||||
FILE *fp;
|
||||
get_tmp_backend_file_name(filename,pid);
|
||||
|
||||
/* Open file */
|
||||
fp = AllocateFile(filename, PG_BINARY_W);
|
||||
if (!fp)
|
||||
{
|
||||
/* As per OpenTemporaryFile... */
|
||||
char dirname[MAXPGPATH];
|
||||
sprintf(dirname,"%s/%s",DataDir,PG_TEMP_FILES_DIR);
|
||||
mkdir(dirname, S_IRWXU);
|
||||
|
||||
fp = AllocateFile(filename, PG_BINARY_W);
|
||||
if (!fp)
|
||||
{
|
||||
ereport(ERROR,
|
||||
(errcode_for_file_access(),
|
||||
errmsg("could not write to file \"%s\": %m", filename)));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* Write vars */
|
||||
write_var(port->sock,fp);
|
||||
write_var(port->proto,fp);
|
||||
write_var(port->laddr,fp);
|
||||
write_var(port->raddr,fp);
|
||||
write_var(port->canAcceptConnections,fp);
|
||||
write_var(MyCancelKey,fp);
|
||||
|
||||
write_var(RedoRecPtr,fp);
|
||||
write_var(LogwrtResult,fp);
|
||||
|
||||
write_var(UsedShmemSegID,fp);
|
||||
write_var(UsedShmemSegAddr,fp);
|
||||
|
||||
write_var(ShmemLock,fp);
|
||||
write_var(ShmemIndexLock,fp);
|
||||
write_var(ShmemVariableCache,fp);
|
||||
write_var(ShmemIndexAlloc,fp);
|
||||
|
||||
write_var(LWLockArray,fp);
|
||||
write_var(ProcStructLock,fp);
|
||||
write_var(pgStatSock,fp);
|
||||
|
||||
/* Release file */
|
||||
FreeFile(fp);
|
||||
}
|
||||
|
||||
void
|
||||
read_backend_variables(pid_t pid, Port *port)
|
||||
{
|
||||
char filename[MAXPGPATH];
|
||||
FILE *fp;
|
||||
get_tmp_backend_file_name(filename,pid);
|
||||
|
||||
/* Open file */
|
||||
fp = AllocateFile(filename, PG_BINARY_R);
|
||||
if (!fp)
|
||||
{
|
||||
ereport(ERROR,
|
||||
(errcode_for_file_access(),
|
||||
errmsg("could not read from backend_variables file \"%s\": %m", filename)));
|
||||
return;
|
||||
}
|
||||
|
||||
/* Read vars */
|
||||
read_var(port->sock,fp);
|
||||
read_var(port->proto,fp);
|
||||
read_var(port->laddr,fp);
|
||||
read_var(port->raddr,fp);
|
||||
read_var(port->canAcceptConnections,fp);
|
||||
read_var(MyCancelKey,fp);
|
||||
|
||||
read_var(RedoRecPtr,fp);
|
||||
read_var(LogwrtResult,fp);
|
||||
|
||||
read_var(UsedShmemSegID,fp);
|
||||
read_var(UsedShmemSegAddr,fp);
|
||||
|
||||
read_var(ShmemLock,fp);
|
||||
read_var(ShmemIndexLock,fp);
|
||||
read_var(ShmemVariableCache,fp);
|
||||
read_var(ShmemIndexAlloc,fp);
|
||||
|
||||
read_var(LWLockArray,fp);
|
||||
read_var(ProcStructLock,fp);
|
||||
read_var(pgStatSock,fp);
|
||||
|
||||
/* Release file */
|
||||
FreeFile(fp);
|
||||
if (unlink(filename) != 0)
|
||||
ereport(WARNING,
|
||||
(errcode_for_file_access(),
|
||||
errmsg("could not remove file \"%s\": %m", filename)));
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/storage/buffer/buf_init.c,v 1.59 2003/12/14 00:34:47 neilc Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/storage/buffer/buf_init.c,v 1.60 2003/12/20 17:31:21 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -125,7 +125,9 @@ InitBufferPool(void)
|
||||
* anyone else attached to the shmem at this point, we've got
|
||||
* problems.
|
||||
*/
|
||||
#ifndef EXEC_BACKEND
|
||||
LWLockAcquire(BufMgrLock, LW_EXCLUSIVE);
|
||||
#endif
|
||||
|
||||
BufferDescriptors = (BufferDesc *)
|
||||
ShmemInitStruct("Buffer Descriptors",
|
||||
@ -177,7 +179,9 @@ InitBufferPool(void)
|
||||
/* Init other shared buffer-management stuff */
|
||||
StrategyInitialize(!foundDescs);
|
||||
|
||||
#ifndef EXEC_BACKEND
|
||||
LWLockRelease(BufMgrLock);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -7,7 +7,7 @@
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/storage/file/fd.c,v 1.104 2003/12/12 18:45:09 petere Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/storage/file/fd.c,v 1.105 2003/12/20 17:31:21 momjian Exp $
|
||||
*
|
||||
* NOTES:
|
||||
*
|
||||
@ -53,11 +53,6 @@
|
||||
#include "storage/ipc.h"
|
||||
|
||||
|
||||
/* Filename components for OpenTemporaryFile */
|
||||
#define PG_TEMP_FILES_DIR "pgsql_tmp"
|
||||
#define PG_TEMP_FILE_PREFIX "pgsql_tmp"
|
||||
|
||||
|
||||
/*
|
||||
* Problem: Postgres does a system(ld...) to do dynamic loading.
|
||||
* This will open several extra files in addition to those used by
|
||||
@ -1217,8 +1212,12 @@ RemovePgTempFiles(void)
|
||||
{
|
||||
while ((db_de = readdir(db_dir)) != NULL)
|
||||
{
|
||||
if (strcmp(db_de->d_name, ".") == 0 ||
|
||||
strcmp(db_de->d_name, "..") == 0)
|
||||
if (strcmp(db_de->d_name, ".") == 0
|
||||
#ifndef EXEC_BACKEND
|
||||
/* no PG_TEMP_FILES_DIR in DataDir in non EXEC_BACKEND case */
|
||||
|| strcmp(db_de->d_name, "..") == 0
|
||||
#endif
|
||||
)
|
||||
continue;
|
||||
|
||||
snprintf(temp_path, sizeof(temp_path),
|
||||
|
@ -8,7 +8,7 @@
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/storage/freespace/freespace.c,v 1.27 2003/12/12 18:45:09 petere Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/storage/freespace/freespace.c,v 1.28 2003/12/20 17:31:21 momjian Exp $
|
||||
*
|
||||
*
|
||||
* NOTES:
|
||||
@ -180,7 +180,6 @@ typedef struct FSMRelation FSMRelation;
|
||||
/* Header for whole map */
|
||||
struct FSMHeader
|
||||
{
|
||||
HTAB *relHash; /* hashtable of FSMRelation entries */
|
||||
FSMRelation *usageList; /* FSMRelations in usage-recency order */
|
||||
FSMRelation *usageListTail; /* tail of usage-recency list */
|
||||
FSMRelation *firstRel; /* FSMRelations in arena storage order */
|
||||
@ -218,6 +217,7 @@ int MaxFSMRelations; /* these are set by guc.c */
|
||||
int MaxFSMPages;
|
||||
|
||||
static FSMHeader *FreeSpaceMap; /* points to FSMHeader in shared memory */
|
||||
static HTAB *FreeSpaceMapRelHash; /* points to (what used to be) FSMHeader->relHash */
|
||||
|
||||
|
||||
static FSMRelation *lookup_fsm_rel(RelFileNode *rel);
|
||||
@ -265,13 +265,15 @@ InitFreeSpaceMap(void)
|
||||
{
|
||||
HASHCTL info;
|
||||
int nchunks;
|
||||
bool found;
|
||||
|
||||
/* Create table header */
|
||||
FreeSpaceMap = (FSMHeader *) ShmemAlloc(sizeof(FSMHeader));
|
||||
FreeSpaceMap = (FSMHeader *) ShmemInitStruct("Free Space Map Header",sizeof(FSMHeader),&found);
|
||||
if (FreeSpaceMap == NULL)
|
||||
ereport(FATAL,
|
||||
(errcode(ERRCODE_OUT_OF_MEMORY),
|
||||
errmsg("insufficient shared memory for free space map")));
|
||||
if (!found)
|
||||
MemSet(FreeSpaceMap, 0, sizeof(FSMHeader));
|
||||
|
||||
/* Create hashtable for FSMRelations */
|
||||
@ -279,17 +281,21 @@ InitFreeSpaceMap(void)
|
||||
info.entrysize = sizeof(FSMRelation);
|
||||
info.hash = tag_hash;
|
||||
|
||||
FreeSpaceMap->relHash = ShmemInitHash("Free Space Map Hash",
|
||||
FreeSpaceMapRelHash = ShmemInitHash("Free Space Map Hash",
|
||||
MaxFSMRelations / 10,
|
||||
MaxFSMRelations,
|
||||
&info,
|
||||
(HASH_ELEM | HASH_FUNCTION));
|
||||
|
||||
if (!FreeSpaceMap->relHash)
|
||||
if (!FreeSpaceMapRelHash)
|
||||
ereport(FATAL,
|
||||
(errcode(ERRCODE_OUT_OF_MEMORY),
|
||||
errmsg("insufficient shared memory for free space map")));
|
||||
|
||||
if (found)
|
||||
return;
|
||||
|
||||
|
||||
/* Allocate page-storage arena */
|
||||
nchunks = (MaxFSMPages - 1) / CHUNKPAGES + 1;
|
||||
/* This check ensures spareChunks will be greater than zero */
|
||||
@ -974,7 +980,7 @@ lookup_fsm_rel(RelFileNode *rel)
|
||||
{
|
||||
FSMRelation *fsmrel;
|
||||
|
||||
fsmrel = (FSMRelation *) hash_search(FreeSpaceMap->relHash,
|
||||
fsmrel = (FSMRelation *) hash_search(FreeSpaceMapRelHash,
|
||||
(void *) rel,
|
||||
HASH_FIND,
|
||||
NULL);
|
||||
@ -995,7 +1001,7 @@ create_fsm_rel(RelFileNode *rel)
|
||||
FSMRelation *fsmrel;
|
||||
bool found;
|
||||
|
||||
fsmrel = (FSMRelation *) hash_search(FreeSpaceMap->relHash,
|
||||
fsmrel = (FSMRelation *) hash_search(FreeSpaceMapRelHash,
|
||||
(void *) rel,
|
||||
HASH_ENTER,
|
||||
&found);
|
||||
@ -1050,7 +1056,7 @@ delete_fsm_rel(FSMRelation *fsmrel)
|
||||
unlink_fsm_rel_usage(fsmrel);
|
||||
unlink_fsm_rel_storage(fsmrel);
|
||||
FreeSpaceMap->numRels--;
|
||||
result = (FSMRelation *) hash_search(FreeSpaceMap->relHash,
|
||||
result = (FSMRelation *) hash_search(FreeSpaceMapRelHash,
|
||||
(void *) &(fsmrel->key),
|
||||
HASH_REMOVE,
|
||||
NULL);
|
||||
|
@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/storage/ipc/ipci.c,v 1.59 2003/12/01 21:59:25 momjian Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/storage/ipc/ipci.c,v 1.60 2003/12/20 17:31:21 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -87,7 +87,7 @@ CreateSharedMemoryAndSemaphores(bool makePrivate,
|
||||
/*
|
||||
* Set up shared memory allocation mechanism
|
||||
*/
|
||||
InitShmemAllocation(seghdr);
|
||||
InitShmemAllocation(seghdr, true);
|
||||
|
||||
/*
|
||||
* Now initialize LWLocks, which do shared memory allocation and are
|
||||
@ -135,12 +135,36 @@ CreateSharedMemoryAndSemaphores(bool makePrivate,
|
||||
}
|
||||
|
||||
|
||||
#ifdef EXEC_BACKEND
|
||||
/*
|
||||
* AttachSharedMemoryAndSemaphores
|
||||
* Attaches to the existing shared resources.
|
||||
*/
|
||||
|
||||
/* FIXME: [fork/exec] This function is starting to look pretty much like
|
||||
CreateSharedMemoryAndSemaphores. Refactor? */
|
||||
void
|
||||
AttachSharedMemoryAndSemaphores(void)
|
||||
{
|
||||
PGShmemHeader *seghdr = PGSharedMemoryCreate(-1,false,-1);
|
||||
|
||||
InitShmemAllocation(seghdr, false);
|
||||
|
||||
InitShmemIndex();
|
||||
|
||||
XLOGShmemInit();
|
||||
CLOGShmemInit();
|
||||
InitBufferPool();
|
||||
|
||||
InitLocks();
|
||||
InitLockTable(MaxBackends);
|
||||
|
||||
InitProcGlobal(MaxBackends);
|
||||
|
||||
CreateSharedInvalidationState(MaxBackends);
|
||||
|
||||
InitFreeSpaceMap();
|
||||
|
||||
PMSignalInit();
|
||||
}
|
||||
#endif
|
||||
|
@ -8,7 +8,7 @@
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/storage/ipc/pmsignal.c,v 1.6 2003/11/29 19:51:56 pgsql Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/storage/ipc/pmsignal.c,v 1.7 2003/12/20 17:31:21 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -44,9 +44,11 @@ static volatile sig_atomic_t *PMSignalFlags;
|
||||
void
|
||||
PMSignalInit(void)
|
||||
{
|
||||
bool found;
|
||||
PMSignalFlags = (sig_atomic_t *)
|
||||
ShmemAlloc(NUM_PMSIGNALS * sizeof(sig_atomic_t));
|
||||
ShmemInitStruct("PMSignalFlags",NUM_PMSIGNALS * sizeof(sig_atomic_t),&found);
|
||||
|
||||
if (!found)
|
||||
MemSet(PMSignalFlags, 0, NUM_PMSIGNALS * sizeof(sig_atomic_t));
|
||||
}
|
||||
|
||||
|
@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/storage/ipc/shmem.c,v 1.74 2003/11/29 19:51:56 pgsql Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/storage/ipc/shmem.c,v 1.75 2003/12/20 17:31:21 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -74,7 +74,11 @@ SHMEM_OFFSET ShmemBase; /* start address of shared memory */
|
||||
|
||||
static SHMEM_OFFSET ShmemEnd; /* end+1 address of shared memory */
|
||||
|
||||
static slock_t *ShmemLock; /* spinlock for shared memory allocation */
|
||||
NON_EXEC_STATIC slock_t *ShmemLock; /* spinlock for shared memory 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 */
|
||||
|
||||
@ -88,7 +92,7 @@ static bool ShmemBootstrap = false; /* bootstrapping shmem index? */
|
||||
* but we use void to avoid having to include ipc.h in shmem.h.
|
||||
*/
|
||||
void
|
||||
InitShmemAllocation(void *seghdr)
|
||||
InitShmemAllocation(void *seghdr, bool init)
|
||||
{
|
||||
PGShmemHeader *shmhdr = (PGShmemHeader *) seghdr;
|
||||
|
||||
@ -97,26 +101,34 @@ InitShmemAllocation(void *seghdr)
|
||||
ShmemBase = (SHMEM_OFFSET) shmhdr;
|
||||
ShmemEnd = ShmemBase + shmhdr->totalsize;
|
||||
|
||||
/*
|
||||
* Initialize the spinlock used by ShmemAlloc. 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);
|
||||
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);
|
||||
|
||||
SpinLockInit(ShmemLock);
|
||||
ShmemIndexLock = (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;
|
||||
|
||||
/*
|
||||
* Initialize ShmemVariableCache for transaction manager.
|
||||
*/
|
||||
ShmemVariableCache = (VariableCache)
|
||||
SpinLockInit(ShmemLock);
|
||||
SpinLockInit(ShmemIndexLock);
|
||||
|
||||
/* ShmemIndex can't be set up yet (need LWLocks first) */
|
||||
ShmemIndex = (HTAB *) NULL;
|
||||
|
||||
/*
|
||||
* Initialize ShmemVariableCache for transaction manager.
|
||||
*/
|
||||
ShmemVariableCache = (VariableCache)
|
||||
ShmemAlloc(sizeof(*ShmemVariableCache));
|
||||
memset(ShmemVariableCache, 0, sizeof(*ShmemVariableCache));
|
||||
memset(ShmemVariableCache, 0, sizeof(*ShmemVariableCache));
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@ -218,25 +230,28 @@ InitShmemIndex(void)
|
||||
/*
|
||||
* Now, create an entry in the hashtable for the index itself.
|
||||
*/
|
||||
MemSet(item.key, 0, SHMEM_INDEX_KEYSIZE);
|
||||
strncpy(item.key, "ShmemIndex", SHMEM_INDEX_KEYSIZE);
|
||||
|
||||
result = (ShmemIndexEnt *)
|
||||
hash_search(ShmemIndex, (void *) &item, HASH_ENTER, &found);
|
||||
if (!result)
|
||||
ereport(FATAL,
|
||||
(errcode(ERRCODE_OUT_OF_MEMORY),
|
||||
errmsg("out of shared memory")));
|
||||
|
||||
Assert(ShmemBootstrap && !found);
|
||||
|
||||
result->location = MAKE_OFFSET(ShmemIndex->hctl);
|
||||
result->size = SHMEM_INDEX_SIZE;
|
||||
|
||||
ShmemBootstrap = false;
|
||||
if (!IsUnderPostmaster)
|
||||
{
|
||||
MemSet(item.key, 0, SHMEM_INDEX_KEYSIZE);
|
||||
strncpy(item.key, "ShmemIndex", SHMEM_INDEX_KEYSIZE);
|
||||
|
||||
result = (ShmemIndexEnt *)
|
||||
hash_search(ShmemIndex, (void *) &item, HASH_ENTER, &found);
|
||||
if (!result)
|
||||
ereport(FATAL,
|
||||
(errcode(ERRCODE_OUT_OF_MEMORY),
|
||||
errmsg("out of shared memory")));
|
||||
|
||||
Assert(ShmemBootstrap && !found);
|
||||
|
||||
result->location = MAKE_OFFSET(ShmemIndex->hctl);
|
||||
result->size = SHMEM_INDEX_SIZE;
|
||||
|
||||
ShmemBootstrap = false;
|
||||
}
|
||||
|
||||
/* now release the lock acquired in ShmemInitStruct */
|
||||
LWLockRelease(ShmemIndexLock);
|
||||
SpinLockRelease(ShmemIndexLock);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -320,21 +335,33 @@ ShmemInitStruct(const char *name, Size size, bool *foundPtr)
|
||||
strncpy(item.key, name, SHMEM_INDEX_KEYSIZE);
|
||||
item.location = BAD_LOCATION;
|
||||
|
||||
LWLockAcquire(ShmemIndexLock, LW_EXCLUSIVE);
|
||||
SpinLockAcquire(ShmemIndexLock);
|
||||
|
||||
if (!ShmemIndex)
|
||||
{
|
||||
/*
|
||||
* If the shmem index doesn't exist, we are bootstrapping: we must
|
||||
* be trying to init the shmem index itself.
|
||||
*
|
||||
* Notice that the ShmemIndexLock is held until the shmem index has
|
||||
* been completely initialized.
|
||||
*/
|
||||
Assert(strcmp(name, "ShmemIndex") == 0);
|
||||
Assert(ShmemBootstrap);
|
||||
*foundPtr = FALSE;
|
||||
return ShmemAlloc(size);
|
||||
if (IsUnderPostmaster)
|
||||
{
|
||||
/* Must be initializing a (non-standalone) backend */
|
||||
Assert(strcmp(name, "ShmemIndex") == 0);
|
||||
Assert(ShmemBootstrap);
|
||||
Assert(ShmemIndexAlloc);
|
||||
*foundPtr = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
* If the shmem index doesn't exist, we are bootstrapping: we must
|
||||
* be trying to init the shmem index itself.
|
||||
*
|
||||
* Notice that the ShmemIndexLock is held until the shmem index has
|
||||
* been completely initialized.
|
||||
*/
|
||||
Assert(strcmp(name, "ShmemIndex") == 0);
|
||||
Assert(ShmemBootstrap);
|
||||
*foundPtr = FALSE;
|
||||
ShmemIndexAlloc = ShmemAlloc(size);
|
||||
}
|
||||
return ShmemIndexAlloc;
|
||||
}
|
||||
|
||||
/* look it up in the shmem index */
|
||||
@ -343,7 +370,7 @@ ShmemInitStruct(const char *name, Size size, bool *foundPtr)
|
||||
|
||||
if (!result)
|
||||
{
|
||||
LWLockRelease(ShmemIndexLock);
|
||||
SpinLockRelease(ShmemIndexLock);
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_OUT_OF_MEMORY),
|
||||
errmsg("out of shared memory")));
|
||||
@ -359,7 +386,7 @@ ShmemInitStruct(const char *name, Size size, bool *foundPtr)
|
||||
*/
|
||||
if (result->size != size)
|
||||
{
|
||||
LWLockRelease(ShmemIndexLock);
|
||||
SpinLockRelease(ShmemIndexLock);
|
||||
|
||||
elog(WARNING, "ShmemIndex entry size is wrong");
|
||||
/* let caller print its message too */
|
||||
@ -376,7 +403,7 @@ ShmemInitStruct(const char *name, Size size, bool *foundPtr)
|
||||
/* out of memory */
|
||||
Assert(ShmemIndex);
|
||||
hash_search(ShmemIndex, (void *) &item, HASH_REMOVE, NULL);
|
||||
LWLockRelease(ShmemIndexLock);
|
||||
SpinLockRelease(ShmemIndexLock);
|
||||
|
||||
ereport(WARNING,
|
||||
(errcode(ERRCODE_OUT_OF_MEMORY),
|
||||
@ -389,6 +416,6 @@ ShmemInitStruct(const char *name, Size size, bool *foundPtr)
|
||||
}
|
||||
Assert(ShmemIsValid((unsigned long) structPtr));
|
||||
|
||||
LWLockRelease(ShmemIndexLock);
|
||||
SpinLockRelease(ShmemIndexLock);
|
||||
return structPtr;
|
||||
}
|
||||
|
@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/storage/ipc/sinvaladt.c,v 1.53 2003/11/29 19:51:56 pgsql Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/storage/ipc/sinvaladt.c,v 1.54 2003/12/20 17:31:21 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -50,10 +50,13 @@ SIBufferInit(int maxBackends)
|
||||
int segSize;
|
||||
SISeg *segP;
|
||||
int i;
|
||||
bool found;
|
||||
|
||||
/* Allocate space in shared memory */
|
||||
segSize = SInvalShmemSize(maxBackends);
|
||||
shmInvalBuffer = segP = (SISeg *) ShmemAlloc(segSize);
|
||||
shmInvalBuffer = segP = (SISeg *) ShmemInitStruct("shmInvalBuffer",segSize,&found);
|
||||
if (found)
|
||||
return;
|
||||
|
||||
/* Clear message counters, save size of procState array */
|
||||
segP->minMsgNum = 0;
|
||||
|
@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/storage/lmgr/lock.c,v 1.130 2003/12/01 21:59:25 momjian Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/storage/lmgr/lock.c,v 1.131 2003/12/20 17:31:21 momjian Exp $
|
||||
*
|
||||
* NOTES
|
||||
* Outside modules can create a lock table and acquire/release
|
||||
@ -153,9 +153,11 @@ PROCLOCK_PRINT(const char *where, const PROCLOCK *proclockP)
|
||||
* map from lock method id to the lock table structure
|
||||
*/
|
||||
static LockMethod LockMethods[MAX_LOCK_METHODS];
|
||||
|
||||
static HTAB* LockMethodLockHash[MAX_LOCK_METHODS];
|
||||
static HTAB* LockMethodProcLockHash[MAX_LOCK_METHODS];
|
||||
static int NumLockMethods;
|
||||
|
||||
|
||||
/*
|
||||
* InitLocks -- Init the lock module. Create a private data
|
||||
* structure for constructing conflict masks.
|
||||
@ -245,8 +247,9 @@ LockMethodTableInit(char *tabName,
|
||||
/*
|
||||
* Lock the LWLock for the table (probably not necessary here)
|
||||
*/
|
||||
#ifndef EXEC_BACKEND
|
||||
LWLockAcquire(LockMgrLock, LW_EXCLUSIVE);
|
||||
|
||||
#endif
|
||||
/*
|
||||
* no zero-th table
|
||||
*/
|
||||
@ -279,15 +282,15 @@ LockMethodTableInit(char *tabName,
|
||||
hash_flags = (HASH_ELEM | HASH_FUNCTION);
|
||||
|
||||
sprintf(shmemName, "%s (lock hash)", tabName);
|
||||
newLockMethod->lockHash = ShmemInitHash(shmemName,
|
||||
LockMethodLockHash[NumLockMethods-1] = ShmemInitHash(shmemName,
|
||||
init_table_size,
|
||||
max_table_size,
|
||||
&info,
|
||||
hash_flags);
|
||||
|
||||
if (!newLockMethod->lockHash)
|
||||
if (!LockMethodLockHash[NumLockMethods-1])
|
||||
elog(FATAL, "could not initialize lock table \"%s\"", tabName);
|
||||
Assert(newLockMethod->lockHash->hash == tag_hash);
|
||||
Assert(LockMethodLockHash[NumLockMethods-1]->hash == tag_hash);
|
||||
|
||||
/*
|
||||
* allocate a hash table for PROCLOCK structs. This is used to store
|
||||
@ -299,20 +302,21 @@ LockMethodTableInit(char *tabName,
|
||||
hash_flags = (HASH_ELEM | HASH_FUNCTION);
|
||||
|
||||
sprintf(shmemName, "%s (proclock hash)", tabName);
|
||||
newLockMethod->proclockHash = ShmemInitHash(shmemName,
|
||||
LockMethodProcLockHash[NumLockMethods-1] = ShmemInitHash(shmemName,
|
||||
init_table_size,
|
||||
max_table_size,
|
||||
&info,
|
||||
hash_flags);
|
||||
|
||||
if (!newLockMethod->proclockHash)
|
||||
if (!LockMethodProcLockHash[NumLockMethods-1])
|
||||
elog(FATAL, "could not initialize lock table \"%s\"", tabName);
|
||||
|
||||
/* init data structures */
|
||||
LockMethodInit(newLockMethod, conflictsP, numModes);
|
||||
|
||||
#ifndef EXEC_BACKEND
|
||||
LWLockRelease(LockMgrLock);
|
||||
|
||||
#endif
|
||||
pfree(shmemName);
|
||||
|
||||
return newLockMethod->lockmethodid;
|
||||
@ -449,8 +453,8 @@ LockAcquire(LOCKMETHODID lockmethodid, LOCKTAG *locktag,
|
||||
/*
|
||||
* Find or create a lock with this tag
|
||||
*/
|
||||
Assert(lockMethodTable->lockHash->hash == tag_hash);
|
||||
lock = (LOCK *) hash_search(lockMethodTable->lockHash,
|
||||
Assert(LockMethodLockHash[lockmethodid]->hash == tag_hash);
|
||||
lock = (LOCK *) hash_search(LockMethodLockHash[lockmethodid],
|
||||
(void *) locktag,
|
||||
HASH_ENTER, &found);
|
||||
if (!lock)
|
||||
@ -497,7 +501,7 @@ LockAcquire(LOCKMETHODID lockmethodid, LOCKTAG *locktag,
|
||||
/*
|
||||
* Find or create a proclock entry with this tag
|
||||
*/
|
||||
proclockTable = lockMethodTable->proclockHash;
|
||||
proclockTable = LockMethodProcLockHash[lockmethodid];
|
||||
proclock = (PROCLOCK *) hash_search(proclockTable,
|
||||
(void *) &proclocktag,
|
||||
HASH_ENTER, &found);
|
||||
@ -988,8 +992,8 @@ LockRelease(LOCKMETHODID lockmethodid, LOCKTAG *locktag,
|
||||
/*
|
||||
* Find a lock with this tag
|
||||
*/
|
||||
Assert(lockMethodTable->lockHash->hash == tag_hash);
|
||||
lock = (LOCK *) hash_search(lockMethodTable->lockHash,
|
||||
Assert(LockMethodLockHash[lockmethodid]->hash == tag_hash);
|
||||
lock = (LOCK *) hash_search(LockMethodLockHash[lockmethodid],
|
||||
(void *) locktag,
|
||||
HASH_FIND, NULL);
|
||||
|
||||
@ -1014,7 +1018,7 @@ LockRelease(LOCKMETHODID lockmethodid, LOCKTAG *locktag,
|
||||
proclocktag.proc = MAKE_OFFSET(MyProc);
|
||||
TransactionIdStore(xid, &proclocktag.xid);
|
||||
|
||||
proclockTable = lockMethodTable->proclockHash;
|
||||
proclockTable = LockMethodProcLockHash[lockmethodid];
|
||||
proclock = (PROCLOCK *) hash_search(proclockTable,
|
||||
(void *) &proclocktag,
|
||||
HASH_FIND_SAVE, NULL);
|
||||
@ -1086,8 +1090,8 @@ LockRelease(LOCKMETHODID lockmethodid, LOCKTAG *locktag,
|
||||
* if there's no one waiting in the queue, we just released the
|
||||
* last lock on this object. Delete it from the lock table.
|
||||
*/
|
||||
Assert(lockMethodTable->lockHash->hash == tag_hash);
|
||||
lock = (LOCK *) hash_search(lockMethodTable->lockHash,
|
||||
Assert(LockMethodLockHash[lockmethodid]->hash == tag_hash);
|
||||
lock = (LOCK *) hash_search(LockMethodLockHash[lockmethodid],
|
||||
(void *) &(lock->tag),
|
||||
HASH_REMOVE,
|
||||
NULL);
|
||||
@ -1269,7 +1273,7 @@ LockReleaseAll(LOCKMETHODID lockmethodid, PGPROC *proc,
|
||||
/*
|
||||
* remove the proclock entry from the hashtable
|
||||
*/
|
||||
proclock = (PROCLOCK *) hash_search(lockMethodTable->proclockHash,
|
||||
proclock = (PROCLOCK *) hash_search(LockMethodProcLockHash[lockmethodid],
|
||||
(void *) proclock,
|
||||
HASH_REMOVE,
|
||||
NULL);
|
||||
@ -1287,8 +1291,8 @@ LockReleaseAll(LOCKMETHODID lockmethodid, PGPROC *proc,
|
||||
* lock object.
|
||||
*/
|
||||
LOCK_PRINT("LockReleaseAll: deleting", lock, 0);
|
||||
Assert(lockMethodTable->lockHash->hash == tag_hash);
|
||||
lock = (LOCK *) hash_search(lockMethodTable->lockHash,
|
||||
Assert(LockMethodLockHash[lockmethodid]->hash == tag_hash);
|
||||
lock = (LOCK *) hash_search(LockMethodLockHash[lockmethodid],
|
||||
(void *) &(lock->tag),
|
||||
HASH_REMOVE, NULL);
|
||||
if (!lock)
|
||||
@ -1367,7 +1371,7 @@ GetLockStatusData(void)
|
||||
|
||||
LWLockAcquire(LockMgrLock, LW_EXCLUSIVE);
|
||||
|
||||
proclockTable = LockMethods[DEFAULT_LOCKMETHOD]->proclockHash;
|
||||
proclockTable = LockMethodProcLockHash[DEFAULT_LOCKMETHOD];
|
||||
|
||||
data->nelements = i = proclockTable->hctl->nentries;
|
||||
|
||||
@ -1480,7 +1484,7 @@ DumpAllLocks(void)
|
||||
if (!lockMethodTable)
|
||||
return;
|
||||
|
||||
proclockTable = lockMethodTable->proclockHash;
|
||||
proclockTable = LockMethodProcLockHash[lockmethodid];
|
||||
|
||||
if (proc->waitLock)
|
||||
LOCK_PRINT("DumpAllLocks: waiting on", proc->waitLock, 0);
|
||||
|
@ -15,7 +15,7 @@
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/storage/lmgr/lwlock.c,v 1.18 2003/11/29 19:51:57 pgsql Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/storage/lmgr/lwlock.c,v 1.19 2003/12/20 17:31:21 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -43,7 +43,7 @@ typedef struct LWLock
|
||||
* the pointer by fork from the postmaster. LWLockIds are indexes into
|
||||
* the array.
|
||||
*/
|
||||
static LWLock *LWLockArray = NULL;
|
||||
NON_EXEC_STATIC LWLock *LWLockArray = NULL;
|
||||
|
||||
/* shared counter for dynamic allocation of LWLockIds */
|
||||
static int *LWLockCounter;
|
||||
|
@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/storage/lmgr/proc.c,v 1.140 2003/12/12 18:45:09 petere Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/storage/lmgr/proc.c,v 1.141 2003/12/20 17:31:21 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -66,7 +66,7 @@ PGPROC *MyProc = NULL;
|
||||
* relatively infrequently (only at backend startup or shutdown) and not for
|
||||
* very long, so a spinlock is okay.
|
||||
*/
|
||||
static slock_t *ProcStructLock = NULL;
|
||||
NON_EXEC_STATIC slock_t *ProcStructLock = NULL;
|
||||
|
||||
static PROC_HDR *ProcGlobal = NULL;
|
||||
|
||||
@ -248,6 +248,7 @@ InitProcess(void)
|
||||
MyProc->waitHolder = NULL;
|
||||
SHMQueueInit(&(MyProc->procHolders));
|
||||
|
||||
|
||||
/*
|
||||
* Arrange to clean up at backend exit.
|
||||
*/
|
||||
|
@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/tcop/postgres.c,v 1.379 2003/12/01 22:15:37 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/tcop/postgres.c,v 1.380 2003/12/20 17:31:21 momjian Exp $
|
||||
*
|
||||
* NOTES
|
||||
* this is the "main" module of the postgres backend and
|
||||
@ -68,6 +68,10 @@
|
||||
extern int optind;
|
||||
extern char *optarg;
|
||||
|
||||
#ifdef EXEC_BACKEND
|
||||
extern bool BackendInit(Port*);
|
||||
extern void read_backend_variables(pid_t, Port*);
|
||||
#endif
|
||||
|
||||
/* ----------------
|
||||
* global variables
|
||||
@ -2052,7 +2056,6 @@ PostgresMain(int argc, char *argv[], const char *username)
|
||||
* initialize globals (already done if under postmaster, but not if
|
||||
* standalone; cheap enough to do over)
|
||||
*/
|
||||
|
||||
MyProcPid = getpid();
|
||||
|
||||
/*
|
||||
@ -2060,7 +2063,7 @@ PostgresMain(int argc, char *argv[], const char *username)
|
||||
*
|
||||
* If we are running under the postmaster, this is done already.
|
||||
*/
|
||||
if (!IsUnderPostmaster)
|
||||
if (!IsUnderPostmaster /* when exec || ExecBackend */)
|
||||
MemoryContextInit();
|
||||
|
||||
set_ps_display("startup");
|
||||
@ -2268,7 +2271,6 @@ PostgresMain(int argc, char *argv[], const char *username)
|
||||
break;
|
||||
|
||||
case 'p':
|
||||
|
||||
/*
|
||||
* p - special flag passed if backend was forked by a
|
||||
* postmaster.
|
||||
@ -2276,23 +2278,11 @@ PostgresMain(int argc, char *argv[], const char *username)
|
||||
if (secure)
|
||||
{
|
||||
#ifdef EXEC_BACKEND
|
||||
char *p;
|
||||
int i;
|
||||
int PMcanAcceptConnections; /* will eventually be
|
||||
* global or static,
|
||||
* when fork */
|
||||
|
||||
sscanf(optarg, "%d,%d,%lu,%p,",
|
||||
&MyProcPort->sock, &PMcanAcceptConnections,
|
||||
&UsedShmemSegID, &UsedShmemSegAddr);
|
||||
/* Grab dbname as last param */
|
||||
for (i = 0, p = optarg - 1; i < 4 && p; i++)
|
||||
p = strchr(p + 1, ',');
|
||||
if (i == 4 && p)
|
||||
dbname = strdup(p + 1);
|
||||
IsUnderPostmaster = true;
|
||||
#else
|
||||
dbname = strdup(optarg);
|
||||
#endif
|
||||
|
||||
secure = false; /* subsequent switches are NOT
|
||||
* secure */
|
||||
ctx = PGC_BACKEND;
|
||||
@ -2477,7 +2467,7 @@ PostgresMain(int argc, char *argv[], const char *username)
|
||||
SetConfigOption("log_statement_stats", "false", ctx, gucsource);
|
||||
}
|
||||
|
||||
if (!IsUnderPostmaster)
|
||||
if (!IsUnderPostmaster || ExecBackend)
|
||||
{
|
||||
if (!potential_DataDir)
|
||||
{
|
||||
@ -2497,10 +2487,27 @@ PostgresMain(int argc, char *argv[], const char *username)
|
||||
if (IsUnderPostmaster)
|
||||
{
|
||||
#ifdef EXEC_BACKEND
|
||||
Port *port =(Port*)malloc(sizeof(Port));
|
||||
if (port == NULL)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_OUT_OF_MEMORY),
|
||||
errmsg("insufficient memory to allocate port")));
|
||||
|
||||
read_nondefault_variables();
|
||||
read_backend_variables(getpid(),port);
|
||||
|
||||
/* FIXME: [fork/exec] Ugh */
|
||||
load_hba();
|
||||
load_ident();
|
||||
load_user();
|
||||
load_group();
|
||||
|
||||
if (!BackendInit(port))
|
||||
return -1;
|
||||
|
||||
dbname = port->database_name;
|
||||
#endif
|
||||
}
|
||||
else
|
||||
} else
|
||||
ProcessConfigFile(PGC_POSTMASTER);
|
||||
|
||||
/*
|
||||
@ -2517,7 +2524,6 @@ PostgresMain(int argc, char *argv[], const char *username)
|
||||
* course, this isn't an issue for signals that are locally generated,
|
||||
* such as SIGALRM and SIGPIPE.)
|
||||
*/
|
||||
|
||||
pqsignal(SIGHUP, SigHupHandler); /* set flag to read config file */
|
||||
pqsignal(SIGINT, StatementCancelHandler); /* cancel current query */
|
||||
pqsignal(SIGTERM, die); /* cancel current query and exit */
|
||||
@ -2565,10 +2571,12 @@ PostgresMain(int argc, char *argv[], const char *username)
|
||||
errmsg("invalid command-line arguments for server process"),
|
||||
errhint("Try \"%s --help\" for more information.", argv[0])));
|
||||
}
|
||||
BaseInit();
|
||||
#ifdef EXECBACKEND
|
||||
#ifdef EXEC_BACKEND
|
||||
AttachSharedMemoryAndSemaphores();
|
||||
#endif
|
||||
XLOGPathInit();
|
||||
|
||||
BaseInit();
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -2845,7 +2853,11 @@ PostgresMain(int argc, char *argv[], const char *username)
|
||||
if (got_SIGHUP)
|
||||
{
|
||||
got_SIGHUP = false;
|
||||
#ifdef EXEC_BACKEND
|
||||
read_nondefault_variables();
|
||||
#else
|
||||
ProcessConfigFile(PGC_SIGHUP);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
@ -3199,4 +3211,3 @@ ShowUsage(const char *title)
|
||||
|
||||
pfree(str.data);
|
||||
}
|
||||
|
||||
|
@ -7,7 +7,7 @@
|
||||
* Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $PostgreSQL: pgsql/src/include/access/xlogdefs.h,v 1.10 2003/11/29 22:40:55 pgsql Exp $
|
||||
* $PostgreSQL: pgsql/src/include/access/xlogdefs.h,v 1.11 2003/12/20 17:31:21 momjian Exp $
|
||||
*/
|
||||
#ifndef XLOG_DEFS_H
|
||||
#define XLOG_DEFS_H
|
||||
@ -33,6 +33,13 @@ typedef struct XLogRecPtr
|
||||
uint32 xrecoff; /* byte offset of location in log file */
|
||||
} XLogRecPtr;
|
||||
|
||||
typedef struct XLogwrtResult
|
||||
{
|
||||
XLogRecPtr Write; /* last byte + 1 written out */
|
||||
XLogRecPtr Flush; /* last byte + 1 flushed */
|
||||
} XLogwrtResult;
|
||||
|
||||
|
||||
/*
|
||||
* Macros for comparing XLogRecPtrs
|
||||
*
|
||||
|
@ -12,7 +12,7 @@
|
||||
* Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $PostgreSQL: pgsql/src/include/c.h,v 1.157 2003/11/29 22:40:53 pgsql Exp $
|
||||
* $PostgreSQL: pgsql/src/include/c.h,v 1.158 2003/12/20 17:31:21 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -793,6 +793,13 @@ extern int fdatasync(int fildes);
|
||||
#define HAVE_STRTOULL 1
|
||||
#endif
|
||||
|
||||
/* EXEC_BACKEND defines */
|
||||
#ifdef EXEC_BACKEND
|
||||
#define NON_EXEC_STATIC
|
||||
#else
|
||||
#define NON_EXEC_STATIC static
|
||||
#endif
|
||||
|
||||
/* /port compatibility functions */
|
||||
#include "port.h"
|
||||
|
||||
|
@ -11,7 +11,7 @@
|
||||
* Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $PostgreSQL: pgsql/src/include/libpq/libpq-be.h,v 1.38 2003/11/29 22:41:03 pgsql Exp $
|
||||
* $PostgreSQL: pgsql/src/include/libpq/libpq-be.h,v 1.39 2003/12/20 17:31:21 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -27,6 +27,11 @@
|
||||
#endif
|
||||
|
||||
|
||||
typedef enum CAC_state
|
||||
{
|
||||
CAC_OK, CAC_STARTUP, CAC_SHUTDOWN, CAC_RECOVERY, CAC_TOOMANY
|
||||
} CAC_state;
|
||||
|
||||
/*
|
||||
* This is used by the postmaster in its communication with frontends. It
|
||||
* contains all state information needed during this communication before the
|
||||
@ -42,6 +47,7 @@ typedef struct Port
|
||||
ProtocolVersion proto; /* FE/BE protocol version */
|
||||
SockAddr laddr; /* local addr (postmaster) */
|
||||
SockAddr raddr; /* remote addr (client) */
|
||||
CAC_state canAcceptConnections; /* postmaster connection status */
|
||||
|
||||
/*
|
||||
* Information that needs to be saved from the startup packet and
|
||||
|
@ -7,7 +7,7 @@
|
||||
* Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $PostgreSQL: pgsql/src/include/storage/fd.h,v 1.40 2003/11/29 22:41:13 pgsql Exp $
|
||||
* $PostgreSQL: pgsql/src/include/storage/fd.h,v 1.41 2003/12/20 17:31:21 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -77,4 +77,8 @@ extern void RemovePgTempFiles(void);
|
||||
extern int pg_fsync(int fd);
|
||||
extern int pg_fdatasync(int fd);
|
||||
|
||||
/* Filename components for OpenTemporaryFile */
|
||||
#define PG_TEMP_FILES_DIR "pgsql_tmp"
|
||||
#define PG_TEMP_FILE_PREFIX "pgsql_tmp"
|
||||
|
||||
#endif /* FD_H */
|
||||
|
@ -11,7 +11,7 @@
|
||||
* Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $PostgreSQL: pgsql/src/include/storage/ipc.h,v 1.63 2003/12/12 18:45:10 petere Exp $
|
||||
* $PostgreSQL: pgsql/src/include/storage/ipc.h,v 1.64 2003/12/20 17:31:21 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -32,6 +32,8 @@ extern void on_exit_reset(void);
|
||||
extern void CreateSharedMemoryAndSemaphores(bool makePrivate,
|
||||
int maxBackends,
|
||||
int port);
|
||||
#ifdef EXEC_BACKEND
|
||||
extern void AttachSharedMemoryAndSemaphores(void);
|
||||
#endif
|
||||
|
||||
#endif /* IPC_H */
|
||||
|
@ -7,7 +7,7 @@
|
||||
* Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $PostgreSQL: pgsql/src/include/storage/lock.h,v 1.75 2003/12/01 21:59:25 momjian Exp $
|
||||
* $PostgreSQL: pgsql/src/include/storage/lock.h,v 1.76 2003/12/20 17:31:21 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -86,8 +86,6 @@ typedef uint16 LOCKMETHODID;
|
||||
*/
|
||||
typedef struct LockMethodData
|
||||
{
|
||||
HTAB *lockHash;
|
||||
HTAB *proclockHash;
|
||||
LOCKMETHODID lockmethodid;
|
||||
int numLockModes;
|
||||
LOCKMASK conflictTab[MAX_LOCKMODES];
|
||||
|
@ -7,7 +7,7 @@
|
||||
* Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $PostgreSQL: pgsql/src/include/storage/lwlock.h,v 1.9 2003/11/29 22:41:13 pgsql Exp $
|
||||
* $PostgreSQL: pgsql/src/include/storage/lwlock.h,v 1.10 2003/12/20 17:31:21 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -29,7 +29,6 @@ typedef enum LWLockId
|
||||
LockMgrLock,
|
||||
OidGenLock,
|
||||
XidGenLock,
|
||||
ShmemIndexLock,
|
||||
SInvalLock,
|
||||
FreeSpaceLock,
|
||||
MMCacheLock,
|
||||
|
@ -7,7 +7,7 @@
|
||||
* Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $PostgreSQL: pgsql/src/include/storage/shmem.h,v 1.40 2003/11/29 22:41:13 pgsql Exp $
|
||||
* $PostgreSQL: pgsql/src/include/storage/shmem.h,v 1.41 2003/12/20 17:31:21 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -61,7 +61,7 @@ typedef struct SHM_QUEUE
|
||||
} SHM_QUEUE;
|
||||
|
||||
/* shmem.c */
|
||||
extern void InitShmemAllocation(void *seghdr);
|
||||
extern void InitShmemAllocation(void *seghdr, bool init);
|
||||
extern void *ShmemAlloc(Size size);
|
||||
extern bool ShmemIsValid(unsigned long addr);
|
||||
extern void InitShmemIndex(void);
|
||||
|
Loading…
Reference in New Issue
Block a user