Пример #1
0
static void
workers_wait (void)
{
	State old_state, new_state;
	++stat_workers_num_waited;
	do {
		old_state = new_state = workers_state;
		/*
		 * Only the last worker thread awake can set the done
		 * posted flag, and since we're awake and haven't set
		 * it yet, it cannot be set.
		 */
		g_assert (!old_state.data.done_posted);
		++new_state.data.num_waiting;
		/*
		 * This is the only place where we use
		 * workers_gc_in_progress in the worker threads.
		 */
		if (new_state.data.num_waiting == workers_num && !old_state.data.gc_in_progress)
			new_state.data.done_posted = 1;
	} while (!set_state (old_state, new_state));
	mono_memory_barrier ();
	if (new_state.data.done_posted)
		MONO_SEM_POST (&workers_done_sem);
	MONO_SEM_WAIT (&workers_waiting_sem);
}
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;
}
Пример #3
0
void
mono_thread_info_self_suspend (void)
{
	gboolean ret;
	MonoThreadInfo *info = mono_thread_info_current ();
	if (!info)
		return;

	EnterCriticalSection (&info->suspend_lock);

	THREADS_DEBUG ("self suspend IN COUNT %d\n", info->suspend_count);

	g_assert (info->suspend_count == 0);
	++info->suspend_count;

	info->thread_state |= STATE_SELF_SUSPENDED;

	ret = mono_threads_get_runtime_callbacks ()->thread_state_init_from_sigctx (&info->suspend_state, NULL);
	g_assert (ret);

	LeaveCriticalSection (&info->suspend_lock);

	while (MONO_SEM_WAIT (&info->resume_semaphore) != 0) {
		/*if (EINTR != errno) ABORT("sem_wait failed"); */
	}

	g_assert (!info->async_target); /*FIXME this should happen normally for suspend. */
	MONO_SEM_POST (&info->finish_resume_semaphore);
}
Пример #4
0
void
mono_threads_notify_initiator_of_suspend (MonoThreadInfo* info)
{
	THREADS_SUSPEND_DEBUG ("[INITIATOR-NOTIFY-SUSPEND] %p\n", mono_thread_info_get_tid (info));
	MONO_SEM_POST (&suspend_semaphore);
	InterlockedIncrement (&suspend_posts);
}
Пример #5
0
static void
ms_signal_sweep_done (void)
{
	if (!concurrent_sweep)
		return;

	MONO_SEM_POST (&ms_sweep_done_semaphore);
}
Пример #6
0
/*
The return value is only valid until a matching mono_thread_info_resume is called
*/
static MonoThreadInfo*
mono_thread_info_suspend_sync (MonoNativeThreadId tid, gboolean interrupt_kernel, const char **error_condition)
{
	MonoThreadHazardPointers *hp = mono_hazard_pointer_get ();	
	MonoThreadInfo *info = mono_thread_info_lookup (tid); /*info on HP1*/
	if (!info) {
		*error_condition = "Thread not found";
		return NULL;
	}

	MONO_SEM_WAIT_UNITERRUPTIBLE (&info->suspend_semaphore);

	/*thread is on the process of detaching*/
	if (mono_thread_info_run_state (info) > STATE_RUNNING) {
		mono_hazard_pointer_clear (hp, 1);
		*error_condition = "Thread is detaching";
		return NULL;
	}

	THREADS_DEBUG ("suspend %x IN COUNT %d\n", tid, info->suspend_count);

	if (info->suspend_count) {
		++info->suspend_count;
		mono_hazard_pointer_clear (hp, 1);
		MONO_SEM_POST (&info->suspend_semaphore);
		return info;
	}

	if (!mono_threads_core_suspend (info)) {
		MONO_SEM_POST (&info->suspend_semaphore);
		mono_hazard_pointer_clear (hp, 1);
		*error_condition = "Could not suspend thread";
		return NULL;
	}

	if (interrupt_kernel) 
		mono_threads_core_interrupt (info);

	++info->suspend_count;
	info->thread_state |= STATE_SUSPENDED;
	MONO_SEM_POST (&info->suspend_semaphore);

	return info;
}
Пример #7
0
static void
ms_signal_sweep_command (void)
{
	if (!concurrent_sweep)
		return;

	g_assert (!ms_sweep_in_progress);
	ms_sweep_in_progress = TRUE;
	MONO_SEM_POST (&ms_sweep_cmd_semaphore);
}
Пример #8
0
gboolean
mono_threads_core_resume (MonoThreadInfo *info)
{
	MONO_SEM_POST (&info->resume_semaphore);
	while (MONO_SEM_WAIT (&info->finish_resume_semaphore) != 0) {
		/* g_assert (errno == EINTR); */
	}

	return TRUE;
}
Пример #9
0
static gboolean
mono_thread_info_core_resume (MonoThreadInfo *info)
{
	gboolean result;
	MonoNativeThreadId tid = mono_thread_info_get_tid (info);
	if (info->create_suspended) {
		/* Have to special case this, as the normal suspend/resume pair are racy, they don't work if he resume is received before the suspend */
		info->create_suspended = FALSE;
		mono_threads_core_resume_created (info, tid);
		return TRUE;
	}

	MONO_SEM_WAIT_UNITERRUPTIBLE (&info->suspend_semaphore);

	THREADS_DEBUG ("resume %x IN COUNT %d\n", tid, info->suspend_count);

	if (info->suspend_count <= 0) {
		MONO_SEM_POST (&info->suspend_semaphore);
		return FALSE;
	}

	/*
	 * The theory here is that if we manage to suspend the thread it means it did not
	 * start cleanup since it take the same lock. 
	*/
	g_assert (mono_thread_info_get_tid (info));

	if (--info->suspend_count == 0) {
		if (mono_thread_info_suspend_state (info) == STATE_SELF_SUSPENDED) {
			MONO_SEM_POST (&info->resume_semaphore);
			MONO_SEM_WAIT_UNITERRUPTIBLE (&info->finish_resume_semaphore);
			result = TRUE;
		} else {
			result = mono_threads_core_resume (info);
		}
		info->thread_state &= ~SUSPEND_STATE_MASK;
	} else {
		result = TRUE;
	}

	MONO_SEM_POST (&info->suspend_semaphore);
	return result;
}
Пример #10
0
gboolean
mono_thread_info_resume (MonoNativeThreadId tid)
{
	gboolean result = TRUE;
	MonoThreadHazardPointers *hp = mono_hazard_pointer_get ();	
	MonoThreadInfo *info = mono_thread_info_lookup (tid); /*info on HP1*/

	if (!info)
		return FALSE;

	if (info->create_suspended) {
		/* Have to special case this, as the normal suspend/resume pair are racy, they don't work if he resume is received before the suspend */
		info->create_suspended = FALSE;
		mono_threads_core_resume_created (info, tid);
		return TRUE;
	}

	MONO_SEM_WAIT_UNITERRUPTIBLE (&info->suspend_semaphore);

	THREADS_DEBUG ("resume %x IN COUNT %d\n",tid, info->suspend_count);

	if (info->suspend_count <= 0) {
		MONO_SEM_POST (&info->suspend_semaphore);
		mono_hazard_pointer_clear (hp, 1);
		return FALSE;
	}

	/*
	 * The theory here is that if we manage to suspend the thread it means it did not
	 * start cleanup since it take the same lock. 
	*/
	g_assert (mono_thread_info_get_tid (info));

	if (--info->suspend_count == 0)
		result = mono_thread_info_resume_internal (info);

	MONO_SEM_POST (&info->suspend_semaphore);
	mono_hazard_pointer_clear (hp, 1);
	mono_atomic_store_release (&mono_thread_info_current ()->inside_critical_region, FALSE);

	return result;
}
Пример #11
0
static void
threadpool_kill_idle_threads (ThreadPool *tp)
{
	gint n;

	n = (gint) InterlockedCompareExchange (&tp->max_threads, 0, -1);
	while (n) {
		n--;
		MONO_SEM_POST (&tp->new_job);
	}
}
Пример #12
0
static void
threadpool_append_jobs (ThreadPool *tp, MonoObject **jobs, gint njobs)
{
	MonoObject *ar;
	gint i;

	if (mono_runtime_is_shutting_down ())
		return;

	if (tp->pool_status == 0 && InterlockedCompareExchange (&tp->pool_status, 1, 0) == 0) {
		if (!tp->is_io) {
			monitor_internal_thread = mono_thread_create_internal (mono_get_root_domain (), monitor_thread, NULL, TRUE, SMALL_STACK);
			monitor_internal_thread->flags |= MONO_THREAD_FLAG_DONT_MANAGE;
			threadpool_start_thread (tp);
		}
		/* Create on demand up to min_threads to avoid startup penalty for apps that don't use
		 * the threadpool that much
		 */
		if (mono_config_is_server_mode ()) {
			mono_thread_create_internal (mono_get_root_domain (), threadpool_start_idle_threads, tp, TRUE, SMALL_STACK);
		}
	}

	InterlockedAdd (&monitor_njobs, njobs);

	if (monitor_state == MONITOR_STATE_SLEEPING && InterlockedCompareExchange (&monitor_state, MONITOR_STATE_AWAKE, MONITOR_STATE_SLEEPING) == MONITOR_STATE_SLEEPING)
		MONO_SEM_POST (&monitor_sem);

	if (monitor_state == MONITOR_STATE_FALLING_ASLEEP)
		InterlockedCompareExchange (&monitor_state, MONITOR_STATE_AWAKE, MONITOR_STATE_FALLING_ASLEEP);

	for (i = 0; i < njobs; i++) {
		ar = jobs [i];
		if (ar == NULL || mono_domain_is_unloading (ar->vtable->domain))
			continue; /* Might happen when cleaning domain jobs */
		threadpool_jobs_inc (ar); 
#ifndef DISABLE_PERFCOUNTERS
		mono_perfcounter_update_value (tp->pc_nitems, TRUE, 1);
#endif
		if (!tp->is_io && mono_wsq_local_push (ar))
			continue;

		mono_cq_enqueue (tp->queue, ar);
	}

#if DEBUG
	InterlockedAdd (&tp->njobs, njobs);
#endif

	for (i = 0; tp->waiting > 0 && i < MIN(njobs, tp->max_threads); i++)
		pulse_on_new_job (tp);
}
Пример #13
0
static void
suspend_signal_handler (int _dummy, siginfo_t *info, void *context)
{
	MonoThreadInfo *current = mono_thread_info_current ();
	gboolean ret;
	
	if (current->syscall_break_signal) {
		current->syscall_break_signal = FALSE;
		return;
	}

	ret = mono_threads_get_runtime_callbacks ()->thread_state_init_from_sigctx (&current->suspend_state, context);

	/* thread_state_init_from_sigctx return FALSE if the current thread is detaching and suspend can't continue. */
	current->suspend_can_continue = ret;

	MONO_SEM_POST (&current->begin_suspend_semaphore);

	/* This thread is doomed, all we can do is give up and let the suspender recover. */
	if (!ret)
		return;

	while (MONO_SEM_WAIT (&current->resume_semaphore) != 0) {
		/*if (EINTR != errno) ABORT("sem_wait failed"); */
	}

	if (current->async_target) {
#if MONO_ARCH_HAS_MONO_CONTEXT
		MonoContext tmp = current->suspend_state.ctx;
		mono_threads_get_runtime_callbacks ()->setup_async_callback (&tmp, current->async_target, current->user_data);
		current->async_target = current->user_data = NULL;
		mono_monoctx_to_sigctx (&tmp, context);
#else
		g_error ("The new interruption machinery requires a working mono-context");
#endif
	}

	MONO_SEM_POST (&current->finish_resume_semaphore);
}
Пример #14
0
static gboolean
mono_thread_info_resume_internal (MonoThreadInfo *info)
{
	gboolean result;
	if (mono_thread_info_suspend_state (info) == STATE_SELF_SUSPENDED) {
		MONO_SEM_POST (&info->resume_semaphore);
		MONO_SEM_WAIT_UNITERRUPTIBLE (&info->finish_resume_semaphore);
		result = TRUE;
	} else {
		result = mono_threads_core_resume (info);
	}
	info->thread_state &= ~SUSPEND_STATE_MASK;
	return result;
}
Пример #15
0
static void
workers_wake_up (int max)
{
	int i;

	for (i = 0; i < max; ++i) {
		int num;
		do {
			num = workers_num_waiting;
			if (num == 0)
				return;
		} while (InterlockedCompareExchange (&workers_num_waiting, num - 1, num) != num);
		MONO_SEM_POST (&workers_waiting_sem);
	}
}
Пример #16
0
static gboolean
mono_thread_info_resume_internal (MonoThreadInfo *info)
{
	gboolean result;
	if (mono_thread_info_suspend_state (info) == STATE_SELF_SUSPENDED) {
		MONO_SEM_POST (&info->resume_semaphore);
		while (MONO_SEM_WAIT (&info->finish_resume_semaphore) != 0) {
			/* g_assert (errno == EINTR); */
		}
		result = TRUE;
	} else {
		result = mono_threads_core_resume (info);
	}
	info->thread_state &= ~SUSPEND_STATE_MASK;
	return result;
}
Пример #17
0
static void
workers_wait (void)
{
	State old_state, new_state;
	gboolean post_done;

	++stat_workers_num_waited;

	do {
		new_state = old_state = workers_state;

		assert_working_or_nursery_collection (old_state);

		--new_state.data.num_awake;
		post_done = FALSE;
		if (!new_state.data.num_awake && !new_state.data.num_posted) {
			/* We are the last thread to go to sleep. */
			if (old_state.data.state == STATE_WORKING)
				new_state.data.state = STATE_NOT_WORKING;

			new_state.data.post_done = 0;
			if (old_state.data.post_done)
				post_done = TRUE;
		}
	} while (!set_state (old_state, new_state));

	if (post_done)
		MONO_SEM_POST (&workers_done_sem);

	MONO_SEM_WAIT (&workers_waiting_sem);

	do {
		new_state = old_state = workers_state;

		SGEN_ASSERT (0, old_state.data.num_posted > 0, "How can we be awake without the semaphore having been posted?");
		SGEN_ASSERT (0, old_state.data.num_awake < workers_num, "There are too many worker threads awake");

		--new_state.data.num_posted;
		++new_state.data.num_awake;

		assert_working_or_nursery_collection (new_state);
	} while (!set_state (old_state, new_state));
}
Пример #18
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;
}
Пример #19
0
static void
workers_wait (void)
{
	int num;
	++stat_workers_num_waited;
	do {
		num = workers_num_waiting;
	} while (InterlockedCompareExchange (&workers_num_waiting, num + 1, num) != num);
	if (num + 1 == workers_num && !workers_gc_in_progress) {
		/* Make sure the done semaphore is only posted once. */
		int posted;
		do {
			posted = workers_done_posted;
			if (posted)
				break;
		} while (InterlockedCompareExchange (&workers_done_posted, 1, 0) != 0);
		if (!posted)
			MONO_SEM_POST (&workers_done_sem);
	}
	MONO_SEM_WAIT (&workers_waiting_sem);
}
Пример #20
0
static void
workers_wake_up (int max)
{
	int i;

	for (i = 0; i < max; ++i) {
		State old_state, new_state;
		do {
			old_state = new_state = workers_state;
			/*
			 * We must not wake workers up once done has
			 * been posted.
			 */
			if (old_state.data.done_posted)
				return;
			if (old_state.data.num_waiting == 0)
				return;
			--new_state.data.num_waiting;
		} while (!set_state (old_state, new_state));
		MONO_SEM_POST (&workers_waiting_sem);
	}
}
Пример #21
0
static void
workers_signal_enqueue_work (int num_wake_up, gboolean from_nursery_collection)
{
	State old_state = workers_state;
	State new_state = old_state;
	int i;
	gboolean did_set_state;

	SGEN_ASSERT (0, num_wake_up <= workers_num, "Cannot wake up more workers than are present");

	if (from_nursery_collection)
		assert_nursery_collection (old_state, FALSE);
	else
		assert_not_working (old_state);

	new_state.data.state = STATE_WORKING;
	new_state.data.num_posted = num_wake_up;

	did_set_state = set_state (old_state, new_state);
	SGEN_ASSERT (0, did_set_state, "Nobody else should be mutating the state");

	for (i = 0; i < num_wake_up; ++i)
		MONO_SEM_POST (&workers_waiting_sem);
}
Пример #22
0
static void
tp_poll_wait (gpointer p)
{
#if MONO_SMALL_CONFIG
#define INITIAL_POLLFD_SIZE	128
#else
#define INITIAL_POLLFD_SIZE	1024
#endif
#define POLL_ERRORS (MONO_POLLERR | MONO_POLLHUP | MONO_POLLNVAL)
	mono_pollfd *pfds;
	gint maxfd = 1;
	gint allocated;
	gint i;
	MonoInternalThread *thread;
	tp_poll_data *data;
	SocketIOData *socket_io_data = p;
	gpointer *async_results;
	gint nresults;

	thread = mono_thread_internal_current ();

	data = socket_io_data->event_data;
	allocated = INITIAL_POLLFD_SIZE;
	pfds = g_new0 (mono_pollfd, allocated);
	async_results = g_new0 (gpointer, allocated * 2);
	INIT_POLLFD (pfds, data->pipe [0], MONO_POLLIN);
	for (i = 1; i < allocated; i++)
		INIT_POLLFD (&pfds [i], -1, 0);

	while (1) {
		int nsock = 0;
		mono_pollfd *pfd;
		char one [1];
		MonoMList *list;
		MonoObject *ares;

		do {
			if (nsock == -1) {
				if (THREAD_WANTS_A_BREAK (thread))
					mono_thread_interruption_checkpoint ();
			}

			nsock = mono_poll (pfds, maxfd, -1);
		} while (nsock == -1 && errno == EINTR);

		/* 
		 * Apart from EINTR, we only check EBADF, for the rest:
		 *  EINVAL: mono_poll() 'protects' us from descriptor
		 *      numbers above the limit if using select() by marking
		 *      then as MONO_POLLERR.  If a system poll() is being
		 *      used, the number of descriptor we're passing will not
		 *      be over sysconf(_SC_OPEN_MAX), as the error would have
		 *      happened when opening.
		 *
		 *  EFAULT: we own the memory pointed by pfds.
		 *  ENOMEM: we're doomed anyway
		 *
		 */

		if (nsock == -1 && errno == EBADF) {
			pfds->revents = 0; /* Just in case... */
			nsock = mark_bad_fds (pfds, maxfd);
		}

		if ((pfds->revents & POLL_ERRORS) != 0) {
			/* We're supposed to die now, as the pipe has been closed */
			g_free (pfds);
			g_free (async_results);
			socket_io_cleanup (socket_io_data);
			return;
		}

		/* Got a new socket */
		if ((pfds->revents & MONO_POLLIN) != 0) {
			int nread;

			for (i = 1; i < allocated; i++) {
				pfd = &pfds [i];
				if (pfd->fd == -1 || pfd->fd == data->newpfd.fd)
					break;
			}

			if (i == allocated) {
				mono_pollfd *oldfd;

				oldfd = pfds;
				i = allocated;
				allocated = allocated * 2;
				pfds = g_renew (mono_pollfd, oldfd, allocated);
				g_free (oldfd);
				for (; i < allocated; i++)
					INIT_POLLFD (&pfds [i], -1, 0);
				async_results = g_renew (gpointer, async_results, allocated * 2);
			}
#ifndef HOST_WIN32
			nread = read (data->pipe [0], one, 1);
#else
			nread = recv ((SOCKET) data->pipe [0], one, 1, 0);
#endif
			if (nread <= 0) {
				g_free (pfds);
				g_free (async_results);
				return; /* we're closed */
			}

			INIT_POLLFD (&pfds [i], data->newpfd.fd, data->newpfd.events);
			memset (&data->newpfd, 0, sizeof (mono_pollfd));
			MONO_SEM_POST (&data->new_sem);
			if (i >= maxfd)
				maxfd = i + 1;
			nsock--;
		}

		if (nsock == 0)
			continue;

		EnterCriticalSection (&socket_io_data->io_lock);
		if (socket_io_data->inited == 3) {
			g_free (pfds);
			g_free (async_results);
			LeaveCriticalSection (&socket_io_data->io_lock);
			return; /* cleanup called */
		}

		nresults = 0;
		for (i = 1; i < maxfd && nsock > 0; i++) {
			pfd = &pfds [i];
			if (pfd->fd == -1 || pfd->revents == 0)
				continue;

			nsock--;
			list = mono_g_hash_table_lookup (socket_io_data->sock_to_state, GINT_TO_POINTER (pfd->fd));
			if (list != NULL && (pfd->revents & (MONO_POLLIN | POLL_ERRORS)) != 0) {
				ares = get_io_event (&list, MONO_POLLIN);
				if (ares != NULL)
					async_results [nresults++] = ares;
			}

			if (list != NULL && (pfd->revents & (MONO_POLLOUT | POLL_ERRORS)) != 0) {
				ares = get_io_event (&list, MONO_POLLOUT);
				if (ares != NULL)
					async_results [nresults++] = ares;
			}

			if (list != NULL) {
				mono_g_hash_table_replace (socket_io_data->sock_to_state, GINT_TO_POINTER (pfd->fd), list);
				pfd->events = get_events_from_list (list);
			} else {
				mono_g_hash_table_remove (socket_io_data->sock_to_state, GINT_TO_POINTER (pfd->fd));
				pfd->fd = -1;
				if (i == maxfd - 1)
					maxfd--;
			}
		}
		LeaveCriticalSection (&socket_io_data->io_lock);
		threadpool_append_jobs (&async_io_tp, (MonoObject **) async_results, nresults);
		memset (async_results, 0, sizeof (gpointer) * nresults);
	}
}
Пример #23
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;
}
Пример #24
0
static void
suspend_thread (SgenThreadInfo *info, void *context)
{
	int stop_count;
#ifndef USE_MONO_CTX
	gpointer regs [ARCH_NUM_REGS];
#endif
	gpointer stack_start;

	info->stopped_domain = mono_domain_get ();
	info->stopped_ip = context ? (gpointer) ARCH_SIGCTX_IP (context) : NULL;
	info->signal = 0;
	stop_count = sgen_global_stop_count;
	/* duplicate signal */
	if (0 && info->stop_count == stop_count)
		return;

	stack_start = context ? (char*) ARCH_SIGCTX_SP (context) - REDZONE_SIZE : NULL;
	/* If stack_start is not within the limits, then don't set it
	   in info and we will be restarted. */
	if (stack_start >= info->stack_start_limit && info->stack_start <= info->stack_end) {
		info->stack_start = stack_start;

#ifdef USE_MONO_CTX
		if (context) {
			mono_sigctx_to_monoctx (context, &info->ctx);
		} else {
			memset (&info->ctx, 0, sizeof (MonoContext));
		}
#else
		if (context) {
			ARCH_COPY_SIGCTX_REGS (regs, context);
			memcpy (&info->regs, regs, sizeof (info->regs));
		} else {
			memset (&info->regs, 0, sizeof (info->regs));
		}
#endif
	} else {
		g_assert (!info->stack_start);
	}

	/* Notify the JIT */
	if (mono_gc_get_gc_callbacks ()->thread_suspend_func)
		mono_gc_get_gc_callbacks ()->thread_suspend_func (info->runtime_data, context, NULL);

	SGEN_LOG (4, "Posting suspend_ack_semaphore for suspend from %p %p", info, (gpointer)mono_native_thread_id_get ());

	/*
	Block the restart signal. 
	We need to block the restart signal while posting to the suspend_ack semaphore or we race to sigsuspend,
	which might miss the signal and get stuck.
	*/
	pthread_sigmask (SIG_BLOCK, &suspend_ack_signal_mask, NULL);

	/* notify the waiting thread */
	MONO_SEM_POST (suspend_ack_semaphore_ptr);
	info->stop_count = stop_count;

	/* wait until we receive the restart signal */
	do {
		info->signal = 0;
		sigsuspend (&suspend_signal_mask);
	} while (info->signal != restart_signal_num);

	/* Unblock the restart signal. */
	pthread_sigmask (SIG_UNBLOCK, &suspend_ack_signal_mask, NULL);

	SGEN_LOG (4, "Posting suspend_ack_semaphore for resume from %p %p\n", info, (gpointer)mono_native_thread_id_get ());
	/* notify the waiting thread */
	MONO_SEM_POST (suspend_ack_semaphore_ptr);
}
Пример #25
0
/*
 * mono_threads_core_resume_created:
 *
 *   Resume a newly created thread created using CREATE_SUSPENDED.
 */
