aboutsummaryrefslogtreecommitdiffstats
path: root/erts/emulator/sys/common
diff options
context:
space:
mode:
authorSverker Eriksson <[email protected]>2016-04-12 20:41:58 +0200
committerSverker Eriksson <[email protected]>2016-04-15 19:02:49 +0200
commit85a6623152988c267cea008d20616b61ea9c223c (patch)
treec83b93cb1ca5e3f396c62bd4cb7f723d97c9221e /erts/emulator/sys/common
parent90641d82a4b07e6b0be142d07ac85107b8ebee9d (diff)
downloadotp-85a6623152988c267cea008d20616b61ea9c223c.tar.gz
otp-85a6623152988c267cea008d20616b61ea9c223c.tar.bz2
otp-85a6623152988c267cea008d20616b61ea9c223c.zip
erts: Add 'exec_alloc' for hipe code
that uses its own super carrier (erts_exec_mmapper) to guarantee low addressed and executable memory (PROT_EXEC). Currently only used on x86_64 that needs low memory for HiPE/AMD64's small code model. By initializing erts_exec_mapper early we secure its low memory area before erts_literal_mmapper might steal it.
Diffstat (limited to 'erts/emulator/sys/common')
-rw-r--r--erts/emulator/sys/common/erl_mmap.c45
-rw-r--r--erts/emulator/sys/common/erl_mmap.h16
-rw-r--r--erts/emulator/sys/common/erl_mseg.c7
-rw-r--r--erts/emulator/sys/common/erl_mseg.h4
4 files changed, 64 insertions, 8 deletions
diff --git a/erts/emulator/sys/common/erl_mmap.c b/erts/emulator/sys/common/erl_mmap.c
index f5f40b35a8..38970bd24e 100644
--- a/erts/emulator/sys/common/erl_mmap.c
+++ b/erts/emulator/sys/common/erl_mmap.c
@@ -356,6 +356,12 @@ char* erts_literals_start;
UWord erts_literals_size;
#endif
+#ifdef ERTS_ALC_A_EXEC
+ErtsMemMapper erts_exec_mmapper;
+#endif
+
+
+
#define ERTS_MMAP_SIZE_SC_SA_INC(SZ) \
do { \
mm->size.supercarrier.used.total += (SZ); \
@@ -1351,10 +1357,39 @@ os_unreserve_physical(char *ptr, UWord size)
}
static void *
-os_mmap_virtual(char *ptr, UWord size)
+os_mmap_virtual(char *ptr, UWord size, int exec)
{
- void *res = mmap((void *) ptr, (size_t) size, ERTS_MMAP_VIRTUAL_PROT,
- ERTS_MMAP_VIRTUAL_FLAGS, ERTS_MMAP_FD, 0);
+ int flags = ERTS_MMAP_VIRTUAL_FLAGS;
+ void* res;
+
+#ifdef ERTS_ALC_A_EXEC
+ if (exec) {
+ ASSERT(!ptr);
+ /* OTP-19.0: Nice hack below cut-and-pasted from hipe_amd64.c */
+
+# ifdef MAP_32BIT
+ /* If we got MAP_32BIT (Linux), then use that to ask for low memory */
+ flags |= MAP_32BIT;
+# else
+ /* FreeBSD doesn't have MAP_32BIT, and it doesn't respect
+ a plain map_hint (returns high mappings even though the
+ hint refers to a free area), so we have to use both map_hint
+ and MAP_FIXED to get addresses below the 2GB boundary.
+ This is even worse than the Linux/ppc64 case.
+ Similarly, Solaris 10 doesn't have MAP_32BIT,
+ and it doesn't respect a plain map_hint. */
+ ptr = (char*)(512*1024*1024); /* 0.5GB */
+
+# if defined(__FreeBSD__) || defined(__sun__)
+ flags |= MAP_FIXED;
+# endif
+# endif /* !MAP_32BIT */
+ }
+#else /* !ERTS_ALC_A_EXEC */
+ ASSERT(!exec);
+#endif
+ res = mmap((void *) ptr, (size_t) size, ERTS_MMAP_VIRTUAL_PROT,
+ flags, ERTS_MMAP_FD, 0);
if (res == (void *) MAP_FAILED)
return NULL;
return res;
@@ -2177,7 +2212,7 @@ erts_mmap_init(ErtsMemMapper* mm, ErtsMMapInit *init, int executable)
ptr = (char *) ERTS_PAGEALIGNED_CEILING(init->virtual_range.start);
end = (char *) ERTS_PAGEALIGNED_FLOOR(init->virtual_range.end);
sz = end - ptr;
- start = os_mmap_virtual(ptr, sz);
+ start = os_mmap_virtual(ptr, sz, executable);
if (!start || start > ptr || start >= end)
erts_exit(1,
"erts_mmap: Failed to create virtual range for super carrier\n");
@@ -2202,7 +2237,7 @@ erts_mmap_init(ErtsMemMapper* mm, ErtsMMapInit *init, int executable)
sz = ERTS_PAGEALIGNED_CEILING(init->scs);
#ifdef ERTS_HAVE_OS_PHYSICAL_MEMORY_RESERVATION
if (!init->scrpm) {
- start = os_mmap_virtual(NULL, sz);
+ start = os_mmap_virtual(NULL, sz, executable);
mm->reserve_physical = os_reserve_physical;
mm->unreserve_physical = os_unreserve_physical;
virtual_map = 1;
diff --git a/erts/emulator/sys/common/erl_mmap.h b/erts/emulator/sys/common/erl_mmap.h
index 30548bd0b0..8a7530d943 100644
--- a/erts/emulator/sys/common/erl_mmap.h
+++ b/erts/emulator/sys/common/erl_mmap.h
@@ -55,6 +55,11 @@ typedef struct {
#define ERTS_MMAP_INIT_LITERAL_INITER \
{{NULL, NULL}, {NULL, NULL}, ERTS_LITERAL_VIRTUAL_AREA_SIZE, 1, (1 << 10), 0}
+#define ERTS_HIPE_EXEC_VIRTUAL_AREA_SIZE (UWORD_CONSTANT(512)*1024*1024)
+
+#define ERTS_MMAP_INIT_HIPE_EXEC_INITER \
+ {{NULL, NULL}, {NULL, NULL}, ERTS_HIPE_EXEC_VIRTUAL_AREA_SIZE, 1, (1 << 10), 0}
+
typedef struct ErtsMemMapper_ ErtsMemMapper;
void *erts_mmap(ErtsMemMapper*, Uint32 flags, UWord *sizep);
@@ -126,10 +131,17 @@ Eterm erts_mmap_debug_info(ErtsMemMapper*, struct process*);
# define ERTS_HAVE_OS_MMAP 1
#endif
+#ifdef ERTS_WANT_MEM_MAPPERS
+# include "erl_alloc_types.h"
+
extern ErtsMemMapper erts_dflt_mmapper;
-#if defined(ARCH_64) && defined(ERTS_HAVE_OS_PHYSICAL_MEMORY_RESERVATION)
+# if defined(ARCH_64) && defined(ERTS_HAVE_OS_PHYSICAL_MEMORY_RESERVATION)
extern ErtsMemMapper erts_literal_mmapper;
-#endif
+# endif
+# ifdef ERTS_ALC_A_EXEC
+extern ErtsMemMapper erts_exec_mmapper;
+# endif
+#endif /* ERTS_WANT_MEM_MAPPERS */
/*#define HARD_DEBUG_MSEG*/
#ifdef HARD_DEBUG_MSEG
diff --git a/erts/emulator/sys/common/erl_mseg.c b/erts/emulator/sys/common/erl_mseg.c
index f0fbb682b0..f373302e65 100644
--- a/erts/emulator/sys/common/erl_mseg.c
+++ b/erts/emulator/sys/common/erl_mseg.c
@@ -31,6 +31,7 @@
# include "config.h"
#endif
+#define ERTS_WANT_MEM_MAPPERS
#include "sys.h"
#include "erl_mseg.h"
#include "global.h"
@@ -1402,6 +1403,12 @@ erts_mseg_init(ErtsMsegInit_t *init)
erts_mtx_init(&init_atoms_mutex, "mseg_init_atoms");
+#ifdef ERTS_ALC_A_EXEC
+ /* Initialize erts_exec_mapper *FIRST*, to increase probability
+ * of getting low memory for HiPE AMD64's small code model.
+ */
+ erts_mmap_init(&erts_exec_mmapper, &init->exec_mmap, 1);
+#endif
erts_mmap_init(&erts_dflt_mmapper, &init->dflt_mmap, 0);
#if defined(ARCH_64) && defined(ERTS_HAVE_OS_PHYSICAL_MEMORY_RESERVATION)
erts_mmap_init(&erts_literal_mmapper, &init->literal_mmap, 0);
diff --git a/erts/emulator/sys/common/erl_mseg.h b/erts/emulator/sys/common/erl_mseg.h
index 2acd8f8505..556a135798 100644
--- a/erts/emulator/sys/common/erl_mseg.h
+++ b/erts/emulator/sys/common/erl_mseg.h
@@ -61,6 +61,7 @@ typedef struct {
Uint nos;
ErtsMMapInit dflt_mmap;
ErtsMMapInit literal_mmap;
+ ErtsMMapInit exec_mmap;
} ErtsMsegInit_t;
#define ERTS_MSEG_INIT_DEFAULT_INITIALIZER \
@@ -70,7 +71,8 @@ typedef struct {
10, /* mcs: Max cache size */ \
1000, /* cci: Cache check interval */ \
ERTS_MMAP_INIT_DEFAULT_INITER, \
- ERTS_MMAP_INIT_LITERAL_INITER \
+ ERTS_MMAP_INIT_LITERAL_INITER, \
+ ERTS_MMAP_INIT_HIPE_EXEC_INITER \
}
typedef struct {