seek n forward and backward implemented in trace context
authorcompudj <compudj@04897980-b3bd-0310-b5e0-8ef037075253>
Tue, 30 Aug 2005 16:19:39 +0000 (16:19 +0000)
committercompudj <compudj@04897980-b3bd-0310-b5e0-8ef037075253>
Tue, 30 Aug 2005 16:19:39 +0000 (16:19 +0000)
git-svn-id: http://ltt.polymtl.ca/svn@1090 04897980-b3bd-0310-b5e0-8ef037075253

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

index bc4f3de0c941ad923c040345795d8818c6bc1616..aab28bca84b0dc71592b4215a1d02428e3a7d939 100644 (file)
@@ -237,8 +237,8 @@ LttvLibrary *lttv_library_load(char *name, GError **error)
   return l;
 }
 
-
-static void library_unload(LttvLibrary *l)
+/* Returns < 0 if still in use, 0 if freed */
+static gint library_unload(LttvLibrary *l)
 {
   guint i;
 
@@ -249,13 +249,13 @@ static void library_unload(LttvLibrary *l)
   if(l->locked_loaded > 0) {
     g_log(G_LOG_DOMAIN, G_LOG_LEVEL_INFO, "Unload library %s: locked loaded", 
         l->info.name);
-    return;
+    return 1;
   }
 
   if(l->info.load_count > 0) {
     g_log(G_LOG_DOMAIN, G_LOG_LEVEL_INFO, "Unload library %s: load count %d", 
        l->info.name, l->info.load_count);
-    return;
+    return l->info.load_count;
   }
 
   /* Check if all its modules have been released */
@@ -265,7 +265,7 @@ static void library_unload(LttvLibrary *l)
     if(m->info.use_count > 0) {
       g_log(G_LOG_DOMAIN, G_LOG_LEVEL_INFO,"Unload library %s: module %s used",
           l->info.name, m->info.name);
-      return;
+      return 1;
     }
   }
 
@@ -278,15 +278,21 @@ static void library_unload(LttvLibrary *l)
   /* insure that module.c will be finalized */
 
   finish_destroy();
+  return 0;
 }
 
 
-void lttv_library_unload(LttvLibrary *l)
+gint lttv_library_unload(LttvLibrary *l)
 {
   /* In the case where we wait for a module to release, the load count is 0
    * and should not be decremented. */
-  if(l->info.load_count != 0) l->info.load_count--;
-  library_unload(l);
+  if(l->info.load_count != 0) {
+    l->info.load_count--;
+    return l->info.load_count;
+  } else {
+    library_unload(l);
+    return 0;
+  }
 }
 
 
@@ -296,10 +302,10 @@ static void library_lock_loaded(LttvLibrary *l)
 }
 
 
-static void library_unlock_loaded(LttvLibrary *l)
+static gint library_unlock_loaded(LttvLibrary *l)
 {
   l->locked_loaded--;
-  library_unload(l);
+  return library_unload(l);
 }
 
 
@@ -571,8 +577,8 @@ static void destroy()
       m = (LttvModule *)(l->modules->pdata[j]);
       while(m->info.require_count > 0) lttv_module_release(m);
     }
-    library_unlock_loaded(l);
-    while(l->info.load_count > 0) lttv_library_unload(l);
+    if(library_unlock_loaded(l) > 0)
+      while(lttv_library_unload(l) > 0);
 
     /* If the number of librairies loaded have changed, restart from the
      * beginning */
index 68791a2dc8dd7ee5ada476c6bed2a72d03cb0997..679314056e4c5a78b760cb77ec3f1f9c65f2a00b 100644 (file)
@@ -111,7 +111,8 @@ LttvModule *lttv_module_prerequisite_get(LttvModule *m, unsigned i);
 
 LttvLibrary *lttv_library_load(char *name, GError **error);
 
-void lttv_library_unload(LttvLibrary *l);
+/* Returns 0 if library is unloaded, > 0 otherwise */
+gint lttv_library_unload(LttvLibrary *l);
 
 
 /* Obtain information about the library */
