From 6010e5bc8c1574a982d4cec2cc323f972f553071 Mon Sep 17 00:00:00 2001
From: Nathan Bossart <bossartn@amazon.com>
Date: Mon, 6 Sep 2021 18:04:59 +0000
Subject: [PATCH v6 2/3] Introduce huge_pages_required GUC.

This runtime-computed GUC shows the number of huge pages required
for the server's main shared memory area.  Like shared_memory_size,
it cannot be viewed with 'postgres -C' yet.
---
 doc/src/sgml/config.sgml       | 21 +++++++++++++++++++++
 src/backend/port/sysv_shmem.c  |  2 +-
 src/backend/storage/ipc/ipci.c | 20 ++++++++++++++++++++
 src/backend/utils/misc/guc.c   | 12 ++++++++++++
 src/include/storage/pg_shmem.h |  4 ++++
 5 files changed, 58 insertions(+), 1 deletion(-)

diff --git a/doc/src/sgml/config.sgml b/doc/src/sgml/config.sgml
index ef0e2a7746..b27d8aff15 100644
--- a/doc/src/sgml/config.sgml
+++ b/doc/src/sgml/config.sgml
@@ -10101,6 +10101,27 @@ dynamic_library_path = 'C:\tools\postgresql;H:\my_project\lib;$libdir'
       </listitem>
      </varlistentry>
 
+     <varlistentry id="guc-huge-pages-required" xreflabel="huge_pages_required">
+      <term><varname>huge_pages_required</varname> (<type>integer</type>)
+      <indexterm>
+       <primary><varname>huge_pages_required</varname> configuration parameter</primary>
+      </indexterm>
+      </term>
+      <listitem>
+       <para>
+        Reports the number of huge pages that are required for the main
+        shared memory area based on the specified
+        <xref linkend="guc-huge-page-size"/>.  If huge pages are not supported,
+        this will be <literal>-1</literal>.
+       </para>
+       <para>
+        This setting is supported only on Linux.  It is always set to
+        <literal>-1</literal> on other platforms.  For more details about using
+        huge pages on Linux, see <xref linkend="linux-huge-pages"/>.
+       </para>
+      </listitem>
+     </varlistentry>
+
      <varlistentry id="guc-integer-datetimes" xreflabel="integer_datetimes">
       <term><varname>integer_datetimes</varname> (<type>boolean</type>)
       <indexterm>
diff --git a/src/backend/port/sysv_shmem.c b/src/backend/port/sysv_shmem.c
index 9de96edf6a..f42f1ac171 100644
--- a/src/backend/port/sysv_shmem.c
+++ b/src/backend/port/sysv_shmem.c
@@ -478,7 +478,7 @@ PGSharedMemoryAttach(IpcMemoryId shmId,
  * Returns the (real, assumed or config provided) page size into *hugepagesize,
  * and the hugepage-related mmap flags to use into *mmap_flags.
  */
-static void
+void
 GetHugePageSize(Size *hugepagesize, int *mmap_flags)
 {
 	Size		default_hugepagesize = 0;
diff --git a/src/backend/storage/ipc/ipci.c b/src/backend/storage/ipc/ipci.c
index 614b8e92c4..e5f94f9e69 100644
--- a/src/backend/storage/ipc/ipci.c
+++ b/src/backend/storage/ipc/ipci.c
@@ -14,6 +14,10 @@
  */
 #include "postgres.h"
 
+#ifndef WIN32
+#include <sys/mman.h>
+#endif
+
 #include "access/clog.h"
 #include "access/commit_ts.h"
 #include "access/heapam.h"
@@ -326,6 +330,11 @@ InitializeShmemGUCs(void)
 	char	buf[64];
 	Size	size_b;
 	Size	size_mb;
+#if defined(MAP_HUGETLB)
+	Size	hp_size;
+	Size	hp_required;
+	int		unused;
+#endif
 
 	/*
 	 * Calculate the shared memory size and round up to the nearest
@@ -336,4 +345,15 @@ InitializeShmemGUCs(void)
 
 	sprintf(buf, "%lu MB", size_mb);
 	SetConfigOption("shared_memory_size", buf, PGC_INTERNAL, PGC_S_OVERRIDE);
+
+#if defined(MAP_HUGETLB)
+
+	/* Calculate the number of huge pages required */
+	GetHugePageSize(&hp_size, &unused);
+	hp_required = (size_b / hp_size) + 1;
+
+	sprintf(buf, "%lu", hp_required);
+	SetConfigOption("huge_pages_required", buf, PGC_INTERNAL, PGC_S_OVERRIDE);
+
+#endif
 }
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index a11387c5ce..1a30d635fc 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -621,6 +621,7 @@ char	   *pgstat_temp_directory;
 char	   *application_name;
 
 int			shmem_size_mb;
+int			huge_pages_required;
 
 int			tcp_keepalives_idle;
 int			tcp_keepalives_interval;
@@ -2225,6 +2226,17 @@ static struct config_int ConfigureNamesInt[] =
 		NULL, NULL, NULL
 	},
 
+	{
+		{"huge_pages_required", PGC_INTERNAL, RESOURCES_MEM,
+			gettext_noop("Shows the number of huge pages needed for the main shared memory area."),
+			gettext_noop("-1 indicates that the value could not be determined."),
+			GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE
+		},
+		&huge_pages_required,
+		-1, -1, INT_MAX,
+		NULL, NULL, NULL
+	},
+
 	{
 		/* This is PGC_SUSET to prevent hiding from log_lock_waits. */
 		{"deadlock_timeout", PGC_SUSET, LOCK_MANAGEMENT,
diff --git a/src/include/storage/pg_shmem.h b/src/include/storage/pg_shmem.h
index 059df1b72c..c44403ed6a 100644
--- a/src/include/storage/pg_shmem.h
+++ b/src/include/storage/pg_shmem.h
@@ -88,4 +88,8 @@ extern PGShmemHeader *PGSharedMemoryCreate(Size size,
 extern bool PGSharedMemoryIsInUse(unsigned long id1, unsigned long id2);
 extern void PGSharedMemoryDetach(void);
 
+#ifdef MAP_HUGETLB
+extern void GetHugePageSize(Size *hugepagesize, int *mmap_flags);
+#endif
+
 #endif							/* PG_SHMEM_H */
-- 
2.16.6

