add state function stack support
authorcompudj <compudj@04897980-b3bd-0310-b5e0-8ef037075253>
Fri, 10 Mar 2006 16:59:39 +0000 (16:59 +0000)
committercompudj <compudj@04897980-b3bd-0310-b5e0-8ef037075253>
Fri, 10 Mar 2006 16:59:39 +0000 (16:59 +0000)
git-svn-id: http://ltt.polymtl.ca/svn@1673 04897980-b3bd-0310-b5e0-8ef037075253

ltt/branches/poly/lttv/lttv/state.c
ltt/branches/poly/lttv/lttv/state.h
ltt/branches/poly/lttv/lttv/stats.c
ltt/branches/poly/lttv/lttv/stats.h

index a9d371a50924ff20237b4b75f3489673f1ef72fe..6bd0b271beed2ab98bb05fb0645bc6055accc777 100644 (file)
@@ -39,7 +39,8 @@ GQuark
     LTT_FACILITY_KERNEL_ARCH,
     LTT_FACILITY_PROCESS,
     LTT_FACILITY_FS,
     LTT_FACILITY_KERNEL_ARCH,
     LTT_FACILITY_PROCESS,
     LTT_FACILITY_FS,
-    LTT_FACILITY_STATEDUMP;
+    LTT_FACILITY_STATEDUMP,
+               LTT_FACILITY_USER_GENERIC;
 
 /* Events Quarks */
 
 
 /* Events Quarks */
 
@@ -58,7 +59,9 @@ GQuark
     LTT_EVENT_EXIT,
     LTT_EVENT_FREE,
     LTT_EVENT_EXEC,
     LTT_EVENT_EXIT,
     LTT_EVENT_FREE,
     LTT_EVENT_EXEC,
-    LTT_EVENT_ENUM_PROCESS_STATE;
+    LTT_EVENT_ENUM_PROCESS_STATE,
+               LTT_EVENT_FUNCTION_ENTRY,
+               LTT_EVENT_FUNCTION_EXIT;
 
 /* Fields Quarks */
 
 
 /* Fields Quarks */
 
@@ -77,7 +80,9 @@ GQuark
     LTT_FIELD_NAME,
     LTT_FIELD_MODE,
     LTT_FIELD_SUBMODE,
     LTT_FIELD_NAME,
     LTT_FIELD_MODE,
     LTT_FIELD_SUBMODE,
-    LTT_FIELD_STATUS;
+    LTT_FIELD_STATUS,
+               LTT_FIELD_THIS_FN,
+               LTT_FIELD_CALL_SITE;
 
 LttvExecutionMode
   LTTV_STATE_MODE_UNKNOWN,
 
 LttvExecutionMode
   LTTV_STATE_MODE_UNKNOWN,
@@ -496,6 +501,17 @@ static void copy_process_state(gpointer key, gpointer value,gpointer user_data)
   }
   new_process->state = &g_array_index(new_process->execution_stack, 
       LttvExecutionState, new_process->execution_stack->len - 1);
   }
   new_process->state = &g_array_index(new_process->execution_stack, 
       LttvExecutionState, new_process->execution_stack->len - 1);
+  new_process->user_stack = g_array_sized_new(FALSE, FALSE, 
+      sizeof(guint64), 0);
+  new_process->user_stack = 
+              g_array_set_size(new_process->user_stack,
+                  process->user_stack->len);
+  for(i = 0 ; i < process->user_stack->len; i++) {
+    g_array_index(new_process->user_stack, guint64, i) =
+        g_array_index(process->user_stack, guint64, i);
+  }
+  new_process->current_function = &g_array_index(new_process->user_stack, 
+      guint64, new_process->user_stack->len - 1);
   g_hash_table_insert(new_processes, new_process, new_process);
 }
 
   g_hash_table_insert(new_processes, new_process, new_process);
 }
 