index 8574778a9843d8ecf96fa49427cbff6407da2499..49fdf382c64aeb016e3120fb2a15d793846442cc 100644 (file)
@@ -1276,6 +1276,11 @@ static gboolean process_free(void *hook_data, void *call_data)
   if(likely(process != NULL)) {
     /* release_task is happening at kernel level : we can now safely release
      * the data structure of the process */
+    guint num_cpus = ltt_trace_get_num_cpu(ts->parent.t);
+    guint i;
+    for(i=0; i< num_cpus; i++) {
+      g_assert(process != ts->running_process[i]);
+    }
     exit_process(s, process);
   }
 
index bd9c1e6cab27d735bb8ef7e3806ec77ae21857ec..abee8199396f6d2e5f9e8ca784e229cb6b8c8ad0 100644 (file)
@@ -89,7 +89,7 @@ static void lttv_stats_init(LttvTracesetStats *self)
                       LTTV_STATS_USE_COUNT, 
                       LTTV_UINT, &v);
 
-  *(v.v_uint)++;
+  (*(v.v_uint))++;
   if(*(v.v_uint) == 1) { 
     g_assert(lttv_attribute_get_number(self->stats) == 0);
   }
@@ -106,7 +106,7 @@ static void lttv_stats_init(LttvTracesetStats *self)
     lttv_attribute_find(tcs->parent.parent.t_a, LTTV_STATS_USE_COUNT, 
         LTTV_UINT, &v);
 
-    *(v.v_uint)++;
+    (*(v.v_uint))++;
     if(*(v.v_uint) == 1) { 
       g_assert(lttv_attribute_get_number(tcs->stats) == 0);
     }
@@ -151,7 +151,7 @@ static void lttv_stats_fini(LttvTracesetStats *self)
 
   lttv_attribute_find(self->parent.parent.ts_a, LTTV_STATS_USE_COUNT, 
         LTTV_UINT, &v);
