Skip to content

Commit

Permalink
fix JuliaLang#11646 on OS X
Browse files Browse the repository at this point in the history
rather than checking if the memory is "in core" (loaded in physical memory), use msync to determine if the page address was valid/mapped for our process
  • Loading branch information
vtjnash committed Jun 12, 2015
1 parent cb9e614 commit 22ecc91
Show file tree
Hide file tree
Showing 2 changed files with 13 additions and 18 deletions.
15 changes: 6 additions & 9 deletions src/gc.c
Original file line number Diff line number Diff line change
Expand Up @@ -66,8 +66,6 @@ static GC_Num gc_num = {0,0,0,0,0,0,0,0,0,0,0,0};
#define total_allocd_bytes gc_num.total_allocd
#define allocd_bytes_since_sweep gc_num.since_sweep

static long system_page_size;

// malloc wrappers, aligned allocation

#if defined(_P64) || defined(__APPLE__)
Expand Down Expand Up @@ -672,7 +670,7 @@ static NOINLINE void *malloc_page(void)
#ifdef _OS_WINDOWS_
char* mem = (char*)VirtualAlloc(NULL, sizeof(region_t) + GC_PAGE_SZ, MEM_RESERVE, PAGE_READWRITE);
#else
if (GC_PAGE_SZ > system_page_size)
if (GC_PAGE_SZ > jl_page_size)
alloc_size += GC_PAGE_SZ;
char* mem = (char*)mmap(0, alloc_size, PROT_READ | PROT_WRITE, MAP_NORESERVE | MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
mem = mem == MAP_FAILED ? NULL : mem;
Expand All @@ -681,7 +679,7 @@ static NOINLINE void *malloc_page(void)
jl_printf(JL_STDERR, "could not allocate pools\n");
abort();
}
if (GC_PAGE_SZ > system_page_size) {
if (GC_PAGE_SZ > jl_page_size) {
// round data pointer up to the nearest GC_PAGE_DATA-aligned boundary
// if mmap didn't already do so
alloc_size += GC_PAGE_SZ;
Expand Down Expand Up @@ -751,11 +749,11 @@ static void free_page(void *p)
free(region->meta[pg_idx].ages);
// tell the OS we don't need these pages right now
size_t decommit_size = GC_PAGE_SZ;
if (GC_PAGE_SZ < system_page_size) {
if (GC_PAGE_SZ < jl_page_size) {
// ensure so we don't release more memory than intended
size_t n_pages = (GC_PAGE_SZ + system_page_size - 1) / GC_PAGE_SZ;
decommit_size = system_page_size;
p = (void*)((uintptr_t)&region->pages[pg_idx][0] & ~(system_page_size - 1)); // round down to the nearest page
size_t n_pages = (GC_PAGE_SZ + jl_page_size - 1) / GC_PAGE_SZ;
decommit_size = jl_page_size;
p = (void*)((uintptr_t)&region->pages[pg_idx][0] & ~(jl_page_size - 1)); // round down to the nearest page
pg_idx = PAGE_INDEX(region, (char*)p+GC_PAGE_OFFSET);
if (pg_idx + n_pages > REGION_PG_COUNT) goto no_decommit;
for (; n_pages--; pg_idx++) {
Expand Down Expand Up @@ -2546,7 +2544,6 @@ static void jl_mk_thread_heap(void) {
// System-wide initializations
void jl_gc_init(void)
{
system_page_size = jl_getpagesize();
jl_mk_thread_heap();

arraylist_new(&finalizer_list, 0);
Expand Down
16 changes: 7 additions & 9 deletions src/init.c
Original file line number Diff line number Diff line change
Expand Up @@ -291,7 +291,7 @@ void segv_handler(int sig, siginfo_t *info, void *context)
jl_throw(jl_memory_exception);
}
#ifdef SEGV_EXCEPTION
else {
else if (sig == SIGSEGV) {
sigemptyset(&sset);
sigaddset(&sset, SIGSEGV);
sigprocmask(SIG_UNBLOCK, &sset, NULL);
Expand Down Expand Up @@ -757,14 +757,12 @@ void *mach_segv_listener(void *arg)
}

#ifdef SEGV_EXCEPTION

void darwin_segv_handler(unw_context_t *uc)
{
bt_size = rec_backtrace_ctx(bt_data, MAX_BT_SIZE, uc);
jl_exception_in_transit = jl_segv_exception;
jl_rethrow();
}

#endif

void darwin_stack_overflow_handler(unw_context_t *uc)
Expand Down Expand Up @@ -822,8 +820,7 @@ kern_return_t catch_exception_raise(mach_port_t exception_port,
#ifdef SEGV_EXCEPTION
if (1) {
#else
if (is_addr_on_stack((void*)fault_addr) ||
((exc_state.__err & PAGE_PRESENT) == PAGE_PRESENT)) {
if (msync((void*)(fault_addr & ~(jl_page_size - 1)), 1, MS_ASYNC) == 0) { // check if this was a valid address
#endif
ret = thread_get_state(thread,x86_THREAD_STATE64,(thread_state_t)&state,&count);
HANDLE_MACH_ERROR("thread_get_state(2)",ret);
Expand All @@ -845,14 +842,14 @@ kern_return_t catch_exception_raise(mach_port_t exception_port,
memset(uc,0,sizeof(unw_context_t));
memcpy(uc,&old_state,sizeof(x86_thread_state64_t));
state.__rdi = (uint64_t)uc;
if ((exc_state.__err & PAGE_PRESENT) == PAGE_PRESENT)
state.__rip = (uint64_t)darwin_accerr_handler;
if (is_addr_on_stack((void*)fault_addr))
state.__rip = (uint64_t)darwin_stack_overflow_handler;
#ifdef SEGV_EXCEPTION
else if (!is_addr_on_stack((void*)fault_addr))
else if (msync((void*)(fault_addr & ~(jl_page_size - 1)), 1, MS_ASYNC) != 0)
state.__rip = (uint64_t)darwin_segv_handler;
#endif
else
state.__rip = (uint64_t)darwin_stack_overflow_handler;
state.__rip = (uint64_t)darwin_accerr_handler;

state.__rbp = state.__rsp;
ret = thread_set_state(thread,x86_THREAD_STATE64,(thread_state_t)&state,count);
Expand Down Expand Up @@ -987,6 +984,7 @@ static void jl_resolve_sysimg_location(JL_IMAGE_SEARCH rel)
void attach_exception_port()
{
kern_return_t ret;
// http:https://www.opensource.apple.com/source/xnu/xnu-2782.1.97/osfmk/man/thread_set_exception_ports.html
ret = thread_set_exception_ports(mach_thread_self(),EXC_MASK_BAD_ACCESS,segv_port,EXCEPTION_DEFAULT,MACHINE_THREAD_STATE);
HANDLE_MACH_ERROR("thread_set_exception_ports",ret);
}
Expand Down

0 comments on commit 22ecc91

Please sign in to comment.