static void *
init_perf_counter (const char *category, const char *counter)
{
	MonoString *category_str;
	MonoString *counter_str;
	MonoString *machine;
	MonoDomain *root;
	MonoBoolean custom;
	int type;

	if (category == NULL || counter == NULL)
		return NULL;
	root = mono_get_root_domain ();
	category_str = mono_string_new (root, category);
	counter_str = mono_string_new (root, counter);
	machine = mono_string_new (root, ".");
	return mono_perfcounter_get_impl (category_str, counter_str, NULL, machine, &type, &custom);
}
Exemple #2
0
static gboolean
threadpool_start_thread (ThreadPool *tp)
{
	gint n;
	guint32 stack_size;

	stack_size = (!tp->is_io) ? 0 : SMALL_STACK;
	while (!mono_runtime_is_shutting_down () && (n = tp->nthreads) < tp->max_threads) {
		if (InterlockedCompareExchange (&tp->nthreads, n + 1, n) == n) {
#ifndef DISABLE_PERFCOUNTERS
			mono_perfcounter_update_value (tp->pc_nthreads, TRUE, 1);
#endif
			mono_thread_create_internal (mono_get_root_domain (), tp->async_invoke, tp, TRUE, stack_size);
			return TRUE;
		}
	}

	return FALSE;
}
Exemple #3
0
gpointer
mono_arch_create_generic_class_init_trampoline (MonoTrampInfo **info, gboolean aot)
{
	guint8 *tramp;
	guint8 *code, *buf;
	static int byte_offset = -1;
	static guint8 bitmask;
	guint8 *jump;
	gint32 displace;
	int tramp_size;
	GSList *unwind_ops = NULL;
	MonoJumpInfo *ji = NULL;

	tramp_size = 48;

	code = buf = mono_global_codeman_reserve (tramp_size);

	unwind_ops = mono_arch_get_cie_program ();

	if (byte_offset < 0)
		mono_marshal_find_bitfield_offset (MonoVTable, initialized, &byte_offset, &bitmask);

	s390_llgc(code, s390_r0, 0, MONO_ARCH_VTABLE_REG, byte_offset);
	s390_nill(code, s390_r0, bitmask);
	s390_bnzr(code, s390_r14);

	tramp = mono_arch_create_specific_trampoline (NULL, MONO_TRAMPOLINE_GENERIC_CLASS_INIT,
		mono_get_root_domain (), NULL);

	/* jump to the actual trampoline */
	displace = (tramp - code) / 2;
	s390_jg (code, displace);

	mono_arch_flush_icache (buf, code - buf);

	g_assert (code - buf <= tramp_size);

	if (info)
		*info = mono_tramp_info_create ("generic_class_init_trampoline", buf, code - buf, ji, unwind_ops);

	return(buf);
}
Exemple #4
0
static void
threadpool_append_jobs (ThreadPool *tp, MonoObject **jobs, gint njobs)
{
	static int job_counter;
	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) {
			mono_thread_create_internal (mono_get_root_domain (), monitor_thread, NULL, TRUE, SMALL_STACK);
			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
		* mono_thread_create_internal (mono_get_root_domain (), threadpool_start_idle_threads, tp, TRUE, SMALL_STACK);
		*/
	}

	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 */
		if (!tp->is_io && (InterlockedIncrement (&job_counter) % 10) == 0) {
			MonoAsyncResult *o = (MonoAsyncResult *) ar;
			o->add_time = mono_100ns_ticks ();
		}
		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);
	}

	for (i = 0; tp->waiting > 0 && i < MIN(njobs, tp->max_threads); i++)
		pulse_on_new_job (tp);
}
Exemple #5
0
void
mono_runtime_setup_stat_profiler (void)
{
	/*
	 * Use a real-time signal when possible. This gives us roughly a 99% signal
	 * delivery rate in all cases. On the other hand, using a regular signal
	 * tends to result in awful delivery rates when the application is heavily
	 * loaded.
	 *
	 * We avoid real-time signals on Android as they're super broken in certain
	 * API levels (too small sigset_t, nonsensical SIGRTMIN/SIGRTMAX values,
	 * etc).
	 *
	 * TODO: On Mac, we should explore using the Mach thread suspend/resume
	 * functions and doing the stack walk from the sampling thread. This would
	 * get us a 100% sampling rate. However, this may interfere with the GC's
	 * STW logic. Could perhaps be solved by taking the suspend lock.
	 */
#if defined (USE_POSIX_BACKEND) && defined (SIGRTMIN) && !defined (HOST_ANDROID)
	/* Just take the first real-time signal we can get. */
	profiler_signal = mono_threads_suspend_search_alternative_signal ();
#else
	profiler_signal = SIGPROF;
#endif

	add_signal_handler (profiler_signal, profiler_signal_handler, SA_RESTART);

	mono_counters_register ("Sampling signals sent", MONO_COUNTER_UINT | MONO_COUNTER_PROFILER | MONO_COUNTER_MONOTONIC, &profiler_signals_sent);
	mono_counters_register ("Sampling signals received", MONO_COUNTER_UINT | MONO_COUNTER_PROFILER | MONO_COUNTER_MONOTONIC, &profiler_signals_received);
	mono_counters_register ("Sampling signals accepted", MONO_COUNTER_UINT | MONO_COUNTER_PROFILER | MONO_COUNTER_MONOTONIC, &profiler_signals_accepted);
	mono_counters_register ("Shutdown signals received", MONO_COUNTER_UINT | MONO_COUNTER_PROFILER | MONO_COUNTER_MONOTONIC, &profiler_interrupt_signals_received);

	mono_os_event_init (&sampling_thread_exited, FALSE);

	mono_atomic_store_i32 (&sampling_thread_running, 1);

	MonoError error;
	MonoInternalThread *thread = mono_thread_create_internal (mono_get_root_domain (), sampling_thread_func, NULL, MONO_THREAD_CREATE_FLAGS_NONE, &error);
	mono_error_assert_ok (&error);

	sampling_thread = MONO_UINT_TO_NATIVE_THREAD_ID (thread->tid);
}
Exemple #6
0
static void
threadpool_start_idle_threads (ThreadPool *tp)
{
	int n;
	guint32 stack_size;

	stack_size = (!tp->is_io) ? 0 : SMALL_STACK;
	do {
		while (1) {
			n = tp->nthreads;
			if (n >= tp->min_threads)
				return;
			if (InterlockedCompareExchange (&tp->nthreads, n + 1, n) == n)
				break;
		}
		mono_perfcounter_update_value (tp->pc_nthreads, TRUE, 1);
		mono_thread_create_internal (mono_get_root_domain (), tp->async_invoke, tp, TRUE, stack_size);
		SleepEx (100, TRUE);
	} while (1);
}
Exemple #7
0
CScriptDomain::~CScriptDomain()
{
	m_bDestroying = true;

	for each(auto assembly in m_assemblies)
		delete assembly;

	m_assemblies.clear();

	if(m_bRootDomain)
		mono_jit_cleanup(m_pDomain);
	else
	{
		if(IsActive())
			mono_domain_set(mono_get_root_domain(), false);

		mono_domain_finalize(m_pDomain, 2000);

		MonoObject *pException;
		try
		{
			mono_domain_try_unload(m_pDomain, &pException);
		}
		catch(char *ex)
		{
			MonoWarning("An exception was raised during ScriptDomain unload: %s", ex);
		}

		if(pException)	
		{	
			MonoWarning("An exception was raised during ScriptDomain unload:");
			MonoMethod *pExceptionMethod = mono_method_desc_search_in_class(mono_method_desc_new("::ToString()", false),mono_get_exception_class());		
			MonoString *exceptionString = (MonoString *)mono_runtime_invoke(pExceptionMethod, pException, nullptr, nullptr);		
			CryLogAlways(ToCryString((mono::string)exceptionString));
		}
	}

	g_pScriptSystem->OnDomainReleased(this);
}
	void MonoManager::unloadScriptDomain()
	{
		if (mScriptDomain != nullptr)
		{
			onDomainUnload();

			mono_domain_set(mono_get_root_domain(), false);
			mono_domain_finalize(mScriptDomain, 2000);

			MonoObject* exception = nullptr;
			mono_domain_try_unload(mScriptDomain, &exception);

			if (exception != nullptr)
				MonoUtil::throwIfException(exception);

			mono_gc_collect(mono_gc_max_generation());

			mScriptDomain = nullptr;
		}

		for (auto& assemblyEntry : mAssemblies)
		{
			assemblyEntry.second->unload();

			// Metas hold references to various assembly objects that were just deleted, so clear them
			Vector<ScriptMeta*>& typeMetas = getScriptMetaData()[assemblyEntry.first];
			for (auto& entry : typeMetas)
			{
				entry->scriptClass = nullptr;
				entry->thisPtrField = nullptr;
			}
		}

		mAssemblies.clear();
		mIsCoreLoaded = false;
	}
