Log profiler: track thread names with the new profiler API.
authorPaolo Molaro <lupus@oddwiz.org>
Wed, 10 Nov 2010 09:38:17 +0000 (10:38 +0100)
committerPaolo Molaro <lupus@oddwiz.org>
Wed, 10 Nov 2010 09:50:53 +0000 (10:50 +0100)
mono/profiler/decode.c
mono/profiler/proflog.c
mono/profiler/proflog.h

index 00b14c0a581cf5db3c029905c2d44e412148ef6f..fc2c13fa7e39df15c0885072ebeca7216dbd5b52 100644 (file)
@@ -424,6 +424,7 @@ typedef struct {
 struct _ThreadContext {
        ThreadContext *next;
        intptr_t thread_id;
+       char *name;
        /* emulated stack */
        MethodDesc **stack;
        uint64_t *time_stack;
@@ -457,7 +458,7 @@ load_data (ProfContext *ctx, int size)
 }
 
 static ThreadContext*
-load_thread (ProfContext *ctx, intptr_t thread_id)
+get_thread (ProfContext *ctx, intptr_t thread_id)
 {
        ThreadContext *thread;
        if (ctx->current && ctx->current->thread_id == thread_id)
@@ -465,7 +466,6 @@ load_thread (ProfContext *ctx, intptr_t thread_id)
        thread = ctx->threads;
        while (thread) {
                if (thread->thread_id == thread_id) {
-                       ctx->current = thread;
                        return thread;
                }
                thread = thread->next;
@@ -473,7 +473,6 @@ load_thread (ProfContext *ctx, intptr_t thread_id)
        thread = calloc (sizeof (ThreadContext), 1);
        thread->next = ctx->threads;
        ctx->threads = thread;
-       ctx->current = thread;
        thread->thread_id = thread_id;
        thread->last_time = 0;
        thread->stack_id = 0;
@@ -484,6 +483,14 @@ load_thread (ProfContext *ctx, intptr_t thread_id)
        return thread;
 }
 
+static ThreadContext*
+load_thread (ProfContext *ctx, intptr_t thread_id)
+{
+       ThreadContext *thread = get_thread (ctx, thread_id);
+       ctx->current = thread;
+       return thread;
+}
+
 static void
 ensure_thread_stack (ThreadContext *thread)
 {
@@ -857,6 +864,8 @@ decode_buffer (ProfContext *ctx)
                        time_from += startup_time;
                        time_to += startup_time;
                }
+               if (!thread->name)
+                       thread->name = pstrdup ("Main");
        }
        for (i = 0; i < thread->stack_id; ++i)
                thread->stack [i]->recurse_count++;
@@ -964,6 +973,19 @@ decode_buffer (ProfContext *ctx)
                                        add_image (ptr_base + ptrdiff, (char*)p);
                                while (*p) p++;
                                p++;
+                       } else if (mtype == TYPE_THREAD) {
+                               ThreadContext *nt;
+                               uint64_t flags = decode_uleb128 (p, &p);
+                               if (flags) {
+                                       fprintf (outfile, "non-zero flags in thread\n");
+                                       return 0;
+                               }
+                               nt = get_thread (ctx, ptr_base * ptrdiff);
+                               nt->name = pstrdup ((char*)p);
+                               if (debug)
+                                       fprintf (outfile, "thread %p named: %s\n", (void*)(ptr_base + ptrdiff), p);
+                               while (*p) p++;
+                               p++;
                        }
                        break;
                }
@@ -1297,7 +1319,7 @@ dump_threads (ProfContext *ctx)
        ThreadContext *thread;
        fprintf (outfile, "\nThread summary\n");
        for (thread = ctx->threads; thread; thread = thread->next) {
-               fprintf (outfile, "\tThread: %p\n", (void*)thread->thread_id);
+               fprintf (outfile, "\tThread: %p, name: \"%s\"\n", (void*)thread->thread_id, thread->name? thread->name: "");
        }
 }
 
index 34bb9ad120ef42e5e2dd66d1b5677b9bc63f5588..c09157c24e9fc9a06f0f980eded0d84f434d171b 100644 (file)
@@ -160,7 +160,8 @@ typedef struct _LogBuffer LogBuffer;
  * type: TYPE_METADATA
  * exinfo: flags: TYPE_LOAD_ERR
  * [time diff: uleb128] nanoseconds since last timing
- * [mtype: byte] metadata type, one of: TYPE_CLASS, TYPE_IMAGE, TYPE_ASSEMBLY, TYPE_DOMAIN
+ * [mtype: byte] metadata type, one of: TYPE_CLASS, TYPE_IMAGE, TYPE_ASSEMBLY, TYPE_DOMAIN,
+ * TYPE_THREAD
  * [pointer: sleb128] pointer of the metadata type depending on mtype
  * if mtype == TYPE_CLASS
  *     [image: sleb128] MonoImage* as a pointer difference from ptr_base
@@ -169,6 +170,9 @@ typedef struct _LogBuffer LogBuffer;
  * if mtype == TYPE_IMAGE
  *     [flags: uleb128] must be 0
  *     [name: string] image file name
+ * if mtype == TYPE_THREAD
+ *     [flags: uleb128] must be 0
+ *     [name: string] thread name
  *
  * type method format:
  * type: TYPE_METHOD
@@ -891,6 +895,23 @@ thread_end (MonoProfiler *prof, uintptr_t tid)
        TLS_SET (tlsbuffer, NULL);
 }
 
+static void
+thread_name (MonoProfiler *prof, uintptr_t tid, const char *name)
+{
+       int len = strlen (name) + 1;
+       uint64_t now;
+       LogBuffer *logbuffer;
+       logbuffer = ensure_logbuf (10 + len);
+       now = current_time ();
+       emit_byte (logbuffer, TYPE_METADATA);
+       emit_time (logbuffer, now);
+       emit_byte (logbuffer, TYPE_THREAD);
+       emit_ptr (logbuffer, (void*)tid);
+       emit_value (logbuffer, 0); /* flags */
+       memcpy (logbuffer->data, name, len);
+       logbuffer->data += len;
+}
+
 static void
 log_shutdown (MonoProfiler *prof)
 {
@@ -1130,6 +1151,7 @@ mono_profiler_startup (const char *desc)
        mono_profiler_install_class (NULL, class_loaded, NULL, NULL);
        mono_profiler_install_module (NULL, image_loaded, NULL, NULL);
        mono_profiler_install_thread (thread_start, thread_end);
+       mono_profiler_install_thread_name (thread_name);
        mono_profiler_install_enter_leave (method_enter, method_leave);
        mono_profiler_install_jit_end (method_jitted);
        mono_profiler_install_exception (throw_exc, method_exc_leave, clause_exc);
index 0a4769d86341a828bb4ab8310d8e52d61a49fba1..5aaf6a4ce5a5c5c09d6a36769cdcb3837e013df4 100644 (file)
@@ -30,6 +30,7 @@ enum {
        TYPE_IMAGE     = 2,
        TYPE_ASSEMBLY  = 3,
        TYPE_DOMAIN    = 4,
+       TYPE_THREAD    = 5,
        /* extended type for TYPE_GC */
        TYPE_GC_EVENT  = 1 << 4,
        TYPE_GC_RESIZE = 2 << 4,