1
0
mirror of https://github.com/postgres/postgres.git synced 2025-11-16 15:02:33 +03:00

Convert the arithmetic for shared memory size calculation from 'int'

to 'Size' (that is, size_t), and install overflow detection checks in it.
This allows us to remove the former arbitrary restrictions on NBuffers
etc.  It won't make any difference in a 32-bit machine, but in a 64-bit
machine you could theoretically have terabytes of shared buffers.
(How efficiently we could manage 'em remains to be seen.)  Similarly,
num_temp_buffers, work_mem, and maintenance_work_mem can be set above
2Gb on a 64-bit machine.  Original patch from Koichi Suzuki, additional
work by moi.
This commit is contained in:
Tom Lane
2005-08-20 23:26:37 +00:00
parent 2299ceab1c
commit 0007490e09
50 changed files with 774 additions and 275 deletions

View File

@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/storage/ipc/ipci.c,v 1.77 2005/06/17 22:32:45 tgl Exp $
* $PostgreSQL: pgsql/src/backend/storage/ipc/ipci.c,v 1.78 2005/08/20 23:26:20 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -61,36 +61,44 @@ CreateSharedMemoryAndSemaphores(bool makePrivate, int port)
if (!IsUnderPostmaster)
{
int size;
Size size;
int numSemas;
/*
* Size of the Postgres shared-memory block is estimated via
* moderately-accurate estimates for the big hogs, plus 100K for
* the stuff that's too small to bother with estimating.
*
* We take some care during this phase to ensure that the total
* size request doesn't overflow size_t. If this gets through,
* we don't need to be so careful during the actual allocation
* phase.
*/
size = hash_estimate_size(SHMEM_INDEX_SIZE, sizeof(ShmemIndexEnt));
size += BufferShmemSize();
size += LockShmemSize();
size += ProcGlobalShmemSize();
size += XLOGShmemSize();
size += CLOGShmemSize();
size += SUBTRANSShmemSize();
size += TwoPhaseShmemSize();
size += MultiXactShmemSize();
size += LWLockShmemSize();
size += ProcArrayShmemSize();
size += SInvalShmemSize(MaxBackends);
size += FreeSpaceShmemSize();
size += BgWriterShmemSize();
size = 100000;
size = add_size(size, hash_estimate_size(SHMEM_INDEX_SIZE,
sizeof(ShmemIndexEnt)));
size = add_size(size, BufferShmemSize());
size = add_size(size, LockShmemSize());
size = add_size(size, ProcGlobalShmemSize());
size = add_size(size, XLOGShmemSize());
size = add_size(size, CLOGShmemSize());
size = add_size(size, SUBTRANSShmemSize());
size = add_size(size, TwoPhaseShmemSize());
size = add_size(size, MultiXactShmemSize());
size = add_size(size, LWLockShmemSize());
size = add_size(size, ProcArrayShmemSize());
size = add_size(size, SInvalShmemSize());
size = add_size(size, FreeSpaceShmemSize());
size = add_size(size, BgWriterShmemSize());
#ifdef EXEC_BACKEND
size += ShmemBackendArraySize();
size = add_size(size, ShmemBackendArraySize());
#endif
size += 100000;
/* might as well round it off to a multiple of a typical page size */
size += 8192 - (size % 8192);
elog(DEBUG3, "invoking IpcMemoryCreate(size=%d)", size);
/* might as well round it off to a multiple of a typical page size */
size = add_size(size, 8192 - (size % 8192));
elog(DEBUG3, "invoking IpcMemoryCreate(size=%lu)",
(unsigned long) size);
/*
* Create the shmem segment
@@ -163,7 +171,7 @@ CreateSharedMemoryAndSemaphores(bool makePrivate, int port)
/*
* Set up shared-inval messaging
*/
CreateSharedInvalidationState(MaxBackends);
CreateSharedInvalidationState();
/*
* Set up free-space map

View File

@@ -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.18 2004/12/31 22:00:56 pgsql Exp $
* $PostgreSQL: pgsql/src/backend/storage/ipc/pmsignal.c,v 1.19 2005/08/20 23:26:20 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -48,7 +48,9 @@ PMSignalInit(void)
bool found;
PMSignalFlags = (sig_atomic_t *)
ShmemInitStruct("PMSignalFlags", NUM_PMSIGNALS * sizeof(sig_atomic_t), &found);
ShmemInitStruct("PMSignalFlags",
NUM_PMSIGNALS * sizeof(sig_atomic_t),
&found);
if (!found)
MemSet(PMSignalFlags, 0, NUM_PMSIGNALS * sizeof(sig_atomic_t));

View File

@@ -23,7 +23,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/storage/ipc/procarray.c,v 1.5 2005/08/20 01:26:36 ishii Exp $
* $PostgreSQL: pgsql/src/backend/storage/ipc/procarray.c,v 1.6 2005/08/20 23:26:20 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -81,11 +81,16 @@ static void DisplayXidCache(void);
/*
* Report shared-memory space needed by CreateSharedProcArray.
*/
int
Size
ProcArrayShmemSize(void)
{
return MAXALIGN(offsetof(ProcArrayStruct, procs) +
(MaxBackends + max_prepared_xacts) * sizeof(PGPROC *));
Size size;
size = offsetof(ProcArrayStruct, procs);
size = add_size(size, mul_size(sizeof(PGPROC *),
add_size(MaxBackends, max_prepared_xacts)));
return size;
}
/*

View File

@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/storage/ipc/shmem.c,v 1.84 2005/05/29 04:23:04 tgl Exp $
* $PostgreSQL: pgsql/src/backend/storage/ipc/shmem.c,v 1.85 2005/08/20 23:26:20 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -141,8 +141,8 @@ InitShmemAllocation(void *seghdr, bool init)
void *
ShmemAlloc(Size size)
{
uint32 newStart;
uint32 newFree;
Size newStart;
Size newFree;
void *newSpace;
/* use volatile pointer to prevent code rearrangement */
@@ -415,3 +415,40 @@ ShmemInitStruct(const char *name, Size size, bool *foundPtr)
SpinLockRelease(ShmemIndexLock);
return structPtr;
}
/*
* Add two Size values, checking for overflow
*/
Size
add_size(Size s1, Size s2)
{
Size result;
result = s1 + s2;
/* We are assuming Size is an unsigned type here... */
if (result < s1 || result < s2)
ereport(ERROR,
(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
errmsg("requested shared memory size overflows size_t")));
return result;
}
/*
* Multiply two Size values, checking for overflow
*/
Size
mul_size(Size s1, Size s2)
{
Size result;
if (s1 == 0 || s2 == 0)
return 0;
result = s1 * s2;
/* We are assuming Size is an unsigned type here... */
if (result / s2 != s1)
ereport(ERROR,
(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
errmsg("requested shared memory size overflows size_t")));
return result;
}

View File

@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/storage/ipc/sinval.c,v 1.76 2005/05/19 21:35:46 tgl Exp $
* $PostgreSQL: pgsql/src/backend/storage/ipc/sinval.c,v 1.77 2005/08/20 23:26:21 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -55,10 +55,10 @@ static void ProcessCatchupEvent(void);
/* should be called only by the POSTMASTER */
/****************************************************************************/
void
CreateSharedInvalidationState(int maxBackends)
CreateSharedInvalidationState(void)
{
/* SInvalLock must be initialized already, during LWLock init */
SIBufferInit(maxBackends);
SIBufferInit();
}
/*

View File

@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/storage/ipc/sinvaladt.c,v 1.59 2005/05/19 21:35:46 tgl Exp $
* $PostgreSQL: pgsql/src/backend/storage/ipc/sinvaladt.c,v 1.60 2005/08/20 23:26:21 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -32,14 +32,15 @@ static void SISetProcStateInvalid(SISeg *segP);
/*
* SInvalShmemSize --- return shared-memory space needed
*/
int
SInvalShmemSize(int maxBackends)
Size
SInvalShmemSize(void)
{
/*
* Figure space needed. Note sizeof(SISeg) includes the first
* ProcState entry.
*/
return sizeof(SISeg) + sizeof(ProcState) * (maxBackends - 1);
Size size;
size = offsetof(SISeg, procState);
size = add_size(size, mul_size(sizeof(ProcState), MaxBackends));
return size;
}
/*
@@ -47,16 +48,15 @@ SInvalShmemSize(int maxBackends)
* Create and initialize a new SI message buffer
*/
void
SIBufferInit(int maxBackends)
SIBufferInit(void)
{
int segSize;
SISeg *segP;
int i;
bool found;
/* Allocate space in shared memory */
segSize = SInvalShmemSize(maxBackends);
shmInvalBuffer = segP = (SISeg *) ShmemInitStruct("shmInvalBuffer", segSize, &found);
shmInvalBuffer = segP = (SISeg *)
ShmemInitStruct("shmInvalBuffer", SInvalShmemSize(), &found);
if (found)
return;
@@ -64,13 +64,13 @@ SIBufferInit(int maxBackends)
segP->minMsgNum = 0;
segP->maxMsgNum = 0;
segP->lastBackend = 0;
segP->maxBackends = maxBackends;
segP->freeBackends = maxBackends;
segP->maxBackends = MaxBackends;
segP->freeBackends = MaxBackends;
/* The buffer[] array is initially all unused, so we need not fill it */
/* Mark all backends inactive */
for (i = 0; i < maxBackends; i++)
for (i = 0; i < segP->maxBackends; i++)
{
segP->procState[i].nextMsgNum = -1; /* inactive */
segP->procState[i].resetState = false;