static int get_stack(void **addr, size_t *size) { #define CHECK_ERR(expr) \ {int err = (expr); if (err) return err;} #if defined HAVE_PTHREAD_GETATTR_NP || defined HAVE_PTHREAD_ATTR_GET_NP pthread_attr_t attr; size_t guard = 0; # ifdef HAVE_PTHREAD_GETATTR_NP CHECK_ERR(pthread_getattr_np(pthread_self(), &attr)); # ifdef HAVE_PTHREAD_ATTR_GETSTACK CHECK_ERR(pthread_attr_getstack(&attr, addr, size)); # else CHECK_ERR(pthread_attr_getstackaddr(&attr, addr)); CHECK_ERR(pthread_attr_getstacksize(&attr, size)); # endif if (pthread_attr_getguardsize(&attr, &guard) == 0) { STACK_GROW_DIR_DETECTION; STACK_DIR_UPPER((void)0, (void)(*addr = (char *)*addr + guard)); *size -= guard; } # else CHECK_ERR(pthread_attr_init(&attr)); CHECK_ERR(pthread_attr_get_np(pthread_self(), &attr)); CHECK_ERR(pthread_attr_getstackaddr(&attr, addr)); CHECK_ERR(pthread_attr_getstacksize(&attr, size)); # endif CHECK_ERR(pthread_attr_getguardsize(&attr, &guard)); *size -= guard; # ifndef HAVE_PTHREAD_GETATTR_NP pthread_attr_destroy(&attr); # endif #elif defined HAVE_PTHREAD_GET_STACKADDR_NP && defined HAVE_PTHREAD_GET_STACKSIZE_NP pthread_t th = pthread_self(); *addr = pthread_get_stackaddr_np(th); *size = pthread_get_stacksize_np(th); #elif defined HAVE_THR_STKSEGMENT || defined HAVE_PTHREAD_STACKSEG_NP stack_t stk; # if defined HAVE_THR_STKSEGMENT CHECK_ERR(thr_stksegment(&stk)); # else CHECK_ERR(pthread_stackseg_np(pthread_self(), &stk)); # endif *addr = stk.ss_sp; *size = stk.ss_size; #elif defined HAVE_PTHREAD_GETTHRDS_NP pthread_t th = pthread_self(); struct __pthrdsinfo thinfo; char reg[256]; int regsiz=sizeof(reg); CHECK_ERR(pthread_getthrds_np(&th, PTHRDSINFO_QUERY_ALL, &thinfo, sizeof(thinfo), ®, ®siz)); *addr = thinfo.__pi_stackaddr; *size = thinfo.__pi_stacksize; #endif return 0; #undef CHECK_ERR }
size_t mdGetStackSize(void) { stack_t stack; if (pthread_stackseg_np(pthread_self(), &stack) != 0) { fprintf(stderr, "Kaffe VM has not been able to retrieve the stack size\n" "Aborting...\n"); exit(1); } return stack.ss_size; }
void *mdGetStackEnd(void) { stack_t stack; if (pthread_stackseg_np(pthread_self(), &stack) != 0) { fprintf(stderr, "Kaffe VM has not been able to retrieve the pointer to the stack base\n" "Aborting...\n"); exit(1); } return stack.ss_sp; }
void StackBounds::initialize() { pthread_t thread = pthread_self(); stack_t stack; pthread_stackseg_np(thread, &stack); m_origin = stack.ss_sp; #if CPU(HPPA) m_bound = static_cast<char*>(m_origin) + stack.ss_size; #else m_bound = static_cast<char*>(m_origin) - stack.ss_size; #endif }
static int get_stack(void **addr, size_t *size) { #define CHECK_ERR(expr) \ {int err = (expr); if (err) return err;} #if defined HAVE_PTHREAD_GETATTR_NP || defined HAVE_PTHREAD_ATTR_GET_NP pthread_attr_t attr; size_t guard = 0; # ifdef HAVE_PTHREAD_GETATTR_NP CHECK_ERR(pthread_getattr_np(pthread_self(), &attr)); # ifdef HAVE_PTHREAD_ATTR_GETSTACK CHECK_ERR(pthread_attr_getstack(&attr, addr, size)); # else CHECK_ERR(pthread_attr_getstackaddr(&attr, addr)); CHECK_ERR(pthread_attr_getstacksize(&attr, size)); # endif if (pthread_attr_getguardsize(&attr, &guard) == 0) { STACK_GROW_DIR_DETECTION; STACK_DIR_UPPER((void)0, *addr = (char *)*addr + guard); *size -= guard; } # else CHECK_ERR(pthread_attr_init(&attr)); CHECK_ERR(pthread_attr_get_np(pthread_self(), &attr)); CHECK_ERR(pthread_attr_getstackaddr(&attr, addr)); CHECK_ERR(pthread_attr_getstacksize(&attr, size)); # endif CHECK_ERR(pthread_attr_getguardsize(&attr, &guard)); # ifndef HAVE_PTHREAD_GETATTR_NP pthread_attr_destroy(&attr); # endif size -= guard; #elif defined HAVE_PTHREAD_GET_STACKADDR_NP && defined HAVE_PTHREAD_GET_STACKSIZE_NP pthread_t th = pthread_self(); *addr = pthread_get_stackaddr_np(th); *size = pthread_get_stacksize_np(th); #elif defined HAVE_THR_STKSEGMENT || defined HAVE_PTHREAD_STACKSEG_NP stack_t stk; # if defined HAVE_THR_STKSEGMENT CHECK_ERR(thr_stksegment(&stk)); # else CHECK_ERR(pthread_stackseg_np(pthread_self(), &stk)); # endif *addr = stk.ss_sp; *size = stk.ss_size; #endif return 0; #undef CHECK_ERR }
void * GetNativeStackBaseImpl() { pthread_t thread = pthread_self(); # if defined(XP_MACOSX) || defined(DARWIN) return pthread_get_stackaddr_np(thread); # else pthread_attr_t sattr; pthread_attr_init(&sattr); # if defined(__OpenBSD__) stack_t ss; # elif defined(PTHREAD_NP_H) || defined(_PTHREAD_NP_H_) || defined(NETBSD) /* e.g. on FreeBSD 4.8 or newer, [email protected] */ pthread_attr_get_np(thread, &sattr); # else /* * FIXME: this function is non-portable; * other POSIX systems may have different np alternatives */ pthread_getattr_np(thread, &sattr); # endif void *stackBase = 0; size_t stackSize = 0; # ifdef DEBUG int rc = # endif # if defined(__OpenBSD__) pthread_stackseg_np(pthread_self(), &ss); stackBase = (void*)((size_t) ss.ss_sp - ss.ss_size); stackSize = ss.ss_size; # else pthread_attr_getstack(&sattr, &stackBase, &stackSize); # endif JS_ASSERT(!rc); JS_ASSERT(stackBase); pthread_attr_destroy(&sattr); # if JS_STACK_GROWTH_DIRECTION > 0 return stackBase; # else return static_cast<char*>(stackBase) + stackSize; # endif # endif }
void attach_os_thread(init_thread_data *scribble) { os_thread_t os = pthread_self(); odxprint(misc, "attach_os_thread: attaching to %p", os); struct thread *th = create_thread_struct(NIL); block_deferrable_signals(&scribble->oldset); th->no_tls_value_marker = NO_TLS_VALUE_MARKER_WIDETAG; /* We don't actually want a pthread_attr here, but rather than add * `if's to the post-mostem, let's just keep that code happy by * keeping it initialized: */ pthread_attr_init(th->os_attr); #ifndef LISP_FEATURE_WIN32 /* On windows, arch_os_thread_init will take care of finding the * stack. */ void *stack_addr; size_t stack_size; #ifdef LISP_FEATURE_OPENBSD stack_t stack; pthread_stackseg_np(os, &stack); stack_size = stack.ss_size; stack_addr = (void*)((size_t)stack.ss_sp - stack_size); #elif defined LISP_FEATURE_SUNOS stack_t stack; thr_stksegment(&stack); stack_size = stack.ss_size; stack_addr = (void*)((size_t)stack.ss_sp - stack_size); #elif defined(LISP_FEATURE_DARWIN) stack_addr = pthread_get_stackaddr_np(os); stack_size = pthread_get_stacksize_np(os); #else pthread_attr_t attr; #ifdef LISP_FEATURE_FREEBSD pthread_attr_get_np(os, &attr); #else int pthread_getattr_np(pthread_t, pthread_attr_t *); pthread_getattr_np(os, &attr); #endif pthread_attr_getstack(&attr, &stack_addr, &stack_size); #endif th->control_stack_start = stack_addr; th->control_stack_end = (void *) (((uintptr_t) stack_addr) + stack_size); #endif init_new_thread(th, scribble, 0); /* We will be calling into Lisp soon, and the functions being called * recklessly ignore the comment in target-thread which says that we * must be careful to not cause GC while initializing a new thread. * Since we first need to create a fresh thread object, it's really * tempting to just perform such unsafe allocation though. So let's * at least try to suppress GC before consing, and hope that it * works: */ bind_variable(GC_INHIBIT, T, th); uword_t stacksize = (uword_t) th->control_stack_end - (uword_t) th->control_stack_start; odxprint(misc, "attach_os_thread: attached %p as %p (0x%lx bytes stack)", os, th, (long) stacksize); }
void mono_gc_base_init (void) { MonoThreadInfoCallbacks cb; char *env; if (gc_initialized) return; /* * Handle the case when we are called from a thread different from the main thread, * confusing libgc. * FIXME: Move this to libgc where it belongs. * * we used to do this only when running on valgrind, * but it happens also in other setups. */ #if defined(HAVE_PTHREAD_GETATTR_NP) && defined(HAVE_PTHREAD_ATTR_GETSTACK) { size_t size; void *sstart; pthread_attr_t attr; pthread_getattr_np (pthread_self (), &attr); pthread_attr_getstack (&attr, &sstart, &size); pthread_attr_destroy (&attr); /*g_print ("stackbottom pth is: %p\n", (char*)sstart + size);*/ #ifdef __ia64__ /* * The calculation above doesn't seem to work on ia64, also we need to set * GC_register_stackbottom as well, but don't know how. */ #else /* apparently with some linuxthreads implementations sstart can be NULL, * fallback to the more imprecise method (bug# 78096). */ if (sstart) { GC_stackbottom = (char*)sstart + size; } else { int dummy; gsize stack_bottom = (gsize)&dummy; stack_bottom += 4095; stack_bottom &= ~4095; GC_stackbottom = (char*)stack_bottom; } #endif } #elif defined(HAVE_PTHREAD_GET_STACKSIZE_NP) && defined(HAVE_PTHREAD_GET_STACKADDR_NP) GC_stackbottom = (char*)pthread_get_stackaddr_np (pthread_self ()); #elif defined(__OpenBSD__) # include <pthread_np.h> { stack_t ss; int rslt; rslt = pthread_stackseg_np(pthread_self(), &ss); g_assert (rslt == 0); GC_stackbottom = (char*)ss.ss_sp; } #elif defined(__native_client__) /* Do nothing, GC_stackbottom is set correctly in libgc */ #else { int dummy; gsize stack_bottom = (gsize)&dummy; stack_bottom += 4095; stack_bottom &= ~4095; /*g_print ("stackbottom is: %p\n", (char*)stack_bottom);*/ GC_stackbottom = (char*)stack_bottom; } #endif #if !defined(PLATFORM_ANDROID) /* If GC_no_dls is set to true, GC_find_limit is not called. This causes a seg fault on Android. */ GC_no_dls = TRUE; #endif GC_init (); GC_oom_fn = mono_gc_out_of_memory; GC_set_warn_proc (mono_gc_warning); GC_finalize_on_demand = 1; GC_finalizer_notifier = mono_gc_finalize_notify; #ifdef HAVE_GC_GCJ_MALLOC GC_init_gcj_malloc (5, NULL); #endif #ifdef HAVE_GC_ALLOW_REGISTER_THREADS GC_allow_register_threads(); #endif if ((env = getenv ("MONO_GC_PARAMS"))) { char **ptr, **opts = g_strsplit (env, ",", -1); for (ptr = opts; *ptr; ++ptr) { char *opt = *ptr; if (g_str_has_prefix (opt, "max-heap-size=")) { glong max_heap; opt = strchr (opt, '=') + 1; if (*opt && mono_gc_parse_environment_string_extract_number (opt, &max_heap)) { if (max_heap < MIN_BOEHM_MAX_HEAP_SIZE) { fprintf (stderr, "max-heap-size must be at least %dMb.\n", MIN_BOEHM_MAX_HEAP_SIZE_IN_MB); exit (1); } GC_set_max_heap_size (max_heap); } else { fprintf (stderr, "max-heap-size must be an integer.\n"); exit (1); } continue; } else { fprintf (stderr, "MONO_GC_PARAMS must be a comma-delimited list of one or more of the following:\n"); fprintf (stderr, " max-heap-size=N (where N is an integer, possibly with a k, m or a g suffix)\n"); exit (1); } } g_strfreev (opts); } memset (&cb, 0, sizeof (cb)); cb.thread_register = boehm_thread_register; cb.mono_method_is_critical = (gpointer)mono_runtime_is_critical_method; #ifndef HOST_WIN32 cb.mono_gc_pthread_create = (gpointer)mono_gc_pthread_create; #endif mono_threads_init (&cb, sizeof (MonoThreadInfo)); mono_gc_enable_events (); gc_initialized = TRUE; }
/* * Get the initial address and size of current thread's stack */ static int get_stack(void **addr, size_t *size) { #define CHECK_ERR(expr) \ {int err = (expr); if (err) return err;} #ifdef HAVE_PTHREAD_GETATTR_NP /* Linux */ pthread_attr_t attr; size_t guard = 0; STACK_GROW_DIR_DETECTION; CHECK_ERR(pthread_getattr_np(pthread_self(), &attr)); # ifdef HAVE_PTHREAD_ATTR_GETSTACK CHECK_ERR(pthread_attr_getstack(&attr, addr, size)); STACK_DIR_UPPER((void)0, (void)(*addr = (char *)*addr + *size)); # else CHECK_ERR(pthread_attr_getstackaddr(&attr, addr)); CHECK_ERR(pthread_attr_getstacksize(&attr, size)); # endif CHECK_ERR(pthread_attr_getguardsize(&attr, &guard)); *size -= guard; pthread_attr_destroy(&attr); #elif defined HAVE_PTHREAD_ATTR_GET_NP /* FreeBSD, DragonFly BSD, NetBSD */ pthread_attr_t attr; CHECK_ERR(pthread_attr_init(&attr)); CHECK_ERR(pthread_attr_get_np(pthread_self(), &attr)); # ifdef HAVE_PTHREAD_ATTR_GETSTACK CHECK_ERR(pthread_attr_getstack(&attr, addr, size)); # else CHECK_ERR(pthread_attr_getstackaddr(&attr, addr)); CHECK_ERR(pthread_attr_getstacksize(&attr, size)); # endif STACK_DIR_UPPER((void)0, (void)(*addr = (char *)*addr + *size)); pthread_attr_destroy(&attr); #elif (defined HAVE_PTHREAD_GET_STACKADDR_NP && defined HAVE_PTHREAD_GET_STACKSIZE_NP) /* MacOS X */ pthread_t th = pthread_self(); *addr = pthread_get_stackaddr_np(th); *size = pthread_get_stacksize_np(th); #elif defined HAVE_THR_STKSEGMENT || defined HAVE_PTHREAD_STACKSEG_NP stack_t stk; # if defined HAVE_THR_STKSEGMENT /* Solaris */ CHECK_ERR(thr_stksegment(&stk)); # else /* OpenBSD */ CHECK_ERR(pthread_stackseg_np(pthread_self(), &stk)); # endif *addr = stk.ss_sp; *size = stk.ss_size; #elif defined HAVE_PTHREAD_GETTHRDS_NP /* AIX */ pthread_t th = pthread_self(); struct __pthrdsinfo thinfo; char reg[256]; int regsiz=sizeof(reg); CHECK_ERR(pthread_getthrds_np(&th, PTHRDSINFO_QUERY_ALL, &thinfo, sizeof(thinfo), ®, ®siz)); *addr = thinfo.__pi_stackaddr; *size = thinfo.__pi_stacksize; STACK_DIR_UPPER((void)0, (void)(*addr = (char *)*addr + *size)); #else #error STACKADDR_AVAILABLE is defined but not implemented. #endif return 0; #undef CHECK_ERR }
void mono_gc_base_init (void) { if (gc_initialized) return; /* * Handle the case when we are called from a thread different from the main thread, * confusing libgc. * FIXME: Move this to libgc where it belongs. * * we used to do this only when running on valgrind, * but it happens also in other setups. */ #if defined(HAVE_PTHREAD_GETATTR_NP) && defined(HAVE_PTHREAD_ATTR_GETSTACK) { size_t size; void *sstart; pthread_attr_t attr; pthread_getattr_np (pthread_self (), &attr); pthread_attr_getstack (&attr, &sstart, &size); pthread_attr_destroy (&attr); /*g_print ("stackbottom pth is: %p\n", (char*)sstart + size);*/ #ifdef __ia64__ /* * The calculation above doesn't seem to work on ia64, also we need to set * GC_register_stackbottom as well, but don't know how. */ #else /* apparently with some linuxthreads implementations sstart can be NULL, * fallback to the more imprecise method (bug# 78096). */ if (sstart) { GC_stackbottom = (char*)sstart + size; } else { int dummy; gsize stack_bottom = (gsize)&dummy; stack_bottom += 4095; stack_bottom &= ~4095; GC_stackbottom = (char*)stack_bottom; } #endif } #elif defined(HAVE_PTHREAD_GET_STACKSIZE_NP) && defined(HAVE_PTHREAD_GET_STACKADDR_NP) GC_stackbottom = (char*)pthread_get_stackaddr_np (pthread_self ()); #elif defined(__OpenBSD__) # include <pthread_np.h> { stack_t ss; int rslt; rslt = pthread_stackseg_np(pthread_self(), &ss); g_assert (rslt == 0); GC_stackbottom = (char*)ss.ss_sp; } #else { int dummy; gsize stack_bottom = (gsize)&dummy; stack_bottom += 4095; stack_bottom &= ~4095; /*g_print ("stackbottom is: %p\n", (char*)stack_bottom);*/ GC_stackbottom = (char*)stack_bottom; } #endif #if !defined(PLATFORM_ANDROID) /* If GC_no_dls is set to true, GC_find_limit is not called. This causes a seg fault on Android. */ GC_no_dls = TRUE; #endif GC_init (); GC_oom_fn = mono_gc_out_of_memory; GC_set_warn_proc (mono_gc_warning); GC_finalize_on_demand = 1; GC_finalizer_notifier = mono_gc_finalize_notify; #ifdef HAVE_GC_GCJ_MALLOC GC_init_gcj_malloc (5, NULL); #endif mono_gc_enable_events (); gc_initialized = TRUE; }
void *nativeStackBase() { stack_t sinfo; pthread_stackseg_np(pthread_self(), &sinfo); return sinfo.ss_sp; }
void mono_threads_core_get_stack_bounds (guint8 **staddr, size_t *stsize) { #if defined(HAVE_PTHREAD_GET_STACKSIZE_NP) && defined(HAVE_PTHREAD_GET_STACKADDR_NP) /* Mac OS X */ *staddr = (guint8*)pthread_get_stackaddr_np (pthread_self()); *stsize = pthread_get_stacksize_np (pthread_self()); #ifdef TARGET_OSX /* * Mavericks reports stack sizes as 512kb: * http://permalink.gmane.org/gmane.comp.java.openjdk.hotspot.devel/11590 * https://bugs.openjdk.java.net/browse/JDK-8020753 */ if (pthread_main_np () && *stsize == 512 * 1024) *stsize = 2048 * mono_pagesize (); #endif /* staddr points to the start of the stack, not the end */ *staddr -= *stsize; /* When running under emacs, sometimes staddr is not aligned to a page size */ *staddr = (guint8*)((gssize)*staddr & ~(mono_pagesize() - 1)); return; #elif (defined(HAVE_PTHREAD_GETATTR_NP) || defined(HAVE_PTHREAD_ATTR_GET_NP)) && defined(HAVE_PTHREAD_ATTR_GETSTACK) /* Linux, BSD */ pthread_attr_t attr; guint8 *current = (guint8*)&attr; *staddr = NULL; *stsize = (size_t)-1; pthread_attr_init (&attr); #if defined(HAVE_PTHREAD_GETATTR_NP) /* Linux */ pthread_getattr_np (pthread_self(), &attr); #elif defined(HAVE_PTHREAD_ATTR_GET_NP) /* BSD */ pthread_attr_get_np (pthread_self(), &attr); #else #error Cannot determine which API is needed to retrieve pthread attributes. #endif pthread_attr_getstack (&attr, (void**)staddr, stsize); pthread_attr_destroy (&attr); if (*staddr) g_assert ((current > *staddr) && (current < *staddr + *stsize)); /* When running under emacs, sometimes staddr is not aligned to a page size */ *staddr = (guint8*)((gssize)*staddr & ~(mono_pagesize () - 1)); return; #elif defined(__OpenBSD__) /* OpenBSD */ /* TODO : Determine if this code is actually still needed. It may already be covered by the case above. */ pthread_attr_t attr; guint8 *current = (guint8*)&attr; *staddr = NULL; *stsize = (size_t)-1; pthread_attr_init (&attr); stack_t ss; int rslt; rslt = pthread_stackseg_np(pthread_self(), &ss); g_assert (rslt == 0); *staddr = (guint8*)((size_t)ss.ss_sp - ss.ss_size); *stsize = ss.ss_size; pthread_attr_destroy (&attr); if (*staddr) g_assert ((current > *staddr) && (current < *staddr + *stsize)); /* When running under emacs, sometimes staddr is not aligned to a page size */ *staddr = (guint8*)((gssize)*staddr & ~(mono_pagesize () - 1)); return; #elif defined(sun) || defined(__native_client__) /* Solaris/Illumos, NaCl */ pthread_attr_t attr; pthread_attr_init (&attr); pthread_attr_getstacksize (&attr, &stsize); pthread_attr_destroy (&attr); *staddr = NULL; return; #else /* FIXME: It'd be better to use the 'error' preprocessor macro here so we know at compile-time if the target platform isn't supported. */ #warning "Unable to determine how to retrieve a thread's stack-bounds for this platform in 'mono_thread_get_stack_bounds()'." *staddr = NULL; *stsize = 0; return; #endif }
inline void* MachineThreads::Thread::Registers::stackPointer() const { #if OS(DARWIN) #if __DARWIN_UNIX03 #if CPU(X86) return reinterpret_cast<void*>(regs.__esp); #elif CPU(X86_64) return reinterpret_cast<void*>(regs.__rsp); #elif CPU(PPC) || CPU(PPC64) return reinterpret_cast<void*>(regs.__r1); #elif CPU(ARM) return reinterpret_cast<void*>(regs.__sp); #elif CPU(ARM64) return reinterpret_cast<void*>(regs.__sp); #else #error Unknown Architecture #endif #else // !__DARWIN_UNIX03 #if CPU(X86) return reinterpret_cast<void*>(regs.esp); #elif CPU(X86_64) return reinterpret_cast<void*>(regs.rsp); #elif CPU(PPC) || CPU(PPC64) return reinterpret_cast<void*>(regs.r1); #else #error Unknown Architecture #endif #endif // __DARWIN_UNIX03 // end OS(DARWIN) #elif OS(WINDOWS) #if CPU(ARM) return reinterpret_cast<void*>((uintptr_t) regs.Sp); #elif CPU(MIPS) return reinterpret_cast<void*>((uintptr_t) regs.IntSp); #elif CPU(X86) return reinterpret_cast<void*>((uintptr_t) regs.Esp); #elif CPU(X86_64) return reinterpret_cast<void*>((uintptr_t) regs.Rsp); #else #error Unknown Architecture #endif #elif USE(PTHREADS) void* stackBase = 0; size_t stackSize = 0; #if OS(OPENBSD) stack_t ss; int rc = pthread_stackseg_np(pthread_self(), &ss); stackBase = (void*)((size_t) ss.ss_sp - ss.ss_size); stackSize = ss.ss_size; #else int rc = pthread_attr_getstack(®s, &stackBase, &stackSize); #endif (void)rc; // FIXME: Deal with error code somehow? Seems fatal. ASSERT(stackBase); return static_cast<char*>(stackBase) + stackSize; #else #error Need a way to get the stack pointer for another thread on this platform #endif }