Esempio n. 1
0
void
mono_gc_base_init (void)
{
  MonoThreadInfoCallbacks cb;
  int dummy;

  if (gc_initialized)
    return;

  mono_counters_init ();

  corgc_init ();

  memset (&cb, 0, sizeof (cb));
  cb.thread_register = corgc_thread_register;
  cb.thread_unregister = corgc_thread_unregister;
  cb.mono_method_is_critical = (gboolean(*)(void*))mono_runtime_is_critical_method;
#ifndef HOST_WIN32
  cb.thread_exit = mono_gc_pthread_exit;
  cb.mono_gc_pthread_create = mono_gc_pthread_create;
#endif
  mono_threads_init (&cb, sizeof (CorgcThreadInfo));
  mono_thread_info_attach (&dummy);

  mono_gc_enable_events ();
  gc_initialized = TRUE;
}
Esempio n. 2
0
int
main (void)
{
	MonoThreadInfoCallbacks cb = { NULL };
	MonoThreadInfoRuntimeCallbacks ticallbacks;
	int res = 0;

	CHECKED_MONO_INIT ();
	mono_threads_init (&cb, sizeof (MonoThreadInfo));
	memset (&ticallbacks, 0, sizeof (ticallbacks));
	ticallbacks.thread_state_init = thread_state_init;
	mono_threads_runtime_init (&ticallbacks);

	mono_thread_info_attach ((gpointer)&cb);

	// benchmark_conc ();
	// benchmark_glib ();

	res += single_writer_single_reader ();
	res += parallel_writer_single_reader ();
	res += single_writer_parallel_reader ();
	res += parallel_writer_parallel_reader ();

	return res;
}
Esempio n. 3
0
int
main (void)
{
	MonoThreadInfoRuntimeCallbacks ticallbacks;
	int res = 0;

	CHECKED_MONO_INIT ();
	mono_thread_info_init (sizeof (MonoThreadInfo));
	memset (&ticallbacks, 0, sizeof (ticallbacks));
	ticallbacks.thread_state_init = thread_state_init;
	mono_thread_info_runtime_init (&ticallbacks);
#ifndef HOST_WIN32
	mono_w32handle_init ();
#endif

	mono_thread_info_attach ();

	// benchmark_conc ();
	// benchmark_glib ();

	res += single_writer_single_reader ();
	res += parallel_writer_single_reader ();
	res += single_writer_parallel_reader ();
	res += parallel_writer_parallel_reader ();

	return res;
}
Esempio n. 4
0
static DWORD WINAPI
inner_start_thread (LPVOID arg)
{
	ThreadStartInfo *start_info = arg;
	void *t_arg = start_info->arg;
	int post_result;
	LPTHREAD_START_ROUTINE start_func = start_info->start_routine;
	DWORD result;
	gboolean suspend = start_info->suspend;
	HANDLE suspend_event = start_info->suspend_event;
	MonoThreadInfo *info;

	info = mono_thread_info_attach (&result);
	info->runtime_thread = TRUE;
	info->create_suspended = suspend;

	post_result = MONO_SEM_POST (&(start_info->registered));
	g_assert (!post_result);

	if (suspend) {
		WaitForSingleObject (suspend_event, INFINITE); /* caller will suspend the thread before setting the event. */
		CloseHandle (suspend_event);
	}

	result = start_func (t_arg);

	mono_thread_info_detach ();

	return result;
}
Esempio n. 5
0
static gsize WINAPI
inner_start_thread (gpointer data)
{
	CreateThreadData *thread_data;
	MonoThreadInfo *info;
	MonoThreadStart start_routine;
	gpointer start_routine_arg;
	gsize start_routine_res;
	gsize dummy;

	thread_data = (CreateThreadData*) data;
	g_assert (thread_data);

	start_routine = thread_data->start_routine;
	start_routine_arg = thread_data->start_routine_arg;

	info = mono_thread_info_attach (&dummy);
	info->runtime_thread = TRUE;

	thread_data->handle = mono_threads_open_thread_handle (info->handle);

	mono_coop_sem_post (&thread_data->registered);

	mono_refcount_dec (thread_data);

	/* thread_data is not valid anymore */
	thread_data = NULL;

	/* Run the actual main function of the thread */
	start_routine_res = start_routine (start_routine_arg);

	mono_thread_info_exit (start_routine_res);

	g_assert_not_reached ();
}
Esempio n. 6
0
static void*
pw_sr_thread (void *arg)
{
	int i, idx = 1000 * GPOINTER_TO_INT (arg);
	mono_thread_info_attach ();

	for (i = 0; i < 1000; ++i) {
		mono_os_mutex_lock (&global_mutex);
		mono_conc_hashtable_insert (hash, GINT_TO_POINTER (i + idx), GINT_TO_POINTER (i + 1));
		mono_os_mutex_unlock (&global_mutex);
	}
	return NULL;
}
Esempio n. 7
0
static void*
inner_start_thread (void *arg)
{
	StartInfo *start_info = (StartInfo *) arg;
	void *t_arg = start_info->arg;
	int res;
	void *(*start_func)(void*) = start_info->start_routine;
	guint32 flags = start_info->flags;
	void *result;
	HANDLE handle;
	MonoThreadInfo *info;

	/* Register the thread with the io-layer */
	handle = wapi_create_thread_handle ();
	if (!handle) {
		res = MONO_SEM_POST (&(start_info->registered));
		g_assert (!res);
		return NULL;
	}
	start_info->handle = handle;

	info = mono_thread_info_attach (&result);
	MONO_PREPARE_BLOCKING

	info->runtime_thread = TRUE;
	info->handle = handle;

	if (flags & CREATE_SUSPENDED) {
		info->create_suspended = TRUE;
		MONO_SEM_INIT (&info->create_suspended_sem, 0);
	}

	/* start_info is not valid after this */
	res = MONO_SEM_POST (&(start_info->registered));
	g_assert (!res);
	start_info = NULL;

	if (flags & CREATE_SUSPENDED) {
		while (MONO_SEM_WAIT (&info->create_suspended_sem) != 0 &&
			   errno == EINTR);
		MONO_SEM_DESTROY (&info->create_suspended_sem);
	}

	MONO_FINISH_BLOCKING
	/* Run the actual main function of the thread */
	result = start_func (t_arg);

	mono_threads_core_exit (GPOINTER_TO_UINT (result));
	g_assert_not_reached ();
}
Esempio n. 8
0
/**
 * mono_threads_attach_tools_thread
 *
 * Attach the current thread as a tool thread. DON'T USE THIS FUNCTION WITHOUT READING ALL DISCLAIMERS.
 *
 * A tools thread is a very special kind of thread that needs access to core runtime facilities but should
 * not be counted as a regular thread for high order facilities such as executing managed code or accessing
 * the managed heap.
 *
 * This is intended only to tools such as a profiler than needs to be able to use our lock-free support when
 * doing things like resolving backtraces in their background processing thread.
 */
