Пример #1
0
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;
}
Пример #2
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
}
Пример #3
0
void Collector::markCurrentThreadConservatively()
{
  jmp_buf registers;
  setjmp(registers);

  pthread_t thread = pthread_self();
  void *stackBase = pthread_get_stackaddr_np(thread);
  int dummy;
  void *stackPointer = &dummy;
  markStackObjectsConservatively(stackPointer, stackBase);
}
Пример #4
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
}
Пример #5
0
void Collector::markOtherThreadConservatively(Thread *thread)
{
  thread_suspend(thread->machThread);

#if defined(__i386__)
  i386_thread_state_t regs;
  unsigned user_count = sizeof(regs)/sizeof(int);
  thread_state_flavor_t flavor = i386_THREAD_STATE;
#elif defined(__ppc__)
  ppc_thread_state_t  regs;
  unsigned user_count = PPC_THREAD_STATE_COUNT;
  thread_state_flavor_t flavor = PPC_THREAD_STATE;
#elif defined(__ppc64__)
  ppc_thread_state64_t  regs;
  unsigned user_count = PPC_THREAD_STATE64_COUNT;
  thread_state_flavor_t flavor = PPC_THREAD_STATE64;
#else
#error Unknown Architecture
#endif
  // get the thread register state
  thread_get_state(thread->machThread, flavor, (thread_state_t)&regs, &user_count);
  
  // scan the registers
  markStackObjectsConservatively((void *)&regs, (void *)((char *)&regs + (user_count * sizeof(usword_t))));
  
  // scan the stack
#if defined(__i386__)
  markStackObjectsConservatively((void *)regs.esp, pthread_get_stackaddr_np(thread->posixThread));
#elif defined(__ppc__) || defined(__ppc64__)
  markStackObjectsConservatively((void *)regs.r1, pthread_get_stackaddr_np(thread->posixThread));
#else
#error Unknown Architecture
#endif

  thread_resume(thread->machThread);
}
Пример #6
0
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;
}
Пример #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
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;
}
Пример #9
0
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;
}
Пример #10
0
ThreadInfo::ThreadInfo(const char* aName, int aThreadId,
                       bool aIsMainThread, PseudoStack* aPseudoStack,
                       void* aStackTop)
  : mName(strdup(aName))
  , mThreadId(aThreadId)
  , mIsMainThread(aIsMainThread)
  , mPseudoStack(aPseudoStack)
  , mPlatformData(Sampler::AllocPlatformData(aThreadId))
  , mProfile(nullptr)
  , mStackTop(aStackTop)
  , mPendingDelete(false)
{
#ifndef SPS_STANDALONE
  mThread = NS_GetCurrentThread();
#endif

  // We don't have to guess on mac
#ifdef XP_MACOSX
  pthread_t self = pthread_self();
  mStackTop = pthread_get_stackaddr_np(self);
#endif
}
Пример #11
0
/**
 * 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;
}
Пример #12
0
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);
}
Пример #13
0
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;
}
Пример #14
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
}
Пример #15
0
void *nativeStackBase() {
    return pthread_get_stackaddr_np(pthread_self());
}
Пример #16
0
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;
}
Пример #17
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
}
Пример #18
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;
	}
}