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:
@@ -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
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user