-  *(v.v_uint)--;
+  (*(v.v_uint))--;
 
   if(*(v.v_uint) == 0) {
     lttv_attribute_remove_by_name(self->parent.parent.ts_a, LTTV_STATS);
@@ -166,7 +166,7 @@ static void lttv_stats_fini(LttvTracesetStats *self)
 
     lttv_attribute_find(tcs->parent.parent.t_a, LTTV_STATS_USE_COUNT, 
         LTTV_UINT, &v);
-    *(v.v_uint)--;
+    (*(v.v_uint))--;
 
     if(*(v.v_uint) == 0) { 
       lttv_attribute_remove_by_name(tcs->parent.parent.t_a,LTTV_STATS);
index 6f1e7b58a334665c1f1254cb9204d67c3bbb9c23..305d736c6b4f6023f4c7610c0a9f9c207f8fa78b 100644 (file)
@@ -28,7 +28,7 @@
 #include <ltt/type.h>
 #include <errno.h>
 
-
+#define min(a,b) (((a)<(b))?(a):(b))
 
 
 gint compare_tracefile(gconstpointer a, gconstpointer b)
@@ -1079,6 +1079,8 @@ void lttv_traceset_context_position_save(const LttvTracesetContext *self,
   
   pos->tfc = g_array_set_size(pos->tfc, 0);
   pos->ep = g_array_set_size(pos->ep, 0);
+
+  pos->timestamp = ltt_time_infinite;
   
   for(i=0; i<num_traces;i++) {
     GArray * tracefiles = self->traces[i]->tracefiles;
@@ -1273,3 +1275,197 @@ void lttv_process_traceset_get_sync_data(LttvTracesetContext *tsc)
   lttv_traceset_context_position_save(tsc, tsc->sync_position);
 }
 
+struct seek_back_data {
+  guint first_event;   /* Index of the first event in the array : we will always
+                         overwrite at this position : this is a circular array. 
+                       */
+  guint events_found;
+  GPtrArray *array; /* array of LttvTracesetContextPositions pointers */
+};
+
+static gint seek_back_event_hook(void *hook_data, void* call_data)
+{
+  struct seek_back_data *sd = (struct seek_back_data*)hook_data;
+  LttvTracefileContext *tfc = (LttvTracefileContext*)call_data;
+  LttvTracesetContext *tsc = tfc->t_context->ts_context;
+  LttvTracesetContextPosition *pos;
+  
+  if(sd->events_found < sd->array->len) {
+    pos = (LttvTracesetContextPosition*)g_ptr_array_index (sd->array,
+                                                           sd->events_found);
+  } else {
+    pos = (LttvTracesetContextPosition*)g_ptr_array_index (sd->array,
+                                                           sd->first_event);
+  }
+
+  lttv_traceset_context_position_save(tsc, pos);
+
+  if(sd->first_event >= sd->array->len - 1) sd->first_event = 0;
+  else sd->first_event++;
+
+  sd->events_found = min(sd->array->len, sd->events_found + 1);
+
+  return FALSE;
+}
+
+
+/* Seek back n events back from the current position.
+ *
+ * Parameters :
+ * @self          The trace set context
+ * @n             number of events to jump over
+ * @first_offset  The initial offset value used. Hint : try about 100000ns.
+ *
+ * Return value : the number of events found (might be lower than the number
+ * requested if beginning of traceset is reached).
+ *
+ * The first search will go back first_offset and try to find the last n events
+ * matching the filter. If there are not enough, it will try to go back from the
+ * new trace point from first_offset*2, and so on, until beginning of trace or n
+ * events are found.
+ *
+ * Note : this function does not take in account the LttvFilter : use the
+ * similar function found in state.c instead.
+ *
+ * Note2 : the caller must make sure that the LttvTracesetContext does not
+ * contain any hook, as process_traceset_middle is used in this routine.
+ */
+guint lttv_process_traceset_seek_n_backward(LttvTracesetContext *self,
+                                            guint n, LttTime first_offset)
+{
+  guint i;
+  LttvTracesetContextPosition *next_iter_end_pos =
+                                lttv_traceset_context_position_new();
+  LttvTracesetContextPosition *end_pos = lttv_traceset_context_position_new();
+  LttTime time;
+  LttTime time_offset;
+  struct seek_back_data sd;
+  LttvHooks *hooks = lttv_hooks_new();
+  
+  sd.first_event = 0;
+  sd.events_found = 0;
+  sd.array = g_ptr_array_sized_new(n);
+  g_ptr_array_set_size(sd.array, n);
+  for(i=0;i<n;i++) {
+    g_ptr_array_index (sd.array, i) = lttv_traceset_context_position_new();
+  }
+                            
+  lttv_traceset_context_position_save(self, next_iter_end_pos);
+  /* Get the current time from which we will offset */
+  time = lttv_traceset_context_position_get_time(next_iter_end_pos);
+  /* the position saved might be end of traceset... */
+  if(ltt_time_compare(time, self->time_span.end_time) > 0) {
+    time = self->time_span.end_time;
+  }
+  time_offset = first_offset;
+  lttv_hooks_add(hooks, seek_back_event_hook, &sd, LTTV_PRIO_DEFAULT);
+  
+  lttv_process_traceset_begin(self, NULL, NULL, NULL, hooks, NULL);
+
+  while(1) {
+    /* stop criteria : - n events found
+     *                 - time < beginning of trace */
+    if(ltt_time_compare(time, self->time_span.start_time) < 0) break;
+    if(sd.events_found == n) break;
+
+    lttv_traceset_context_position_copy(end_pos, next_iter_end_pos);
+
+    /* We must seek the traceset back to time - time_offset */
+    /* this time becomes the new reference time */
+    time = ltt_time_sub(time, time_offset);
+    
+    lttv_process_traceset_seek_time(self, time);
+    lttv_traceset_context_position_save(self, next_iter_end_pos);
+
+    /* Process the traceset, calling a hook which adds events 
+     * to the array, overwriting the tail. It changes first_event and
+     * events_found too. */
+    /* We would like to have a clean context here : no other hook than our's */
+    
+    lttv_process_traceset_middle(self, ltt_time_infinite,
+        G_MAXUINT, end_pos);
+
+    time_offset = ltt_time_mul(time_offset, BACKWARD_SEEK_MUL);
+  }
+  
+  lttv_traceset_context_position_destroy(end_pos);
+  lttv_traceset_context_position_destroy(next_iter_end_pos);
+  
+  lttv_process_traceset_end(self, NULL, NULL, NULL, hooks, NULL);
+
+  if(sd.events_found > 0) {
+    /* Seek the traceset to the first event in the circular array */
+    LttvTracesetContextPosition *pos =
+      (LttvTracesetContextPosition*)g_ptr_array_index (sd.array,
+                                                       sd.first_event);
+    g_assert(lttv_process_traceset_seek_position(self, pos) == 0);
+  }
+  
+  for(i=0;i<n;i++) {
+    LttvTracesetContextPosition *pos =
+      (LttvTracesetContextPosition*)g_ptr_array_index (sd.array, i);
+    lttv_traceset_context_position_destroy(pos);
+  }
+  g_ptr_array_free(sd.array, TRUE);
+
+  lttv_hooks_destroy(hooks);
+
+  return sd.events_found;
+}
+
+
+struct seek_forward_data {
+  guint event_count;  /* event counter */
+  guint n;            /* requested number of events to jump over */
+};
+
+static gint seek_forward_event_hook(void *hook_data, void* call_data)
+{
+  struct seek_forward_data *sd = (struct seek_forward_data*)hook_data;
+
+  sd->event_count++;
+
+  if(sd->event_count >= sd->n)
+    return TRUE;
+  else
+    return FALSE;
+}
+
+/* Seek back n events forward from the current position
+ *
+ * Parameters :
+ * @self the trace set context
+ * @n    number of events to jump over
+ *
+ * returns : the number of events jumped over (may be less than requested if end
+ * of traceset reached) */
+guint lttv_process_traceset_seek_n_forward(LttvTracesetContext *self,
+                                          guint n)
+{
+  struct seek_forward_data sd;
+  sd.event_count = 0;
+  sd.n = n;
+  LttvHooks *hooks = lttv_hooks_new();
+
+  lttv_hooks_add(hooks, seek_forward_event_hook, &sd, LTTV_PRIO_DEFAULT);
+
+  lttv_process_traceset_begin(self, NULL, NULL, NULL, hooks, NULL);
+  
+  /* it will end on the end of traceset, or the fact that the
+   * hook returns TRUE.
+   */
+  lttv_process_traceset_middle(self, ltt_time_infinite,
+        G_MAXUINT, NULL);
+
+  /* Here, our position is either the end of traceset, or the exact position
+   * after n events : leave it like this. */
+
+  lttv_process_traceset_end(self, NULL, NULL, NULL, hooks, NULL);
+
+  lttv_hooks_destroy(hooks);
+
+  return sd.event_count;
+}
+
+
index 429a90162f5545343d884e2991a850d0f504f80c..f1396463e79cfdc15165070a12e5b6239c218bb9 100644 (file)
@@ -335,4 +335,16 @@ void lttv_process_traceset_synchronize_tracefiles(LttvTracesetContext *tsc);
 
 void lttv_process_traceset_get_sync_data(LttvTracesetContext *tsc);
 
+/* Seek n events forward and backward (without filtering) : only use these where
+ * necessary : the seek backward is costy. */
+
+#define BACKWARD_SEEK_MUL 2 /* Multiplication factor of time_offset between
+                               backward seek iterations */
+
+guint lttv_process_traceset_seek_n_forward(LttvTracesetContext *self,
+                                           guint n);
+
+guint lttv_process_traceset_seek_n_backward(LttvTracesetContext *self,
+                                           guint n, LttTime first_offset);
+
 #endif // PROCESSTRACE_H
This page took 0.030646 seconds and 4 git commands to generate.