예제 #1
0
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),
				  &reg, &regsiz));
    *addr = thinfo.__pi_stackaddr;
    *size = thinfo.__pi_stacksize;
#endif
    return 0;
#undef CHECK_ERR
}
예제 #2
0
파일: t_join.c 프로젝트: 2asoft/freebsd
static void *
threadfunc2(void *arg)
{
	static uintptr_t i = 0;
	uintptr_t j;
	pthread_attr_t attr;
	size_t stacksize;

	j = (uintptr_t)arg;

#ifdef __FreeBSD__
	pthread_attr_init(&attr);
#endif
	ATF_REQUIRE(pthread_attr_get_np(pthread_self(), &attr) == 0);
	ATF_REQUIRE(pthread_attr_getstacksize(&attr, &stacksize) == 0);
	ATF_REQUIRE(stacksize == STACKSIZE * (j + 1));
	ATF_REQUIRE(pthread_attr_destroy(&attr) == 0);

	if (i++ == j)
		error = false;

	pthread_exit((void *)i);

	return NULL;
}
예제 #3
0
size_t MachineThreads::Thread::getRegisters(MachineThreads::Thread::Registers& registers)
{
    Thread::Registers::PlatformRegisters& regs = registers.regs;
#if OS(DARWIN)
#if CPU(X86)
    unsigned user_count = sizeof(regs)/sizeof(int);
    thread_state_flavor_t flavor = i386_THREAD_STATE;
#elif CPU(X86_64)
    unsigned user_count = x86_THREAD_STATE64_COUNT;
    thread_state_flavor_t flavor = x86_THREAD_STATE64;
#elif CPU(PPC) 
    unsigned user_count = PPC_THREAD_STATE_COUNT;
    thread_state_flavor_t flavor = PPC_THREAD_STATE;
#elif CPU(PPC64)
    unsigned user_count = PPC_THREAD_STATE64_COUNT;
    thread_state_flavor_t flavor = PPC_THREAD_STATE64;
#elif CPU(ARM)
    unsigned user_count = ARM_THREAD_STATE_COUNT;
    thread_state_flavor_t flavor = ARM_THREAD_STATE;
#elif CPU(ARM64)
    unsigned user_count = ARM_THREAD_STATE64_COUNT;
    thread_state_flavor_t flavor = ARM_THREAD_STATE64;
#else
#error Unknown Architecture
#endif

    kern_return_t result = thread_get_state(platformThread, flavor, (thread_state_t)&regs, &user_count);
    if (result != KERN_SUCCESS) {
        WTFReportFatalError(__FILE__, __LINE__, WTF_PRETTY_FUNCTION, 
                            "JavaScript garbage collection failed because thread_get_state returned an error (%d). This is probably the result of running inside Rosetta, which is not supported.", result);
        CRASH();
    }
    return user_count * sizeof(uintptr_t);
// end OS(DARWIN)

#elif OS(WINDOWS)
    regs.ContextFlags = CONTEXT_INTEGER | CONTEXT_CONTROL;
    GetThreadContext(platformThreadHandle, &regs);
    return sizeof(CONTEXT);
#elif USE(PTHREADS)
    pthread_attr_init(&regs);
#if HAVE(PTHREAD_NP_H) || OS(NETBSD)
#if !OS(OPENBSD)
    // e.g. on FreeBSD 5.4, [email protected]
    pthread_attr_get_np(platformThread, &regs);
#endif
#else
    // FIXME: this function is non-portable; other POSIX systems may have different np alternatives
    pthread_getattr_np(platformThread, &regs);
#endif
    return 0;
#else
#error Need a way to get thread registers on this platform
#endif
}
예제 #4
0
파일: os.c 프로젝트: cfriedt/jamvm
void *nativeStackBase() {
    pthread_attr_t attr;
    size_t size;
    void *addr;

    pthread_attr_init(&attr);
    pthread_attr_get_np(pthread_self(), &attr);
    pthread_attr_getstack(&attr, &addr, &size);

    return addr+size;
}
예제 #5
0
void
mono_threads_platform_get_stack_bounds (guint8 **staddr, size_t *stsize)
{
	pthread_attr_t attr;

	*staddr = NULL;
	*stsize = (size_t)-1;

	pthread_attr_init (&attr);
	pthread_attr_get_np (pthread_self (), &attr);

	pthread_attr_getstack (&attr, (void**)staddr, stsize);
	pthread_attr_destroy (&attr);
}
예제 #6
0
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
}
예제 #7
0
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
}
예제 #8
0
void StackBounds::initialize()
{
    void* stackBase = 0;
    size_t stackSize = 0;

    pthread_t thread = pthread_self();
    pthread_attr_t sattr;
    pthread_attr_init(&sattr);
#if HAVE(PTHREAD_NP_H) || OS(NETBSD)
    // e.g. on FreeBSD 5.4, [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
    int rc = pthread_attr_getstack(&sattr, &stackBase, &stackSize);
    (void)rc; // FIXME: Deal with error code somehow? Seems fatal.
    ASSERT(stackBase);
    pthread_attr_destroy(&sattr);
    m_bound = stackBase;
    m_origin = static_cast<char*>(stackBase) + stackSize;
}
예제 #9
0
inline int find_stack_addr_size(void** paddr, size_t* psize)
{
#if defined (HAIKU)
	int status;
	thread_info info;
	thread_id this_thread = find_thread(NULL);
	status = get_thread_info(this_thread,&info);
	*paddr = info.stack_base;
    *psize = (size_t)info.stack_base - (size_t)info.stack_end;
    return 0;
#else
    int err;
    pthread_attr_t pthread_attr;
    void* stack_addr;
    size_t stack_size;
    pthread_t thread = pthread_self();

    if (!paddr) return EINVAL;

    err = pthread_attr_init(&pthread_attr);
    if (err != 0) return err;
  #if defined(FREEBSD)
    err = pthread_attr_get_np(thread, &pthread_attr);
  #else
    err = pthread_getattr_np(thread, &pthread_attr);
  #endif
    if (err != 0) return err;

    err = pthread_attr_getstack(&pthread_attr, &stack_addr, &stack_size);
    if (err != 0) return err;

    pthread_attr_destroy(&pthread_attr);
    *paddr = (void*)((size_t)stack_addr + stack_size);
    *psize = stack_size;
    return 0;
#endif
}
예제 #10
0
파일: thread.c 프로젝트: budden/sbcl-ita
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);
}
예제 #11
0
/*********************************************************************************************************
** 函数名称: pthread_getattr_np
** 功能描述: 获取线程属性控制块 (Linux 扩展接口)
** 输 入  : thread        线程 ID
**           pattr         需要设置的 attr 指针.
** 输 出  : ERROR CODE
** 全局变量: 
** 调用模块: 
                                           API 函数
*********************************************************************************************************/
LW_API 
int  pthread_getattr_np (pthread_t thread, pthread_attr_t *pattr)
{
    return  (pthread_attr_get_np(thread, pattr));
}
예제 #12
0
/*
 * 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),
				   &reg, &regsiz));
    *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
}
static size_t getPlatformThreadRegisters(const PlatformThread& platformThread, PlatformThreadRegisters& regs)
{
#if OS(DARWIN)

#if CPU(X86)
    unsigned user_count = sizeof(regs)/sizeof(int);
    thread_state_flavor_t flavor = i386_THREAD_STATE;
#elif CPU(X86_64)
    unsigned user_count = x86_THREAD_STATE64_COUNT;
    thread_state_flavor_t flavor = x86_THREAD_STATE64;
#elif CPU(PPC) 
    unsigned user_count = PPC_THREAD_STATE_COUNT;
    thread_state_flavor_t flavor = PPC_THREAD_STATE;
#elif CPU(PPC64)
    unsigned user_count = PPC_THREAD_STATE64_COUNT;
    thread_state_flavor_t flavor = PPC_THREAD_STATE64;
#elif CPU(ARM)
    unsigned user_count = ARM_THREAD_STATE_COUNT;
    thread_state_flavor_t flavor = ARM_THREAD_STATE;
#else
#error Unknown Architecture
#endif

    kern_return_t result = thread_get_state(platformThread, flavor, (thread_state_t)&regs, &user_count);
    if (result != KERN_SUCCESS) {
        WTFReportFatalError(__FILE__, __LINE__, WTF_PRETTY_FUNCTION, 
                            "JavaScript garbage collection failed because thread_get_state returned an error (%d). This is probably the result of running inside Rosetta, which is not supported.", result);
        CRASH();
    }
    return user_count * sizeof(usword_t);
// end OS(DARWIN)

#elif OS(WINDOWS)
    regs.ContextFlags = CONTEXT_INTEGER | CONTEXT_CONTROL;
    GetThreadContext(platformThread, &regs);
    return sizeof(CONTEXT);
#elif OS(QNX)
    memset(&regs, 0, sizeof(regs));
    regs.tid = platformThread;
    // FIXME: If we find this hurts performance, we can consider caching the fd and keeping it open.
    int fd = open("/proc/self/as", O_RDONLY);
    if (fd == -1) {
        LOG_ERROR("Unable to open /proc/self/as (errno: %d)", errno);
        CRASH();
    }
    int rc = devctl(fd, DCMD_PROC_TIDSTATUS, &regs, sizeof(regs), 0);
    if (rc != EOK) {
        LOG_ERROR("devctl(DCMD_PROC_TIDSTATUS) failed (error: %d)", rc);
        CRASH();
    }
    close(fd);
    return sizeof(struct _debug_thread_info);
#elif USE(PTHREADS)
    pthread_attr_init(&regs);
#if HAVE(PTHREAD_NP_H) || OS(NETBSD)
    // e.g. on FreeBSD 5.4, [email protected]
    pthread_attr_get_np(platformThread, &regs);
#else
    // FIXME: this function is non-portable; other POSIX systems may have different np alternatives
    pthread_getattr_np(platformThread, &regs);
#endif
    return 0;
#else
#error Need a way to get thread registers on this platform
#endif
}
예제 #14
0
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
}
예제 #15
0
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;
	}
}