/* * mono_threads_create_thread: * * Create a new thread executing START with argument ARG. Store its id into OUT_TID. * Returns: a windows or io-layer handle for the thread. */ MonoThreadHandle* mono_threads_create_thread (MonoThreadStart start, gpointer arg, gsize * const stack_size, MonoNativeThreadId *out_tid) { CreateThreadData *thread_data; gint res; MonoThreadHandle *ret; thread_data = g_new0 (CreateThreadData, 1); mono_refcount_init (thread_data, create_thread_data_destroy); thread_data->start_routine = start; thread_data->start_routine_arg = arg; mono_coop_sem_init (&thread_data->registered, 0); res = mono_threads_platform_create_thread (inner_start_thread, (gpointer) mono_refcount_inc (thread_data), stack_size, out_tid); if (res != 0) { /* ref is not going to be decremented in inner_start_thread */ mono_refcount_dec (thread_data); ret = NULL; goto done; } res = mono_coop_sem_wait (&thread_data->registered, MONO_SEM_FLAGS_NONE); g_assert (res == 0); ret = thread_data->handle; g_assert (ret); done: mono_refcount_dec (thread_data); return ret; }
static void* register_thread (MonoThreadInfo *info, gpointer baseptr) { size_t stsize = 0; guint8 *staddr = NULL; int small_id = mono_thread_info_register_small_id (); gboolean result; mono_thread_info_set_tid (info, mono_native_thread_id_get ()); info->small_id = small_id; info->handle = g_new0 (MonoThreadHandle, 1); mono_refcount_init (info->handle, thread_handle_destroy); mono_os_event_init (&info->handle->event, FALSE); mono_os_sem_init (&info->resume_semaphore, 0); /*set TLS early so SMR works */ mono_native_tls_set_value (thread_info_key, info); THREADS_DEBUG ("registering info %p tid %p small id %x\n", info, mono_thread_info_get_tid (info), info->small_id); if (threads_callbacks.thread_register) { if (threads_callbacks.thread_register (info, baseptr) == NULL) { // g_warning ("thread registation failed\n"); mono_native_tls_set_value (thread_info_key, NULL); g_free (info); return NULL; } } mono_thread_info_get_stack_bounds (&staddr, &stsize); g_assert (staddr); g_assert (stsize); info->stack_start_limit = staddr; info->stack_end = staddr + stsize; info->stackdata = g_byte_array_new (); mono_threads_suspend_register (info); /* Transition it before taking any locks or publishing itself to reduce the chance of others witnessing a detached thread. We can reasonably expect that until this thread gets published, no other thread will try to manipulate it. */ mono_threads_transition_attach (info); mono_thread_info_suspend_lock (); /*If this fail it means a given thread has been registered twice, which doesn't make sense. */ result = mono_thread_info_insert (info); g_assert (result); mono_thread_info_suspend_unlock (); return info; }
void mono_threadpool_worker_init (MonoThreadPoolWorkerCallback callback) { ThreadPoolHillClimbing *hc; const char *threads_per_cpu_env; gint threads_per_cpu; gint threads_count; mono_refcount_init (&worker, destroy); worker.callback = callback; mono_coop_mutex_init (&worker.parked_threads_lock); worker.parked_threads_count = 0; mono_coop_cond_init (&worker.parked_threads_cond); worker.worker_creation_current_second = -1; mono_coop_mutex_init (&worker.worker_creation_lock); worker.heuristic_adjustment_interval = 10; mono_coop_mutex_init (&worker.heuristic_lock); mono_rand_open (); hc = &worker.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; worker.limit_worker_min = threads_count; #if defined (PLATFORM_ANDROID) || defined (HOST_IOS) worker.limit_worker_max = CLAMP (threads_count * 100, MIN (threads_count, 200), MAX (threads_count, 200)); #else worker.limit_worker_max = threads_count * 100; #endif worker.counters._.max_working = worker.limit_worker_min; worker.cpu_usage_state = g_new0 (MonoCpuUsageState, 1); worker.suspended = FALSE; worker.monitor_status = MONITOR_STATUS_NOT_RUNNING; }