Skip to content

Commit

Permalink
Merge pull request #14501 from JuliaLang/yyc/stack_rng
Browse files Browse the repository at this point in the history
Don't use pthread_*_np functions to get stack master thread
  • Loading branch information
yuyichao committed Dec 30, 2015
2 parents 6bf6f35 + 426d5ac commit 01c701f
Show file tree
Hide file tree
Showing 5 changed files with 64 additions and 50 deletions.
85 changes: 44 additions & 41 deletions src/init.c
Original file line number Diff line number Diff line change
Expand Up @@ -88,46 +88,10 @@ jl_options_t jl_options = { 0, // quiet
int jl_boot_file_loaded = 0;
size_t jl_page_size;

void jl_init_stack_limits(void)
void jl_init_stack_limits(int ismaster)
{
#if defined(_OS_LINUX_)
pthread_attr_t attr;
if (pthread_getattr_np(pthread_self(), &attr)) {
// On linux `pthread_getattr_np` can fail on master thread if
// `/proc/self/maps` is not readable, in which case we fall back to
// `rlimit`
struct rlimit rl;
getrlimit(RLIMIT_STACK, &rl);
jl_stack_hi = (char*)&attr;
jl_stack_lo = jl_stack_hi - rl.rlim_cur;
}
else {
void *stackaddr;
size_t stacksize;
pthread_attr_getstack(&attr, &stackaddr, &stacksize);
pthread_attr_destroy(&attr);
jl_stack_lo = (char*)stackaddr;
jl_stack_hi = (char*)stackaddr + stacksize;
}
#elif defined(_OS_DARWIN_)
extern void *pthread_get_stackaddr_np(pthread_t thread);
extern size_t pthread_get_stacksize_np(pthread_t thread);
pthread_t thread = pthread_self();
void *stackaddr = pthread_get_stackaddr_np(thread);
size_t stacksize = pthread_get_stacksize_np(thread);
jl_stack_lo = (char*)stackaddr;
jl_stack_hi = (char*)stackaddr + stacksize;
#elif defined(_OS_FREEBSD_)
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_attr_get_np(pthread_self(), &attr);
void *stackaddr;
size_t stacksize;
pthread_attr_getstack(&attr, &stackaddr, &stacksize);
pthread_attr_destroy(&attr);
jl_stack_lo = (char*)stackaddr;
jl_stack_hi = (char*)stackaddr + stacksize;
#elif defined(_OS_WINDOWS_)
#ifdef _OS_WINDOWS_
(void)ismaster;
# ifdef _COMPILER_MICROSOFT_
# ifdef _P64
void **tib = (void**)__readgsqword(0x30);
Expand All @@ -147,7 +111,46 @@ void jl_init_stack_limits(void)
jl_stack_lo = (char*)tib[2]; // Stack Limit / Ceiling of stack (low address)
#else
# ifdef JULIA_ENABLE_THREADING
# warning "Getting stack size for thread is not supported."
// Only use pthread_*_np functions to get stack address for non-master
// threads since it seems to return bogus values for master thread on Linux
// and possibly OSX.
if (!ismaster) {
# if defined(_OS_LINUX_)
pthread_attr_t attr;
pthread_getattr_np(pthread_self(), &attr);
void *stackaddr;
size_t stacksize;
pthread_attr_getstack(&attr, &stackaddr, &stacksize);
pthread_attr_destroy(&attr);
jl_stack_lo = (char*)stackaddr;
jl_stack_hi = (char*)stackaddr + stacksize;
return;
# elif defined(_OS_DARWIN_)
extern void *pthread_get_stackaddr_np(pthread_t thread);
extern size_t pthread_get_stacksize_np(pthread_t thread);
pthread_t thread = pthread_self();
void *stackaddr = pthread_get_stackaddr_np(thread);
size_t stacksize = pthread_get_stacksize_np(thread);
jl_stack_lo = (char*)stackaddr;
jl_stack_hi = (char*)stackaddr + stacksize;
return;
# elif defined(_OS_FREEBSD_)
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_attr_get_np(pthread_self(), &attr);
void *stackaddr;
size_t stacksize;
pthread_attr_getstack(&attr, &stackaddr, &stacksize);
pthread_attr_destroy(&attr);
jl_stack_lo = (char*)stackaddr;
jl_stack_hi = (char*)stackaddr + stacksize;
return;
# else
# warning "Getting stack size for thread is not supported."
# endif
}
# else
(void)ismaster;
# endif
struct rlimit rl;
getrlimit(RLIMIT_STACK, &rl);
Expand Down Expand Up @@ -180,7 +183,7 @@ static void jl_find_stack_bottom(void)
}
#endif
#endif
jl_init_stack_limits();
jl_init_stack_limits(1);
}

