2009-11-02 Zoltan Varga <vargaz@gmail.com>
authorZoltan Varga <vargaz@gmail.com>
Mon, 2 Nov 2009 15:18:21 +0000 (15:18 -0000)
committerZoltan Varga <vargaz@gmail.com>
Mon, 2 Nov 2009 15:18:21 +0000 (15:18 -0000)
* 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

mono/metadata/ChangeLog
mono/metadata/class-internals.h
mono/metadata/debug-mono-symfile.c
mono/metadata/loader.c
mono/metadata/object-internals.h
mono/metadata/object.c
mono/metadata/profiler-private.h
mono/metadata/profiler.c
mono/metadata/profiler.h
mono/metadata/threads.c

index cf65178c314c3a4579cab1a6863c2b57c4600524..f1d9cd286dc68f23407f9a337cf6d98be317bde8 100644 (file)
@@ -1,3 +1,18 @@
+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
index 05956cb0b5604a04b35c9aed6a9e6754707d3a31..e942e6198425fe96959c64195a789029383fda4b 100644 (file)
@@ -1037,6 +1037,12 @@ mono_loader_lock           (void) MONO_INTERNAL;
 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;
 
index ab04bcb90b71817fbcc6c14b9d138e0efa3fddd4..3ae35ac68d77308f0cc56f5e54756447995ccae6 100644 (file)
@@ -213,7 +213,7 @@ check_line (StatementMachine *stm, int offset, MonoDebugSourceLocation **locatio
 {
        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)
index ec11c8f494a214bc4156fd718e91c3632a6cafe9..e8a415aaf2baa098f60fe2cce526f494e28d319d 100644 (file)
@@ -63,6 +63,12 @@ static guint32 memberref_sig_cache_size;
  */
 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 ()
 {
@@ -72,6 +78,7 @@ 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);
@@ -86,6 +93,7 @@ void
 mono_loader_cleanup (void)
 {
        TlsFree (loader_error_thread_id);
+       TlsFree (loader_lock_nest_id);
 
        /*DeleteCriticalSection (&loader_mutex);*/
 }
@@ -1992,6 +2000,8 @@ mono_method_get_last_managed (void)
        return m;
 }
 
+static gboolean loader_lock_track_ownership = FALSE;
+
 /**
  * mono_loader_lock:
  *
@@ -2001,12 +2011,45 @@ void
 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;
 }
 
 /**
index 7dcaa5dae836bca189cee4dc3dcee23670d34d86..dfa1bfeb4851e5d519b6b8919f6e98259104b21d 100644 (file)
@@ -310,6 +310,10 @@ typedef struct {
        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 */
@@ -346,12 +350,12 @@ struct _MonoInternalThread {
        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;
index ee7ecb9e25ef4668d8f2f032e1933f91123af5af..89fc79ee1b5f5ed2538ebd5d550de43e0556e8c6 100644 (file)
@@ -2579,10 +2579,20 @@ static MonoInvokeFunc default_mono_runtime_invoke = dummy_mono_runtime_invoke;
 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;
 }
 
 /**
index f2be1f0f5fb4f05b73821274bf923c29af19ad29..d060c8c0344d2f2e5b4829abd8afde8f2109e312 100644 (file)
@@ -29,6 +29,8 @@ void mono_profiler_method_leave    (MonoMethod *method) MONO_INTERNAL;
 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;
index 97974bcbca3239cf1bc170954655f561b413d063..4efa5ffb2a5b8ebf5eab5e703342f84bf010c3f5 100644 (file)
@@ -56,6 +56,8 @@ static MonoProfileMethodFunc   jit_start;
 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;
@@ -184,6 +186,13 @@ mono_profiler_install_method_free (MonoProfileMethodFunc callback)
        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)
 {
@@ -339,6 +348,20 @@ mono_profiler_method_free (MonoMethod *method)
                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)
 {
index aa69760c7587b237a52f0bd6f2100433d13dda3d..4601153088aaa8a62878dccb92ade8488c95e0a8 100644 (file)
@@ -142,6 +142,7 @@ void mono_profiler_install_class       (MonoProfileClassFunc start_load, MonoPro
 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);
index 1dcb49a077352add5929500f2b20218718fe60c1..15174cf6732565495c3c9cb93e9333cba6947681 100644 (file)
@@ -1016,6 +1016,9 @@ mono_thread_attach (MonoDomain *domain)
                        mono_thread_attach_cb (tid, staddr + stsize);
        }
 
+       // FIXME: Need a separate callback
+       mono_profiler_thread_start (tid);
+
        return current_thread;
 }
 
@@ -2777,6 +2780,11 @@ static void build_wait_tids (gpointer key, gpointer value, gpointer user)
                        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));
@@ -2814,7 +2822,8 @@ remove_and_abort_threads (gpointer key, gpointer value, gpointer user)
                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)