@@ -1134,6 +1150,7 @@ lttv_state_create_process(LttvTraceState *tcs, LttvProcessState *parent,
   //process->last_cpu_index = ltt_tracefile_num(((LttvTracefileContext*)tfs)->tf);
        process->kernel_thread = 0;
        process->usertrace = ltt_state_usertrace_find(tcs, pid, timestamp);
   //process->last_cpu_index = ltt_tracefile_num(((LttvTracefileContext*)tfs)->tf);
        process->kernel_thread = 0;
        process->usertrace = ltt_state_usertrace_find(tcs, pid, timestamp);
+       process->current_function = 0; //function 0x0 by default.
 
   g_info("Process %u, core %p", process->pid, process);
   g_hash_table_insert(tcs->processes, process, process);
 
   g_info("Process %u, core %p", process->pid, process);
   g_hash_table_insert(tcs->processes, process, process);
@@ -1179,7 +1196,11 @@ lttv_state_create_process(LttvTraceState *tcs, LttvProcessState *parent,
   //g_assert(timestamp->tv_sec != 0);
   es->change = *timestamp;
   es->s = LTTV_STATE_WAIT_FORK;
   //g_assert(timestamp->tv_sec != 0);
   es->change = *timestamp;
   es->s = LTTV_STATE_WAIT_FORK;
-
+       
+       /* Allocate an empty function call stack. If it's empty, use 0x0. */
+       process->user_stack = g_array_sized_new(FALSE, FALSE,
+                       sizeof(guint64), 0);
+       
   return process;
 }
 
   return process;
 }
 
@@ -1230,6 +1251,7 @@ static void exit_process(LttvTracefileState *tfs, LttvProcessState *process)
   key.cpu = process->cpu;
   g_hash_table_remove(ts->processes, &key);
   g_array_free(process->execution_stack, TRUE);
   key.cpu = process->cpu;
   g_hash_table_remove(ts->processes, &key);
   g_array_free(process->execution_stack, TRUE);
+  g_array_free(process->user_stack, TRUE);
   g_free(process);
 }
 
   g_free(process);
 }
 
@@ -1237,6 +1259,7 @@ static void exit_process(LttvTracefileState *tfs, LttvProcessState *process)
 static void free_process_state(gpointer key, gpointer value,gpointer user_data)
 {
   g_array_free(((LttvProcessState *)value)->execution_stack, TRUE);
 static void free_process_state(gpointer key, gpointer value,gpointer user_data)
 {
   g_array_free(((LttvProcessState *)value)->execution_stack, TRUE);
+  g_array_free(((LttvProcessState *)value)->user_stack, TRUE);
   g_free(value);
 }
 
   g_free(value);
 }
 
@@ -1331,6 +1354,15 @@ static gboolean irq_entry(void *hook_data, void *call_data)
   return FALSE;
 }
 
   return FALSE;
 }
 
+static gboolean soft_irq_exit(void *hook_data, void *call_data)
+{
+  LttvTracefileState *s = (LttvTracefileState *)call_data;
+
+  pop_state(s, LTTV_STATE_SOFT_IRQ);
+  return FALSE;
+}
+
+
 
 static gboolean irq_exit(void *hook_data, void *call_data)
 {
 
 static gboolean irq_exit(void *hook_data, void *call_data)
 {
@@ -1362,15 +1394,89 @@ static gboolean soft_irq_entry(void *hook_data, void *call_data)
   return FALSE;
 }
 
   return FALSE;
 }
 
