summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBen Gamari <ben@smart-cactus.org>2020-11-25 16:18:54 -0500
committerMatthew Pickering <matthewtpickering@gmail.com>2021-03-01 21:12:41 +0000
commitf02fb193bd59862840fa3946a20923298dac0745 (patch)
tree0bb7e6ecb734ee77d90c91d8228d35070606230b
parenta9f23793126251844944e00bca8e84370c759aa7 (diff)
downloadhaskell-f02fb193bd59862840fa3946a20923298dac0745.tar.gz
rts: Add support for hugepages
Co-authored-by: Matthew Pickering <matthewtpickering@gmail.com>
-rw-r--r--includes/rts/Constants.h2
-rw-r--r--includes/rts/Flags.h1
-rw-r--r--rts/RtsFlags.c19
-rw-r--r--rts/posix/OSMem.c24
4 files changed, 38 insertions, 8 deletions
diff --git a/includes/rts/Constants.h b/includes/rts/Constants.h
index 043099bd1a..6efdd977d8 100644
--- a/includes/rts/Constants.h
+++ b/includes/rts/Constants.h
@@ -170,7 +170,7 @@
#define BLOCK_SHIFT 12
/* The size of a megablock (2^MBLOCK_SHIFT bytes) */
-#define MBLOCK_SHIFT 20
+#define MBLOCK_SHIFT 21
/* -----------------------------------------------------------------------------
Bitmap/size fields (used in info tables)
diff --git a/includes/rts/Flags.h b/includes/rts/Flags.h
index 35b45b0940..5b4e29fe3f 100644
--- a/includes/rts/Flags.h
+++ b/includes/rts/Flags.h
@@ -89,6 +89,7 @@ typedef struct _GC_FLAGS {
bool numa; /* Use NUMA */
StgWord numaMask;
+ bool hugepages; /* Enable hugepages support */
} GC_FLAGS;
/* See Note [Synchronization of flags and base APIs] */
diff --git a/rts/RtsFlags.c b/rts/RtsFlags.c
index 380ccc3afc..f86191ed57 100644
--- a/rts/RtsFlags.c
+++ b/rts/RtsFlags.c
@@ -182,6 +182,7 @@ void initRtsFlagsDefaults(void)
RtsFlags.GcFlags.allocLimitGrace = (100*1024) / BLOCK_SIZE;
RtsFlags.GcFlags.numa = false;
RtsFlags.GcFlags.numaMask = 1;
+ RtsFlags.GcFlags.hugepages = false;
RtsFlags.GcFlags.ringBell = false;
RtsFlags.GcFlags.longGCSync = 0; /* detection turned off */
@@ -517,6 +518,7 @@ usage_text[] = {
#endif
" -xq The allocation limit given to a thread after it receives",
" an AllocationLimitExceeded exception. (default: 100k)",
+" -xH Use hugepages to allocate huge",
"",
" -Mgrace=<n>",
" The amount of allocation after the program receives a",
@@ -1698,13 +1700,18 @@ error = true;
*/
case 'q':
- OPTION_UNSAFE;
- RtsFlags.GcFlags.allocLimitGrace
- = decodeSize(rts_argv[arg], 3, BLOCK_SIZE, HS_INT_MAX)
- / BLOCK_SIZE;
- break;
+ OPTION_UNSAFE;
+ RtsFlags.GcFlags.allocLimitGrace
+ = decodeSize(rts_argv[arg], 3, BLOCK_SIZE, HS_INT_MAX)
+ / BLOCK_SIZE;
+ break;
- default:
+ case 'H':
+ OPTION_SAFE;
+ RtsFlags.GcFlags.hugepages = true;
+ break;
+
+ default:
OPTION_SAFE;
errorBelch("unknown RTS option: %s",rts_argv[arg]);
error = true;
diff --git a/rts/posix/OSMem.c b/rts/posix/OSMem.c
index 30d9981f16..53ea69702d 100644
--- a/rts/posix/OSMem.c
+++ b/rts/posix/OSMem.c
@@ -60,6 +60,11 @@
# endif
#endif
+#define HUGEPAGE_SIZE (2*1024*1024)
+// This constant is from linux/mman.h
+#define MAP_HUGE_2MB (21 << MAP_HUGE_SHIFT)
+#define HUGEPAGE_FLAGS MAP_HUGETLB
+
#if !defined(darwin_HOST_OS)
# undef RESERVE_FLAGS
# if defined(MAP_GUARD)
@@ -73,6 +78,9 @@
# endif
#endif
+int huge_tried = 0;
+int huge_failed = 0;
+
static void *next_request = 0;
void osMemInit(void)
@@ -233,12 +241,24 @@ my_mmap (void *addr, W_ size, int operation)
errorBelch("my_mmap(,,MEM_RESERVE) not supported on this platform");
# endif
} else if (operation == MEM_COMMIT) {
- flags = MAP_FIXED | MAP_ANON | MAP_PRIVATE;
+ flags = MAP_FIXED | MAP_ANONYMOUS | MAP_PRIVATE;
+ if ( RtsFlags.GcFlags.hugepages &&
+ (size & (HUGEPAGE_SIZE - 1)) == 0) {
+ huge_tried += 1;
+ flags |= HUGEPAGE_FLAGS;
+ }
} else {
flags = MAP_ANON | MAP_PRIVATE;
}
ret = mmap(addr, size, prot, flags, -1, 0);
+ // If the mmap failed, and we tried with HUGEPAGE_FLAGS
+ // then retry without.
+ if (ret == MAP_FAILED && flags & HUGEPAGE_FLAGS){
+ huge_failed += 1;
+ flags &= ~HUGEPAGE_FLAGS;
+ ret = mmap(addr, size, prot, flags, -1, 0);
+ }
# if defined(linux_HOST_OS)
if (ret == MAP_FAILED && errno == EPERM) {
// Linux may return EPERM if it tried to give us
@@ -472,6 +492,7 @@ void setExecutable (void *p, W_ len, bool exec)
#if defined(USE_LARGE_ADDRESS_SPACE)
+
static void *
osTryReserveHeapMemory (W_ len, void *hint)
{
@@ -485,6 +506,7 @@ osTryReserveHeapMemory (W_ len, void *hint)
and then we discard what we don't need */
base = my_mmap(hint, len + MBLOCK_SIZE, MEM_RESERVE);
+
if (base == NULL)
return NULL;