void
mono_threads_core_resume_created (MonoThreadInfo *info, MonoNativeThreadId tid)
{
	MONO_SEM_POST (&info->create_suspended_sem);
}
Пример #26
0
void
mono_thread_info_suspend_unlock (void)
{
	MONO_SEM_POST (&global_suspend_semaphore);
}
Пример #27
0
static void
pulse_on_new_job (ThreadPool *tp)
{
	if (tp->waiting)
		MONO_SEM_POST (&tp->new_job);
}
Пример #28
0
static void
resume_self_suspended (MonoThreadInfo* info)
{
	THREADS_SUSPEND_DEBUG ("**BEGIN self-resume %p\n", mono_thread_info_get_tid (info));
	MONO_SEM_POST (&info->resume_semaphore);
}
Пример #29
0
static void _wapi_thread_resume (struct _WapiHandle_thread *thread)
{
	MONO_SEM_POST (&thread->suspend_sem);
}
Пример #30
0
static void
suspend_thread (SgenThreadInfo *info, void *context)
{
	int stop_count;
#ifdef USE_MONO_CTX
	MonoContext monoctx;
#else
	gpointer regs [ARCH_NUM_REGS];
#endif
	gpointer stack_start;

	g_assert (info->doing_handshake);

	info->stopped_domain = mono_domain_get ();
	info->stopped_ip = context ? (gpointer) ARCH_SIGCTX_IP (context) : NULL;
	stop_count = mono_sgen_global_stop_count;
	/* duplicate signal */
	if (0 && info->stop_count == stop_count)
		return;

	mono_sgen_fill_thread_info_for_suspend (info);

	stack_start = context ? (char*) ARCH_SIGCTX_SP (context) - REDZONE_SIZE : NULL;
	/* If stack_start is not within the limits, then don't set it
	   in info and we will be restarted. */
	if (stack_start >= info->stack_start_limit && info->stack_start <= info->stack_end) {
		info->stack_start = stack_start;

#ifdef USE_MONO_CTX
		if (context) {
			mono_sigctx_to_monoctx (context, &monoctx);
			info->monoctx = &monoctx;
		} else {
			info->monoctx = NULL;
		}
#else
		if (context) {
			ARCH_COPY_SIGCTX_REGS (regs, context);
			info->stopped_regs = regs;
		} else {
			info->stopped_regs = NULL;
		}
#endif
	} else {
		g_assert (!info->stack_start);
	}

	/* Notify the JIT */
	if (mono_gc_get_gc_callbacks ()->thread_suspend_func)
		mono_gc_get_gc_callbacks ()->thread_suspend_func (info->runtime_data, context);

	DEBUG (4, fprintf (gc_debug_file, "Posting suspend_ack_semaphore for suspend from %p %p\n", info, (gpointer)mono_native_thread_id_get ()));
	/* notify the waiting thread */
	MONO_SEM_POST (suspend_ack_semaphore_ptr);
	info->stop_count = stop_count;

	/* wait until we receive the restart signal */
	do {
		info->signal = 0;
		sigsuspend (&suspend_signal_mask);
	} while (info->signal != restart_signal_num && info->doing_handshake);

	DEBUG (4, fprintf (gc_debug_file, "Posting suspend_ack_semaphore for resume from %p %p\n", info, (gpointer)mono_native_thread_id_get ()));
	/* notify the waiting thread */
	MONO_SEM_POST (suspend_ack_semaphore_ptr);
}