struct uv_shutdown_queue_item { uv_handle_t *h; struct uv_shutdown_queue_item *next; };
Expand Down
2 changes: 1 addition & 1 deletion src/julia_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -228,7 +228,7 @@ void jl_init_primitives(void);
void jl_init_codegen(void);
void jl_init_intrinsic_functions(void);
void jl_init_tasks(void);
void jl_init_stack_limits(void);
void jl_init_stack_limits(int ismaster);
void jl_init_root_task(void *stack, size_t ssize);
void jl_init_serializer(void);
void jl_gc_init(void);
Expand Down
13 changes: 12 additions & 1 deletion src/signals-mach.c
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,17 @@ kern_return_t catch_exception_raise(mach_port_t exception_port,
if (thread == mach_profiler_thread) {
return profiler_segv_handler(exception_port, thread, task, exception, code, code_count);
}
#endif
#ifdef JULIA_ENABLE_THREADING
jl_tls_states_t *ptls = NULL;
for (int16_t tid = 0;tid < jl_n_threads;tid++) {
if (pthread_mach_thread_np(jl_all_task_states[tid].system_id) == thread) {
ptls = jl_all_task_states[tid].ptls;
break;
}
}
#else
jl_tls_states_t *ptls = &jl_tls_states;
#endif
kern_return_t ret = thread_get_state(thread, x86_EXCEPTION_STATE64, (thread_state_t)&exc_state, &exc_count);
HANDLE_MACH_ERROR("thread_get_state", ret);
Expand All @@ -126,7 +137,7 @@ kern_return_t catch_exception_raise(mach_port_t exception_port,
if (msync((void*)(fault_addr & ~(jl_page_size - 1)), 1, MS_ASYNC) == 0) { // check if this was a valid address
#endif
jl_value_t *excpt;
if (is_addr_on_stack((void*)fault_addr)) {
if (is_addr_on_stack(ptls, (void*)fault_addr)) {
excpt = jl_stackovf_exception;
}
#ifdef SEGV_EXCEPTION
Expand Down
12 changes: 6 additions & 6 deletions src/signals-unix.c
Original file line number Diff line number Diff line change
Expand Up @@ -35,14 +35,14 @@ unsigned sig_stack_size = SIGSTKSZ;
static pthread_t signals_thread;
static volatile int remote_sig;

static int is_addr_on_stack(void *addr)
static int is_addr_on_stack(jl_tls_states_t *ptls, void *addr)
{
#ifdef COPY_STACKS
return ((char*)addr > (char*)jl_stack_lo-3000000 &&
(char*)addr < (char*)jl_stack_hi);
return ((char*)addr > (char*)ptls->stack_lo-3000000 &&
(char*)addr < (char*)ptls->stack_hi);
#else
return ((char*)addr > (char*)jl_current_task->stkbuf &&
(char*)addr < (char*)jl_current_task->stkbuf + jl_current_task->ssize);
return ((char*)addr > (char*)ptls->current_task->stkbuf &&
(char*)addr < (char*)ptls->current_task->stkbuf + ptls->current_task->ssize);
#endif
}

Expand Down Expand Up @@ -75,7 +75,7 @@ static void segv_handler(int sig, siginfo_t *info, void *context)
sigset_t sset;
assert(sig == SIGSEGV);

if (jl_in_jl_ || is_addr_on_stack(info->si_addr)) { // stack overflow, or restarting jl_
if (jl_in_jl_ || is_addr_on_stack(jl_get_ptls_states(), info->si_addr)) { // stack overflow, or restarting jl_
sigemptyset(&sset);
sigaddset(&sset, SIGSEGV);
sigprocmask(SIG_UNBLOCK, &sset, NULL);
Expand Down
2 changes: 1 addition & 1 deletion src/threading.c
Original file line number Diff line number Diff line change
Expand Up @@ -216,7 +216,7 @@ void ti_threadfun(void *arg)

// initialize this thread (set tid, create heap, etc.)
ti_initthread(ta->tid);
jl_init_stack_limits();
jl_init_stack_limits(0);

// set up tasking
jl_init_root_task(jl_stack_lo, jl_stack_hi - jl_stack_lo);
Expand Down

0 comments on commit 01c701f

Please sign in to comment.