Beispiel #1
0
gboolean
mono_gc_register_thread (void *baseptr)
{
#if GC_VERSION_MAJOR >= 7
	struct GC_stack_base sb;
	int res;

	res = GC_get_stack_base (&sb);
	if (res != GC_SUCCESS) {
		sb.mem_base = baseptr;
#ifdef __ia64__
		/* Can't determine the register stack bounds */
		g_error ("mono_gc_register_thread failed ().\n");
#endif
	}
	res = GC_register_my_thread (&sb);
	if ((res != GC_SUCCESS) && (res != GC_DUPLICATE)) {
		g_warning ("GC_register_my_thread () failed.\n");
		return FALSE;
	}
	return TRUE;
#else
	if (mono_gc_is_gc_thread())
		return TRUE;
#if defined(USE_INCLUDED_LIBGC) && !defined(PLATFORM_WIN32)
	return GC_thread_register_foreign (baseptr);
#else
	return FALSE;
#endif
#endif
}
Beispiel #2
0
static void*
boehm_thread_register (MonoThreadInfo* info, void *baseptr)
{
#if GC_VERSION_MAJOR >= 7
	struct GC_stack_base sb;
	int res;

	res = GC_get_stack_base (&sb);
	if (res != GC_SUCCESS) {
		sb.mem_base = baseptr;
#ifdef __ia64__
		/* Can't determine the register stack bounds */
		g_error ("mono_gc_register_thread failed ().\n");
#endif
	}
	res = GC_register_my_thread (&sb);
	if ((res != GC_SUCCESS) && (res != GC_DUPLICATE)) {
		g_warning ("GC_register_my_thread () failed.\n");
		return NULL;
	}
	return info;
#else
	if (mono_gc_is_gc_thread())
		return info;
#if defined(USE_INCLUDED_LIBGC) && !defined(HOST_WIN32)
	return GC_thread_register_foreign (baseptr) ? info : NULL;
#else
	return NULL;
#endif
#endif
}
extern unsigned long scheme_get_stack_base()
{
#if !defined(MZ_PRECISE_GC) && !defined(USE_SENORA_GC)
  if (GC_stackbottom)
    return (unsigned long)GC_stackbottom;
  else
#endif
    return (unsigned long)GC_get_stack_base();
}
Beispiel #4
0
GC_API BOOL WINAPI DllMain(HINSTANCE inst, ULONG reason, LPVOID reserved)
{
  struct GC_stack_base sb;
  DWORD thread_id;
  int sb_result;
  static int entry_count = 0;

  if (parallel_initialized && !GC_win32_dll_threads) return TRUE;

  switch (reason) {
   case DLL_THREAD_ATTACH:
    GC_ASSERT(entry_count == 0 || parallel_initialized);
    ++entry_count; /* and fall through: */
   case DLL_PROCESS_ATTACH:
    /* This may run with the collector uninitialized. */
    thread_id = GetCurrentThreadId();
    if (parallel_initialized && GC_main_thread != thread_id) {
	/* Don't lock here.	*/
        sb_result = GC_get_stack_base(&sb);
        GC_ASSERT(sb_result == GC_SUCCESS);
#       ifdef THREAD_LOCAL_ALLOC
	  ABORT("Cannot initialize thread local cache from DllMain");
#       endif
	GC_register_my_thread_inner(&sb, thread_id);
    } /* o.w. we already did it during GC_thr_init(), called by GC_init() */
    break;

   case DLL_THREAD_DETACH:
    /* We are hopefully running in the context of the exiting thread.	*/
    GC_ASSERT(parallel_initialized);
    if (!GC_win32_dll_threads) return TRUE;
    GC_delete_thread(GetCurrentThreadId());
    break;

   case DLL_PROCESS_DETACH:
    {
      int i;

      if (!GC_win32_dll_threads) return TRUE;
      for (i = 0; i <= GC_get_max_thread_index(); ++i)
      {
          if (AO_load(&(dll_thread_table[i].in_use)))
	    GC_delete_gc_thread(dll_thread_table + i);
      }

      GC_deinit();
      DeleteCriticalSection(&GC_allocate_ml);
    }
    break;

  }
  return TRUE;
}
/* At the start of a thread other than the main thread, we need to
   register the new thread with the collector. */