void
mono_threads_attach_tools_thread (void)
{
	int dummy = 0;
	MonoThreadInfo *info;

	/* Must only be called once */
	g_assert (!mono_native_tls_get_value (thread_info_key));

	info = mono_thread_info_attach (&dummy);
	g_assert (info);

	info->tools_thread = TRUE;
}
Esempio n. 9
0
static void*
pw_pr_w_del_thread (void *arg)
{
	int i, idx = 1000 * GPOINTER_TO_INT (arg);

	mono_thread_info_attach ();

	for (i = idx; i < idx + 1000; i++) {
		mono_os_mutex_lock (&global_mutex);
		mono_conc_hashtable_remove (hash, GINT_TO_POINTER (i + 1));
		mono_os_mutex_unlock (&global_mutex);
	}
	return NULL;
}
Esempio n. 10
0
static void*
pr_sw_thread (void *arg)
{
	int i = 0, idx = 100 * GPOINTER_TO_INT (arg);
	mono_thread_info_attach ();

	while (i < 100) {
		gpointer res = mono_conc_hashtable_lookup (hash, GINT_TO_POINTER (i + idx + 1));
		if (!res)
			continue;
		if (res != GINT_TO_POINTER ((i + idx) * 2 + 1))
			return GINT_TO_POINTER (i);
		++i;
	}
	return NULL;
}
Esempio n. 11
0
void
mono_gc_base_init (void)
{
	MonoThreadInfoCallbacks cb;
	int dummy;

	mono_counters_init ();

	memset (&cb, 0, sizeof (cb));
	/* TODO: This casts away an incompatible pointer type warning in the same
	         manner that boehm-gc does it. This is probably worth investigating
	         more carefully. */
	cb.mono_method_is_critical = (gpointer)mono_runtime_is_critical_method;

	mono_threads_init (&cb, sizeof (MonoThreadInfo));

	mono_thread_info_attach (&dummy);
}
Esempio n. 12
0
static gsize WINAPI
inner_start_thread (gpointer data)
{
	CreateThreadData *thread_data;
	MonoThreadInfo *info;
	MonoThreadStart start_routine;
	gpointer start_routine_arg;
	guint32 start_routine_res;
	gint32 priority;
	gsize dummy;

	thread_data = (CreateThreadData*) data;
	g_assert (thread_data);

	start_routine = thread_data->start_routine;
	start_routine_arg = thread_data->start_routine_arg;

	priority = thread_data->priority;

	info = mono_thread_info_attach (&dummy);
	info->runtime_thread = TRUE;

	mono_threads_platform_set_priority (info, priority);

	thread_data->handle = mono_thread_info_duplicate_handle (info);

	mono_coop_sem_post (&thread_data->registered);

	if (InterlockedDecrement (&thread_data->ref) == 0) {
		mono_coop_sem_destroy (&thread_data->registered);
		g_free (thread_data);
	}

	/* thread_data is not valid anymore */
	thread_data = NULL;

	/* Run the actual main function of the thread */
	start_routine_res = start_routine (start_routine_arg);

	mono_threads_platform_exit (start_routine_res);

	g_assert_not_reached ();
}
Esempio n. 13
0
static void*
inner_start_thread (void *arg)
{
	ThreadStartInfo *start_info = arg;
	void *t_arg = start_info->arg;
	int post_result;
	void *(*start_func)(void*) = start_info->start_routine;
	void *result;

	mono_thread_info_attach (&result);

	post_result = MONO_SEM_POST (&(start_info->registered));
	g_assert (!post_result);

	result = start_func (t_arg);
	g_assert (!mono_domain_get ());


	return result;
}
Esempio n. 14
0
static void*
pw_pr_r_thread (void *arg)
{
	int key, val, i;
	mono_thread_info_attach ();

	/* i will not be incremented as long as running is set to 1, this guarantee that
	   we loop over all the keys at least once after the writer threads have finished */
	for (i = 0; i < 2; i += 1 - running) {
		for (key = 1; key < 3 * 1000 + 1; key++) {
			val = GPOINTER_TO_INT (mono_conc_hashtable_lookup (hash, GINT_TO_POINTER (key)));

			if (!val)
				continue;
			if (key != val)
				return GINT_TO_POINTER (key);
		}
	}
	return NULL;
}
Esempio n. 15
0
static void*
inner_start_thread (void *arg)
{
	StartInfo *start_info = arg;
	void *t_arg = start_info->arg;
	int res;
	void *(*start_func)(void*) = start_info->start_routine;
	guint32 flags = start_info->flags;
	void *result;
	HANDLE handle;
	MonoThreadInfo *info;

	/* Register the thread with the io-layer */
	handle = wapi_create_thread_handle ();
	if (!handle) {
		res = MONO_SEM_POST (&(start_info->registered));
		g_assert (!res);
		return NULL;
	}
	start_info->handle = handle;

	info = mono_thread_info_attach (&result);
	info->runtime_thread = TRUE;
	info->handle = handle;

	if (flags & CREATE_SUSPENDED) {
		info->create_suspended = TRUE;
		MONO_SEM_INIT (&info->create_suspended_sem, 0);
	}

	/* start_info is not valid after this */
	res = MONO_SEM_POST (&(start_info->registered));
	g_assert (!res);
	start_info = NULL;

	if (flags & CREATE_SUSPENDED) {
		while (MONO_SEM_WAIT (&info->create_suspended_sem) != 0 &&
			   errno == EINTR);
		MONO_SEM_DESTROY (&info->create_suspended_sem);
	}

	/* Run the actual main function of the thread */
	result = start_func (t_arg);

	/*
	mono_thread_info_detach ();
	*/

#if defined(__native_client__)
	nacl_shutdown_gc_thread();
#endif

	wapi_thread_handle_set_exited (handle, GPOINTER_TO_UINT (result));
	/* This is needed by mono_threads_core_unregister () which is called later */
	info->handle = NULL;

	g_assert (mono_threads_get_callbacks ()->thread_exit);
	mono_threads_get_callbacks ()->thread_exit (NULL);
	g_assert_not_reached ();
	return result;
}
Esempio n. 16
0
gboolean
mono_gc_register_thread (void *baseptr)
{
	return mono_thread_info_attach (baseptr) != NULL;
}
Esempio n. 17
0
void
mono_gc_base_init (void)
{
    MonoThreadInfoCallbacks cb;
    const char *env;
    int dummy;

    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) && !defined(__native_client__)
    {
        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 = g_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 if (g_str_has_prefix (opt, "toggleref-test")) {
                register_test_toggleref_callback ();
                continue;
            } else {
                /* Could be a parameter for sgen */
                /*
                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.thread_unregister = boehm_thread_unregister;
    cb.mono_method_is_critical = (gpointer)mono_runtime_is_critical_method;
#ifndef HOST_WIN32
    cb.thread_exit = mono_gc_pthread_exit;
    cb.mono_gc_pthread_create = (gpointer)mono_gc_pthread_create;
#endif

    mono_threads_init (&cb, sizeof (MonoThreadInfo));
    mono_mutex_init (&mono_gc_lock);

    mono_thread_info_attach (&dummy);

    mono_gc_enable_events ();
    gc_initialized = TRUE;
}