# 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
{
/* 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 ()
+ }
}
}
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 ()
}
}