Skip to content

Commit 6066aa5

Browse files
erthalionCommitfest Bot
authored andcommitted
Allow to use multiple shared memory mappings
Currently all the work with shared memory is done via a single anonymous memory mapping, which limits ways how the shared memory could be organized. Introduce possibility to allocate multiple shared memory mappings, where a single mapping is associated with a specified shared memory segment. There is only fixed amount of available segments, currently only one main shared memory segment is allocated. A new shared memory API is introduces, extended with a segment as a new parameter. As a path of least resistance, the original API is kept in place, utilizing the main shared memory segment.
1 parent 11274f1 commit 6066aa5

File tree

12 files changed

+283
-128
lines changed

12 files changed

+283
-128
lines changed

src/backend/port/posix_sema.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -193,7 +193,7 @@ PGSemaphoreShmemSize(int maxSemas)
193193
* we don't have to expose the counters to other processes.)
194194
*/
195195
void
196-
PGReserveSemaphores(int maxSemas)
196+
PGReserveSemaphores(int maxSemas, int shmem_segment)
197197
{
198198
struct stat statbuf;
199199

@@ -220,7 +220,7 @@ PGReserveSemaphores(int maxSemas)
220220
* ShmemAlloc() won't be ready yet.
221221
*/
222222
sharedSemas = (PGSemaphore)
223-
ShmemAllocUnlocked(PGSemaphoreShmemSize(maxSemas));
223+
ShmemAllocUnlockedInSegment(PGSemaphoreShmemSize(maxSemas), shmem_segment);
224224
#endif
225225

226226
numSems = 0;

src/backend/port/sysv_sema.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -327,7 +327,7 @@ PGSemaphoreShmemSize(int maxSemas)
327327
* have clobbered.)
328328
*/
329329
void
330-
PGReserveSemaphores(int maxSemas)
330+
PGReserveSemaphores(int maxSemas, int shmem_segment)
331331
{
332332
struct stat statbuf;
333333

@@ -348,7 +348,7 @@ PGReserveSemaphores(int maxSemas)
348348
* ShmemAlloc() won't be ready yet.
349349
*/
350350
sharedSemas = (PGSemaphore)
351-
ShmemAllocUnlocked(PGSemaphoreShmemSize(maxSemas));
351+
ShmemAllocUnlockedInSegment(PGSemaphoreShmemSize(maxSemas), shmem_segment);
352352
numSharedSemas = 0;
353353
maxSharedSemas = maxSemas;
354354

src/backend/port/sysv_shmem.c

Lines changed: 95 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -94,8 +94,19 @@ typedef enum
9494
unsigned long UsedShmemSegID = 0;
9595
void *UsedShmemSegAddr = NULL;
9696

97-
static Size AnonymousShmemSize;
98-
static void *AnonymousShmem = NULL;
97+
typedef struct AnonymousMapping
98+
{
99+
int shmem_segment;
100+
Size shmem_size; /* Size of the mapping */
101+
Pointer shmem; /* Pointer to the start of the mapped memory */
102+
Pointer seg_addr; /* SysV shared memory for the header */
103+
unsigned long seg_id; /* IPC key */
104+
} AnonymousMapping;
105+
106+
static AnonymousMapping Mappings[ANON_MAPPINGS];
107+
108+
/* Keeps track of used mapping segments */
109+
static int next_free_segment = 0;
99110

100111
static void *InternalIpcMemoryCreate(IpcMemoryKey memKey, Size size);
101112
static void IpcMemoryDetach(int status, Datum shmaddr);
@@ -104,6 +115,28 @@ static IpcMemoryState PGSharedMemoryAttach(IpcMemoryId shmId,
104115
void *attachAt,
105116
PGShmemHeader **addr);
106117

118+
static const char*
119+
MappingName(int shmem_segment)
120+
{
121+
switch (shmem_segment)
122+
{
123+
case MAIN_SHMEM_SEGMENT:
124+
return "main";
125+
default:
126+
return "unknown";
127+
}
128+
}
129+
130+
static void
131+
DebugMappings()
132+
{
133+
for(int i = 0; i < next_free_segment; i++)
134+
{
135+
AnonymousMapping m = Mappings[i];
136+
elog(DEBUG1, "Mapping[%s]: addr %p, size %zu",
137+
MappingName(i), m.shmem, m.shmem_size);
138+
}
139+
}
107140

108141
/*
109142
* InternalIpcMemoryCreate(memKey, size)
@@ -591,14 +624,13 @@ check_huge_page_size(int *newval, void **extra, GucSource source)
591624
/*
592625
* Creates an anonymous mmap()ed shared memory segment.
593626
*
594-
* Pass the requested size in *size. This function will modify *size to the
595-
* actual size of the allocation, if it ends up allocating a segment that is
596-
* larger than requested.
627+
* This function will modify mapping size to the actual size of the allocation,
628+
* if it ends up allocating a segment that is larger than requested.
597629
*/
598-
static void *
599-
CreateAnonymousSegment(Size *size)
630+
static void
631+
CreateAnonymousSegment(AnonymousMapping *mapping)
600632
{
601-
Size allocsize = *size;
633+
Size allocsize = mapping->shmem_size;
602634
void *ptr = MAP_FAILED;
603635
int mmap_errno = 0;
604636

@@ -623,8 +655,11 @@ CreateAnonymousSegment(Size *size)
623655
PG_MMAP_FLAGS | mmap_flags, -1, 0);
624656
mmap_errno = errno;
625657
if (huge_pages == HUGE_PAGES_TRY && ptr == MAP_FAILED)
626-
elog(DEBUG1, "mmap(%zu) with MAP_HUGETLB failed, huge pages disabled: %m",
627-
allocsize);
658+
{
659+
DebugMappings();
660+
elog(DEBUG1, "segment[%s]: mmap(%zu) with MAP_HUGETLB failed, huge pages disabled: %m",
661+
MappingName(mapping->shmem_segment), allocsize);
662+
}
628663
}
629664
#endif
630665

