static void LINUXcomputeStackTop(CVMThreadID *self) { size_t stackSize = pthread_get_stacksize_np(POSIX_COOKIE(self)); char* stackAddr = pthread_get_stackaddr_np(POSIX_COOKIE(self)); self->stackTop = stackAddr - stackSize; }
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 }
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 StackBounds::initialize() { pthread_t thread = pthread_self(); m_origin = pthread_get_stackaddr_np(thread); rlim_t size = 0; if (pthread_main_np()) { // FIXME: <rdar://problem/13741204> // pthread_get_size lies to us when we're the main thread, use get_rlimit instead rlimit limit; getrlimit(RLIMIT_STACK, &limit); size = limit.rlim_cur; } else size = pthread_get_stacksize_np(thread); m_bound = static_cast<char*>(m_origin) - size; }
void mono_threads_core_get_stack_bounds (guint8 **staddr, size_t *stsize) { *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; }
static Thread * NewThread(void) { Thread *thrPtr; static unsigned int nextuid = 0; pthread_t tid; #if defined(HAVE_PTHREAD_GETATTR_NP) static char *func = "NewThread"; pthread_attr_t attr; int err; #endif thrPtr = ns_calloc(1, sizeof(Thread)); Ns_MutexLock(&uidlock); thrPtr->uid = nextuid++; Ns_MutexUnlock(&uidlock); tid = pthread_self(); #if defined(HAVE_PTHREAD_GETATTR_NP) err = pthread_getattr_np(tid, &attr); if (err != 0) { NsThreadFatal(func, "pthread_getattr_np", err); } err = pthread_attr_getstackaddr(&attr, &thrPtr->stackaddr); if (err != 0) { NsThreadFatal(func, "pthread_attr_getstackaddr", err); } err = pthread_attr_getstacksize(&attr, &thrPtr->stacksize); if (err != 0) { NsThreadFatal(func, "pthread_attr_getstacksize", err); } thrPtr->stacksize -= guardsize; err = pthread_attr_destroy(&attr); if (err != 0) { NsThreadFatal(func, "pthread_attr_destroy", err); } #elif defined(HAVE_PTHREAD_GET_STACKADDR_NP) thrPtr->stackaddr = pthread_get_stackaddr_np(tid); thrPtr->stacksize = pthread_get_stacksize_np(tid) - guardsize; #endif return thrPtr; }
/** * Determines the stack address of the current thread */ static void* getStackAddress(void) { void* result = NULL; size_t stackSize = 0; pthread_t self = pthread_self(); #if defined(DARWIN) result = pthread_get_stackaddr_np(self); stackSize = pthread_get_stacksize_np(self); // pthread_get_stackaddr_np returns the beginning (highest address) of the stack // while we want the address of the memory area allocated for the stack (lowest address). result -= stackSize; #else size_t guardSize = 0; pthread_attr_t attr; pthread_getattr_np(self, &attr); pthread_attr_getstack(&attr, &result, &stackSize); pthread_attr_getguardsize(&attr, &guardSize); // On Linux pthread_attr_getstack() returns the address of the memory area allocated for the stack // including the guard page (except for the main thread which returns the correct stack address and // pthread_attr_getguardsize() returns 0 even if there is a guard page). result += guardSize; #endif return result; }
static size_t getUnderestimatedStackSize() { #if defined(__GLIBC__) || OS(ANDROID) || OS(FREEBSD) // We cannot get the stack size in these platforms because // pthread_getattr_np() can fail for the main thread. // This is OK because ThreadState::current() doesn't use the stack size // in these platforms. return 0; #elif OS(MACOSX) return pthread_get_stacksize_np(pthread_self()); #elif OS(WIN) && COMPILER(MSVC) // On Windows stack limits for the current thread are available in // the thread information block (TIB). Its fields can be accessed through // FS segment register on x86 and GS segment register on x86_64. #ifdef _WIN64 return __readgsqword(offsetof(NT_TIB64, StackBase)) - __readgsqword(offsetof(NT_TIB64, StackLimit)); #else return __readfsdword(offsetof(NT_TIB, StackBase)) - __readfsdword(offsetof(NT_TIB, StackLimit)); #endif #else return 0; #endif }
size_t TclpThreadGetStackSize(void) { size_t stackSize = 0; #if defined(HAVE_PTHREAD_ATTR_SETSTACKSIZE) && defined(TclpPthreadGetAttrs) pthread_attr_t threadAttr; /* This will hold the thread attributes for * the current thread. */ #ifdef __GLIBC__ /* * Fix for [Bug 1815573] * * DESCRIPTION: * On linux TclpPthreadGetAttrs (which is pthread_attr_get_np) may return * bogus values on the initial thread. * * ASSUMPTIONS: * There seems to be no api to determine if we are on the initial * thread. The simple scheme implemented here assumes: * 1. The first Tcl interp to be created lives in the initial thread. If * this assumption is not true, the fix is to call * TclpThreadGetStackSize from the initial thread previous to * creating any Tcl interpreter. In this case, especially if another * Tcl interpreter may be created in the initial thread, it might be * better to enable the second branch in the #if below * 2. There will be no races in creating the first Tcl interp - ie, the * second Tcl interp will be created only after the first call to * Tcl_CreateInterp returns. * * These assumptions are satisfied by tclsh. Embedders on linux may want * to check their validity, and possibly adapt the code on failing to meet * them. */ static int initialized = 0; if (!initialized) { initialized = 1; return 0; } else { #else { #endif if (pthread_attr_init(&threadAttr) != 0) { return -1; } if (TclpPthreadGetAttrs(pthread_self(), &threadAttr) != 0) { pthread_attr_destroy(&threadAttr); return (size_t)-1; } } if (pthread_attr_getstacksize(&threadAttr, &stackSize) != 0) { pthread_attr_destroy(&threadAttr); return (size_t)-1; } pthread_attr_destroy(&threadAttr); #elif defined(HAVE_PTHREAD_GET_STACKSIZE_NP) #ifdef __APPLE__ /* * On Darwin, the API below does not return the correct stack size for the * main thread (which is not a real pthread), so fallback to getrlimit(). */ if (!pthread_main_np()) #endif stackSize = pthread_get_stacksize_np(pthread_self()); #else /* * Cannot determine the real stack size of this thread. The caller might * want to try looking at the process accounting limits instead. */ #endif return stackSize; } #endif /* TCL_THREADS */ /* *---------------------------------------------------------------------- * * Tcl_GetCurrentThread -- * * This procedure returns the ID of the currently running thread. * * Results: * A thread ID. * * Side effects: * None. * *---------------------------------------------------------------------- */ Tcl_ThreadId Tcl_GetCurrentThread(void) { #ifdef TCL_THREADS return (Tcl_ThreadId) pthread_self(); #else return (Tcl_ThreadId) 0; #endif } /* *---------------------------------------------------------------------- * * TclpInitLock * * This procedure is used to grab a lock that serializes initialization * and finalization of Tcl. On some platforms this may also initialize * the mutex used to serialize creation of more mutexes and thread local * storage keys. * * Results: * None. * * Side effects: * Acquire the initialization mutex. * *---------------------------------------------------------------------- */ void TclpInitLock(void) { #ifdef TCL_THREADS pthread_mutex_lock(&initLock); #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); }
/* * 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_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 }
static void internal_pthread_backtrace(pthread_t thread, void** buffer, size_t max, size_t* depth, size_t skip) { *depth = 0; //! Get information about the stack (pos & size). uint8_t* stackbot; size_t stack_size; //! in bytes size_t guard_size; //! in bytes #if defined(__FreeBSD__) pthread_attr_t attr; pthread_attr_init(&attr); pthread_attr_get_np(thread, &attr); pthread_attr_getstack(&attr, (void**)&stackbot, &stack_size); pthread_attr_getguardsize(&attr, &guard_size); pthread_attr_destroy(&attr); #elif defined(__APPLE__) stackbot = (uint8_t*)pthread_get_stackaddr_np(thread); stack_size = pthread_get_stacksize_np(thread); guard_size = 0; //FIXME anyway to get that? #else pthread_attr_t attr; pthread_getattr_np(thread, &attr); pthread_attr_getstack(&attr, (void**)&stackbot, &stack_size); pthread_attr_getguardsize(&attr, &guard_size); pthread_attr_destroy(&attr); #endif stack_size -= guard_size; //! The thread is is still running!!! //! So make a buffer copy of the stack, else it gets changed while we reading from it! std::vector<uint8_t> sbuffer(stack_size); uint8_t* stack_buffer = &sbuffer[0]; memcpy(stack_buffer, stackbot, stack_size); //! It is impossible to get the current frame (the current function pos) on the stack //! for other pthreads, so we need to find it ourself. The beneath method is very naive //! and just searchs for the starting address that gives us the longest stackdepth. unsigned longest_stack = 0; unsigned longest_offset = 0; int check_area = MAX(0, stack_size - 1024*sizeof(uintptr_t)); check_area *= 0.8f; //! only check ~20% from the top of the stack for (int offset = stack_size - sizeof(uintptr_t); offset >= check_area; offset -= sizeof(uintptr_t)) { unsigned stack_depth = 0; uint8_t* frame = stack_buffer + offset; frame = TranslateStackAddrToBufferAddr(frame, stackbot, stack_buffer); uint8_t* last_frame = frame; while (INSTACK(frame) && (frame > last_frame)) { last_frame = frame; frame = TranslateStackAddrToBufferAddr(frame, stackbot, stack_buffer); stack_depth++; } if (stack_depth > longest_stack) { longest_stack = stack_depth; longest_offset = offset; } } //! Now get the list of function addresses from the stack. uint8_t* frame = stack_buffer + longest_offset; if(!INSTACK(frame)) return; while (skip--) { uint8_t* next = TranslateStackAddrToBufferAddr(frame, stackbot, stack_buffer); if(!INSTACK(next)) return; frame = next; } while (max--) { uint8_t* next = TranslateStackAddrToBufferAddr(frame, stackbot, stack_buffer); buffer[*depth] = (void*)*((uintptr_t*)frame + FP_OFFSET); (*depth)++; if(!INSTACK(next)) return; frame = next; } }
static void thread_check_stack(void* arg) { /* 512KB is the default stack size of threads other than the main thread * on OSX. */ ASSERT(pthread_get_stacksize_np(pthread_self()) > 512*1024); }