* debug-mono-symfile.c (check_line): Fix the handling of IL offset 0.
* threads.c (mono_thread_attach): Call the profiler thread start callback.
* object-internals.h (_MonoThreadInternal): Add a 'flags' field.
* threads.c (build_wait_tids): Ignore threads which have the DONT_MANAGE
flag set.
* profiler.c: Add new profiler callbacks for runtime invoke.
* object.c (mono_runtime_invoke): Call the runtime invoke callbacks.
svn path=/trunk/mono/; revision=145200
+2009-11-02 Zoltan Varga <vargaz@gmail.com>
+
+ * debug-mono-symfile.c (check_line): Fix the handling of IL offset 0.
+
+ * threads.c (mono_thread_attach): Call the profiler thread start callback.
+
+ * object-internals.h (_MonoThreadInternal): Add a 'flags' field.
+
+ * threads.c (build_wait_tids): Ignore threads which have the DONT_MANAGE
+ flag set.
+
+ * profiler.c: Add new profiler callbacks for runtime invoke.
+
+ * object.c (mono_runtime_invoke): Call the runtime invoke callbacks.
+
2009-11-01 Mark Probst <mark.probst@gmail.com>
* sgen-gc.c: Keep track of the reason for a major collection and
void
mono_loader_unlock (void) MONO_INTERNAL;
+void
+mono_loader_lock_track_ownership (gboolean track) MONO_INTERNAL;
+
+gboolean
+mono_loader_lock_is_owned_by_self (void) MONO_INTERNAL;
+
void
mono_loader_set_error_assembly_load (const char *assembly_name, gboolean ref_only) MONO_INTERNAL;
{
gchar *source_file = NULL;
- if ((offset > 0) && (stm->offset <= offset)) {
+ if (stm->offset <= offset) {
stm->last_offset = stm->offset;
stm->last_file = stm->file;
if (stm->line != 0xfeefee)
*/
guint32 loader_error_thread_id;
+/*
+ * This TLS variable holds how many times the current thread has acquired the loader
+ * lock.
+ */
+guint32 loader_lock_nest_id;
+
void
mono_loader_init ()
{
InitializeCriticalSection (&loader_mutex);
loader_error_thread_id = TlsAlloc ();
+ loader_lock_nest_id = TlsAlloc ();
mono_counters_register ("Inflated signatures size",
MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_signatures_size);
mono_loader_cleanup (void)
{
TlsFree (loader_error_thread_id);
+ TlsFree (loader_lock_nest_id);
/*DeleteCriticalSection (&loader_mutex);*/
}
return m;
}
+static gboolean loader_lock_track_ownership = FALSE;
+
/**
* mono_loader_lock:
*
mono_loader_lock (void)
{
mono_locks_acquire (&loader_mutex, LoaderLock);
+ if (G_UNLIKELY (loader_lock_track_ownership)) {
+ TlsSetValue (loader_lock_nest_id, GUINT_TO_POINTER (GPOINTER_TO_UINT (TlsGetValue (loader_lock_nest_id)) + 1));
+ }
}
void
mono_loader_unlock (void)
{
mono_locks_release (&loader_mutex, LoaderLock);
+ if (G_UNLIKELY (loader_lock_track_ownership)) {
+ TlsSetValue (loader_lock_nest_id, GUINT_TO_POINTER (GPOINTER_TO_UINT (TlsGetValue (loader_lock_nest_id)) - 1));
+ }
+}
+
+/*
+ * mono_loader_lock_track_ownership:
+ *
+ * Set whenever the runtime should track ownership of the loader lock. If set to TRUE,
+ * the mono_loader_lock_is_owned_by_self () can be called to query whenever the current
+ * thread owns the loader lock.
+ */
+void
+mono_loader_lock_track_ownership (gboolean track)
+{
+ loader_lock_track_ownership = track;
+}
+
+/*
+ * mono_loader_lock_is_owned_by_self:
+ *
+ * Return whenever the current thread owns the loader lock.
+ * This is useful to avoid blocking operations while holding the loader lock.
+ */
+gboolean
+mono_loader_lock_is_owned_by_self (void)
+{
+ g_assert (loader_lock_track_ownership);
+
+ return GPOINTER_TO_UINT (TlsGetValue (loader_lock_nest_id)) > 0;
}
/**
MonoString *internal_method_name;
} MonoStackFrame;
+typedef enum {
+ MONO_THREAD_FLAG_DONT_MANAGE = 1, // Don't wait for or abort this thread
+} MonoThreadFlags;
+
struct _MonoInternalThread {
MonoObject obj;
int lock_thread_id; /* to be used as the pre-shifted thread id in thin locks */
MonoThreadManageCallback manage_callback;
MonoException *pending_exception;
MonoThread *root_domain_thread;
+ gpointer interrupt_on_stop;
+ gsize flags;
/*
* These fields are used to avoid having to increment corlib versions
* when a new field is added to the unmanaged MonoThread structure.
*/
- gpointer interrupt_on_stop;
- gpointer unused3;
gpointer unused4;
gpointer unused5;
gpointer unused6;
MonoObject*
mono_runtime_invoke (MonoMethod *method, void *obj, void **params, MonoObject **exc)
{
+ MonoObject *result;
+
if (mono_runtime_get_no_exec ())
g_warning ("Invoking method '%s' when running in no-exec mode.\n", mono_method_full_name (method, TRUE));
- return default_mono_runtime_invoke (method, obj, params, exc);
+ if (mono_profiler_get_events () & MONO_PROFILE_METHOD_EVENTS)
+ mono_profiler_method_start_invoke (method);
+
+ result = default_mono_runtime_invoke (method, obj, params, exc);
+
+ if (mono_profiler_get_events () & MONO_PROFILE_METHOD_EVENTS)
+ mono_profiler_method_end_invoke (method);
+
+ return result;
}
/**
void mono_profiler_method_jit (MonoMethod *method) MONO_INTERNAL;
void mono_profiler_method_end_jit (MonoMethod *method, MonoJitInfo* jinfo, int result) MONO_INTERNAL;
void mono_profiler_method_free (MonoMethod *method) MONO_INTERNAL;
+void mono_profiler_method_start_invoke (MonoMethod *method) MONO_INTERNAL;
+void mono_profiler_method_end_invoke (MonoMethod *method) MONO_INTERNAL;
void mono_profiler_code_transition (MonoMethod *method, int result) MONO_INTERNAL;
void mono_profiler_allocation (MonoObject *obj, MonoClass *klass) MONO_INTERNAL;
static MonoProfileMethodResult jit_end;
static MonoProfileJitResult jit_end2;
static MonoProfileMethodFunc method_free;
+static MonoProfileMethodFunc method_start_invoke;
+static MonoProfileMethodFunc method_end_invoke;
static MonoProfileMethodResult man_unman_transition;
static MonoProfileAllocFunc allocation_cb;
static MonoProfileMonitorFunc monitor_event_cb;
method_free = callback;
}
+void
+mono_profiler_install_method_invoke (MonoProfileMethodFunc start, MonoProfileMethodFunc end)
+{
+ method_start_invoke = start;
+ method_end_invoke = end;
+}
+
void
mono_profiler_install_thread (MonoProfileThreadFunc start, MonoProfileThreadFunc end)
{
method_free (current_profiler, method);
}
+void
+mono_profiler_method_start_invoke (MonoMethod *method)
+{
+ if ((mono_profiler_events & MONO_PROFILE_METHOD_EVENTS) && method_start_invoke)
+ method_start_invoke (current_profiler, method);
+}
+
+void
+mono_profiler_method_end_invoke (MonoMethod *method)
+{
+ if ((mono_profiler_events & MONO_PROFILE_METHOD_EVENTS) && method_end_invoke)
+ method_end_invoke (current_profiler, method);
+}
+
void
mono_profiler_code_transition (MonoMethod *method, int result)
{
void mono_profiler_install_jit_compile (MonoProfileMethodFunc start, MonoProfileMethodResult end);
void mono_profiler_install_jit_end (MonoProfileJitResult end);
void mono_profiler_install_method_free (MonoProfileMethodFunc callback);
+void mono_profiler_install_method_invoke (MonoProfileMethodFunc start, MonoProfileMethodFunc end);
void mono_profiler_install_enter_leave (MonoProfileMethodFunc enter, MonoProfileMethodFunc fleave);
void mono_profiler_install_thread (MonoProfileThreadFunc start, MonoProfileThreadFunc end);
void mono_profiler_install_transition (MonoProfileMethodResult callback);
mono_thread_attach_cb (tid, staddr + stsize);
}
+ // FIXME: Need a separate callback
+ mono_profiler_thread_start (tid);
+
return current_thread;
}
return;
}
+ if (thread->flags & MONO_THREAD_FLAG_DONT_MANAGE) {
+ THREAD_DEBUG (g_message ("%s: ignoring thread %" G_GSIZE_FORMAT "with DONT_MANAGE flag set.", __func__, (gsize)thread->tid));
+ return;
+ }
+
handle = OpenThread (THREAD_ALL_ACCESS, TRUE, thread->tid);
if (handle == NULL) {
THREAD_DEBUG (g_message ("%s: ignoring unopenable thread %"G_GSIZE_FORMAT, __func__, (gsize)thread->tid));
return FALSE;
/* The finalizer thread is not a background thread */
- if (thread->tid != self && (thread->state & ThreadState_Background) != 0) {
+ if (thread->tid != self && (thread->state & ThreadState_Background) != 0 &&
+ !(thread->flags & MONO_THREAD_FLAG_DONT_MANAGE)) {
handle = OpenThread (THREAD_ALL_ACCESS, TRUE, thread->tid);
if (handle == NULL)