@@ -642,7 +677,7 @@ CreateAnonymousSegment(Size *size)
642677
* Use the original size, not the rounded-up value, when falling back
643678
* to non-huge pages.
644679
*/
645-
allocsize = *size;
680+
allocsize = mapping->shmem_size;
646681
ptr = mmap(NULL, allocsize, PROT_READ | PROT_WRITE,
647682
PG_MMAP_FLAGS, -1, 0);
648683
mmap_errno = errno;
@@ -651,8 +686,10 @@ CreateAnonymousSegment(Size *size)
651686
if (ptr == MAP_FAILED)
652687
{
653688
errno = mmap_errno;
689+
DebugMappings();
654690
ereport(FATAL,
655-
(errmsg("could not map anonymous shared memory: %m"),
691+
(errmsg("segment[%s]: could not map anonymous shared memory: %m",
692+
MappingName(mapping->shmem_segment)),
656693
(mmap_errno == ENOMEM) ?
657694
errhint("This error usually means that PostgreSQL's request "
658695
"for a shared memory segment exceeded available memory, "
@@ -663,8 +700,8 @@ CreateAnonymousSegment(Size *size)
663700
allocsize) : 0));
664701
}
665702

666-
*size = allocsize;
667-
return ptr;
703+
mapping->shmem = ptr;
704+
mapping->shmem_size = allocsize;
668705
}
669706

670707
/*
@@ -674,13 +711,18 @@ CreateAnonymousSegment(Size *size)
674711
static void
675712
AnonymousShmemDetach(int status, Datum arg)
676713
{
677-
/* Release anonymous shared memory block, if any. */
678-
if (AnonymousShmem != NULL)
714+
for(int i = 0; i < next_free_segment; i++)
679715
{
680-
if (munmap(AnonymousShmem, AnonymousShmemSize) < 0)
681-
elog(LOG, "munmap(%p, %zu) failed: %m",
682-
AnonymousShmem, AnonymousShmemSize);
683-
AnonymousShmem = NULL;
716+
AnonymousMapping m = Mappings[i];
717+
718+
/* Release anonymous shared memory block, if any. */
719+
if (m.shmem != NULL)
720+
{
721+
if (munmap(m.shmem, m.shmem_size) < 0)
722+
elog(LOG, "munmap(%p, %zu) failed: %m",
723+
m.shmem, m.shmem_size);
724+
m.shmem = NULL;
725+
}
684726
}
685727
}
686728

