-ff output coherency fixes.
[staptrace.git] / src / staptrace.stp
old mode 100644 (file)
new mode 100755 (executable)
index bcb9b3f..692abed
 # You should have received a copy of the GNU General Public License
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
-global opt_f
-global opt_q
+# ` = 0' is there to prevent: WARNING: never-assigned global variable
+
+# `opt_f' is a boolean for both -f and -ff.
+global opt_f = 0
+# Modify the [pid %5d] output to [%d] for the -ff postprocessor.
+global opt_ff = 0
+global opt_q = 0
+# Override target().
+global opt_child = 0
+
+/* systemtap bug?  /usr/share/doc/systemtap-1.3/SystemTap_Beginners_Guide.pdf
+   Example 3.19 reads or writes?  */
 
 global trace
-# FIXME: count()?
-global trace_count
 global last_tid
 probe begin
 {
-  trace[target ()] = 1
-  trace_count = 1
-  last_tid = target ()
+  tid = opt_child > 0 ? opt_child : target ()
+  trace[tid] = 1
+  last_tid = tid
 }
 
-function heading:string ()
+function heading (tid:long)
 {
-  if (trace_count > 1)
+  if (opt_ff)
+    return printf ("[%d]", tid)
+
+  foreach (tidi in trace limit 2)
+    tid_count++
+
+  if (tid_count > 1)
     {
       /* strace really calls TID a "pid".  */
-      return sprintf ("[pid %5d] ", tid ())
+      return printf ("[pid %5d] ", tid)
     }
-  else
-    return ""
 }
 
-global namea
+global funcname
+global nest
 
-function destroy (tid:long)
+function realnl ()
 {
-  delete namea[tid]
+  if (opt_ff)
+    print ("n\n")
+  else
+    print ("\n")
 }
 
-function lhs:string (tid:long)
-{
-  return namea[tid]
-}
 probe end
 {
-  foreach (tid in namea)
-    printf ("%s = ? <tracer terminated>\n", lhs (tid))
+  if (nest[last_tid] && funcname[last_tid] != "")
+    {
+      printf (") = ? <tracer terminated>")
+      realnl ()
+    }
+  foreach (tid in nest)
+    if (tid != last_tid)
+      {
+       heading (tid)
+       printf ("<... %s resumed> ) = ? <tracer terminated>",
+               funcname[tid] != "" ? funcname[tid] : "?");
+       realnl ()
+      }
 }
 
-/* BUG: sleeping function called from invalid context at kernel/mutex.c:94
+/* BUG: sleeping function called from invalid context at kernel/mutex.c:94  */
 %{static DEFINE_MUTEX (tracer_mutex);%}
-function lock ()
+function lock:long ()
 %{
+  if (in_atomic () || irqs_disabled())
+    {
+      THIS->__retvalue = 0;
+      return;
+    }
   mutex_lock (&tracer_mutex);
+  THIS->__retvalue = 1;
 %}
 function unlock ()
 %{
   mutex_unlock (&tracer_mutex);
 %}
+/*
+# systamtap bug? on void function value use no warning is given.
+global lockvar
+function lock:long ()
+{
+  lockvar++
+  return 1
+}
+function unlock ()
+{
+  lockvar--
+}
 */
-global dummy
-function lock () { dummy = 1; }
-function unlock () { dummy = 1; }
 
 #probe kprocess.start
 #{
 #  trace[pid ()] = 1
-#  trace_count++
 #}
 #probe kprocess.exit
 #{
 #  trace[pid ()] = 0
-#  trace_count--
 #}
 probe kprocess.create
 {
@@ -89,9 +125,11 @@ probe kprocess.create
       /* systemtap bug?  Why `new_pid' is provided but `new_tid' is not?  */
       new_tid = task_tid (task)
       trace[new_tid] = 1
-      trace_count++
       if (!opt_q)
-       printf ("Process %d attached\n", new_tid);
+       {
+         printf ("Process %d attached", new_tid);
+         realnl ()
+       }
     }
 }
 
@@ -103,56 +141,80 @@ probe kprocess.release
   tid = task_tid (task)
   if (trace[tid] != 0)
     {
-      if (namea[tid] != "")
-       {
-         printf ("%s = ?\n", lhs (tid))
-         destroy (tid)
-       }
-# FIXME
-      else if (0)
+      if (nest[tid])
        {
-         /* systemtap bug?  exit_group(2) systemtap calls "exit" and _exit(2)
-            is not caught at all.  */
-         lock ()
-         if (last_tid != tid () && namea[last_tid] != "")
-           printf (" <unfinished ...>\n")
-         last_tid = tid
-         printf ("%s_exit(?) = ?\n", heading ())
-         unlock ()
+         heading (tid)
+         /* FIXME: Do not assume "exit" for the nested calls.  */
+         printf ("<... %s resumed> = ?",
+                 funcname[tid] != "" ? funcname[tid] : "exit")
+         realnl ()
+         delete nest[tid]
+         delete funcname[tid]
        }
       delete trace[tid]
-      trace_count--
       if (!opt_q)
-       printf ("Process %d detached\n", tid);
+       {
+         printf ("Process %d detached", tid);
+         realnl ()
+       }
     }
 }
 probe syscall.*
 {
-  if (trace[tid ()] != 0)
+  if (trace[tid ()] != 0 && lock ())
     {
-      lock ()
       /* Why is mmap() called recursively twice?  */
-      if (namea[last_tid] != "")
-       printf (" <unfinished ...>\n")
+      if (nest[last_tid] && funcname[last_tid] != "")
+       {
+         if (last_tid != tid ())
+           {
+             if (opt_ff)
+               print ("c\n")
+             else
+               print (" <unfinished ...>\n")
+           }
+         else
+           {
+             print (" <unfinished ...>")
+             realnl ()
+           }
+       }
       last_tid = tid ();
-      namea[tid ()] = name
-      printf ("%s%s(%s", heading (), name, argstr)
+      funcname[tid ()] = name
+      nest[tid ()]++
+      heading (tid ())
+      printf ("%s(%s",name, argstr)
       unlock ()
     }
 }
 probe syscall.*.return
 {
-  if (trace[tid ()] != 0)
+  if (trace[tid ()] != 0 && lock ())
     {
-      lock ()
-      if (last_tid != tid () && namea[last_tid] != "")
-       printf (" <unfinished ...>\n")
-      if ((last_tid != tid () && namea[last_tid] != "")
-          || (last_tid == tid () && namea[last_tid] == ""))
-       printf ("%s<... %s resumed> ", heading (), name);
+      if (last_tid != tid () && nest[last_tid] && funcname[last_tid] != "")
+       {
+         if (opt_ff)
+           print ("c\n")
+         else
+           print (" <unfinished ...>\n")
+       }
+      if (last_tid != tid ())
+       {
+         heading (tid ())
+         if (!opt_ff)
+           printf ("<... %s resumed> ", name);
+       }
+      if (last_tid == tid () && funcname[last_tid] == "")
+       {
+         heading (tid ())
+         printf ("<... %s resumed> ", name);
+       }
       last_tid = tid ();
-      printf (") = %s\n", retstr)
-      destroy (tid ())
+      printf (") = %s", retstr)
+      realnl ()
+      if (!--nest[tid ()])
+       delete nest[tid ()]
+      delete funcname[tid ()]
       unlock ()
     }
 }