struct _ThreadContext {
ThreadContext *next;
intptr_t thread_id;
+ char *name;
/* emulated stack */
MethodDesc **stack;
uint64_t *time_stack;
}
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)
thread = ctx->threads;
while (thread) {
if (thread->thread_id == thread_id) {
- ctx->current = thread;
return thread;
}
thread = thread->next;
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;
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)
{
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++;
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;
}
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: "");
}
}
* 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
* 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
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)
{
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);