@@ -705,6 +747,7 @@ PGSharedMemoryCreate(Size size,
705747
PGShmemHeader *hdr;
706748
struct stat statbuf;
707749
Size sysvsize;
750+
AnonymousMapping *mapping = &Mappings[next_free_segment];
708751

709752
/*
710753
* We use the data directory's ID info (inode and device numbers) to
@@ -733,11 +776,15 @@ PGSharedMemoryCreate(Size size,
733776

734777
/* Room for a header? */
735778
Assert(size > MAXALIGN(sizeof(PGShmemHeader)));
779+
mapping->shmem_size = size;
780+
mapping->shmem_segment = next_free_segment;
736781

737782
if (shared_memory_type == SHMEM_TYPE_MMAP)
738783
{
739-
AnonymousShmem = CreateAnonymousSegment(&size);
740-
AnonymousShmemSize = size;
784+
/* On success, mapping data will be modified. */
785+
CreateAnonymousSegment(mapping);
786+
787+
next_free_segment++;
741788

742789
/* Register on-exit routine to unmap the anonymous segment */
743790
on_shmem_exit(AnonymousShmemDetach, (Datum) 0);
@@ -760,7 +807,7 @@ PGSharedMemoryCreate(Size size,
760807
* loop simultaneously. (CreateDataDirLockFile() does not entirely ensure
761808
* that, but prefer fixing it over coping here.)
762809
*/
763-
NextShmemSegID = statbuf.st_ino;
810+
NextShmemSegID = statbuf.st_ino + next_free_segment;
764811

765812
for (;;)
766813
{
@@ -852,24 +899,24 @@ PGSharedMemoryCreate(Size size,
852899
/*
853900
* Initialize space allocation status for segment.
854901
*/
855-
hdr->totalsize = size;
902+
hdr->totalsize = mapping->shmem_size;
856903
hdr->freeoffset = MAXALIGN(sizeof(PGShmemHeader));
857904
*shim = hdr;
858905

859906
/* Save info for possible future use */
860-
UsedShmemSegAddr = memAddress;
861-
UsedShmemSegID = (unsigned long) NextShmemSegID;
907+
mapping->seg_addr = memAddress;
908+
mapping->seg_id = (unsigned long) NextShmemSegID;
862909

863910
/*
864911
* If AnonymousShmem is NULL here, then we're not using anonymous shared
865912
* memory, and should return a pointer to the System V shared memory
866913
* block. Otherwise, the System V shared memory block is only a shim, and
867914
* we must return a pointer to the real block.
868915
*/
869-
if (AnonymousShmem == NULL)
916+
if (mapping->shmem == NULL)
870917
return hdr;
871-
memcpy(AnonymousShmem, hdr, sizeof(PGShmemHeader));
872-
return (PGShmemHeader *) AnonymousShmem;
918+
memcpy(mapping->shmem, hdr, sizeof(PGShmemHeader));
919+
return (PGShmemHeader *) mapping->shmem;
873920
}
874921

875922
#ifdef EXEC_BACKEND
@@ -969,23 +1016,28 @@ PGSharedMemoryNoReAttach(void)
9691016
void
9701017
PGSharedMemoryDetach(void)
9711018
{
972-
if (UsedShmemSegAddr != NULL)
1019+
for(int i = 0; i < next_free_segment; i++)
9731020
{
974-
if ((shmdt(UsedShmemSegAddr) < 0)
1021+
AnonymousMapping m = Mappings[i];
1022+
1023+
if (m.seg_addr != NULL)
1024+
{
1025+
if ((shmdt(m.seg_addr) < 0)
9751026
#if defined(EXEC_BACKEND) && defined(__CYGWIN__)
976-
/* Work-around for cygipc exec bug */
977-
&& shmdt(NULL) < 0
1027+
/* Work-around for cygipc exec bug */
1028+
&& shmdt(NULL) < 0
9781029
#endif
979-
)
980-
elog(LOG, "shmdt(%p) failed: %m", UsedShmemSegAddr);
981-
UsedShmemSegAddr = NULL;
982-
}
1030+
)
1031+
elog(LOG, "shmdt(%p) failed: %m", m.seg_addr);
1032+
m.seg_addr = NULL;
1033+
}
9831034

984-
if (AnonymousShmem != NULL)
985-
{
986-
if (munmap(AnonymousShmem, AnonymousShmemSize) < 0)
987-
elog(LOG, "munmap(%p, %zu) failed: %m",
988-
AnonymousShmem, AnonymousShmemSize);
989-
AnonymousShmem = NULL;
1035+
if (m.shmem != NULL)
1036+
{
1037+
if (munmap(m.shmem, m.shmem_size) < 0)
1038+
elog(LOG, "munmap(%p, %zu) failed: %m",
1039+
m.shmem, m.shmem_size);
1040+
m.shmem = NULL;
1041+
}
9901042
}
9911043
}

src/backend/port/win32_sema.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ PGSemaphoreShmemSize(int maxSemas)
4444
* process exits.
4545
*/
4646
void
47-
PGReserveSemaphores(int maxSemas)
47+
PGReserveSemaphores(int maxSemas, int shmem_segment)
4848
{
4949
mySemSet = (HANDLE *) malloc(maxSemas * sizeof(HANDLE));
5050
if (mySemSet == NULL)

src/backend/storage/ipc/ipc.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,14 +61,16 @@ static void proc_exit_prepare(int code);
6161
* but provide some additional features we need --- in particular,
6262
* we want to register callbacks to invoke when we are disconnecting
6363
* from a broken shared-memory context but not exiting the postmaster.
64+
* Maximum number of such exit callbacks depends on the number of shared
65+
* segments.
6466
*
6567
* Callback functions can take zero, one, or two args: the first passed
6668
* arg is the integer exitcode, the second is the Datum supplied when
6769
* the callback was registered.
6870
* ----------------------------------------------------------------
6971
*/
7072

71-
#define MAX_ON_EXITS 20
73+
#define MAX_ON_EXITS 40
7274

7375
struct ONEXIT
7476
{

src/backend/storage/ipc/ipci.c

Lines changed: 34 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ RequestAddinShmemSpace(Size size)
8686
* required.
8787
*/
8888
Size
89-
CalculateShmemSize(int *num_semaphores)
89+
CalculateShmemSize(int *num_semaphores, int shmem_segment)
9090
{
9191
Size size;
9292
int numSemas;
@@ -206,33 +206,38 @@ CreateSharedMemoryAndSemaphores(void)
206206

207207
Assert(!IsUnderPostmaster);
208208

209-
/* Compute the size of the shared-memory block */
210-
size = CalculateShmemSize(&numSemas);
211-
elog(DEBUG3, "invoking IpcMemoryCreate(size=%zu)", size);
212-
213-
/*
214-
* Create the shmem segment
215-
*/
216-
seghdr = PGSharedMemoryCreate(size, &shim);
217-
218-
/*
219-
* Make sure that huge pages are never reported as "unknown" while the
220-
* server is running.
221-
*/
222-
Assert(strcmp("unknown",
223-
GetConfigOption("huge_pages_status", false, false)) != 0);
224-
225-
InitShmemAccess(seghdr);
226-
227-
/*
228-
* Create semaphores
229-
*/
230-
PGReserveSemaphores(numSemas);
231-
232-
/*
233-
* Set up shared memory allocation mechanism
234-
*/
235-
InitShmemAllocation();
209+
for(int segment = 0; segment < ANON_MAPPINGS; segment++)
210+
{
211+
/* Compute the size of the shared-memory block */
212+
size = CalculateShmemSize(&numSemas, segment);
213+
elog(DEBUG3, "invoking IpcMemoryCreate(size=%zu)", size);
214+
215+
/*
216+
* Create the shmem segment.
217+
*
218+
* XXX: Do multiple shims are needed, one per segment?
219+
*/
220+
seghdr = PGSharedMemoryCreate(size, &shim);
221+
222+
/*
223+
* Make sure that huge pages are never reported as "unknown" while the
224+
* server is running.
225+
*/
226+
Assert(strcmp("unknown",
227+
GetConfigOption("huge_pages_status", false, false)) != 0);
228+
229+
InitShmemAccessInSegment(seghdr, segment);
230+
231+
/*
232+
* Create semaphores
233+
*/
234+
PGReserveSemaphores(numSemas, segment);
235+
236+
/*
237+
* Set up shared memory allocation mechanism
238+
*/
239+
InitShmemAllocationInSegment(segment);
240+
}
236241

237242
/* Initialize subsystems */
238243
CreateOrAttachShmemStructs();
@@ -363,7 +368,7 @@ InitializeShmemGUCs(void)
363368
/*
364369
* Calculate the shared memory size and round up to the nearest megabyte.
365370
*/
366-
size_b = CalculateShmemSize(&num_semas);
371+
size_b = CalculateShmemSize(&num_semas, MAIN_SHMEM_SEGMENT);
367372
size_mb = add_size(size_b, (1024 * 1024) - 1) / (1024 * 1024);
368373
sprintf(buf, "%zu", size_mb);
369374
SetConfigOption("shared_memory_size", buf,

0 commit comments

Comments
 (0)