Beispiel #1
0
static void
sleep_interrupt (gpointer data)
{
	mono_coop_mutex_lock (&sleep_mutex);
	mono_coop_cond_broadcast (&sleep_cond);
	mono_coop_mutex_unlock (&sleep_mutex);
}
Beispiel #2
0
void
ves_icall_System_IOSelector_Add (gpointer handle, MonoIOSelectorJob *job)
{
	ThreadPoolIOUpdate *update;

	g_assert (handle >= 0);

	g_assert ((job->operation == EVENT_IN) ^ (job->operation == EVENT_OUT));
	g_assert (job->callback);

	if (mono_runtime_is_shutting_down ())
		return;
	if (mono_domain_is_unloading (mono_object_domain (job)))
		return;

	mono_lazy_initialize (&io_status, initialize);

	mono_coop_mutex_lock (&threadpool_io->updates_lock);

	update = update_get_new ();
	update->type = UPDATE_ADD;
	update->data.add.fd = GPOINTER_TO_INT (handle);
	update->data.add.job = job;
	mono_memory_barrier (); /* Ensure this is safely published before we wake up the selector */

	selector_thread_wakeup ();

	mono_coop_mutex_unlock (&threadpool_io->updates_lock);
}
Beispiel #3
0
static inline guint32
sleep_interruptable (guint32 ms, gboolean *alerted)
{
	guint32 start, now, end;

	g_assert (INFINITE == G_MAXUINT32);

	g_assert (alerted);
	*alerted = FALSE;

	start = mono_msec_ticks ();

	if (start < G_MAXUINT32 - ms) {
		end = start + ms;
	} else {
		/* start + ms would overflow guint32 */
		end = G_MAXUINT32;
	}

	mono_lazy_initialize (&sleep_init, sleep_initialize);

	mono_coop_mutex_lock (&sleep_mutex);

	for (now = mono_msec_ticks (); ms == INFINITE || now - start < ms; now = mono_msec_ticks ()) {
		mono_thread_info_install_interrupt (sleep_interrupt, NULL, alerted);
		if (*alerted) {
			mono_coop_mutex_unlock (&sleep_mutex);
			return WAIT_IO_COMPLETION;
		}

		if (ms < INFINITE)
			mono_coop_cond_timedwait (&sleep_cond, &sleep_mutex, end - now);
		else
			mono_coop_cond_wait (&sleep_cond, &sleep_mutex);

		mono_thread_info_uninstall_interrupt (alerted);
		if (*alerted) {
			mono_coop_mutex_unlock (&sleep_mutex);
			return WAIT_IO_COMPLETION;
		}
	}

	mono_coop_mutex_unlock (&sleep_mutex);

	return 0;
}
Beispiel #4
0
static inline guint32
sleep_interruptable (guint32 ms, gboolean *alerted)
{
	gint64 now, end;

	g_assert (INFINITE == G_MAXUINT32);

	g_assert (alerted);
	*alerted = FALSE;

	if (ms != INFINITE)
		end = mono_100ns_ticks () + (ms * 1000 * 10);

	mono_lazy_initialize (&sleep_init, sleep_initialize);

	mono_coop_mutex_lock (&sleep_mutex);

	for (;;) {
		if (ms != INFINITE) {
			now = mono_100ns_ticks ();
			if (now > end)
				break;
		}

		mono_thread_info_install_interrupt (sleep_interrupt, NULL, alerted);
		if (*alerted) {
			mono_coop_mutex_unlock (&sleep_mutex);
			return WAIT_IO_COMPLETION;
		}

		if (ms != INFINITE)
			mono_coop_cond_timedwait (&sleep_cond, &sleep_mutex, (end - now) / 10 / 1000);
		else
			mono_coop_cond_wait (&sleep_cond, &sleep_mutex);

		mono_thread_info_uninstall_interrupt (alerted);
		if (*alerted) {
			mono_coop_mutex_unlock (&sleep_mutex);
			return WAIT_IO_COMPLETION;
		}
	}

	mono_coop_mutex_unlock (&sleep_mutex);

	return 0;
}
Beispiel #5
0
static inline void
break_coop_alertable_wait (gpointer user_data)
{
	BreakCoopAlertableWaitUD *ud = (BreakCoopAlertableWaitUD*)user_data;

	mono_coop_mutex_lock (ud->mutex);
	mono_coop_cond_signal (ud->cond);
	mono_coop_mutex_unlock (ud->mutex);

	g_free (ud);
}
Beispiel #6
0
void
mono_threadpool_ms_io_remove_domain_jobs (MonoDomain *domain)
{
	ThreadPoolIOUpdate *update;

	if (!mono_lazy_is_initialized (&io_status))
		return;

	mono_coop_mutex_lock (&threadpool_io->updates_lock);

	update = update_get_new ();
	update->type = UPDATE_REMOVE_DOMAIN;
	update->data.remove_domain.domain = domain;
	mono_memory_barrier (); /* Ensure this is safely published before we wake up the selector */

	selector_thread_wakeup ();

	mono_coop_cond_wait (&threadpool_io->updates_cond, &threadpool_io->updates_lock);

	mono_coop_mutex_unlock (&threadpool_io->updates_lock);
}
Beispiel #7
0
void
mono_threadpool_ms_io_remove_socket (int fd)
{
	ThreadPoolIOUpdate *update;

	if (!mono_lazy_is_initialized (&io_status))
		return;

	mono_coop_mutex_lock (&threadpool_io->updates_lock);

	update = update_get_new ();
	update->type = UPDATE_REMOVE_SOCKET;
	update->data.add.fd = fd;
	mono_memory_barrier (); /* Ensure this is safely published before we wake up the selector */

	selector_thread_wakeup ();

	mono_coop_cond_wait (&threadpool_io->updates_cond, &threadpool_io->updates_lock);

	mono_coop_mutex_unlock (&threadpool_io->updates_lock);
}
static void
named_regions_unlock (void)
{
	mono_coop_mutex_unlock (&named_regions_mutex);
}
Beispiel #9
0
void
mono_w32handle_namespace_unlock (void)
{
	mono_coop_mutex_unlock (&lock);
}
Beispiel #10
0
static void
selector_thread (gpointer data)
{
	MonoError error;
	MonoGHashTable *states;

	io_selector_running = TRUE;

	if (mono_runtime_is_shutting_down ()) {
		io_selector_running = FALSE;
		return;
	}

	states = mono_g_hash_table_new_type (g_direct_hash, g_direct_equal, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_THREAD_POOL, "i/o thread pool states table");

	for (;;) {
		gint i, j;
		gint res;

		mono_coop_mutex_lock (&threadpool_io->updates_lock);

		for (i = 0; i < threadpool_io->updates_size; ++i) {
			ThreadPoolIOUpdate *update = &threadpool_io->updates [i];

			switch (update->type) {
			case UPDATE_EMPTY:
				break;
			case UPDATE_ADD: {
				gint fd;
				gint operations;
				gpointer k;
				gboolean exists;
				MonoMList *list = NULL;
				MonoIOSelectorJob *job;

				fd = update->data.add.fd;
				g_assert (fd >= 0);

				job = update->data.add.job;
				g_assert (job);

				exists = mono_g_hash_table_lookup_extended (states, GINT_TO_POINTER (fd), &k, (gpointer*) &list);
				list = mono_mlist_append_checked (list, (MonoObject*) job, &error);
				mono_error_assert_ok (&error);
				mono_g_hash_table_replace (states, GINT_TO_POINTER (fd), list);

				operations = get_operations_for_jobs (list);

				mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_THREADPOOL, "io threadpool: %3s fd %3d, operations = %2s | %2s | %3s",
					exists ? "mod" : "add", fd, (operations & EVENT_IN) ? "RD" : "..", (operations & EVENT_OUT) ? "WR" : "..", (operations & EVENT_ERR) ? "ERR" : "...");

				threadpool_io->backend.register_fd (fd, operations, !exists);

				break;
			}
			case UPDATE_REMOVE_SOCKET: {
				gint fd;
				gpointer k;
				MonoMList *list = NULL;

				fd = update->data.remove_socket.fd;
				g_assert (fd >= 0);

				if (mono_g_hash_table_lookup_extended (states, GINT_TO_POINTER (fd), &k, (gpointer*) &list)) {
					mono_g_hash_table_remove (states, GINT_TO_POINTER (fd));

					for (j = i + 1; j < threadpool_io->updates_size; ++j) {
						ThreadPoolIOUpdate *update = &threadpool_io->updates [j];
						if (update->type == UPDATE_ADD && update->data.add.fd == fd)
							memset (update, 0, sizeof (ThreadPoolIOUpdate));
					}

					for (; list; list = mono_mlist_remove_item (list, list)) {
						mono_threadpool_ms_enqueue_work_item (mono_object_domain (mono_mlist_get_data (list)), mono_mlist_get_data (list), &error);
						mono_error_assert_ok (&error);
					}

					mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_THREADPOOL, "io threadpool: del fd %3d", fd);
					threadpool_io->backend.remove_fd (fd);
				}

				break;
			}
			case UPDATE_REMOVE_DOMAIN: {
				MonoDomain *domain;

				domain = update->data.remove_domain.domain;
				g_assert (domain);

				FilterSockaresForDomainData user_data = { .domain = domain, .states = states };
				mono_g_hash_table_foreach (states, filter_jobs_for_domain, &user_data);

				for (j = i + 1; j < threadpool_io->updates_size; ++j) {
					ThreadPoolIOUpdate *update = &threadpool_io->updates [j];
					if (update->type == UPDATE_ADD && mono_object_domain (update->data.add.job) == domain)
						memset (update, 0, sizeof (ThreadPoolIOUpdate));
				}

				break;
			}
			default:
				g_assert_not_reached ();
			}
		}

		mono_coop_cond_broadcast (&threadpool_io->updates_cond);

		if (threadpool_io->updates_size > 0) {
			threadpool_io->updates_size = 0;
			memset (&threadpool_io->updates, 0, UPDATES_CAPACITY * sizeof (ThreadPoolIOUpdate));
		}

		mono_coop_mutex_unlock (&threadpool_io->updates_lock);

		mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_THREADPOOL, "io threadpool: wai");

		res = threadpool_io->backend.event_wait (wait_callback, states);

		if (res == -1 || mono_runtime_is_shutting_down ())
			break;
	}

	mono_g_hash_table_destroy (states);

	io_selector_running = FALSE;
}