+static void push_function(LttvTracefileState *tfs, guint64 funcptr)
+{
+  guint64 *new_func;
+  
+  LttvTraceState *ts = (LttvTraceState*)tfs->parent.t_context;
+  guint cpu = tfs->cpu;
+  LttvProcessState *process = ts->running_process[cpu];
 
 
-static gboolean soft_irq_exit(void *hook_data, void *call_data)
+  guint depth = process->user_stack->len;
+
+  process->user_stack = 
+    g_array_set_size(process->user_stack, depth + 1);
+    
+  new_func = &g_array_index(process->user_stack, guint64, depth);
+       *new_func = funcptr;
+  process->current_function = 
+               g_array_index(process->user_stack, guint64, depth - 1);
+}
+
+static void pop_function(LttvTracefileState *tfs, guint64 funcptr)
+{
+  guint cpu = tfs->cpu;
+  LttvTraceState *ts = (LttvTraceState*)tfs->parent.t_context;
+  LttvProcessState *process = ts->running_process[cpu];
+
+  guint depth = process->user_stack->len;
+  if(process->current_function != funcptr){
+    g_info("Different functions (%lu.%09lu): ignore it\n",
+        tfs->parent.timestamp.tv_sec, tfs->parent.timestamp.tv_nsec);
+    g_info("process state has %llu when pop_function is %llu\n",
+                   process->current_function, funcptr);
+    g_info("{ %u, %u, %s, %s }\n",
+                   process->pid,
+                   process->ppid,
+                   g_quark_to_string(process->name),
+                   g_quark_to_string(process->state->s));
+    return;
+  }
+
+  if(depth == 0){
+    g_info("Trying to pop last function on stack (%lu.%09lu): ignore it\n",
+        tfs->parent.timestamp.tv_sec, tfs->parent.timestamp.tv_nsec);
+    return;
+  }
+
+  process->user_stack = 
+    g_array_set_size(process->user_stack, depth - 1);
+  process->current_function =
+               g_array_index(process->user_stack, guint64, depth - 2);
+}
+
+
+static gboolean function_entry(void *hook_data, void *call_data)
 {
   LttvTracefileState *s = (LttvTracefileState *)call_data;
 {
   LttvTracefileState *s = (LttvTracefileState *)call_data;
+  LttEvent *e = ltt_tracefile_get_event(s->parent.tf);
+  guint8 fac_id = ltt_event_facility_id(e);
+  guint8 ev_id = ltt_event_eventtype_id(e);
+  LttvTraceHookByFacility *thf = (LttvTraceHookByFacility *)hook_data;
+  g_assert(thf->f1 != NULL);
+  LttField *f = thf->f1;
+       guint64 funcptr = ltt_event_get_long_unsigned(e, f);
 
 
-  pop_state(s, LTTV_STATE_SOFT_IRQ);
+  push_function(s, funcptr);
   return FALSE;
 }
 
   return FALSE;
 }
 
