Example #1
0
static void
file_mmap_init (void)
{
retry:	
	switch (mmap_init_state) {
	case  0:
		if (InterlockedCompareExchange (&mmap_init_state, 1, 0) != 0)
			goto retry;
		named_regions = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, NULL);
		mono_mutex_init (&named_regions_mutex);

		mono_atomic_store_release (&mmap_init_state, 2);
		break;

	case 1:
		do {
			g_usleep (1000); /* Been init'd by other threads, this is very rare. */
		} while (mmap_init_state != 2);
		break;
	case 2:
		break;
	default:
		g_error ("Invalid init state %d", mmap_init_state);
	}
}
Example #2
0
/**
 * InitializeCriticalSection:
 * @section: The critical section to initialise
 *
 * Initialises a critical section.
 */
void InitializeCriticalSection(WapiCriticalSection *section)
{
	int ret;
	
	mono_once(&attr_key_once, attr_init);
	ret = mono_mutex_init(&section->mutex, &attr);
	g_assert (ret == 0);
}
Example #3
0
static void
noshm_semaphores_init (void)
{
	int i;

	for (i = 0; i < _WAPI_SHARED_SEM_COUNT; i++) 
		mono_mutex_init (&noshm_sems [i]);
}
Example #4
0
void
sgen_workers_init (int num_workers)
{
	int i;

	if (!sgen_get_major_collector ()->is_parallel)
		return;

	//g_print ("initing %d workers\n", num_workers);

	workers_num = num_workers;

	workers_data = sgen_alloc_internal_dynamic (sizeof (WorkerData) * num_workers, INTERNAL_MEM_WORKER_DATA, TRUE);
	memset (workers_data, 0, sizeof (WorkerData) * num_workers);

	MONO_SEM_INIT (&workers_waiting_sem, 0);
	MONO_SEM_INIT (&workers_done_sem, 0);

	sgen_gray_object_queue_init_with_alloc_prepare (&workers_distribute_gray_queue,
			workers_gray_queue_share_redirect, &workers_gc_thread_data);
	mono_mutex_init (&workers_gc_thread_data.stealable_stack_mutex, NULL);
	workers_gc_thread_data.stealable_stack_fill = 0;

	if (sgen_get_major_collector ()->alloc_worker_data)
		workers_gc_thread_data.major_collector_data = sgen_get_major_collector ()->alloc_worker_data ();

	for (i = 0; i < workers_num; ++i) {
		/* private gray queue is inited by the thread itself */
		mono_mutex_init (&workers_data [i].stealable_stack_mutex, NULL);
		workers_data [i].stealable_stack_fill = 0;

		if (sgen_get_major_collector ()->alloc_worker_data)
			workers_data [i].major_collector_data = sgen_get_major_collector ()->alloc_worker_data ();
	}

	LOCK_INIT (workers_job_queue_mutex);

	sgen_register_fixed_internal_mem_type (INTERNAL_MEM_JOB_QUEUE_ENTRY, sizeof (JobQueueEntry));

	mono_counters_register ("Stolen from self lock", MONO_COUNTER_GC | MONO_COUNTER_LONG, &stat_workers_stolen_from_self_lock);
	mono_counters_register ("Stolen from self no lock", MONO_COUNTER_GC | MONO_COUNTER_LONG, &stat_workers_stolen_from_self_no_lock);
	mono_counters_register ("Stolen from others", MONO_COUNTER_GC | MONO_COUNTER_LONG, &stat_workers_stolen_from_others);
	mono_counters_register ("# workers waited", MONO_COUNTER_GC | MONO_COUNTER_LONG, &stat_workers_num_waited);
}
Example #5
0
void
mono_counters_init (void)
{
	if (initialized)
		return;

	mono_mutex_init (&counters_mutex);

	initialize_system_counters ();

	initialized = TRUE;
}
Example #6
0
void
sgen_thread_pool_init (int num_threads, SgenThreadPoolThreadInitFunc init_func, SgenThreadPoolIdleJobFunc idle_func, SgenThreadPoolContinueIdleJobFunc continue_idle_func, void **thread_datas)
{
	SGEN_ASSERT (0, num_threads == 1, "We only support 1 thread pool thread for now.");

	mono_mutex_init (&lock);
	mono_cond_init (&work_cond, NULL);
	mono_cond_init (&done_cond, NULL);

	thread_init_func = init_func;
	idle_job_func = idle_func;
	continue_idle_job_func = continue_idle_func;

	mono_native_thread_create (&thread, thread_func, thread_datas ? thread_datas [0] : NULL);
}
Example #7
0
void mono_profiler_startup (const char *desc)
{
	MonoProfiler *prof = g_new0 (MonoProfiler, 1);

	mono_mutex_init (&mismatched_files_section);
	prof->mismatched_files_hash = g_hash_table_new (mismatched_files_guint32_hash, mismatched_files_guint32_equal);
	prof->saved_strings_hash = g_hash_table_new (NULL, NULL);
	prof->string_locations_hash = g_hash_table_new (mismatched_files_guint32_hash, mismatched_files_guint32_equal);

	mono_profiler_install (prof, profiler_shutdown);
	mono_profiler_install_runtime_initialized (runtime_initialized_cb);
	mono_profiler_install_iomap (mono_portability_iomap_event);
	mono_profiler_install_allocation (mono_portability_remember_alloc);

	mono_profiler_set_events (MONO_PROFILE_ALLOCATIONS | MONO_PROFILE_IOMAP_EVENTS);
}
Example #8
0
/*
Returns a recursive mutex that is safe under suspension.

A suspension safe mutex means one that can handle this scenario:

mutex M

thread 1:
1)lock M
2)suspend thread 2
3)unlock M
4)lock M

thread 2:
5)lock M

Say (1) happens before (5) and (5) happens before (2).
This means that thread 2 was suspended by the kernel because
it's waiting on mutext M.

Thread 1 then proceed to suspend thread 2 and unlock/lock the
mutex.

If the kernel implements mutexes with FIFO wait lists, this means
that thread 1 will be blocked waiting for thread 2 acquire the lock.
Since thread 2 is suspended, we have a deadlock.

A suspend safe mutex is an unfair lock but will schedule any runable
thread that is waiting for a the lock.

This problem was witnessed on OSX in mono/tests/thread-exit.cs.

*/
int
mono_mutex_init_suspend_safe (mono_mutex_t *mutex)
{
#if defined(__APPLE__)
	int res;
	pthread_mutexattr_t attr;

	pthread_mutexattr_init (&attr);
	pthread_mutexattr_settype (&attr, PTHREAD_MUTEX_RECURSIVE);
	pthread_mutexattr_setpolicy_np (&attr, _PTHREAD_MUTEX_POLICY_FIRSTFIT);
	res = pthread_mutex_init (mutex, &attr);
	pthread_mutexattr_destroy (&attr);

	return res;
#else
	return mono_mutex_init (mutex);
#endif
}
Example #9
0
static void
ensure_initialized (gboolean *enable_worker_tracking)
{
	ThreadPoolHillClimbing *hc;
	const char *threads_per_cpu_env;
	gint threads_per_cpu;
	gint threads_count;

	if (enable_worker_tracking) {
		// TODO implement some kind of switch to have the possibily to use it
		*enable_worker_tracking = FALSE;
	}

	if (status >= STATUS_INITIALIZED)
		return;
	if (status == STATUS_INITIALIZING || InterlockedCompareExchange (&status, STATUS_INITIALIZING, STATUS_NOT_INITIALIZED) != STATUS_NOT_INITIALIZED) {
		while (status == STATUS_INITIALIZING)
			mono_thread_info_yield ();
		g_assert (status >= STATUS_INITIALIZED);
		return;
	}

	g_assert (!threadpool);
	threadpool = g_new0 (ThreadPool, 1);
	g_assert (threadpool);

	threadpool->domains = g_ptr_array_new ();
	mono_mutex_init_recursive (&threadpool->domains_lock);

	threadpool->parked_threads = g_ptr_array_new ();
	mono_mutex_init (&threadpool->parked_threads_lock);

	threadpool->working_threads = g_ptr_array_new ();
	mono_mutex_init (&threadpool->working_threads_lock);

	threadpool->heuristic_adjustment_interval = 10;
	mono_mutex_init (&threadpool->heuristic_lock);

	mono_rand_open ();

	hc = &threadpool->heuristic_hill_climbing;

	hc->wave_period = HILL_CLIMBING_WAVE_PERIOD;
	hc->max_thread_wave_magnitude = HILL_CLIMBING_MAX_WAVE_MAGNITUDE;
	hc->thread_magnitude_multiplier = (gdouble) HILL_CLIMBING_WAVE_MAGNITUDE_MULTIPLIER;
	hc->samples_to_measure = hc->wave_period * HILL_CLIMBING_WAVE_HISTORY_SIZE;
	hc->target_throughput_ratio = (gdouble) HILL_CLIMBING_BIAS;
	hc->target_signal_to_noise_ratio = (gdouble) HILL_CLIMBING_TARGET_SIGNAL_TO_NOISE_RATIO;
	hc->max_change_per_second = (gdouble) HILL_CLIMBING_MAX_CHANGE_PER_SECOND;
	hc->max_change_per_sample = (gdouble) HILL_CLIMBING_MAX_CHANGE_PER_SAMPLE;
	hc->sample_interval_low = HILL_CLIMBING_SAMPLE_INTERVAL_LOW;
	hc->sample_interval_high = HILL_CLIMBING_SAMPLE_INTERVAL_HIGH;
	hc->throughput_error_smoothing_factor = (gdouble) HILL_CLIMBING_ERROR_SMOOTHING_FACTOR;
	hc->gain_exponent = (gdouble) HILL_CLIMBING_GAIN_EXPONENT;
	hc->max_sample_error = (gdouble) HILL_CLIMBING_MAX_SAMPLE_ERROR_PERCENT;
	hc->current_control_setting = 0;
	hc->total_samples = 0;
	hc->last_thread_count = 0;
	hc->average_throughput_noise = 0;
	hc->elapsed_since_last_change = 0;
	hc->accumulated_completion_count = 0;
	hc->accumulated_sample_duration = 0;
	hc->samples = g_new0 (gdouble, hc->samples_to_measure);
	hc->thread_counts = g_new0 (gdouble, hc->samples_to_measure);
	hc->random_interval_generator = rand_create ();
	hc->current_sample_interval = rand_next (&hc->random_interval_generator, hc->sample_interval_low, hc->sample_interval_high);

	if (!(threads_per_cpu_env = g_getenv ("MONO_THREADS_PER_CPU")))
		threads_per_cpu = 1;
	else
		threads_per_cpu = CLAMP (atoi (threads_per_cpu_env), 1, 50);

	threads_count = mono_cpu_count () * threads_per_cpu;

	threadpool->limit_worker_min = threadpool->limit_io_min = threads_count;
	threadpool->limit_worker_max = threadpool->limit_io_max = threads_count * 100;

	threadpool->counters._.max_working = threadpool->limit_worker_min;

	threadpool->cpu_usage_state = g_new0 (MonoCpuUsageState, 1);

	threadpool->suspended = FALSE;

	status = STATUS_INITIALIZED;
}
Example #10
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;
}
Example #11
0
void
mono_thread_pool_init (void)
{
	gint threads_per_cpu = 1;
	gint thread_count;
	gint cpu_count = mono_cpu_count ();
	int result;

	if (tp_inited == 2)
		return;

	result = InterlockedCompareExchange (&tp_inited, 1, 0);
	if (result == 1) {
		while (1) {
			SleepEx (1, FALSE);
			if (tp_inited == 2)
				return;
		}
	}

	MONO_GC_REGISTER_ROOT_FIXED (socket_io_data.sock_to_state);
	mono_mutex_init_recursive (&socket_io_data.io_lock);
	if (g_getenv ("MONO_THREADS_PER_CPU") != NULL) {
		threads_per_cpu = atoi (g_getenv ("MONO_THREADS_PER_CPU"));
		if (threads_per_cpu < 1)
			threads_per_cpu = 1;
	}

	thread_count = MIN (cpu_count * threads_per_cpu, 100 * cpu_count);
	threadpool_init (&async_tp, thread_count, MAX (100 * cpu_count, thread_count), async_invoke_thread);
	threadpool_init (&async_io_tp, cpu_count * 2, cpu_count * 4, async_invoke_thread);
	async_io_tp.is_io = TRUE;

	async_call_klass = mono_class_from_name (mono_defaults.corlib, "System", "MonoAsyncCall");
	g_assert (async_call_klass);

	mono_mutex_init (&threads_lock);
	threads = g_ptr_array_sized_new (thread_count);
	g_assert (threads);

	mono_mutex_init_recursive (&wsqs_lock);
	wsqs = g_ptr_array_sized_new (MAX (100 * cpu_count, thread_count));

#ifndef DISABLE_PERFCOUNTERS
	async_tp.pc_nitems = init_perf_counter ("Mono Threadpool", "Work Items Added");
	g_assert (async_tp.pc_nitems);

	async_io_tp.pc_nitems = init_perf_counter ("Mono Threadpool", "IO Work Items Added");
	g_assert (async_io_tp.pc_nitems);

	async_tp.pc_nthreads = init_perf_counter ("Mono Threadpool", "# of Threads");
	g_assert (async_tp.pc_nthreads);

	async_io_tp.pc_nthreads = init_perf_counter ("Mono Threadpool", "# of IO Threads");
	g_assert (async_io_tp.pc_nthreads);
#endif
	tp_inited = 2;
#ifdef DEBUG
	signal (SIGALRM, signal_handler);
	alarm (2);
#endif

	MONO_SEM_INIT (&monitor_sem, 0);
	monitor_state = MONITOR_STATE_AWAKE;
	monitor_njobs = 0;
}