static void conservative_thread_start() {
    struct GC_stack_base sb;

    if(GC_get_stack_base(&sb) != GC_SUCCESS) {
        fprintf(stderr, "Failure getting stack base for interpreter thread.\n");
        exit(EXIT_FAILURE);
    }

    if(GC_register_my_thread(&sb) != GC_SUCCESS) {
        fprintf(stderr, "Failure registering interpreter thread.\n");
        exit(EXIT_FAILURE);
    }
}
Beispiel #6
0
/* Called by GC_init() - we hold the allocation lock.	*/
void GC_thr_init(void) {
    struct GC_stack_base sb;
    int sb_result;

    GC_ASSERT(I_HOLD_LOCK());
    if (GC_thr_initialized) return;
    GC_main_thread = GetCurrentThreadId();
    GC_thr_initialized = TRUE;

    /* Add the initial thread, so we can stop it.	*/
    sb_result = GC_get_stack_base(&sb);
    GC_ASSERT(sb_result == GC_SUCCESS);
    GC_register_my_thread(&sb);
}
Beispiel #7
0
EXTERN bool neko_thread_register( bool t ) {
#	if !defined(NEKO_THREADS)
	return 0;
#	elif defined(NEKO_WINDOWS)
	struct GC_stack_base sb;
	int r;
	if( !t )
		return GC_unregister_my_thread() == GC_SUCCESS;
	if( GC_get_stack_base(&sb) != GC_SUCCESS )
		return 0;
	r = GC_register_my_thread(&sb);
	return( r == GC_SUCCESS || r == GC_DUPLICATE );
#	else
	// since the API is only available on GC 7.0,
	// we will do our best to locate it dynamically
	static gc_stack_ptr get_sb = NULL, my_thread = NULL;
	static std_func unreg_my_thread = NULL;
	if( !t && unreg_my_thread != NULL ) {
		return unreg_my_thread() == GC_SUCCESS;
	} else if( my_thread != NULL ) {
		__stack_base sb;
		int r;
		if( get_sb(&sb) != GC_SUCCESS )
			return 0;
		r = my_thread(&sb);
		return( r == GC_SUCCESS || r == GC_DUPLICATE );
	} else {
		void *self = dlopen(NULL,0);
		my_thread = (gc_stack_ptr)dlsym(self,"GC_register_my_thread");
		get_sb = (gc_stack_ptr)dlsym(self,"GC_get_stack_base");
		unreg_my_thread = (std_func)dlsym(self,"GC_unregister_my_thread");
		if( my_thread == NULL ) my_thread = do_nothing;
		if( get_sb == NULL ) get_sb = do_nothing;
		if( unreg_my_thread == NULL ) unreg_my_thread = (std_func)do_nothing;
		return neko_thread_register(t);
	}
#	endif
}
Beispiel #8
0
/*
 * This may be called from DllMain, and hence operates under unusual
 * constraints.
 */
static GC_thread GC_new_thread(void) {
  int i;
  /* It appears to be unsafe to acquire a lock here, since this	*/
  /* code is apparently not preeemptible on some systems.	*/
  /* (This is based on complaints, not on Microsoft's official	*/
  /* documentation, which says this should perform "only simple	*/
  /* initialization tasks".)					*/
  /* Hence we make do with nonblocking synchronization.		*/

  /* The following should be a noop according to the win32	*/
  /* documentation.  There is empirical evidence that it	*/
  /* isn't.		- HB					*/
# if defined(MPROTECT_VDB)
   if (GC_incremental) SetUnhandledExceptionFilter(GC_write_fault_handler);
# endif
                /* cast away volatile qualifier */
  for (i = 0; InterlockedExchange((IE_t)&thread_table[i].in_use,1) != 0; i++) {
    /* Compare-and-swap would make this cleaner, but that's not 	*/
    /* supported before Windows 98 and NT 4.0.  In Windows 2000,	*/
    /* InterlockedExchange is supposed to be replaced by		*/
    /* InterlockedExchangePointer, but that's not really what I		*/
    /* want here.							*/
    if (i == MAX_THREADS - 1)
      ABORT("too many threads");
  }
  /* Update GC_max_thread_index if necessary.  The following is safe,	*/
  /* and unlike CompareExchange-based solutions seems to work on all	*/
  /* Windows95 and later platforms.					*/
  /* Unfortunately, GC_max_thread_index may be temporarily out of 	*/
  /* bounds, so readers have to compensate.				*/
  while (i > GC_max_thread_index) {
    InterlockedIncrement((IE_t)&GC_max_thread_index);
  }
  if (GC_max_thread_index >= MAX_THREADS) {
    /* We overshot due to simultaneous increments.	*/
    /* Setting it to MAX_THREADS-1 is always safe.	*/
    GC_max_thread_index = MAX_THREADS - 1;
  }
  
# ifdef CYGWIN32
    thread_table[i].pthread_id = pthread_self();
# endif
  if (!DuplicateHandle(GetCurrentProcess(),
	               GetCurrentThread(),
		       GetCurrentProcess(),
		       (HANDLE*)&thread_table[i].handle,
		       0,
		       0,
		       DUPLICATE_SAME_ACCESS)) {
	DWORD last_error = GetLastError();
	GC_printf1("Last error code: %lx\n", last_error);
	ABORT("DuplicateHandle failed");
  }
  thread_table[i].stack_base = GC_get_stack_base();
  /* Up until this point, GC_push_all_stacks considers this thread	*/
  /* invalid.								*/
  if (thread_table[i].stack_base == NULL) 
    ABORT("Failed to find stack base in GC_new_thread");
  /* Up until this point, this entry is viewed as reserved but invalid	*/
  /* by GC_delete_thread.						*/
  thread_table[i].id = GetCurrentThreadId();
  /* If this thread is being created while we are trying to stop	*/
  /* the world, wait here.  Hopefully this can't happen on any	*/
  /* systems that don't allow us to block here.			*/
  while (GC_please_stop) Sleep(20);
  GC_ASSERT(!thread_table[i]->thread_blocked);
  return thread_table + i;
}