+static gboolean function_exit(void *hook_data, void *call_data)
+{
+  LttvTracefileState *s = (LttvTracefileState *)call_data;
+  LttEvent *e = ltt_tracefile_get_event(s->parent.tf);
+  guint8 fac_id = ltt_event_facility_id(e);
+  guint8 ev_id = ltt_event_eventtype_id(e);
+  LttvTraceHookByFacility *thf = (LttvTraceHookByFacility *)hook_data;
+  g_assert(thf->f1 != NULL);
+  LttField *f = thf->f1;
+       guint64 funcptr = ltt_event_get_long_unsigned(e, f);
+
+  LttvExecutionSubmode submode;
+
+  pop_function(s, funcptr);
+  return FALSE;
+}
 
 static gboolean schedchange(void *hook_data, void *call_data)
 {
 
 static gboolean schedchange(void *hook_data, void *call_data)
 {
@@ -1730,6 +1836,7 @@ void lttv_state_add_event_hooks(LttvTracesetState *self)
   LttvAttributeValue val;
 
   gint ret;
   LttvAttributeValue val;
 
   gint ret;
+       gint hn;
 
   nb_trace = lttv_traceset_number(traceset);
   for(i = 0 ; i < nb_trace ; i++) {
 
   nb_trace = lttv_traceset_number(traceset);
   for(i = 0 ; i < nb_trace ; i++) {
@@ -1738,101 +1845,116 @@ void lttv_state_add_event_hooks(LttvTracesetState *self)
     /* Find the eventtype id for the following events and register the
        associated by id hooks. */
 
     /* Find the eventtype id for the following events and register the
        associated by id hooks. */
 
-    hooks = g_array_sized_new(FALSE, FALSE, sizeof(LttvTraceHook), 15);
-    hooks = g_array_set_size(hooks, 15);
+    hooks = g_array_sized_new(FALSE, FALSE, sizeof(LttvTraceHook), 17);
+    hooks = g_array_set_size(hooks, 17); // Max possible number of hooks.
+               hn = 0;
 
     ret = lttv_trace_find_hook(ts->parent.t,
         LTT_FACILITY_KERNEL_ARCH, LTT_EVENT_SYSCALL_ENTRY,
         LTT_FIELD_SYSCALL_ID, 0, 0,
 
     ret = lttv_trace_find_hook(ts->parent.t,
         LTT_FACILITY_KERNEL_ARCH, LTT_EVENT_SYSCALL_ENTRY,
         LTT_FIELD_SYSCALL_ID, 0, 0,
-        syscall_entry, NULL, &g_array_index(hooks, LttvTraceHook, 0));
-    g_assert(!ret);
+        syscall_entry, NULL, &g_array_index(hooks, LttvTraceHook, hn++));
+               if(ret) hn--;
 
     ret = lttv_trace_find_hook(ts->parent.t,
         LTT_FACILITY_KERNEL_ARCH, LTT_EVENT_SYSCALL_EXIT,
         0, 0, 0,
 
     ret = lttv_trace_find_hook(ts->parent.t,
         LTT_FACILITY_KERNEL_ARCH, LTT_EVENT_SYSCALL_EXIT,
         0, 0, 0,
-        syscall_exit, NULL, &g_array_index(hooks, LttvTraceHook, 1));
-    g_assert(!ret);
+        syscall_exit, NULL, &g_array_index(hooks, LttvTraceHook, hn++));
+               if(ret) hn--;
 
     ret = lttv_trace_find_hook(ts->parent.t,
         LTT_FACILITY_KERNEL, LTT_EVENT_TRAP_ENTRY,
         LTT_FIELD_TRAP_ID, 0, 0,
 
     ret = lttv_trace_find_hook(ts->parent.t,
         LTT_FACILITY_KERNEL, LTT_EVENT_TRAP_ENTRY,
         LTT_FIELD_TRAP_ID, 0, 0,
-        trap_entry, NULL, &g_array_index(hooks, LttvTraceHook, 2));
-    g_assert(!ret);
+        trap_entry, NULL, &g_array_index(hooks, LttvTraceHook, hn++));
+               if(ret) hn--;
 
     ret = lttv_trace_find_hook(ts->parent.t,
         LTT_FACILITY_KERNEL, LTT_EVENT_TRAP_EXIT,
         0, 0, 0, 
 
     ret = lttv_trace_find_hook(ts->parent.t,
         LTT_FACILITY_KERNEL, LTT_EVENT_TRAP_EXIT,
         0, 0, 0, 
-        trap_exit, NULL, &g_array_index(hooks, LttvTraceHook, 3));
-    g_assert(!ret);
+        trap_exit, NULL, &g_array_index(hooks, LttvTraceHook, hn++));
+               if(ret) hn--;
 
     ret = lttv_trace_find_hook(ts->parent.t,
         LTT_FACILITY_KERNEL, LTT_EVENT_IRQ_ENTRY,
         LTT_FIELD_IRQ_ID, 0, 0,
 
     ret = lttv_trace_find_hook(ts->parent.t,
         LTT_FACILITY_KERNEL, LTT_EVENT_IRQ_ENTRY,
         LTT_FIELD_IRQ_ID, 0, 0,
-        irq_entry, NULL, &g_array_index(hooks, LttvTraceHook, 4));
-    g_assert(!ret);
+        irq_entry, NULL, &g_array_index(hooks, LttvTraceHook, hn++));
+               if(ret) hn--;
 
     ret = lttv_trace_find_hook(ts->parent.t,
         LTT_FACILITY_KERNEL, LTT_EVENT_IRQ_EXIT,
         0, 0, 0, 
 
     ret = lttv_trace_find_hook(ts->parent.t,
         LTT_FACILITY_KERNEL, LTT_EVENT_IRQ_EXIT,
         0, 0, 0, 
-        irq_exit, NULL, &g_array_index(hooks, LttvTraceHook, 5));
-    g_assert(!ret);
+        irq_exit, NULL, &g_array_index(hooks, LttvTraceHook, hn++));
+               if(ret) hn--;
 
     ret = lttv_trace_find_hook(ts->parent.t,
         LTT_FACILITY_KERNEL, LTT_EVENT_SOFT_IRQ_ENTRY,
         LTT_FIELD_SOFT_IRQ_ID, 0, 0,
 
     ret = lttv_trace_find_hook(ts->parent.t,
         LTT_FACILITY_KERNEL, LTT_EVENT_SOFT_IRQ_ENTRY,
         LTT_FIELD_SOFT_IRQ_ID, 0, 0,
-        soft_irq_entry, NULL, &g_array_index(hooks, LttvTraceHook, 6));
-    g_assert(!ret);
+        soft_irq_entry, NULL, &g_array_index(hooks, LttvTraceHook, hn++));
+               if(ret) hn--;
 
     ret = lttv_trace_find_hook(ts->parent.t,
         LTT_FACILITY_KERNEL, LTT_EVENT_SOFT_IRQ_EXIT,
         0, 0, 0, 
 
     ret = lttv_trace_find_hook(ts->parent.t,
         LTT_FACILITY_KERNEL, LTT_EVENT_SOFT_IRQ_EXIT,
         0, 0, 0, 
-        soft_irq_exit, NULL, &g_array_index(hooks, LttvTraceHook, 7));
-    g_assert(!ret);
+        soft_irq_exit, NULL, &g_array_index(hooks, LttvTraceHook, hn++));
+               if(ret) hn--;
 
     ret = lttv_trace_find_hook(ts->parent.t,
         LTT_FACILITY_PROCESS, LTT_EVENT_SCHEDCHANGE,
         LTT_FIELD_OUT, LTT_FIELD_IN, LTT_FIELD_OUT_STATE,
 
     ret = lttv_trace_find_hook(ts->parent.t,
         LTT_FACILITY_PROCESS, LTT_EVENT_SCHEDCHANGE,
         LTT_FIELD_OUT, LTT_FIELD_IN, LTT_FIELD_OUT_STATE,
-        schedchange, NULL, &g_array_index(hooks, LttvTraceHook, 8));
-    g_assert(!ret);
+        schedchange, NULL, &g_array_index(hooks, LttvTraceHook, hn++));
+               if(ret) hn--;
 
     ret = lttv_trace_find_hook(ts->parent.t,
         LTT_FACILITY_PROCESS, LTT_EVENT_FORK,
         LTT_FIELD_PARENT_PID, LTT_FIELD_CHILD_PID, 0,
 
     ret = lttv_trace_find_hook(ts->parent.t,
         LTT_FACILITY_PROCESS, LTT_EVENT_FORK,
         LTT_FIELD_PARENT_PID, LTT_FIELD_CHILD_PID, 0,
-        process_fork, NULL, &g_array_index(hooks, LttvTraceHook, 9));
-    g_assert(!ret);
+        process_fork, NULL, &g_array_index(hooks, LttvTraceHook, hn++));
+               if(ret) hn--;
 
     ret = lttv_trace_find_hook(ts->parent.t,
         LTT_FACILITY_PROCESS, LTT_EVENT_KERNEL_THREAD,
         LTT_FIELD_PID, 0, 0,
 
     ret = lttv_trace_find_hook(ts->parent.t,
         LTT_FACILITY_PROCESS, LTT_EVENT_KERNEL_THREAD,
         LTT_FIELD_PID, 0, 0,
-        process_kernel_thread, NULL, &g_array_index(hooks, LttvTraceHook, 10));
-    g_assert(!ret);
+        process_kernel_thread, NULL, &g_array_index(hooks, LttvTraceHook,
+                                       hn++));
+               if(ret) hn--;
 
     ret = lttv_trace_find_hook(ts->parent.t,
         LTT_FACILITY_PROCESS, LTT_EVENT_EXIT,
         LTT_FIELD_PID, 0, 0,
 
     ret = lttv_trace_find_hook(ts->parent.t,
         LTT_FACILITY_PROCESS, LTT_EVENT_EXIT,
         LTT_FIELD_PID, 0, 0,
-        process_exit, NULL, &g_array_index(hooks, LttvTraceHook, 11));
-    g_assert(!ret);
+        process_exit, NULL, &g_array_index(hooks, LttvTraceHook, hn++));
+               if(ret) hn--;
     
     ret = lttv_trace_find_hook(ts->parent.t,
         LTT_FACILITY_PROCESS, LTT_EVENT_FREE,
         LTT_FIELD_PID, 0, 0,
     
     ret = lttv_trace_find_hook(ts->parent.t,
         LTT_FACILITY_PROCESS, LTT_EVENT_FREE,
         LTT_FIELD_PID, 0, 0,
-        process_free, NULL, &g_array_index(hooks, LttvTraceHook, 12));
-    g_assert(!ret);
+        process_free, NULL, &g_array_index(hooks, LttvTraceHook, hn++));
+               if(ret) hn--;
 
     ret = lttv_trace_find_hook(ts->parent.t,
         LTT_FACILITY_FS, LTT_EVENT_EXEC,
         LTT_FIELD_FILENAME, 0, 0,
 
     ret = lttv_trace_find_hook(ts->parent.t,
         LTT_FACILITY_FS, LTT_EVENT_EXEC,
         LTT_FIELD_FILENAME, 0, 0,
-        process_exec, NULL, &g_array_index(hooks, LttvTraceHook, 13));
-    g_assert(!ret);
+        process_exec, NULL, &g_array_index(hooks, LttvTraceHook, hn++));
+               if(ret) hn--;
 
      /* statedump-related hooks */
     ret = lttv_trace_find_hook(ts->parent.t,
         LTT_FACILITY_STATEDUMP, LTT_EVENT_ENUM_PROCESS_STATE,
         LTT_FIELD_PID, LTT_FIELD_PARENT_PID, LTT_FIELD_NAME,
 
      /* statedump-related hooks */
     ret = lttv_trace_find_hook(ts->parent.t,
         LTT_FACILITY_STATEDUMP, LTT_EVENT_ENUM_PROCESS_STATE,
         LTT_FIELD_PID, LTT_FIELD_PARENT_PID, LTT_FIELD_NAME,
-        enum_process_state, NULL, &g_array_index(hooks, LttvTraceHook, 14));
-    g_assert(!ret);
+        enum_process_state, NULL, &g_array_index(hooks, LttvTraceHook, hn++));
+               if(ret) hn--;
 
 
-    
+    ret = lttv_trace_find_hook(ts->parent.t,
+        LTT_FACILITY_USER_GENERIC, LTT_EVENT_FUNCTION_ENTRY,
+        LTT_FIELD_THIS_FN, LTT_FIELD_CALL_SITE, 0,
+        function_entry, NULL, &g_array_index(hooks, LttvTraceHook, hn++));
+               if(ret) hn--;
+
+    ret = lttv_trace_find_hook(ts->parent.t,
+        LTT_FACILITY_USER_GENERIC, LTT_EVENT_FUNCTION_EXIT,
+        LTT_FIELD_THIS_FN, LTT_FIELD_CALL_SITE, 0,
+        function_exit, NULL, &g_array_index(hooks, LttvTraceHook, hn++));
+               if(ret) hn--;
+
+    hooks = g_array_set_size(hooks, hn);
+  
     /* Add these hooks to each event_by_id hooks list */
 
     nb_tracefile = ts->parent.tracefiles->len;
     /* Add these hooks to each event_by_id hooks list */
 
     nb_tracefile = ts->parent.tracefiles->len;
@@ -2496,6 +2618,7 @@ static void module_init()
   LTT_FACILITY_PROCESS    = g_quark_from_string("process");
   LTT_FACILITY_FS    = g_quark_from_string("fs");
   LTT_FACILITY_STATEDUMP    = g_quark_from_string("statedump");
   LTT_FACILITY_PROCESS    = g_quark_from_string("process");
   LTT_FACILITY_FS    = g_quark_from_string("fs");
   LTT_FACILITY_STATEDUMP    = g_quark_from_string("statedump");
+  LTT_FACILITY_USER_GENERIC    = g_quark_from_string("user_generic");
 
   
   LTT_EVENT_SYSCALL_ENTRY = g_quark_from_string("syscall_entry");
 
   
   LTT_EVENT_SYSCALL_ENTRY = g_quark_from_string("syscall_entry");
@@ -2513,6 +2636,8 @@ static void module_init()
   LTT_EVENT_FREE          = g_quark_from_string("free");
   LTT_EVENT_EXEC          = g_quark_from_string("exec");
   LTT_EVENT_ENUM_PROCESS_STATE  = g_quark_from_string("enumerate_process_state");
   LTT_EVENT_FREE          = g_quark_from_string("free");
   LTT_EVENT_EXEC          = g_quark_from_string("exec");
   LTT_EVENT_ENUM_PROCESS_STATE  = g_quark_from_string("enumerate_process_state");
+  LTT_EVENT_FUNCTION_ENTRY  = g_quark_from_string("function_entry");
+  LTT_EVENT_FUNCTION_EXIT  = g_quark_from_string("function_exit");
 
 
   LTT_FIELD_SYSCALL_ID    = g_quark_from_string("syscall_id");
 
 
   LTT_FIELD_SYSCALL_ID    = g_quark_from_string("syscall_id");
@@ -2530,6 +2655,8 @@ static void module_init()
   LTT_FIELD_MODE          = g_quark_from_string("mode");
   LTT_FIELD_SUBMODE       = g_quark_from_string("submode");
   LTT_FIELD_STATUS        = g_quark_from_string("status");
   LTT_FIELD_MODE          = g_quark_from_string("mode");
   LTT_FIELD_SUBMODE       = g_quark_from_string("submode");
   LTT_FIELD_STATUS        = g_quark_from_string("status");
+  LTT_FIELD_THIS_FN       = g_quark_from_string("this_fn");
+  LTT_FIELD_CALL_SITE     = g_quark_from_string("call_site");
   
 }
 
   
 }
 
index f374db2028cf41c4955e9393182386c9236a0e92..b4fa430ffdb7107ef42a438a6aa6b41c0da89578 100644 (file)
@@ -208,6 +208,8 @@ typedef struct _LttvProcessState {
 //  guint  last_tracefile_index;    /* index in the trace for cpu tracefile */
        LttvTracefileState      *usertrace;             /* Associated usertrace */
   /* opened file descriptors, address map?... */
 //  guint  last_tracefile_index;    /* index in the trace for cpu tracefile */
        LttvTracefileState      *usertrace;             /* Associated usertrace */
   /* opened file descriptors, address map?... */
+  GArray *user_stack;                                  /* User space function call stack */
+       guint64 current_function;
 } LttvProcessState;
 
 #define ANY_CPU 0 /* For clarity sake : a call to lttv_state_find_process for
 } LttvProcessState;
 
 #define ANY_CPU 0 /* For clarity sake : a call to lttv_state_find_process for
@@ -273,7 +275,6 @@ struct _LttvTraceState {
 
   /* Array of per cpu running process */
   LttvProcessState **running_process;
 
   /* Array of per cpu running process */
   LttvProcessState **running_process;
-  
 };
 
 struct _LttvTraceStateClass {
 };
 
 struct _LttvTraceStateClass {
index f7ba2ff0585ba9418f18e802d0574713d5692aad..22600255efde4a29dcc9eb5bde8c88311dce8a53 100644 (file)
@@ -39,6 +39,7 @@ GQuark
   LTTV_STATS_MODE_TYPES,
   LTTV_STATS_MODES,
   LTTV_STATS_SUBMODES,
   LTTV_STATS_MODE_TYPES,
   LTTV_STATS_MODES,
   LTTV_STATS_SUBMODES,
+       LTTV_STATS_FUNCTIONS,
   LTTV_STATS_EVENT_TYPES,
   LTTV_STATS_CPU_TIME,
   LTTV_STATS_ELAPSED_TIME,
   LTTV_STATS_EVENT_TYPES,
   LTTV_STATS_CPU_TIME,
   LTTV_STATS_ELAPSED_TIME,
@@ -1109,6 +1110,7 @@ static void module_init()
   LTTV_STATS_MODE_TYPES = g_quark_from_string("mode_types");
   LTTV_STATS_MODES = g_quark_from_string("modes");
   LTTV_STATS_SUBMODES = g_quark_from_string("submodes");
   LTTV_STATS_MODE_TYPES = g_quark_from_string("mode_types");
   LTTV_STATS_MODES = g_quark_from_string("modes");
   LTTV_STATS_SUBMODES = g_quark_from_string("submodes");
+  LTTV_STATS_SUBMODES = g_quark_from_string("functions");
   LTTV_STATS_EVENT_TYPES = g_quark_from_string("event_types");
   LTTV_STATS_CPU_TIME = g_quark_from_string("cpu time");
   LTTV_STATS_ELAPSED_TIME = g_quark_from_string("elapsed time");
   LTTV_STATS_EVENT_TYPES = g_quark_from_string("event_types");
   LTTV_STATS_CPU_TIME = g_quark_from_string("cpu time");
   LTTV_STATS_ELAPSED_TIME = g_quark_from_string("elapsed time");
index 090cbe5e2461b91c35420162524ef8a5f8cf3885..ab13872e70adba2f2dc57e788baaf1f8b2fe50b3 100644 (file)
@@ -79,7 +79,9 @@
    "cpu number" stands for the cpu identifier, and "process_id-start_time"
    is a unique process identifier composed of the process id
    (unique at any given time but which may be reused over time) concatenated
    "cpu number" stands for the cpu identifier, and "process_id-start_time"
    is a unique process identifier composed of the process id
    (unique at any given time but which may be reused over time) concatenated
-   with the process start time.
+   with the process start time. Each process has a "functions" tree which
+        contains each process'function address (when the information is available).
+        If not, only the 0x0 function will appear.
 
    modes/
      Execution Modes Tree
 
    modes/
      Execution Modes Tree
        cpu/
          "cpu number"/
            Execution Modes Tree
        cpu/
          "cpu number"/
            Execution Modes Tree
+              functions/
+                            "function address"/
+                                           Execution Modes Tree
+            functions/
+                          "function address"/
+                                         Execution Modes Tree
 
    All the events and derived values (cpu, elapsed and wait time) are
    added during the trace analysis in the relevant 
 
    All the events and derived values (cpu, elapsed and wait time) are
    added during the trace analysis in the relevant 
-   trace / processes / * / cpu / * / mode_types / * /submodes / * 
+   trace/processes/ * /cpu/ * /functions/ * /mode_types/ * /submodes/ * 
    "events tree". To achieve this efficiently, each tracefile context 
    contains a pointer to the current relevant "events tree" and "event_types" 
    tree within it.
 
    Once all the events are processed, the total number of events is computed
    "events tree". To achieve this efficiently, each tracefile context 
    contains a pointer to the current relevant "events tree" and "event_types" 
    tree within it.
 
    Once all the events are processed, the total number of events is computed
-   within each trace / processes / * / cpu / * / mode_types / * / submodes / *.
+   within each
+   trace/processes/ * /cpu/ * /functions/ * /mode_types/ * /submodes/ *.
    Then, the "events tree" are summed for all submodes within each mode type 
    Then, the "events tree" are summed for all submodes within each mode type 
-   and for all mode types within a processes / * / cpu / * 
+   and for all mode types within a processes/ * /cpu/ * /functions/ *
    "execution modes tree".
    "execution modes tree".
-
+   
+        Then, the "execution modes trees" for all functions within a
+        trace/processes/ * /cpu for all cpu within a process, for all processes,
+        and for all traces are computed. Separately, the "execution modes tree" for
+        each function (over all cpus) for all processes, and for all traces are
+        summed in the trace/processes/ * /functions/ * subtree.
+        
    Finally, the "execution modes trees" for all cpu within a process,
    for all processes, and for all traces are computed. Separately,
    the "execution modes tree" for each cpu but for all processes within a
    Finally, the "execution modes trees" for all cpu within a process,
    for all processes, and for all traces are computed. Separately,
    the "execution modes tree" for each cpu but for all processes within a
@@ -132,6 +147,7 @@ extern GQuark
   LTTV_STATS_CPU,
   LTTV_STATS_MODE_TYPES,
   LTTV_STATS_SUBMODES,
   LTTV_STATS_CPU,
   LTTV_STATS_MODE_TYPES,
   LTTV_STATS_SUBMODES,
+  LTTV_STATS_FUNCTIONS,
   LTTV_STATS_EVENT_TYPES,
   LTTV_STATS_CPU_TIME,
   LTTV_STATS_ELAPSED_TIME,
   LTTV_STATS_EVENT_TYPES,
   LTTV_STATS_CPU_TIME,
   LTTV_STATS_ELAPSED_TIME,
This page took 0.035107 seconds and 4 git commands to generate.