Skip to content

Commit

Permalink
use erts_mem_guard for global literals
Browse files Browse the repository at this point in the history
  • Loading branch information
lucioleKi committed Jul 11, 2024
1 parent 6f11039 commit 9d0aba7
Show file tree
Hide file tree
Showing 3 changed files with 64 additions and 17 deletions.
51 changes: 41 additions & 10 deletions erts/emulator/beam/erl_global_literals.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,12 @@
#include "sys.h"
#include "global.h"
#include "erl_global_literals.h"
#include "erl_mmap.h"


#define GLOBAL_LITERAL_INITIAL_SIZE (1<<16)
#define GLOBAL_LITERAL_EXPAND_SIZE 512

#ifndef DEBUG
# define GLOBAL_LITERAL_INITIAL_SIZE (1<<16)
# define GLOBAL_LITERAL_EXPAND_SIZE 512
#else
# define GLOBAL_LITERAL_INITIAL_SIZE 0
# define GLOBAL_LITERAL_EXPAND_SIZE 0
#endif

/*
* Global Constant Literals
Expand Down Expand Up @@ -89,11 +87,22 @@ ErtsLiteralArea *erts_global_literal_iterate_area(ErtsLiteralArea *prev)

static void expand_shared_global_literal_area(Uint heap_size)
{
const size_t size = sizeof(struct global_literal_chunk) +
(heap_size - 1) * sizeof(Eterm);
struct global_literal_chunk *chunk;

#ifndef DEBUG
chunk = (struct global_literal_chunk *) erts_alloc(ERTS_ALC_T_LITERAL, size);
#else
/* erts_mem_guard requires the memory area to be page aligned. Overallocate
* and align the address to ensure that is the case. */
UWord address;
address = (UWord) erts_alloc(ERTS_ALC_T_LITERAL, size + sys_page_size * 2);
heap_size += address & (sys_page_size - 1);
address = (address + (sys_page_size - 1)) & ~(sys_page_size - 1);
chunk = (struct global_literal_chunk *) address;
#endif

chunk = erts_alloc(ERTS_ALC_T_LITERAL,
sizeof(struct global_literal_chunk) +
(heap_size - 1) * sizeof(Eterm));
chunk->hp = &chunk->area.start[0];
chunk->area.end = &chunk->hp[heap_size];
chunk->area.off_heap = NULL;
Expand All @@ -117,11 +126,33 @@ Eterm *erts_global_literal_allocate(Uint heap_size, struct erl_off_heap_header *
*ohp = &global_literal_chunk->area.off_heap;
hp = global_literal_chunk->hp;
global_literal_chunk->hp += heap_size;

#ifdef DEBUG
{
struct global_literal_chunk *chunk = global_literal_chunk;
erts_mem_guard(&chunk->area.start[0],
(chunk->area.end - &chunk->area.start[0]) * sizeof(Eterm),
1,
1);
}
#endif

return hp;
}

void erts_global_literal_register(Eterm *variable, Eterm *hp, Uint heap_size) {
erts_set_literal_tag(variable, hp, heap_size);

#ifdef DEBUG
{
struct global_literal_chunk *chunk = global_literal_chunk;
erts_mem_guard(&chunk->area.start[0],
(chunk->area.end - &chunk->area.start[0]) * sizeof(Eterm),
1,
0);
}
#endif

erts_mtx_unlock(&global_literal_lock);
}

Expand Down
24 changes: 20 additions & 4 deletions erts/emulator/sys/common/erl_mmap.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,19 +32,35 @@
#include <sys/mman.h>
#endif

int erts_mem_guard(void *p, UWord size) {
int erts_mem_guard(void *p, UWord size, int readable, int writable) {

#if defined(WIN32)
DWORD oldProtect;
DWORD newProtect = PAGE_NOACCESS;
BOOL success;

if (readable && writable) {
newProtect = PAGE_READWRITE;
} else if (readable) {
newProtect = PAGE_READONLY;
} else {
ERTS_INTERNAL_ERROR(!"mem_guard invalid page permissions");
}
success = VirtualProtect((LPVOID*)p,
size,
PAGE_NOACCESS,
newProtect,
&oldProtect);

return success ? 0 : -1;
#elif defined(HAVE_SYS_MMAN_H)
return mprotect(p, size, PROT_NONE);
int flags = 0;

if (writable) {
flags |= PROT_WRITE;
}
if (readable) {
flags |= PROT_READ;
}
return mprotect(p, size, flags);
#else
errno = ENOTSUP;
return -1;
Expand Down
6 changes: 3 additions & 3 deletions erts/emulator/sys/common/erl_mmap.h
Original file line number Diff line number Diff line change
Expand Up @@ -182,10 +182,10 @@ void hard_dbg_remove_mseg(void* seg, UWord sz);

#endif /* HAVE_ERTS_MMAP */

/* Marks the given memory region as permanently inaccessible.
*
/* Changes the permissions of the given memory region.
* Assumes proper page alignment.
* Returns 0 on success, and -1 on error. */
int erts_mem_guard(void *p, UWord size);
int erts_mem_guard(void *p, UWord size, int readable, int writable);

/* Marks the given memory region as unused without freeing it, letting the OS
* reclaim its physical memory with the promise that we'll get it back (without
Expand Down

0 comments on commit 9d0aba7

Please sign in to comment.