Exemple #9
0
gpointer
mono_arch_create_monitor_exit_trampoline (MonoTrampInfo **info, gboolean aot)
{
	guint8	*tramp,
		*code, *buf;
	gint16	*jump_obj_null, 
		*jump_have_waiters, 
		*jump_sync_null, 
		*jump_not_owned, 
		*jump_cs_failed,
		*jump_next,
		*jump_sync_thin_hash = NULL;
	int	tramp_size,
		status_offset, nest_offset;
	MonoJumpInfo *ji = NULL;
	GSList *unwind_ops = NULL;
	int	obj_reg = s390_r2,
		sync_reg = s390_r3,
		status_reg = s390_r4;

	g_assert (obj_reg == MONO_ARCH_MONITOR_OBJECT_REG);

	mono_monitor_threads_sync_members_offset (&status_offset, &nest_offset);
	g_assert (MONO_THREADS_SYNC_MEMBER_SIZE (status_offset) == sizeof (guint32));
	g_assert (MONO_THREADS_SYNC_MEMBER_SIZE (nest_offset) == sizeof (guint32));
	status_offset = MONO_THREADS_SYNC_MEMBER_OFFSET (status_offset);
	nest_offset = MONO_THREADS_SYNC_MEMBER_OFFSET (nest_offset);

	tramp_size = 160;

	code = buf = mono_global_codeman_reserve (tramp_size);

	unwind_ops = mono_arch_get_cie_program ();

	if (mono_thread_get_tls_offset () != -1) {
		/* MonoObject* obj is in obj_reg */
		/* is obj null? */
		s390_ltgr (code, obj_reg, obj_reg);
		/* if yes, jump to actual trampoline */
		s390_jz (code, 0); CODEPTR(code, jump_obj_null);

		/* load obj->synchronization to RCX */
		s390_lg (code, sync_reg, 0, obj_reg, MONO_STRUCT_OFFSET (MonoObject, synchronisation));

		if (mono_gc_is_moving ()) {
			/*if bit zero is set it's a thin hash*/
			s390_tmll (code, sync_reg, 1);
			s390_jo   (code, 0); CODEPTR(code, jump_sync_thin_hash);

			/* Clear bits used by the gc */
			s390_nill (code, sync_reg, ~0x3);
		}

		/* is synchronization null? */
		s390_ltgr (code, sync_reg, sync_reg);
		/* if yes, jump to actual trampoline */
		s390_jz (code, 0); CODEPTR(code, jump_sync_null);

		/* next case: synchronization is not null */
		/* load MonoInternalThread* into r5 */
		s390_ear (code, s390_r5, 0);
		s390_sllg(code, s390_r5, s390_r5, 0, 32);
		s390_ear (code, s390_r5, 1);
		/* load TID into r1 */
		s390_lg  (code, s390_r1, 0, s390_r5, mono_thread_get_tls_offset ());
		s390_lgf (code, s390_r1, 0, s390_r1, MONO_STRUCT_OFFSET (MonoInternalThread, small_id));
		/* is synchronization->owner == TID */
		s390_lgf (code, status_reg, 0, sync_reg, status_offset);
		s390_xr  (code, s390_r1, status_reg);
		s390_tmlh (code, s390_r1, OWNER_MASK);
		/* if not, jump to actual trampoline */
		s390_jno (code, 0); CODEPTR(code, jump_not_owned);

		/* next case: synchronization->owner == TID */
		/* is synchronization->nest == 1 */
		s390_lgf (code, s390_r0, 0, sync_reg, nest_offset);
		s390_chi (code, s390_r0, 1);
		/* if not, jump to next case */
		s390_jne (code, 0); CODEPTR(code, jump_next);
		/* if yes, is synchronization->entry_count greater than zero */
		s390_cfi (code, status_reg, ENTRY_COUNT_WAITERS);
		/* if not, jump to actual trampoline */
		s390_jnz (code, 0); CODEPTR(code, jump_have_waiters);
		/* if yes, try to set synchronization->owner to null and return */
		/* old status in s390_r0 */
		s390_lgfr (code, s390_r0, status_reg);
		/* form new status */
		s390_nilf (code, status_reg, ENTRY_COUNT_MASK);
		/* compare and exchange */
		s390_cs (code, s390_r0, status_reg, sync_reg, status_offset);
		/* if not successful, jump to actual trampoline */
		s390_jnz (code, 0); CODEPTR(code, jump_cs_failed);
		s390_br  (code, s390_r14);

		/* next case: synchronization->nest is not 1 */
		PTRSLOT (code, jump_next);
		/* decrease synchronization->nest and return */
		s390_lgf (code, s390_r0, 0, sync_reg, nest_offset);
		s390_ahi (code, s390_r0, -1);
		s390_st  (code, s390_r0, 0, sync_reg, nest_offset);
		s390_br  (code, s390_r14);

		PTRSLOT (code, jump_obj_null);
		if (jump_sync_thin_hash)
			PTRSLOT (code, jump_sync_thin_hash);
		PTRSLOT (code, jump_have_waiters);
		PTRSLOT (code, jump_not_owned);
		PTRSLOT (code, jump_cs_failed);
		PTRSLOT (code, jump_sync_null);
	}

	/* jump to the actual trampoline */
	tramp = mono_arch_create_specific_trampoline (NULL, MONO_TRAMPOLINE_MONITOR_EXIT, mono_get_root_domain (), NULL);

	S390_SET (code, s390_r1, tramp);
	s390_br (code, s390_r1);

	mono_arch_flush_icache (code, code - buf);
	mono_profiler_code_buffer_new (buf, code - buf, MONO_PROFILER_CODE_BUFFER_MONITOR, NULL);
	g_assert (code - buf <= tramp_size);

	if (info)
		*info = mono_tramp_info_create ("monitor_exit_trampoline", buf, code - buf, ji, unwind_ops);

	return buf;
}
Exemple #10
0
static void
async_invoke_thread (gpointer data)
{
	MonoDomain *domain;
	MonoInternalThread *thread;
	MonoWSQ *wsq;
	ThreadPool *tp;
	gboolean must_die;
	const gchar *name;
  
	tp = data;
	wsq = NULL;
	if (!tp->is_io)
		wsq = add_wsq ();

	thread = mono_thread_internal_current ();

	mono_profiler_thread_start (thread->tid);
	name = (tp->is_io) ? "IO Threadpool worker" : "Threadpool worker";
	mono_thread_set_name_internal (thread, mono_string_new (mono_domain_get (), name), FALSE);

	if (tp_start_func)
		tp_start_func (tp_hooks_user_data);

	data = NULL;
	for (;;) {
		MonoAsyncResult *ar;
		MonoClass *klass;
		gboolean is_io_task;
		gboolean is_socket;
		int n_naps = 0;

		is_io_task = FALSE;
		ar = (MonoAsyncResult *) data;
		if (ar) {
			InterlockedIncrement (&tp->busy_threads);
			domain = ((MonoObject *)ar)->vtable->domain;
#ifndef DISABLE_SOCKETS
			klass = ((MonoObject *) data)->vtable->klass;
			is_io_task = !is_corlib_asyncresult (domain, klass);
			is_socket = FALSE;
			if (is_io_task) {
				MonoSocketAsyncResult *state = (MonoSocketAsyncResult *) data;
				is_socket = is_socketasyncresult (domain, klass);
				ar = state->ares;
				switch (state->operation) {
				case AIO_OP_RECEIVE:
					state->total = ICALL_RECV (state);
					break;
				case AIO_OP_SEND:
					state->total = ICALL_SEND (state);
					break;
				}
			}
#endif
			/* worker threads invokes methods in different domains,
			 * so we need to set the right domain here */
			g_assert (domain);

			if (mono_domain_is_unloading (domain) || mono_runtime_is_shutting_down ()) {
				threadpool_jobs_dec ((MonoObject *)ar);
				data = NULL;
				ar = NULL;
				InterlockedDecrement (&tp->busy_threads);
			} else {
				mono_thread_push_appdomain_ref (domain);
				if (threadpool_jobs_dec ((MonoObject *)ar)) {
					data = NULL;
					ar = NULL;
					mono_thread_pop_appdomain_ref ();
					InterlockedDecrement (&tp->busy_threads);
					continue;
				}

				if (mono_domain_set (domain, FALSE)) {
					MonoObject *exc;

					if (tp_item_begin_func)
						tp_item_begin_func (tp_item_user_data);

					if (!is_io_task && ar->add_time > 0)
						process_idle_times (tp, ar->add_time);
					exc = mono_async_invoke (tp, ar);
					if (tp_item_end_func)
						tp_item_end_func (tp_item_user_data);
					if (exc)
						mono_internal_thread_unhandled_exception (exc);
					if (is_socket && tp->is_io) {
						MonoSocketAsyncResult *state = (MonoSocketAsyncResult *) data;

						if (state->completed && state->callback) {
							MonoAsyncResult *cb_ares;
							cb_ares = create_simple_asyncresult ((MonoObject *) state->callback,
												(MonoObject *) state);
							icall_append_job ((MonoObject *) cb_ares);
						}
					}
					mono_domain_set (mono_get_root_domain (), TRUE);
				}
				mono_thread_pop_appdomain_ref ();
				InterlockedDecrement (&tp->busy_threads);
				/* If the callee changes the background status, set it back to TRUE */
				mono_thread_clr_state (thread , ~ThreadState_Background);
				if (!mono_thread_test_state (thread , ThreadState_Background))
					ves_icall_System_Threading_Thread_SetState (thread, ThreadState_Background);
			}
		}

		ar = NULL;
		data = NULL;
		must_die = should_i_die (tp);
		if (!must_die && (tp->is_io || !mono_wsq_local_pop (&data)))
			dequeue_or_steal (tp, &data, wsq);

		n_naps = 0;
		while (!must_die && !data && n_naps < 4) {
			gboolean res;

			InterlockedIncrement (&tp->waiting);

			// Another thread may have added a job into its wsq since the last call to dequeue_or_steal
			// Check all the queues again before entering the wait loop
			dequeue_or_steal (tp, &data, wsq);
			if (data) {
				InterlockedDecrement (&tp->waiting);
				break;
			}

			mono_gc_set_skip_thread (TRUE);

#if defined(__OpenBSD__)
			while (mono_cq_count (tp->queue) == 0 && (res = mono_sem_wait (&tp->new_job, TRUE)) == -1) {// && errno == EINTR) {
#else
			while (mono_cq_count (tp->queue) == 0 && (res = mono_sem_timedwait (&tp->new_job, 2000, TRUE)) == -1) {// && errno == EINTR) {
#endif
				if (mono_runtime_is_shutting_down ())
					break;
				if (THREAD_WANTS_A_BREAK (thread))
					mono_thread_interruption_checkpoint ();
			}
			InterlockedDecrement (&tp->waiting);

			mono_gc_set_skip_thread (FALSE);

			if (mono_runtime_is_shutting_down ())
				break;
			must_die = should_i_die (tp);
			dequeue_or_steal (tp, &data, wsq);
			n_naps++;
		}

		if (!data && !tp->is_io && !mono_runtime_is_shutting_down ()) {
			mono_wsq_local_pop (&data);
			if (data && must_die) {
				InterlockedCompareExchange (&tp->destroy_thread, 1, 0);
				pulse_on_new_job (tp);
			}
		}

		if (!data) {
			gint nt;
			gboolean down;
			while (1) {
				nt = tp->nthreads;
				down = mono_runtime_is_shutting_down ();
				if (!down && nt <= tp->min_threads)
					break;
				if (down || InterlockedCompareExchange (&tp->nthreads, nt - 1, nt) == nt) {
					mono_perfcounter_update_value (tp->pc_nthreads, TRUE, -1);
					if (!tp->is_io) {
						remove_wsq (wsq);
					}

					mono_profiler_thread_end (thread->tid);

					if (tp_finish_func)
						tp_finish_func (tp_hooks_user_data);
					return;
				}
			}
		}
	}

	g_assert_not_reached ();
}

void
ves_icall_System_Threading_ThreadPool_GetAvailableThreads (gint *workerThreads, gint *completionPortThreads)
{
	*workerThreads = async_tp.max_threads - async_tp.busy_threads;
	*completionPortThreads = async_io_tp.max_threads - async_io_tp.busy_threads;
}
Exemple #11
0
static gsize
sampling_thread_func (gpointer unused)
{
	MonoInternalThread *thread = mono_thread_internal_current ();

	thread->flags |= MONO_THREAD_FLAG_DONT_MANAGE;

	ERROR_DECL (error);

	MonoString *name = mono_string_new_checked (mono_get_root_domain (), "Profiler Sampler", error);
	mono_error_assert_ok (error);
	mono_thread_set_name_internal (thread, name, FALSE, FALSE, error);
	mono_error_assert_ok (error);

	mono_thread_info_set_flags (MONO_THREAD_INFO_FLAGS_NO_GC | MONO_THREAD_INFO_FLAGS_NO_SAMPLE);

	int old_policy;
	struct sched_param old_sched;
	pthread_getschedparam (pthread_self (), &old_policy, &old_sched);

	/*
	 * Attempt to switch the thread to real time scheduling. This will not
	 * necessarily work on all OSs; for example, most Linux systems will give
	 * us EPERM here unless configured to allow this.
	 *
	 * TODO: This does not work on Mac (and maybe some other OSs). On Mac, we
	 * have to use the Mach thread policy routines to switch to real-time
	 * scheduling. This is quite tricky as we need to specify how often we'll
	 * be doing work (easy), the normal processing time needed (also easy),
	 * and the maximum amount of processing time needed (hard). This is
	 * further complicated by the fact that if we misbehave and take too long
	 * to do our work, the kernel may knock us back down to the normal thread
	 * scheduling policy without telling us.
	 */
	struct sched_param sched = { .sched_priority = sched_get_priority_max (SCHED_FIFO) };
	pthread_setschedparam (pthread_self (), SCHED_FIFO, &sched);

	MonoProfilerSampleMode mode;

init:
	mono_profiler_get_sample_mode (NULL, &mode, NULL);

	if (mode == MONO_PROFILER_SAMPLE_MODE_NONE) {
		mono_profiler_sampling_thread_wait ();

		if (!mono_atomic_load_i32 (&sampling_thread_running))
			goto done;

		goto init;
	}

	clock_init (mode);

	for (guint64 sleep = clock_get_time_ns (); mono_atomic_load_i32 (&sampling_thread_running); clock_sleep_ns_abs (sleep)) {
		uint32_t freq;
		MonoProfilerSampleMode new_mode;

		mono_profiler_get_sample_mode (NULL, &new_mode, &freq);

		if (new_mode != mode) {
			clock_cleanup ();
			goto init;
		}

		sleep += 1000000000 / freq;

		FOREACH_THREAD_SAFE_EXCLUDE (info, MONO_THREAD_INFO_FLAGS_NO_SAMPLE) {
			g_assert (mono_thread_info_get_tid (info) != sampling_thread);

			/*
			 * Require an ack for the last sampling signal sent to the thread
			 * so that we don't overflow the signal queue, leading to all sorts
			 * of problems (e.g. GC STW failing).
			 */
			if (profiler_signal != SIGPROF && !mono_atomic_cas_i32 (&info->profiler_signal_ack, 0, 1))
				continue;

			mono_threads_pthread_kill (info, profiler_signal);
			mono_atomic_inc_i32 (&profiler_signals_sent);
		} FOREACH_THREAD_SAFE_END
	}
Exemple #12
0
gboolean
mono_domain_finalize (MonoDomain *domain, guint32 timeout) 
{
	DomainFinalizationReq *req;
	MonoInternalThread *thread = mono_thread_internal_current ();
	gint res;
	gboolean ret;
	gint64 start;

#if defined(__native_client__)
	return FALSE;
#endif

	if (mono_thread_internal_current () == gc_thread)
		/* We are called from inside a finalizer, not much we can do here */
		return FALSE;

	/* 
	 * No need to create another thread 'cause the finalizer thread
	 * is still working and will take care of running the finalizers
	 */ 
	
	if (gc_disabled)
		return TRUE;

	/* We don't support domain finalization without a GC */
	if (mono_gc_is_null ())
		return FALSE;

	mono_gc_collect (mono_gc_max_generation ());

	req = g_new0 (DomainFinalizationReq, 1);
	req->ref = 2;
	req->domain = domain;
	mono_coop_sem_init (&req->done, 0);

	if (domain == mono_get_root_domain ())
		finalizing_root_domain = TRUE;
	
	mono_finalizer_lock ();

	domains_to_finalize = g_slist_append (domains_to_finalize, req);

	mono_finalizer_unlock ();

	/* Tell the finalizer thread to finalize this appdomain */
	mono_gc_finalize_notify ();

	if (timeout == -1)
		timeout = INFINITE;
	if (timeout != INFINITE)
		start = mono_msec_ticks ();

	ret = TRUE;

	for (;;) {
		if (timeout == INFINITE) {
			res = mono_coop_sem_wait (&req->done, MONO_SEM_FLAGS_ALERTABLE);
		} else {
			gint64 elapsed = mono_msec_ticks () - start;
			if (elapsed >= timeout) {
				ret = FALSE;
				break;
			}

			res = mono_coop_sem_timedwait (&req->done, timeout - elapsed, MONO_SEM_FLAGS_ALERTABLE);
		}

		if (res == MONO_SEM_TIMEDWAIT_RET_SUCCESS) {
			break;
		} else if (res == MONO_SEM_TIMEDWAIT_RET_ALERTED) {
			if ((thread->state & (ThreadState_StopRequested | ThreadState_SuspendRequested)) != 0) {
				ret = FALSE;
				break;
			}
		} else if (res == MONO_SEM_TIMEDWAIT_RET_TIMEDOUT) {
			ret = FALSE;
			break;
		} else {
			g_error ("%s: unknown result %d", __func__, res);
		}
	}

	if (!ret) {
		/* Try removing the req from domains_to_finalize:
		 *  - if it's not found: the domain is being finalized,
		 *     so we the ref count is already decremented
		 *  - if it's found: the domain is not yet being finalized,
		 *     so we can safely decrement the ref */

		gboolean found;

		mono_finalizer_lock ();

		found = g_slist_index (domains_to_finalize, req) != -1;
		if (found)
			domains_to_finalize = g_slist_remove (domains_to_finalize, req);

		mono_finalizer_unlock ();

		if (found) {
			/* We have to decrement it wherever we
			 * remove it from domains_to_finalize */
			if (InterlockedDecrement (&req->ref) != 1)
				g_error ("%s: req->ref should be 1, as we are the first one to decrement it", __func__);
		}

		goto done;
	}

	if (domain == mono_get_root_domain ()) {
		mono_threadpool_ms_cleanup ();
		mono_gc_finalize_threadpool_threads ();
	}

done:
	if (InterlockedDecrement (&req->ref) == 0) {
		mono_coop_sem_destroy (&req->done);
		g_free (req);
	}

	return ret;
}
Exemple #13
0
gpointer
mono_arch_create_rgctx_lazy_fetch_trampoline (guint32 slot, MonoTrampInfo **info, gboolean aot)
{
	guint8 *tramp;
	guint8 *code, *buf;
	guint8 **rgctx_null_jumps;
	int tramp_size;
	int depth, index;
	int i;
	gboolean mrgctx;
	MonoJumpInfo *ji = NULL;
	GSList *unwind_ops = NULL;

	unwind_ops = mono_arch_get_cie_program ();

	mrgctx = MONO_RGCTX_SLOT_IS_MRGCTX (slot);
	index = MONO_RGCTX_SLOT_INDEX (slot);
	if (mrgctx)
		index += MONO_SIZEOF_METHOD_RUNTIME_GENERIC_CONTEXT / sizeof (target_mgreg_t);
	for (depth = 0; ; ++depth) {
		int size = mono_class_rgctx_get_array_size (depth, mrgctx);

		if (index < size - 1)
			break;
		index -= size - 1;
	}

	tramp_size = (aot ? 64 : 36) + 6 * depth;

	code = buf = mono_global_codeman_reserve (tramp_size);

	rgctx_null_jumps = g_malloc (sizeof (guint8*) * (depth + 2));

	/* load vtable/mrgctx ptr */
	x86_mov_reg_membase (code, X86_EAX, X86_ESP, 4, 4);
	if (!mrgctx) {
		/* load rgctx ptr from vtable */
		x86_mov_reg_membase (code, X86_EAX, X86_EAX, MONO_STRUCT_OFFSET (MonoVTable, runtime_generic_context), 4);
		/* is the rgctx ptr null? */
		x86_test_reg_reg (code, X86_EAX, X86_EAX);
		/* if yes, jump to actual trampoline */
		rgctx_null_jumps [0] = code;
		x86_branch8 (code, X86_CC_Z, -1, 1);
	}

	for (i = 0; i < depth; ++i) {
		/* load ptr to next array */
		if (mrgctx && i == 0)
			x86_mov_reg_membase (code, X86_EAX, X86_EAX, MONO_SIZEOF_METHOD_RUNTIME_GENERIC_CONTEXT, 4);
		else
			x86_mov_reg_membase (code, X86_EAX, X86_EAX, 0, 4);
		/* is the ptr null? */
		x86_test_reg_reg (code, X86_EAX, X86_EAX);
		/* if yes, jump to actual trampoline */
		rgctx_null_jumps [i + 1] = code;
		x86_branch8 (code, X86_CC_Z, -1, 1);
	}

	/* fetch slot */
	x86_mov_reg_membase (code, X86_EAX, X86_EAX, sizeof (target_mgreg_t) * (index + 1), 4);
	/* is the slot null? */
	x86_test_reg_reg (code, X86_EAX, X86_EAX);
	/* if yes, jump to actual trampoline */
	rgctx_null_jumps [depth + 1] = code;
	x86_branch8 (code, X86_CC_Z, -1, 1);
	/* otherwise return */
	x86_ret (code);

	for (i = mrgctx ? 1 : 0; i <= depth + 1; ++i)
		x86_patch (rgctx_null_jumps [i], code);

	g_free (rgctx_null_jumps);

	x86_mov_reg_membase (code, MONO_ARCH_VTABLE_REG, X86_ESP, 4, 4);

	if (aot) {
		code = mono_arch_emit_load_aotconst (buf, code, &ji, MONO_PATCH_INFO_SPECIFIC_TRAMPOLINE_LAZY_FETCH_ADDR, GUINT_TO_POINTER (slot));
		x86_jump_reg (code, X86_EAX);
	} else {
		tramp = (guint8*)mono_arch_create_specific_trampoline (GUINT_TO_POINTER (slot), MONO_TRAMPOLINE_RGCTX_LAZY_FETCH, mono_get_root_domain (), NULL);

		/* jump to the actual trampoline */
		x86_jump_code (code, tramp);
	}

	mono_arch_flush_icache (buf, code - buf);
	MONO_PROFILER_RAISE (jit_code_buffer, (buf, code - buf, MONO_PROFILER_CODE_BUFFER_GENERICS_TRAMPOLINE, NULL));

	g_assert (code - buf <= tramp_size);

	char *name = mono_get_rgctx_fetch_trampoline_name (slot);
	*info = mono_tramp_info_create (name, buf, code - buf, ji, unwind_ops);
	g_free (name);

	return buf;
}
Exemple #14
0
bool VdsViewEventHandler::handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& us)
{
	if (!_eventClass)
		return false;
	int x = ea.getX();
	int y = ea.getY();
	MonoImage* monoImage = NULL;
	MonoClass* eventClass = NULL;
	MonoObject* eventClassObject = NULL;
	MonoMethod*	mousePushMethod = NULL;
	MonoMethod*	mouseReleaseMethod = NULL;
	MonoMethod*	mouseMoveMethod = NULL;
	MonoMethod*	mouseDoubleClickMethod = NULL;
	MonoMethod*	mouseZoomMethod = NULL;
	MonoMethod*	keyDownMethod = NULL;
	MonoMethod*	keyUpMethod = NULL;
	MonoMethod*	layerInSceneChangedMethod = NULL;
	MonoMethod*	gameManagerAddActorEventMethod = NULL;
	MonoMethod*	gameManagerRemoveActorEventMethod = NULL;
	MonoMethod*	gameManagerPlayPlotEventMethod = NULL;
	MonoMethod*	gameManagerStopPlotEventMethod = NULL;
	MonoMethod*	gameManagerPausePlotEventMethod = NULL;
	MonoMethod*	uiEventMethod = NULL;
	{
		OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_pMutex);
		monoImage = _monoImage;
		eventClass = _eventClass;
		eventClassObject = _eventClassObject;
		mousePushMethod = _mousePushMethod;
		mouseReleaseMethod = _mouseReleaseMethod;
		mouseMoveMethod = _mouseMoveMethod;
		mouseDoubleClickMethod = _mouseDoubleClickMethod;
		mouseZoomMethod = _mouseZoomMethod;
		keyDownMethod = _keyDownMethod;
		keyUpMethod = _keyUpMethod;
		layerInSceneChangedMethod = _layerInSceneChangedMethod;
		gameManagerAddActorEventMethod = _gameManagerAddActorEventMethod;
		gameManagerRemoveActorEventMethod = _gameManagerRemoveActorEventMethod;
		gameManagerPlayPlotEventMethod = _gameManagerPlayPlotEventMethod;
		gameManagerStopPlotEventMethod = _gameManagerStopPlotEventMethod;
		gameManagerPausePlotEventMethod = _gameManagerPausePlotEventMethod;
		uiEventMethod = _uiEventMethod;
	}
	switch (ea.getEventType())
	{
	case osgGA::GUIEventAdapter::MOVE:
	{
		if (!mouseMoveMethod)
			mouseMoveMethod = mono_class_get_method_from_name(eventClass, "MouseMoveEvent", 3);
		MonoObject* exception = NULL;
		void* args[3];
		args[0] = &_viewID;
		args[1] = &x;
		args[2] = &y;
		_eventThread = mono_thread_attach(mono_get_root_domain());
		mono_runtime_invoke(mouseMoveMethod, eventClassObject, args, &exception);
		break;
	}
	case osgGA::GUIEventAdapter::PUSH:
	{
		if (!mousePushMethod)
			mousePushMethod = mono_class_get_method_from_name(eventClass, "MouseButtonPressEvent", 4);
		MonoObject* exception = NULL;
		int arg0 = 1;
		void* args[4];
		args[0] = &_viewID;
		if (ea.getButton() == osgGA::GUIEventAdapter::LEFT_MOUSE_BUTTON)
			arg0 = 1;
		else if (ea.getButton() == osgGA::GUIEventAdapter::MIDDLE_MOUSE_BUTTON)
			arg0 = 2;
		else if (ea.getButton() == osgGA::GUIEventAdapter::RIGHT_MOUSE_BUTTON)
			arg0 = 3;
		args[1] = &arg0;
		args[2] = &x;
		args[3] = &y;
		_eventThread = mono_thread_attach(mono_get_root_domain());
		mono_runtime_invoke(mousePushMethod, eventClassObject, args, &exception);
		break;
	}
	case osgGA::GUIEventAdapter::RELEASE:
	{
		if (!mouseReleaseMethod)
			mouseReleaseMethod = mono_class_get_method_from_name(eventClass, "MouseButtonReleaseEvent", 4);
		MonoObject* exception = NULL;
		int arg0 = 1;
		void* args[4];
		args[0] = &_viewID;
		if (ea.getButton() == osgGA::GUIEventAdapter::LEFT_MOUSE_BUTTON)
			arg0 = 1;
		else if (ea.getButton() == osgGA::GUIEventAdapter::MIDDLE_MOUSE_BUTTON)
			arg0 = 2;
		else if (ea.getButton() == osgGA::GUIEventAdapter::RIGHT_MOUSE_BUTTON)
			arg0 = 3;
		args[1] = &arg0;
		args[2] = &x;
		args[3] = &y;
		_eventThread = mono_thread_attach(mono_get_root_domain());
		mono_runtime_invoke(mouseReleaseMethod, eventClassObject, args, &exception);
		break;
	}
	case osgGA::GUIEventAdapter::DOUBLECLICK:
	{
		if (!mouseDoubleClickMethod)
			mouseDoubleClickMethod = mono_class_get_method_from_name(eventClass, "MouseDoubleClickEvent", 4);
		MonoObject* exception = NULL;
		int arg0 = 1;
		void* args[4];
		args[0] = &_viewID;
		if (ea.getButton() == osgGA::GUIEventAdapter::LEFT_MOUSE_BUTTON)
			arg0 = 1;
		else if (ea.getButton() == osgGA::GUIEventAdapter::MIDDLE_MOUSE_BUTTON)
			arg0 = 2;
		else if (ea.getButton() == osgGA::GUIEventAdapter::RIGHT_MOUSE_BUTTON)
			arg0 = 3;
		args[1] = &arg0;
		args[2] = &x;
		args[3] = &y;
		_eventThread = mono_thread_attach(mono_get_root_domain());
		mono_runtime_invoke(mouseDoubleClickMethod, eventClassObject, args, &exception);
		break;
	}
	case osgGA::GUIEventAdapter::KEYDOWN:
	{
		if (!keyDownMethod)
			keyDownMethod = mono_class_get_method_from_name(eventClass, "KeyboardDownEvent", 2);
		MonoObject* exception = NULL;
		void* args[2];
		args[0] = &_viewID;
		int keyValue = ea.getKey();
		args[1] = &keyValue;
		_eventThread = mono_thread_attach(mono_get_root_domain());
		mono_runtime_invoke(keyDownMethod, eventClassObject, args, &exception);
		break;
	}
	case osgGA::GUIEventAdapter::KEYUP:
	{
		if (!keyUpMethod)
			keyUpMethod = mono_class_get_method_from_name(eventClass, "KeyboardUpEvent", 2);
		MonoObject* exception = NULL;
		void* args[2];
		args[0] = &_viewID;
		int keyValue = ea.getKey();
		args[1] = &keyValue;
		_eventThread = mono_thread_attach(mono_get_root_domain());
		mono_runtime_invoke(keyUpMethod, eventClassObject, args, &exception);
		break;
	}
	case osgGA::GUIEventAdapter::SCROLL:
	{
		if (!mouseZoomMethod)
			mouseZoomMethod = mono_class_get_method_from_name(eventClass, "MouseZoomEvent", 2);
		MonoObject* exception = NULL;
		void* args[2];
		args[0] = &_viewID;
		osgGA::GUIEventAdapter::ScrollingMotion sm = ea.getScrollingMotion();
		int zoomValue = 0;
		if (sm == osgGA::GUIEventAdapter::SCROLL_DOWN)
			zoomValue = 1;
		args[1] = &zoomValue;
		_eventThread = mono_thread_attach(mono_get_root_domain());
		mono_runtime_invoke(mouseZoomMethod, eventClassObject, args, &exception);
		break;
	}
	case osgGA::GUIEventAdapter::USER:
	{
		osg::ref_ptr<osg::Referenced> userData = const_cast<osg::Referenced*>(ea.getUserData());
		UserEventData* data = static_cast<UserEventData*>(userData.get());
		switch (data->_eventType)
		{
		case UserEventData::LAYERCHANGED:
		{
			if (!layerInSceneChangedMethod)
				layerInSceneChangedMethod = mono_class_get_method_from_name(eventClass, "LayerInSceneChangedEvent", 1);
			MonoObject* exception = NULL;
			void* args[1];
			args[0] = &_viewID;
			_eventThread = mono_thread_attach(mono_get_root_domain());
			mono_runtime_invoke(layerInSceneChangedMethod, eventClassObject, args, &exception);
			break;
		}
		case UserEventData::UI_EVENT:
		{
			if (!uiEventMethod)
				uiEventMethod = mono_class_get_method_from_name(eventClass, "UIEvent", 3);
			void* widthData = data->_data;
			std::vector<std::string>* dList = (std::vector<std::string>*)widthData;
			MonoDomain* domain = mono_object_get_domain(eventClassObject);
			MonoObject* exception = NULL;
			void* args[3];
			args[0] = &_viewID;
			args[1] = mono_string_new(domain, dList->at(0).c_str());
			args[2] = mono_string_new(domain, dList->at(1).c_str());
			_eventThread = mono_thread_attach(mono_get_root_domain());
			mono_runtime_invoke(uiEventMethod, eventClassObject, args, &exception);
			break;
		}
		case UserEventData::GAMEMANAGER_ACTORADD:
		{
			if (!gameManagerAddActorEventMethod)
				gameManagerAddActorEventMethod = mono_class_get_method_from_name(eventClass, "GameLayerAddActorEvent", 2);
			MonoDomain* domain = mono_object_get_domain(eventClassObject);
			MonoObject* exception = NULL;
			void* args[2];
			args[0] = &_viewID;
			args[1] = mono_string_new(domain, dynamic_cast<VirtualDataSceneBase::ActorBase*>(data->_eventObject.get())->getId().c_str());
			_eventThread = mono_thread_attach(mono_get_root_domain());
			mono_runtime_invoke(gameManagerAddActorEventMethod, eventClassObject, args, &exception);
			break;
		}
		case UserEventData::GAMEMANAGER_ACTORREMOVE:
		{
			if (!gameManagerRemoveActorEventMethod)
				gameManagerRemoveActorEventMethod = mono_class_get_method_from_name(eventClass, "GameLayerRemoveActorEvent", 2);
			MonoDomain* domain = mono_object_get_domain(eventClassObject);
			MonoObject* exception = NULL;
			void* args[2];
			args[0] = &_viewID;
			args[1] = mono_string_new(domain, dynamic_cast<VirtualDataSceneBase::ActorBase*>(data->_eventObject.get())->getId().c_str());
			_eventThread = mono_thread_attach(mono_get_root_domain());
			mono_runtime_invoke(gameManagerRemoveActorEventMethod, eventClassObject, args, &exception);
			break;
		}
		case UserEventData::GAMEMANAGER_PLAYPLOT:
		{
			if (!gameManagerPlayPlotEventMethod)
				gameManagerPlayPlotEventMethod = mono_class_get_method_from_name(eventClass, "PlayPlotScriptEvent", 3);
			void* widthData = data->_data;
			std::vector<std::string>* dList = (std::vector<std::string>*)widthData;
			MonoDomain* domain = mono_object_get_domain(eventClassObject);
			MonoObject* exception = NULL;
			void* args[3];
			args[0] = &_viewID;
			args[1] = mono_string_new(domain, dList->at(0).c_str());
			args[2] = mono_string_new(domain, dList->at(1).c_str());
			_eventThread = mono_thread_attach(mono_get_root_domain());
			mono_runtime_invoke(gameManagerPlayPlotEventMethod, eventClassObject, args, &exception);
			break;
		}
		case UserEventData::GAMEMANAGER_STOPPLOT:
		{
			if (!gameManagerStopPlotEventMethod)
				gameManagerStopPlotEventMethod = mono_class_get_method_from_name(eventClass, "StopPlotScriptEvent", 2);
			MonoDomain* domain = mono_object_get_domain(eventClassObject);
			MonoObject* exception = NULL;
			void* args[2];
			args[0] = &_viewID;
			args[1] = mono_string_new(domain, dynamic_cast<VirtualDataSceneBase::ActorBase*>(data->_eventObject.get())->getId().c_str());
			_eventThread = mono_thread_attach(mono_get_root_domain());
			mono_runtime_invoke(gameManagerStopPlotEventMethod, eventClassObject, args, &exception);
			break;
		}
		case UserEventData::GAMEMANAGER_PAUSEPLOT:
		{
			if (!gameManagerPausePlotEventMethod)
				gameManagerPausePlotEventMethod = mono_class_get_method_from_name(eventClass, "PausePlotScriptEvent", 2);
			MonoDomain* domain = mono_object_get_domain(eventClassObject);
			MonoObject* exception = NULL;
			void* args[2];
			args[0] = &_viewID;
			args[1] = mono_string_new(domain, dynamic_cast<VirtualDataSceneBase::ActorBase*>(data->_eventObject.get())->getId().c_str());
			_eventThread = mono_thread_attach(mono_get_root_domain());
			mono_runtime_invoke(gameManagerPausePlotEventMethod, eventClassObject, args, &exception);
			break;
		}
		default:
			break;
		}
		break;
	}
	case osgGA::GUIEventAdapter::CLOSE_WINDOW:
	case osgGA::GUIEventAdapter::QUIT_APPLICATION:
	{
		//mono_thread_detach(_eventThread);
		break;
	}
	default:
		break;
	}
	return false;
}
Exemple #15
0
void *
mono_arch_create_method_pointer (MonoMethod *method)
{
	MonoMethodSignature *sig;
	MonoJitInfo *ji;
	guint8 *p, *code_buffer;
	guint i, align = 0, simple_type, retSize, reg_save = 0,
		stackval_arg_pos, local_pos, float_pos,
		local_start, reg_param = 0, stack_param,
		this_flag, arg_pos, fpr_param, parSize;
	guint32 simpletype;
	size_data sz;
	int *vtbuf, cpos, vt_cur;

	sz.code_size   = 1024;
	sz.stack_size  = 1024;
	stack_param     = 0;
	fpr_param       = 0;
	arg_pos	        = 0;

	sig = method->signature;

	p = code_buffer = g_malloc (sz.code_size);

	DEBUG (printf ("\nDelegate [start emiting] %s at 0x%08x\n", 
		       method->name,p));

	/*----------------------------------------------------------*/ 
	/* prolog 					     	    */
	/*----------------------------------------------------------*/ 
	s390_stmg(p, s390_r6, STK_BASE, STK_BASE, S390_REG_SAVE_OFFSET);
	s390_lg  (p, s390_r7, 0, STK_BASE, MINV_POS);
	s390_lgr (p, s390_r0, STK_BASE);
	s390_aghi(p, STK_BASE, -(sz.stack_size+MINV_POS));
	s390_stg (p, s390_r0, 0, STK_BASE, 0);
	s390_la	 (p, s390_r8, 0, STK_BASE, 4);
	s390_lgr (p, s390_r10, s390_r8);
	s390_lghi(p, s390_r9, sz.stack_size+92);
	s390_lghi(p, s390_r11, 0);
	s390_mvcl(p, s390_r8, s390_r10);

	/*----------------------------------------------------------*/ 
	/* Let's fill MonoInvocation - first zero some fields 	    */
	/*----------------------------------------------------------*/ 
	s390_lghi (p, s390_r0, 0);
	s390_stg  (p, s390_r0, 0, STK_BASE, (MINV_POS + G_STRUCT_OFFSET (MonoInvocation, ex)));
	s390_stg  (p, s390_r0, 0, STK_BASE, (MINV_POS + G_STRUCT_OFFSET (MonoInvocation, ex_handler)));
	s390_stg  (p, s390_r0, 0, STK_BASE, (MINV_POS + G_STRUCT_OFFSET (MonoInvocation, parent)));
	s390_lghi (p, s390_r0, 1);
	s390_stg  (p, s390_r0, 0, STK_BASE, (MINV_POS + G_STRUCT_OFFSET (MonoInvocation, invoke_trap)));

	/*----------------------------------------------------------*/ 
	/* set method pointer 					    */
	/*----------------------------------------------------------*/ 
	s390_bras (p, s390_r13, 4);
	s390_llong(p, method);
	s390_lg	  (p, s390_r0, 0, s390_r13, 0);
	s390_stg  (p, s390_r0, 0, STK_BASE, (MINV_POS + G_STRUCT_OFFSET (MonoInvocation, method)));

	local_start = local_pos = MINV_POS + 
		      sizeof (MonoInvocation) + (sig->param_count + 1) * sizeof (stackval);
	this_flag   = (sig->hasthis ? 1 : 0);

	/*----------------------------------------------------------*/
	/* if we are returning a structure, checks it's length to   */
	/* see if there's a "hidden" parameter that points to the   */
	/* area. If necessary save this hidden parameter for later  */
	/*----------------------------------------------------------*/
	if (MONO_TYPE_ISSTRUCT(sig->ret)) {
		if (sig->pinvoke) 
			retSize = mono_class_native_size (sig->ret->data.klass, &align);
		else
			retSize = mono_class_value_size (sig->ret->data.klass, &align);
		switch(retSize) {
			case 0:
			case 1:
			case 2:
			case 4:
			case 8:
				sz.retStruct = 0;
				break;
			default:
				sz.retStruct = 1;
				s390_lgr(p, s390_r8, s390_r2);
				reg_save = 1;
		}
	} else  {
		reg_save = 0;
	}

	if (this_flag) {
		s390_stg (p, s390_r2 + reg_save, 0, STK_BASE, 
			  (MINV_POS + G_STRUCT_OFFSET (MonoInvocation, obj)));
		reg_param++;
	} else {
		s390_stg (p, s390_r2 + reg_save, 0, STK_BASE, local_pos);
		local_pos += sizeof(int);
		s390_stg (p, s390_r0, 0, STK_BASE, 
			 (MINV_POS + G_STRUCT_OFFSET (MonoInvocation, obj)));
	}

	s390_stmg (p, s390_r3 + reg_param, s390_r6, STK_BASE, local_pos);
	local_pos += 4 * sizeof(long);
	float_pos  = local_pos;
	s390_std (p, s390_f0, 0, STK_BASE, local_pos);
	local_pos += sizeof(double);
	s390_std (p, s390_f2, 0, STK_BASE, local_pos);
	local_pos += sizeof(double);

	/*----------------------------------------------------------*/ 
	/* prepare space for valuetypes			     	    */
	/*----------------------------------------------------------*/ 
	vt_cur = local_pos;
	vtbuf  = alloca (sizeof(int)*sig->param_count);
	cpos   = 0;
	for (i = 0; i < sig->param_count; i++) {
		MonoType *type = sig->params [i];
		vtbuf [i] = -1;
		DEBUG(printf("par: %d type: %d ref: %d\n",i,type->type,type->byref));
		if (type->type == MONO_TYPE_VALUETYPE) {
			MonoClass *klass = type->data.klass;
			gint size;

			if (klass->enumtype)
				continue;
			size = mono_class_native_size (klass, &align);
			cpos += align - 1;
			cpos &= ~(align - 1);
			vtbuf [i] = cpos;
			cpos += size;
		}
	}
	cpos += 3;
	cpos &= ~3;

	local_pos += cpos;

	/*----------------------------------------------------------*/ 
	/* set MonoInvocation::stack_args			    */
	/*----------------------------------------------------------*/ 
	stackval_arg_pos = MINV_POS + sizeof (MonoInvocation);
	s390_la  (p, s390_r0, 0, STK_BASE, stackval_arg_pos);
	s390_stg (p, s390_r0, 0, STK_BASE, (MINV_POS + G_STRUCT_OFFSET (MonoInvocation, stack_args)));

	/*----------------------------------------------------------*/ 
	/* add stackval arguments 				    */	
	/*----------------------------------------------------------*/ 
	for (i = 0; i < sig->param_count; ++i) {
		if (sig->params [i]->byref) {
			ADD_ISTACK_PARM(0, 1);
		} else {
			simple_type = sig->params [i]->type;
		enum_savechk:
			switch (simple_type) {
			case MONO_TYPE_I8:
				ADD_ISTACK_PARM(-1, 2);
				break;
			case MONO_TYPE_R4:
				ADD_RSTACK_PARM(1);
				break;
			case MONO_TYPE_R8:
				ADD_RSTACK_PARM(2);
				break;
			case MONO_TYPE_VALUETYPE:
				if (sig->params [i]->data.klass->enumtype) {
					simple_type = sig->params [i]->data.klass->enum_basetype->type;
					goto enum_savechk;
				}
				if (sig->pinvoke)
					parSize = mono_class_native_size (sig->params [i]->data.klass, &align);
				else
					parSize = mono_class_value_size (sig->params [i]->data.klass, &align);
				switch(parSize) {
				case 0:
				case 1:
				case 2:
				case 4:
					ADD_PSTACK_PARM(0, 1);
					break;
				case 8:
					ADD_PSTACK_PARM(-1, 2);
					break;
				default:
					ADD_TSTACK_PARM;
				}
				break;
			default:
				ADD_ISTACK_PARM(0, 1);
			}
		}
				
		if (vtbuf [i] >= 0) {
			s390_la	 (p, s390_r3, 0, STK_BASE, vt_cur);
			s390_stg (p, s390_r3, 0, STK_BASE, stackval_arg_pos);
			s390_la	 (p, s390_r3, 0, STK_BASE, stackval_arg_pos);
			vt_cur += vtbuf [i];
		} else {
			s390_la  (p, s390_r3, 0, STK_BASE, stackval_arg_pos);
		}

		/*--------------------------------------*/
		/* Load the parameter registers for the */
		/* call to stackval_from_data		*/
		/*--------------------------------------*/
		s390_bras (p, s390_r13, 8);
		s390_llong(p, sig->params [i]);
		s390_llong(p, sig->pinvoke);
		s390_llong(p, stackval_from_data);
		s390_lg   (p, s390_r2, 0, s390_r13, 0);
		s390_lg	  (p, s390_r5, 0, s390_r13, 4);
		s390_lg	  (p, s390_r1, 0, s390_r13, 8);
		s390_basr (p, s390_r14, s390_r1);

		stackval_arg_pos += sizeof(stackval);

		/* fixme: alignment */
		DEBUG (printf ("arg_pos %d --> ", arg_pos));
		if (sig->pinvoke)
			arg_pos += mono_type_native_stack_size (sig->params [i], &align);
		else
			arg_pos += mono_type_stack_size (sig->params [i], &align);
		
		DEBUG (printf ("%d\n", stackval_arg_pos));
	}

	/*----------------------------------------------------------*/ 
	/* Set return area pointer. 				    */
	/*----------------------------------------------------------*/ 
	s390_la (p, s390_r10, 0, STK_BASE, stackval_arg_pos);
	s390_stg(p, s390_r10, 0, STK_BASE, (MINV_POS + G_STRUCT_OFFSET (MonoInvocation, retval)));
	if (sig->ret->type == MONO_TYPE_VALUETYPE && !sig->ret->byref) {
		MonoClass *klass  = sig->ret->data.klass;
		if (!klass->enumtype) {
			s390_la (p, s390_r9, 0, s390_r10, sizeof(stackval));
			s390_st (p, s390_r9, 0,STK_BASE, stackval_arg_pos);
			stackval_arg_pos += sizeof(stackval);
		}
	}

	/*----------------------------------------------------------*/ 
	/* call ves_exec_method					    */
	/*----------------------------------------------------------*/ 
	s390_bras (p, s390_r13, 4);
	s390_llong(p, ves_exec_method);
	s390_lg	  (p, s390_r1, 0, s390_r13, 0);
	s390_la	  (p, s390_r2, 0, STK_BASE, MINV_POS);
	s390_basr (p, s390_r14, s390_r1);

	/*----------------------------------------------------------*/ 
	/* move retval from stackval to proper place (r3/r4/...)    */
	/*----------------------------------------------------------*/ 
	DEBUG(printf("retType: %d byRef: %d\n",sig->ret->type,sig->ret->byref));
	if (sig->ret->byref) {
		DEBUG (printf ("ret by ref\n"));
		s390_stg(p, s390_r2, 0, s390_r10, 0);
	} else {
	enum_retvalue:
		switch (sig->ret->type) {
		case MONO_TYPE_VOID:
			break;
		case MONO_TYPE_BOOLEAN:
		case MONO_TYPE_U1:
			s390_lghi(p, s390_r2, 0);
			s390_ic  (p, s390_r2, 0, s390_r10, 0);
			break;
		case MONO_TYPE_I2:
		case MONO_TYPE_U2:
			s390_lh (p, s390_r2, 0,s390_r10, 0);
			break;
		case MONO_TYPE_I4:
		case MONO_TYPE_U4:
		case MONO_TYPE_I:
		case MONO_TYPE_U:
			s390_lgf(p, s390_r2, 0, s390_r10, 0);
			break;
		case MONO_TYPE_OBJECT:
		case MONO_TYPE_STRING:
		case MONO_TYPE_CLASS:
		case MONO_TYPE_I8:
			s390_lg (p, s390_r2, 0, s390_r10, 0);
			break;
		case MONO_TYPE_R4:
			s390_le (p, s390_f0, 0, s390_r10, 0);
			break;
		case MONO_TYPE_R8:
			s390_ld (p, s390_f0, 0, s390_r10, 0);
			break;
		case MONO_TYPE_VALUETYPE:
			if (sig->ret->data.klass->enumtype) {
				simpletype = sig->ret->data.klass->enum_basetype->type;
				goto enum_retvalue;
			}
			/*---------------------------------*/
			/* Call stackval_to_data to return */
			/* the structure		   */
			/*---------------------------------*/
			s390_bras (p, s390_r13, 8);
			s390_llong(p, sig->ret);
			s390_llong(p, sig->pinvoke);
			s390_llong(p, stackval_to_data);
			s390_lg	  (p, s390_r2, 0, s390_r13, 0);
			s390_lg	  (p, s390_r3, 0, STK_BASE, (MINV_POS + G_STRUCT_OFFSET (MonoInvocation, retval)));
			if (sz.retStruct) {	
				/*------------------------------------------*/
				/* Get stackval_to_data to set result area  */
				/*------------------------------------------*/
				s390_lgr (p, s390_r4, s390_r8);
			} else {		
				/*------------------------------------------*/
				/* Give stackval_to_data a temp result area */
				/*------------------------------------------*/ 
				s390_la (p, s390_r4, 0, STK_BASE, stackval_arg_pos);
			}
			s390_lg   (p, s390_r5, 0,s390_r13, 4);
			s390_lg   (p, s390_r1, 0, s390_r13, 8);
			s390_basr (p, s390_r14, s390_r1);
			switch (retSize) {
				case 0:
					break;
				case 1:
					s390_lghi(p, s390_r2, 0);
					s390_ic  (p, s390_r2, 0, s390_r10, 0);
					break;
				case 2:
					s390_lh (p, s390_r2, 0, s390_r10, 0);
					break;
				case 4:
					s390_lgf(p, s390_r2, 0, s390_r10, 0);
					break;
				case 8:
					s390_lg (p, s390_r2, 0, s390_r10, 0);
					break;
				default: ;
					/*-------------------------------------------------*/
					/* stackval_to_data has placed data in result area */
					/*-------------------------------------------------*/
			}
			break;
		default:
			g_error ("Type 0x%x not handled yet in thunk creation", 
				 sig->ret->type);
			break;
		}
	}

	/*----------------------------------------------------------*/ 
	/* epilog 						    */
	/*----------------------------------------------------------*/ 
	s390_lg   (p, STK_BASE, 0, STK_BASE, 0);
	s390_lg   (p, s390_r4, 0, STK_BASE, S390_RET_ADDR_OFFSET);
	s390_lmg  (p, s390_r6, STK_BASE, STK_BASE, S390_REG_SAVE_OFFSET);
	s390_br   (p, s390_r4);

	DEBUG (printf ("emited code size: %d\n", p - code_buffer));

	DEBUG (printf ("Delegate [end emiting]\n"));

	ji = g_new0 (MonoJitInfo, 1);
	ji->method = method;
	ji->code_size = p - code_buffer;
	ji->code_start = code_buffer;

	mono_jit_info_table_add (mono_get_root_domain (), ji);

	return ji->code_start;
}
Exemple #16
0
gpointer
mono_arch_create_rgctx_lazy_fetch_trampoline (guint32 slot, MonoTrampInfo **info, gboolean aot)
{
#ifdef MONO_ARCH_VTABLE_REG
	guint8 *tramp;
	guint8 *code, *buf;
	guint8 **rgctx_null_jumps;
	gint32 displace;
	int tramp_size,
	    depth, 
	    index, 
	    iPatch = 0,
	    i;
	gboolean mrgctx;
	MonoJumpInfo *ji = NULL;
	GSList *unwind_ops = NULL;

	mrgctx = MONO_RGCTX_SLOT_IS_MRGCTX (slot);
	index = MONO_RGCTX_SLOT_INDEX (slot);
	if (mrgctx)
		index += MONO_SIZEOF_METHOD_RUNTIME_GENERIC_CONTEXT / sizeof (gpointer);
	for (depth = 0; ; ++depth) {
		int size = mono_class_rgctx_get_array_size (depth, mrgctx);

		if (index < size - 1)
			break;
		index -= size - 1;
	}

	tramp_size = 48 + 16 * depth;
	if (mrgctx)
		tramp_size += 4;
	else
		tramp_size += 12;

	code = buf = mono_global_codeman_reserve (tramp_size);

	unwind_ops = mono_arch_get_cie_program ();

	rgctx_null_jumps = g_malloc (sizeof (guint8*) * (depth + 2));

	if (mrgctx) {
		/* get mrgctx ptr */
		s390_lgr (code, s390_r1, s390_r2);
	} else {
		/* load rgctx ptr from vtable */
		s390_lg (code, s390_r1, 0, s390_r2, G_STRUCT_OFFSET(MonoVTable, runtime_generic_context));
		/* is the rgctx ptr null? */
		s390_ltgr (code, s390_r1, s390_r1);
		/* if yes, jump to actual trampoline */
		rgctx_null_jumps [iPatch++] = code;
		s390_jge (code, 0);
	}

	for (i = 0; i < depth; ++i) {
		/* load ptr to next array */
		if (mrgctx && i == 0)
			s390_lg (code, s390_r1, 0, s390_r1, MONO_SIZEOF_METHOD_RUNTIME_GENERIC_CONTEXT);
		else
			s390_lg (code, s390_r1, 0, s390_r1, 0);
		s390_ltgr (code, s390_r1, s390_r1);
		/* if the ptr is null then jump to actual trampoline */
		rgctx_null_jumps [iPatch++] = code;
		s390_jge (code, 0);
	}

	/* fetch slot */
	s390_lg (code, s390_r1, 0, s390_r1, (sizeof (gpointer) * (index  + 1)));
	/* is the slot null? */
	s390_ltgr (code, s390_r1, s390_r1);
	/* if yes, jump to actual trampoline */
	rgctx_null_jumps [iPatch++] = code;
	s390_jge (code, 0);
	/* otherwise return r1 */
	s390_lgr (code, s390_r2, s390_r1);
	s390_br  (code, s390_r14);

	for (i = 0; i < iPatch; i++) {
		displace = ((uintptr_t) code - (uintptr_t) rgctx_null_jumps[i]) / 2;
		s390_patch_rel ((rgctx_null_jumps [i] + 2), displace);
	}

	g_free (rgctx_null_jumps);

	/* move the rgctx pointer to the VTABLE register */
	s390_lgr (code, MONO_ARCH_VTABLE_REG, s390_r2);

	tramp = mono_arch_create_specific_trampoline (GUINT_TO_POINTER (slot),
		MONO_TRAMPOLINE_RGCTX_LAZY_FETCH, mono_get_root_domain (), NULL);

	/* jump to the actual trampoline */
	displace = (tramp - code) / 2;
	s390_jg (code, displace);

	mono_arch_flush_icache (buf, code - buf);

	g_assert (code - buf <= tramp_size);

	if (info) {
		char *name = mono_get_rgctx_fetch_trampoline_name (slot);
		*info = mono_tramp_info_create (name, buf, code - buf, ji, unwind_ops);
		g_free (name);
	}

	return(buf);
#else
	g_assert_not_reached ();
#endif
	return(NULL);
}	
Exemple #17
0
MonoDomain* JniManager::getMonoDomain()
{
    MonoDomain* monoDomain = mono_get_root_domain();
    mono_thread_attach(monoDomain);
    return monoDomain;
}
Exemple #18
0
gpointer
mono_arch_create_monitor_enter_trampoline (MonoTrampInfo **info, gboolean is_v4, gboolean aot)
{
	guint8	*tramp,
		*code, *buf;
	gint16	*jump_obj_null, 
		*jump_sync_null, 
		*jump_cs_failed, 
		*jump_other_owner, 
		*jump_tid, 
		*jump_sync_thin_hash = NULL,
		*jump_lock_taken_true = NULL;
	int tramp_size,
	    status_reg = s390_r0,
	    lock_taken_reg = s390_r1,
	    obj_reg = s390_r2,
	    sync_reg = s390_r3,
	    tid_reg = s390_r4,
	    status_offset,
	    nest_offset;
	MonoJumpInfo *ji = NULL;
	GSList *unwind_ops = NULL;

	g_assert (MONO_ARCH_MONITOR_OBJECT_REG == obj_reg);
#ifdef MONO_ARCH_MONITOR_LOCK_TAKEN_REG
	g_assert (MONO_ARCH_MONITOR_LOCK_TAKEN_REG == lock_taken_reg);
#else
	g_assert (!is_v4);
#endif

	mono_monitor_threads_sync_members_offset (&status_offset, &nest_offset);
	g_assert (MONO_THREADS_SYNC_MEMBER_SIZE (status_offset) == sizeof (guint32));
	g_assert (MONO_THREADS_SYNC_MEMBER_SIZE (nest_offset) == sizeof (guint32));
	status_offset = MONO_THREADS_SYNC_MEMBER_OFFSET (status_offset);
	nest_offset = MONO_THREADS_SYNC_MEMBER_OFFSET (nest_offset);

	tramp_size = 160;

	code = buf = mono_global_codeman_reserve (tramp_size);

	unwind_ops = mono_arch_get_cie_program ();

	if (mono_thread_get_tls_offset () != -1) {
		/* MonoObject* obj is in obj_reg */
		/* is obj null? */
		s390_ltgr (code, obj_reg, obj_reg);
		/* if yes, jump to actual trampoline */
		s390_jz (code, 0); CODEPTR(code, jump_obj_null);

		if (is_v4) {
			s390_cli (code, lock_taken_reg, 0, 1);
			/* if *lock_taken is 1, jump to actual trampoline */
			s390_je (code, 0); CODEPTR(code, jump_lock_taken_true);
		}

		/* load obj->synchronization to sync_reg */
		s390_lg (code, sync_reg, 0, obj_reg, MONO_STRUCT_OFFSET (MonoObject, synchronisation));

		if (mono_gc_is_moving ()) {
			/*if bit zero is set it's a thin hash*/
			s390_tmll (code, sync_reg, 1);
			s390_jo  (code, 0); CODEPTR(code, jump_sync_thin_hash);

			/* Clear bits used by the gc */
			s390_nill (code, sync_reg, ~0x3);
		}

		/* is synchronization null? */
		s390_ltgr (code, sync_reg, sync_reg);
		/* if yes, jump to actual trampoline */
		s390_jz (code, 0); CODEPTR(code, jump_sync_null);

		/* load MonoInternalThread* into tid_reg */
		s390_ear (code, s390_r5, 0);
		s390_sllg(code, s390_r5, s390_r5, 0, 32);
		s390_ear (code, s390_r5, 1);
		/* load tid */
		s390_lg  (code, tid_reg, 0, s390_r5, mono_thread_get_tls_offset ());
		s390_lgf (code, tid_reg, 0, tid_reg, MONO_STRUCT_OFFSET (MonoInternalThread, small_id));

		/* is synchronization->owner free */
		s390_lgf  (code, status_reg, 0, sync_reg, status_offset);
		s390_nilf (code, status_reg, OWNER_MASK);
		/* if not, jump to next case */
		s390_jnz  (code, 0); CODEPTR(code, jump_tid);

		/* if yes, try a compare-exchange with the TID */
		/* Form new status in tid_reg */
		s390_xr (code, tid_reg, status_reg);
		/* compare and exchange */
		s390_cs (code, status_reg, tid_reg, sync_reg, status_offset);
		s390_jnz (code, 0); CODEPTR(code, jump_cs_failed);
		/* if successful, return */
		if (is_v4)
			s390_mvi (code, lock_taken_reg, 0, 1);
		s390_br (code, s390_r14);

		/* next case: synchronization->owner is not null */
		PTRSLOT(code, jump_tid);
		/* is synchronization->owner == TID? */
		s390_nilf (code, status_reg, OWNER_MASK);
		s390_cr (code, status_reg, tid_reg);
		/* if not, jump to actual trampoline */
		s390_jnz (code, 0); CODEPTR(code, jump_other_owner);
		/* if yes, increment nest */
		s390_lgf (code, s390_r5, 0, sync_reg, nest_offset);
		s390_ahi (code, s390_r5, 1);
		s390_st  (code, s390_r5, 0, sync_reg, nest_offset);
		/* return */
		if (is_v4)
			s390_mvi (code, lock_taken_reg, 0, 1);
		s390_br (code, s390_r14);

		PTRSLOT (code, jump_obj_null);
		if (jump_sync_thin_hash)
			PTRSLOT (code, jump_sync_thin_hash);
		PTRSLOT (code, jump_sync_null);
		PTRSLOT (code, jump_cs_failed);
		PTRSLOT (code, jump_other_owner);
		if (is_v4)
			PTRSLOT (code, jump_lock_taken_true);
	}

	/* jump to the actual trampoline */
	if (is_v4)
		tramp = mono_arch_create_specific_trampoline (NULL, MONO_TRAMPOLINE_MONITOR_ENTER_V4, mono_get_root_domain (), NULL);
	else
		tramp = mono_arch_create_specific_trampoline (NULL, MONO_TRAMPOLINE_MONITOR_ENTER, mono_get_root_domain (), NULL);

	/* jump to the actual trampoline */
	S390_SET (code, s390_r1, tramp);
	s390_br (code, s390_r1);

	mono_arch_flush_icache (code, code - buf);
	mono_profiler_code_buffer_new (buf, code - buf, MONO_PROFILER_CODE_BUFFER_MONITOR, NULL);
	g_assert (code - buf <= tramp_size);

	if (info) {
		if (is_v4)
			*info = mono_tramp_info_create ("monitor_enter_v4_trampoline", buf, code - buf, ji, unwind_ops);
		else
			*info = mono_tramp_info_create ("monitor_enter_trampoline", buf, code - buf, ji, unwind_ops);
	}

	return buf;
}
Exemple #19
0
gboolean
mono_domain_finalize (MonoDomain *domain, guint32 timeout) 
{
	DomainFinalizationReq *req;
	guint32 res;
	HANDLE done_event;
	MonoInternalThread *thread = mono_thread_internal_current ();

	if (mono_thread_internal_current () == gc_thread)
		/* We are called from inside a finalizer, not much we can do here */
		return FALSE;

	/* 
	 * No need to create another thread 'cause the finalizer thread
	 * is still working and will take care of running the finalizers
	 */ 
	
#ifndef HAVE_NULL_GC
	if (gc_disabled)
		return TRUE;

	mono_gc_collect (mono_gc_max_generation ());

	done_event = CreateEvent (NULL, TRUE, FALSE, NULL);
	if (done_event == NULL) {
		return FALSE;
	}

	req = g_new0 (DomainFinalizationReq, 1);
	req->domain = domain;
	req->done_event = done_event;

	if (domain == mono_get_root_domain ())
		finalizing_root_domain = TRUE;
	
	mono_finalizer_lock ();

	domains_to_finalize = g_slist_append (domains_to_finalize, req);

	mono_finalizer_unlock ();

	/* Tell the finalizer thread to finalize this appdomain */
	mono_gc_finalize_notify ();

	if (timeout == -1)
		timeout = INFINITE;

	while (TRUE) {
		res = WaitForSingleObjectEx (done_event, timeout, TRUE);
		/* printf ("WAIT RES: %d.\n", res); */

		if (res == WAIT_IO_COMPLETION) {
			if ((thread->state & (ThreadState_StopRequested | ThreadState_SuspendRequested)) != 0)
				return FALSE;
		} else if (res == WAIT_TIMEOUT) {
			/* We leak the handle here */
			return FALSE;
		} else {
			break;
		}
	}

	CloseHandle (done_event);

	if (domain == mono_get_root_domain ()) {
		mono_thread_pool_cleanup ();
		mono_gc_finalize_threadpool_threads ();
	}

	return TRUE;
#else
	/* We don't support domain finalization without a GC */
	return FALSE;
#endif
}
Exemple #20
0
void *
mono_arch_create_method_pointer (MonoMethod *method)
{
	MonoMethodSignature *sig;
	MonoJitInfo *ji;
	guint stack_size, code_size, stackval_arg_pos, local_pos;
	guint i, local_start, reg_param = 0, stack_param, cpos, vt_cur;
	guint32 align = 0;
	guint32 *p, *code_buffer;
	gint *vtbuf;
	gint32 simpletype;

	code_size = 1024; /* these should be calculated... */
	stack_size = 1024;
	stack_param = 0;

	sig = method->signature;

	p = code_buffer = g_malloc (code_size);

	DEBUG(fprintf(stderr, "Delegate [start emiting] %s\n", method->name));
	DEBUG(fprintf(stderr, "%s\n", sig_to_name(sig, FALSE)));

	p = emit_prolog (p, sig, stack_size);

	/* fill MonoInvocation */
	sparc_st_imm_ptr (p, sparc_g0, sparc_sp,
		  (MINV_POS + G_STRUCT_OFFSET (MonoInvocation, ex)));
	sparc_st_imm_ptr (p, sparc_g0, sparc_sp,
		  (MINV_POS + G_STRUCT_OFFSET (MonoInvocation, ex_handler)));
	sparc_st_imm_ptr (p, sparc_g0, sparc_sp,
		  (MINV_POS + G_STRUCT_OFFSET (MonoInvocation, parent)));

	sparc_set_ptr (p, (void *)method, sparc_l0);
	sparc_st_imm_ptr (p, sparc_l0, sparc_sp,
		  (MINV_POS + G_STRUCT_OFFSET (MonoInvocation, method)));

	stackval_arg_pos = MINV_POS + sizeof (MonoInvocation);
	local_start = local_pos = stackval_arg_pos + (sig->param_count + 1) * sizeof (stackval);

	if (sig->hasthis) {
		sparc_st_imm_ptr (p, sparc_i0, sparc_sp,
			  (MINV_POS + G_STRUCT_OFFSET (MonoInvocation, obj)));
		reg_param = 1;
	} 

	if (sig->param_count) {
		gint save_count = MIN (OUT_REGS, sig->param_count + sig->hasthis);
		for (i = reg_param; i < save_count; i++) {
			sparc_st_imm_ptr (p, sparc_i0 + i, sparc_sp, local_pos);
			local_pos += SLOT_SIZE;
		}
	}

	/* prepare space for valuetypes */
        vt_cur = local_pos;
        vtbuf = alloca (sizeof(int)*sig->param_count);
        cpos = 0;
        for (i = 0; i < sig->param_count; i++) {
                MonoType *type = sig->params [i];
                vtbuf [i] = -1;
                if (!sig->params[i]->byref && type->type == MONO_TYPE_VALUETYPE) {
                        MonoClass *klass = type->data.klass;
                        gint size;
			
                        if (klass->enumtype)
                                continue;
                        size = mono_class_native_size (klass, &align);
                        cpos += align - 1;
                        cpos &= ~(align - 1);
                        vtbuf [i] = cpos;
                        cpos += size;
                }
        }
        cpos += SLOT_SIZE - 1;
        cpos &= ~(SLOT_SIZE - 1);
	
	local_pos += cpos;
	
	/* set MonoInvocation::stack_args */
	sparc_add_imm (p, 0, sparc_sp, stackval_arg_pos, sparc_l0);
	sparc_st_imm_ptr (p, sparc_l0, sparc_sp,
		  (MINV_POS + G_STRUCT_OFFSET (MonoInvocation, stack_args)));

	/* add stackval arguments */
	for (i=0; i < sig->param_count; i++) {
		int stack_offset;
		int type;
		if (reg_param < OUT_REGS) {
			stack_offset = local_start + i * SLOT_SIZE;
			reg_param++;
		} else {
			stack_offset = stack_size + 8 + stack_param;
			stack_param++;
		}

		if (!sig->params[i]->byref) {
			type = sig->params[i]->type;
		enum_arg:
			switch (type) {
			case MONO_TYPE_I8:
			case MONO_TYPE_U8:
			case MONO_TYPE_I:
			case MONO_TYPE_U:
			case MONO_TYPE_STRING:
			case MONO_TYPE_OBJECT:
			case MONO_TYPE_CLASS:
			case MONO_TYPE_SZARRAY:
			case MONO_TYPE_PTR:
			case MONO_TYPE_R8:
				break;
			case MONO_TYPE_I4:
			case MONO_TYPE_U4:
				stack_offset += SLOT_SIZE - 4;
				break;
			case MONO_TYPE_CHAR:
			case MONO_TYPE_I2:
			case MONO_TYPE_U2:
				stack_offset += SLOT_SIZE - 2;
				break;
			case MONO_TYPE_I1:
			case MONO_TYPE_U1:
			case MONO_TYPE_BOOLEAN:
				stack_offset += SLOT_SIZE - 1;
				break;
	                case MONO_TYPE_VALUETYPE:
	                        if (sig->params[i]->data.klass->enumtype) {
	                                type = sig->params[i]->data.klass->enum_basetype->type;
	                                goto enum_arg;
	                        }
				g_assert(vtbuf[i] >= 0);
	                        break;
			default:
				g_error ("can not cope with delegate arg type %d", type);
			}
		}
	
		sparc_add_imm (p, 0, sparc_sp, stack_offset, sparc_o2);

		if (vtbuf[i] >= 0) {
			sparc_add_imm (p, 0, sparc_sp, vt_cur, sparc_o1);
			sparc_st_imm_ptr (p, sparc_o1, sparc_sp, stackval_arg_pos);
			sparc_add_imm (p, 0, sparc_sp, stackval_arg_pos, 
				       sparc_o1);
			sparc_ld_imm_ptr (p, sparc_o2, 0, sparc_o2);
			vt_cur += vtbuf[i];
		} else {
			sparc_add_imm (p, 0, sparc_sp, stackval_arg_pos, 
				       sparc_o1);
		}

		sparc_set_ptr (p, (void *)sig->params[i], sparc_o0);
		sparc_set (p, (guint32)sig->pinvoke, sparc_o3);

		/* YOU make the CALL! */
		sparc_set_ptr (p, (void *)stackval_from_data, sparc_l0);
		sparc_jmpl_imm (p, sparc_l0, 0, sparc_callsite);
		sparc_nop (p);
                stackval_arg_pos += sizeof(stackval);
	}

	/* return value storage */
	/* Align to dword */
	stackval_arg_pos = (stackval_arg_pos + (8 - 1)) & (~(8 -1));
	if (sig->param_count) {
		sparc_add_imm (p, 0, sparc_sp, stackval_arg_pos, sparc_l0);
	}
	if (!sig->ret->byref && sig->ret->type == MONO_TYPE_VALUETYPE && !sig->ret->data.klass->enumtype) {
#if !SPARCV9
		/* pass on callers buffer */
		sparc_ld_imm_ptr (p, sparc_fp, 64, sparc_l1);
		sparc_st_imm_ptr (p, sparc_l1, sparc_l0, 0);
#else
		sparc_add_imm (p, 0, sparc_l0, sizeof(stackval), sparc_l1);
		sparc_st_imm_ptr (p, sparc_l1, sparc_l0, 0);
#endif
	}

	sparc_st_imm_ptr (p, sparc_l0, sparc_sp,
		  (MINV_POS + G_STRUCT_OFFSET (MonoInvocation, retval)));

	/* call ves_exec_method */
	sparc_add_imm (p, 0, sparc_sp, MINV_POS, sparc_o0);
	sparc_set_ptr (p, (void *)ves_exec_method, sparc_l0);
	sparc_jmpl_imm (p, sparc_l0, 0, sparc_callsite);
	sparc_nop (p);

	/* move retval from stackval to proper place (r3/r4/...) */
        if (sig->ret->byref) {
		sparc_ld_imm_ptr (p, sparc_sp, stackval_arg_pos, sparc_i0 );
        } else {
        enum_retvalue:
                switch (sig->ret->type) {
                case MONO_TYPE_VOID:
                        break;
                case MONO_TYPE_BOOLEAN:
                case MONO_TYPE_I1:
                case MONO_TYPE_U1:
                case MONO_TYPE_I2:
                case MONO_TYPE_U2:
                case MONO_TYPE_I4:
                case MONO_TYPE_U4:
                        sparc_ld_imm (p, sparc_sp, stackval_arg_pos, sparc_i0);
                        break;
                case MONO_TYPE_I:
                case MONO_TYPE_U:
                case MONO_TYPE_OBJECT:
		case MONO_TYPE_STRING:
                case MONO_TYPE_CLASS:
                        sparc_ld_imm_ptr (p, sparc_sp, stackval_arg_pos, sparc_i0);
                        break;
                case MONO_TYPE_I8:
                case MONO_TYPE_U8:
#if SPARCV9
                        sparc_ldx_imm (p, sparc_sp, stackval_arg_pos, sparc_i0);
#else
                        sparc_ld_imm (p, sparc_sp, stackval_arg_pos, sparc_i0);
                        sparc_ld_imm (p, sparc_sp, stackval_arg_pos + 4, sparc_i1);
#endif
                        break;
                case MONO_TYPE_R4:
                        sparc_lddf_imm (p, sparc_sp, stackval_arg_pos, sparc_f0);
			sparc_fdtos(p, sparc_f0, sparc_f0);
                        break;
                case MONO_TYPE_R8:
                        sparc_lddf_imm (p, sparc_sp, stackval_arg_pos, sparc_f0);
                        break;
                case MONO_TYPE_VALUETYPE: {
			gint size;
			gint reg = sparc_i0;
                        if (sig->ret->data.klass->enumtype) {
                                simpletype = sig->ret->data.klass->enum_basetype->type;
                                goto enum_retvalue;
                        }
#if SPARCV9
                        size = mono_class_native_size (sig->ret->data.klass, NULL);
                        sparc_ldx_imm (p, sparc_sp, stackval_arg_pos, sparc_l0);
			if (size <= 16) {
				gint off = 0;
				if (size >= 8) {
		                        sparc_ldx_imm (p, sparc_l0, 0, reg);
					size -= 8;
					off += 8;
					reg++;
				}
				if (size > 0)
		                        sparc_ldx_imm (p, sparc_l0, off, reg);
			} else
	                        NOT_IMPL("value type as ret val from delegate");
#endif
                        break;
		}
                default: 
			g_error ("Type 0x%x not handled yet in thunk creation",
				 sig->ret->type);
                        break;
                }
        }

	p = emit_epilog (p, sig, stack_size);

	for (i = 0; i < ((p - code_buffer)/2); i++)
		flushi((code_buffer + (i*8)));
	
	ji = g_new0 (MonoJitInfo, 1);
        ji->method = method;
        ji->code_size = p - code_buffer;
	ji->code_start = code_buffer;
	
	mono_jit_info_table_add (mono_get_root_domain (), ji);

	DEBUG(sparc_disassemble_code (code_buffer, p, method->name));

	DEBUG(fprintf(stderr, "Delegate [end emiting] %s\n", method->name));

	return ji->code_start;
}
Exemple #21
0
/* Entry point called by LdrLoadDll of ntdll.dll after _CorValidateImage. */
BOOL STDMETHODCALLTYPE _CorDllMain(HINSTANCE hInst, DWORD dwReason, LPVOID lpReserved)
{
	MonoAssembly* assembly;
	MonoImage* image;
	gchar* file_name;
	gchar* error;

	switch (dwReason)
	{
	case DLL_PROCESS_ATTACH:
		DisableThreadLibraryCalls (hInst);

		file_name = mono_get_module_file_name (hInst);

		if (mono_get_root_domain ()) {
			image = mono_image_open_from_module_handle (hInst, mono_path_resolve_symlinks (file_name), TRUE, NULL);
		} else {
			init_from_coree = TRUE;
			mono_runtime_load (file_name, NULL);
			error = (gchar*) mono_check_corlib_version ();
			if (error) {
				g_free (error);
				g_free (file_name);
				mono_runtime_quit ();
				return FALSE;
			}

			image = mono_image_open (file_name, NULL);
			if (image) {
				image->has_entry_point = TRUE;
				mono_close_exe_image ();
				/* Decrement reference count to zero. (Image will not be closed.) */
				mono_image_close (image);
			}
		}

		if (!image) {
			g_free (file_name);
			return FALSE;
		}

		/*
		 * FIXME: Find a better way to call mono_image_fixup_vtable. Only
		 * loader trampolines should be used and assembly loading should
		 * probably be delayed until the first call to an exported function.
		 */
		if (image->tables [MONO_TABLE_ASSEMBLY].rows && ((MonoCLIImageInfo*) image->image_info)->cli_cli_header.ch_vtable_fixups.rva)
			assembly = mono_assembly_open (file_name, NULL);

		g_free (file_name);
		break;
	case DLL_PROCESS_DETACH:
		if (lpReserved != NULL)
			/* The process is terminating. */
			return TRUE;
		file_name = mono_get_module_file_name (hInst);
		image = mono_image_loaded (file_name);
		if (image)
			mono_image_close (image);

		g_free (file_name);
		break;
	}

	return TRUE;
}
Exemple #22
0
void CPipeServer::InitMono()
{
	HMODULE hMono=GetModuleHandle(L"mono.dll");

	if (!hMono)
	{
		//this process doesn't use mono.dll  Perhaps it's renamed.  Find a module that exports mono_thread_attach
		HANDLE ths=CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, GetCurrentProcessId());
		if (ths != INVALID_HANDLE_VALUE)
		{
			MODULEENTRY32 me;
			me.dwSize = sizeof(me);
			
			if (Module32First(ths, &me))
			{
				do
				{
					if (GetProcAddress(me.hModule, "mono_thread_attach"))
					{
						hMono = me.hModule;
						break;
					}

				} while (Module32Next(ths, &me));

			}



			CloseHandle(ths);
		}


	}

	WriteQword((UINT64)hMono);
	if (hMono)
	{		
		std::stringstream x;
		x.clear();
		x << "Mono dll found at " << std::hex << hMono <<"\n";
		OutputDebugStringA(x.str().c_str());

		if (attached==FALSE)
		{
			

			g_free=(G_FREE)GetProcAddress(hMono, "g_free");
			mono_get_root_domain=(MONO_GET_ROOT_DOMAIN)GetProcAddress(hMono, "mono_get_root_domain");
			mono_thread_attach=(MONO_THREAD_ATTACH)GetProcAddress(hMono, "mono_thread_attach");
			mono_thread_detach=(MONO_THREAD_DETACH)GetProcAddress(hMono, "mono_thread_detach");

			mono_object_get_class=(MONO_OBJECT_GET_CLASS)GetProcAddress(hMono, "mono_object_get_class");
			
			mono_domain_foreach=(MONO_DOMAIN_FOREACH)GetProcAddress(hMono, "mono_domain_foreach");
			mono_domain_set=(MONO_DOMAIN_SET)GetProcAddress(hMono, "mono_domain_set");
			mono_assembly_foreach=(MONO_ASSEMBLY_FOREACH)GetProcAddress(hMono, "mono_assembly_foreach");
			mono_assembly_get_image=(MONO_ASSEMBLY_GET_IMAGE)GetProcAddress(hMono, "mono_assembly_get_image");
			
			mono_image_get_name=(MONO_IMAGE_GET_NAME)GetProcAddress(hMono, "mono_image_get_name");
			mono_image_get_table_info=(MONO_IMAGE_GET_TABLE_INFO)GetProcAddress(hMono, "mono_image_get_table_info");
			mono_image_rva_map=(MONO_IMAGE_RVA_MAP)GetProcAddress(hMono, "mono_image_rva_map");

			mono_table_info_get_rows=(MONO_TABLE_INFO_GET_ROWS)GetProcAddress(hMono, "mono_table_info_get_rows");
			mono_metadata_decode_row_col=(MONO_METADATA_DECODE_ROW_COL)GetProcAddress(hMono, "mono_metadata_decode_row_col");
			mono_metadata_string_heap=(MONO_METADATA_STRING_HEAP)GetProcAddress(hMono, "mono_metadata_string_heap");

			
			mono_class_get=(MONO_CLASS_GET)GetProcAddress(hMono, "mono_class_get");		
			mono_class_from_name_case=(MONO_CLASS_FROM_NAME_CASE)GetProcAddress(hMono, "mono_class_from_name_case");	
			mono_class_get_name=(MONO_CLASS_GET_NAME)GetProcAddress(hMono, "mono_class_get_name");
			mono_class_get_namespace=(MONO_CLASS_GET_NAMESPACE)GetProcAddress(hMono, "mono_class_get_namespace");
			mono_class_get_methods=(MONO_CLASS_GET_METHODS)GetProcAddress(hMono, "mono_class_get_methods");		
			mono_class_get_method_from_name=(MONO_CLASS_GET_METHOD_FROM_NAME)GetProcAddress(hMono, "mono_class_get_method_from_name");		
			mono_class_get_fields=(MONO_CLASS_GET_FIELDS)GetProcAddress(hMono, "mono_class_get_fields");	
			mono_class_get_parent=(MONO_CLASS_GET_PARENT)GetProcAddress(hMono, "mono_class_get_parent");
			mono_class_vtable=(MONO_CLASS_VTABLE)GetProcAddress(hMono, "mono_class_vtable");
			
			mono_class_num_fields=(MONO_CLASS_NUM_FIELDS)GetProcAddress(hMono, "mono_class_num_fields");	
			mono_class_num_methods=(MONO_CLASS_NUM_METHODS)GetProcAddress(hMono, "mono_class_num_methods");		
			

			mono_field_get_name=(MONO_FIELD_GET_NAME)GetProcAddress(hMono, "mono_field_get_name");	
			mono_field_get_type=(MONO_FIELD_GET_TYPE)GetProcAddress(hMono, "mono_field_get_type");	
			mono_field_get_parent=(MONO_FIELD_GET_PARENT)GetProcAddress(hMono, "mono_field_get_parent");	
			mono_field_get_offset=(MONO_FIELD_GET_OFFSET)GetProcAddress(hMono, "mono_field_get_offset");	
			mono_field_get_flags = (MONO_FIELD_GET_FLAGS)GetProcAddress(hMono, "mono_field_get_flags");

			mono_type_get_name=(MONO_TYPE_GET_NAME)GetProcAddress(hMono, "mono_type_get_name");
			mono_type_get_type=(MONO_TYPE_GET_TYPE)GetProcAddress(hMono, "mono_type_get_type");

			mono_method_get_name=(MONO_METHOD_GET_NAME)GetProcAddress(hMono, "mono_method_get_name");	
			mono_method_get_class=(MONO_METHOD_GET_CLASS)GetProcAddress(hMono, "mono_method_get_class");	
			mono_method_get_header=(MONO_METHOD_GET_HEADER)GetProcAddress(hMono, "mono_method_get_header");	
			mono_method_signature=(MONO_METHOD_SIG)GetProcAddress(hMono, "mono_method_signature");
			mono_method_get_param_names = (MONO_METHOD_GET_PARAM_NAMES)GetProcAddress(hMono, "mono_method_get_param_names");

			

			mono_signature_get_desc = (MONO_SIGNATURE_GET_DESC)GetProcAddress(hMono, "mono_signature_get_desc");
			mono_signature_get_param_count = (MONO_SIGNATURE_GET_PARAM_COUNT)GetProcAddress(hMono, "mono_signature_get_param_count");
			mono_signature_get_return_type = (MONO_SIGNATURE_GET_RETURN_TYPE)GetProcAddress(hMono, "mono_signature_get_return_type");
			


			mono_compile_method=(MONO_COMPILE_METHOD)GetProcAddress(hMono, "mono_compile_method");	
			mono_free_method=(MONO_FREE_METHOD)GetProcAddress(hMono, "mono_free_method");	
			mono_jit_info_table_find=(MONO_JIT_INFO_TABLE_FIND)GetProcAddress(hMono, "mono_jit_info_table_find");	
			mono_jit_info_get_method=(MONO_JIT_INFO_GET_METHOD)GetProcAddress(hMono, "mono_jit_info_get_method");	
			mono_jit_info_get_code_start=(MONO_JIT_INFO_GET_CODE_START)GetProcAddress(hMono, "mono_jit_info_get_code_start");	
			mono_jit_info_get_code_size=(MONO_JIT_INFO_GET_CODE_SIZE)GetProcAddress(hMono, "mono_jit_info_get_code_size");	

			mono_method_header_get_code=(MONO_METHOD_HEADER_GET_CODE)GetProcAddress(hMono, "mono_method_header_get_code");	
			mono_disasm_code=(MONO_DISASM_CODE)GetProcAddress(hMono, "mono_disasm_code");	

			mono_vtable_get_static_field_data = (MONO_VTABLE_GET_STATIC_FIELD_DATA)GetProcAddress(hMono, "mono_vtable_get_static_field_data");

			
			if (mono_get_root_domain==NULL) OutputDebugStringA("mono_get_root_domain not assigned");
			if (mono_thread_attach==NULL) OutputDebugStringA("mono_thread_attach not assigned");
			if (mono_object_get_class==NULL) OutputDebugStringA("mono_object_get_class not assigned");
			if (mono_class_get_name==NULL) OutputDebugStringA("mono_class_get_name not assigned");
			if (mono_domain_foreach==NULL) OutputDebugStringA("mono_domain_foreach not assigned");
			if (mono_domain_set==NULL) OutputDebugStringA("mono_domain_set not assigned");
			if (mono_assembly_foreach==NULL) OutputDebugStringA("mono_assembly_foreach not assigned");
			if (mono_assembly_get_image==NULL) OutputDebugStringA("mono_assembly_get_image not assigned");
			if (mono_image_get_name==NULL) OutputDebugStringA("mono_image_get_name not assigned");


			mono_selfthread=mono_thread_attach(mono_get_root_domain());
			attached=TRUE;
		}
		else
			OutputDebugStringA("Already attached");
	}
}