Author: dds
Date: Tue May 12 20:42:12 2009
New Revision: 192025
URL: http://svn.freebsd.org/changeset/base/192025

Log:
  Add -c option to summarize number of calls, errors, and system time.
  
  Reviewed by:  alfred

Modified:
  head/usr.bin/truss/amd64-fbsd.c
  head/usr.bin/truss/amd64-fbsd32.c
  head/usr.bin/truss/amd64-linux32.c
  head/usr.bin/truss/i386-fbsd.c
  head/usr.bin/truss/i386-linux.c
  head/usr.bin/truss/ia64-fbsd.c
  head/usr.bin/truss/main.c
  head/usr.bin/truss/powerpc-fbsd.c
  head/usr.bin/truss/sparc64-fbsd.c
  head/usr.bin/truss/syscall.h
  head/usr.bin/truss/syscalls.c
  head/usr.bin/truss/truss.1
  head/usr.bin/truss/truss.h

Modified: head/usr.bin/truss/amd64-fbsd.c
==============================================================================
--- head/usr.bin/truss/amd64-fbsd.c     Tue May 12 19:33:36 2009        
(r192024)
+++ head/usr.bin/truss/amd64-fbsd.c     Tue May 12 20:42:12 2009        
(r192025)
@@ -323,7 +323,8 @@ amd64_syscall_exit(struct trussinfo *tru
    * but that complicates things considerably.
    */
 
-  print_syscall_ret(trussinfo, fsc.name, fsc.nargs, fsc.s_args, errorp, 
retval);
+  print_syscall_ret(trussinfo, fsc.name, fsc.nargs, fsc.s_args, errorp,
+                   retval, fsc.sc);
   clear_fsc();
 
   return (retval);

Modified: head/usr.bin/truss/amd64-fbsd32.c
==============================================================================
--- head/usr.bin/truss/amd64-fbsd32.c   Tue May 12 19:33:36 2009        
(r192024)
+++ head/usr.bin/truss/amd64-fbsd32.c   Tue May 12 20:42:12 2009        
(r192025)
@@ -339,7 +339,8 @@ amd64_fbsd32_syscall_exit(struct trussin
    * but that complicates things considerably.
    */
 
-  print_syscall_ret(trussinfo, fsc.name, fsc.nargs, fsc.s_args, errorp, 
retval);
+  print_syscall_ret(trussinfo, fsc.name, fsc.nargs, fsc.s_args, errorp,
+                   retval, fsc.sc);
   clear_fsc();
 
   return (retval);

Modified: head/usr.bin/truss/amd64-linux32.c
==============================================================================
--- head/usr.bin/truss/amd64-linux32.c  Tue May 12 19:33:36 2009        
(r192024)
+++ head/usr.bin/truss/amd64-linux32.c  Tue May 12 20:42:12 2009        
(r192025)
@@ -309,7 +309,7 @@ amd64_linux32_syscall_exit(struct trussi
   }
 
   print_syscall_ret(trussinfo, fsc.name, fsc.nargs, fsc.s_args, errorp,
-                    errorp ? i : retval);
+                    errorp ? i : retval, fsc.sc);
   clear_fsc();
 
   return (retval);

Modified: head/usr.bin/truss/i386-fbsd.c
==============================================================================
--- head/usr.bin/truss/i386-fbsd.c      Tue May 12 19:33:36 2009        
(r192024)
+++ head/usr.bin/truss/i386-fbsd.c      Tue May 12 20:42:12 2009        
(r192025)
@@ -329,7 +329,8 @@ i386_syscall_exit(struct trussinfo *trus
    * but that complicates things considerably.
    */
 
-  print_syscall_ret(trussinfo, fsc.name, fsc.nargs, fsc.s_args, errorp, 
retval);
+  print_syscall_ret(trussinfo, fsc.name, fsc.nargs, fsc.s_args, errorp,
+                   retval, fsc.sc);
   clear_fsc();
 
   return (retval);

Modified: head/usr.bin/truss/i386-linux.c
==============================================================================
--- head/usr.bin/truss/i386-linux.c     Tue May 12 19:33:36 2009        
(r192024)
+++ head/usr.bin/truss/i386-linux.c     Tue May 12 20:42:12 2009        
(r192025)
@@ -309,7 +309,7 @@ i386_linux_syscall_exit(struct trussinfo
   }
 
   print_syscall_ret(trussinfo, fsc.name, fsc.nargs, fsc.s_args, errorp,
-                    errorp ? i : retval);
+                    errorp ? i : retval, fsc.sc);
   clear_fsc();
 
   return (retval);

Modified: head/usr.bin/truss/ia64-fbsd.c
==============================================================================
--- head/usr.bin/truss/ia64-fbsd.c      Tue May 12 19:33:36 2009        
(r192024)
+++ head/usr.bin/truss/ia64-fbsd.c      Tue May 12 20:42:12 2009        
(r192025)
@@ -294,7 +294,8 @@ ia64_syscall_exit(struct trussinfo *trus
    * but that complicates things considerably.
    */
 
-  print_syscall_ret(trussinfo, fsc.name, fsc.nargs, fsc.s_args, errorp, 
retval);
+  print_syscall_ret(trussinfo, fsc.name, fsc.nargs, fsc.s_args, errorp,
+                   fsc.sc, retval);
   clear_fsc();
 
   return (retval);

Modified: head/usr.bin/truss/main.c
==============================================================================
--- head/usr.bin/truss/main.c   Tue May 12 19:33:36 2009        (r192024)
+++ head/usr.bin/truss/main.c   Tue May 12 20:42:12 2009        (r192025)
@@ -58,6 +58,7 @@ __FBSDID("$FreeBSD$");
 
 #include "truss.h"
 #include "extern.h"
+#include "syscall.h"
 
 #define MAXARGS 6
 
@@ -65,8 +66,8 @@ static void
 usage(void)
 {
        fprintf(stderr, "%s\n%s\n",
-           "usage: truss [-faedDS] [-o file] [-s strsize] -p pid",
-           "       truss [-faedDS] [-o file] [-s strsize] command [args]");
+           "usage: truss [-cfaedDS] [-o file] [-s strsize] -p pid",
+           "       truss [-cfaedDS] [-o file] [-s strsize] command [args]");
        exit(1);
 }
 
@@ -188,7 +189,7 @@ main(int ac, char **av)
        trussinfo->pr_why = S_NONE;
        trussinfo->curthread = NULL;
        SLIST_INIT(&trussinfo->threadlist);
-       while ((c = getopt(ac, av, "p:o:faedDs:S")) != -1) {
+       while ((c = getopt(ac, av, "p:o:facedDs:S")) != -1) {
                switch (c) {
                case 'p':       /* specified pid */
                        trussinfo->pid = atoi(optarg);
@@ -204,6 +205,9 @@ main(int ac, char **av)
                case 'a': /* Print execve() argument strings. */
                        trussinfo->flags |= EXECVEARGS;
                        break;
+               case 'c': /* Count number of system calls and time. */
+                       trussinfo->flags |= COUNTONLY;
+                       break;
                case 'e': /* Print execve() environment strings. */
                        trussinfo->flags |= EXECVEENVS;
                        break;
@@ -337,6 +341,8 @@ START_TRACE:
                        free(signame);
                        break;
                case S_EXIT:
+                       if (trussinfo->flags & COUNTONLY)
+                               break;
                        if (trussinfo->flags & FOLLOWFORKS)
                                fprintf(trussinfo->outfile, "%5d: ",
                                    trussinfo->pid);
@@ -360,12 +366,16 @@ START_TRACE:
                        break;
                }
        } while (trussinfo->pr_why != S_EXIT);
-       fflush(trussinfo->outfile);
 
        if (trussinfo->flags & FOLLOWFORKS)
                do {
                        childpid = wait(&status);
                } while (childpid != -1);
 
+       if (trussinfo->flags & COUNTONLY)
+               print_summary(trussinfo);
+
+       fflush(trussinfo->outfile);
+
        return (0);
 }

Modified: head/usr.bin/truss/powerpc-fbsd.c
==============================================================================
--- head/usr.bin/truss/powerpc-fbsd.c   Tue May 12 19:33:36 2009        
(r192024)
+++ head/usr.bin/truss/powerpc-fbsd.c   Tue May 12 20:42:12 2009        
(r192025)
@@ -331,7 +331,8 @@ powerpc_syscall_exit(struct trussinfo *t
    * but that complicates things considerably.
    */
 
-  print_syscall_ret(trussinfo, fsc.name, fsc.nargs, fsc.s_args, errorp, 
retval);
+  print_syscall_ret(trussinfo, fsc.name, fsc.nargs, fsc.s_args, errorp,
+                   retval, fsc.sc);
   clear_fsc();
 
   return (retval);

Modified: head/usr.bin/truss/sparc64-fbsd.c
==============================================================================
--- head/usr.bin/truss/sparc64-fbsd.c   Tue May 12 19:33:36 2009        
(r192024)
+++ head/usr.bin/truss/sparc64-fbsd.c   Tue May 12 20:42:12 2009        
(r192025)
@@ -336,7 +336,8 @@ sparc64_syscall_exit(struct trussinfo *t
    * but that complicates things considerably.
    */
 
-  print_syscall_ret(trussinfo, fsc.name, fsc.nargs, fsc.s_args, errorp, 
retval);
+  print_syscall_ret(trussinfo, fsc.name, fsc.nargs, fsc.s_args, errorp,
+                   retval, fsc.sc);
   clear_fsc();
 
   return (retval);

Modified: head/usr.bin/truss/syscall.h
==============================================================================
--- head/usr.bin/truss/syscall.h        Tue May 12 19:33:36 2009        
(r192024)
+++ head/usr.bin/truss/syscall.h        Tue May 12 20:42:12 2009        
(r192025)
@@ -57,10 +57,14 @@ struct syscall {
        int nargs;      /* actual number of meaningful arguments */
                        /* Hopefully, no syscalls with > 10 args */
        struct syscall_args args[10];
+       struct timespec time; /* Time spent for this call */
+       int ncalls;     /* Number of calls */
+       int nerror;     /* Number of calls that returned with error */
 };
 
 struct syscall *get_syscall(const char*);
 char *print_arg(struct syscall_args *, unsigned long*, long, struct trussinfo 
*);
 void print_syscall(struct trussinfo *, const char *, int, char **);
 void print_syscall_ret(struct trussinfo *, const char *, int, char **, int,
-    long);
+    long, struct syscall *);
+void print_summary(struct trussinfo *trussinfo);

Modified: head/usr.bin/truss/syscalls.c
==============================================================================
--- head/usr.bin/truss/syscalls.c       Tue May 12 19:33:36 2009        
(r192024)
+++ head/usr.bin/truss/syscalls.c       Tue May 12 20:42:12 2009        
(r192025)
@@ -89,135 +89,162 @@ static const char rcsid[] =
 /*
  * This should probably be in its own file, sorted alphabetically.
  */
-
 struct syscall syscalls[] = {
-       { "fcntl", 1, 3,
-         { { Int, 0 } , { Fcntl, 1 }, { Fcntlflag | OUT, 2 } } },
-       { "readlink", 1, 3,
-         { { Name, 0 } , { Readlinkres | OUT, 1 }, { Int, 2 } } },
-       { "lseek", 2, 3,
-         { { Int, 0 }, { Quad, 1 + QUAD_ALIGN }, { Whence, 1 + QUAD_SLOTS + 
QUAD_ALIGN } } },
-       { "linux_lseek", 2, 3,
-         { { Int, 0 }, { Int, 1 }, { Whence, 2 } } },
-       { "mmap", 2, 6,
-         { { Ptr, 0 }, { Int, 1 }, { Mprot, 2 }, { Mmapflags, 3 }, { Int, 4 }, 
{ Quad, 5 + QUAD_ALIGN } } },
-       { "mprotect", 1, 3,
-         { { Ptr, 0 }, { Int, 1 }, { Mprot, 2 } } },
-       { "open", 1, 3,
-         { { Name | IN, 0 } , { Open, 1 }, { Octal, 2 } } },
-       { "mkdir", 1, 2,
-         { { Name, 0 } , { Octal, 1 } } },
-       { "linux_open", 1, 3,
-         { { Name, 0 }, { Hex, 1 }, { Octal, 2 } } },
-       { "close", 1, 1,
-         { { Int, 0 } } },
-       { "link", 0, 2,
-         { { Name, 0 }, { Name, 1 } } },
-       { "unlink", 0, 1,
-         { { Name, 0 } } },
-       { "chdir", 0, 1,
-         { { Name, 0 } } },
-       { "chroot", 0, 1,
-         { { Name, 0 } } },
-       { "mknod", 0, 3,
-         { { Name, 0 }, { Octal, 1 }, { Int, 3 } } },
-       { "chmod", 0, 2,
-         { { Name, 0 }, { Octal, 1 } } },
-       { "chown", 0, 3,
-         { { Name, 0 }, { Int, 1 }, { Int, 2 } } },
-       { "mount", 0, 4,
-         { { Name, 0 }, { Name, 1 }, { Int, 2 }, { Ptr, 3 } } },
-       { "umount", 0, 2,
-         { { Name, 0 }, { Int, 2 } } },
-       { "fstat", 1, 2,
-         { { Int, 0 }, { Stat | OUT , 1 } } },
-       { "stat", 1, 2,
-         { { Name | IN, 0 }, { Stat | OUT, 1 } } },
-       { "lstat", 1, 2,
-         { { Name | IN, 0 }, { Stat | OUT, 1 } } },
-       { "linux_newstat", 1, 2,
-         { { Name | IN, 0 }, { Ptr | OUT, 1 } } },
-       { "linux_newfstat", 1, 2,
-         { { Int, 0 }, { Ptr | OUT, 1 } } },
-       { "write", 1, 3,
-         { { Int, 0 }, { BinString | IN, 1 }, { Int, 2 } } },
-       { "ioctl", 1, 3,
-         { { Int, 0 }, { Ioctl, 1 }, { Hex, 2 } } },
-       { "break", 1, 1, { { Ptr, 0 } } },
-       { "exit", 0, 1, { { Hex, 0 } } },
-       { "access", 1, 2, { { Name | IN, 0 }, { Int, 1 } } },
-       { "sigaction", 1, 3,
-         { { Signal, 0 }, { Sigaction | IN, 1 }, { Sigaction | OUT, 2 } } },
-       { "accept", 1, 3,
-         { { Int, 0 }, { Sockaddr | OUT, 1 }, { Ptr | OUT, 2 } } },
-       { "bind", 1, 3,
-         { { Int, 0 }, { Sockaddr | IN, 1 }, { Int, 2 } } },
-       { "connect", 1, 3,
-         { { Int, 0 }, { Sockaddr | IN, 1 }, { Int, 2 } } },
-       { "getpeername", 1, 3,
-         { { Int, 0 }, { Sockaddr | OUT, 1 }, { Ptr | OUT, 2 } } },
-       { "getsockname", 1, 3,
-         { { Int, 0 }, { Sockaddr | OUT, 1 }, { Ptr | OUT, 2 } } },
-       { "recvfrom", 1, 6,
-         { { Int, 0 }, { BinString | OUT, 1 }, { Int, 2 }, { Hex, 3 }, { 
Sockaddr | OUT, 4 }, { Ptr | OUT, 5 } } },
-       { "sendto", 1, 6,
-         { { Int, 0 }, { BinString | IN, 1 }, { Int, 2 }, { Hex, 3 }, { 
Sockaddr | IN, 4 }, { Ptr | IN, 5 } } },
-       { "execve", 1, 3,
-         { { Name | IN, 0 }, { StringArray | IN, 1 }, { StringArray | IN, 2 } 
} },
-       { "linux_execve", 1, 3,
-         { { Name | IN, 0 }, { StringArray | IN, 1 }, { StringArray | IN, 2 } 
} },
-       { "kldload", 0, 1, { { Name | IN, 0 } } },
-       { "kldunload", 0, 1, { { Int, 0 } } },
-       { "kldfind", 0, 1, { { Name | IN, 0 } } },
-       { "kldnext", 0, 1, { { Int, 0 } } },
-       { "kldstat", 0, 2, { { Int, 0 }, { Ptr, 1 } } },
-       { "kldfirstmod", 0, 1, { { Int, 0 } } },
-       { "nanosleep", 0, 1, { { Timespec, 0 } } },
-       { "select", 1, 5, { { Int, 0 }, { Fd_set, 1 }, { Fd_set, 2 }, { Fd_set, 
3 }, { Timeval, 4 } } },
-       { "poll", 1, 3, { { Pollfd, 0 }, { Int, 1 }, { Int, 2 } } },
-       { "gettimeofday", 1, 2, { { Timeval | OUT, 0 }, { Ptr, 1 } } },
-       { "clock_gettime", 1, 2, { { Int, 0 }, { Timespec | OUT, 1 } } },
-       { "getitimer", 1, 2, { { Int, 0 }, { Itimerval | OUT, 2 } } },
-       { "setitimer", 1, 3, { { Int, 0 }, { Itimerval, 1 } , { Itimerval | 
OUT, 2 } } },
-       { "kse_release", 0, 1, { { Timespec, 0 } } },
-       { "kevent", 0, 6, { { Int, 0 }, { Kevent, 1 }, { Int, 2 }, { Kevent | 
OUT, 3 }, { Int, 4 }, { Timespec, 5 } } },
-       { "_umtx_lock", 0, 1, { { Umtx, 0 } } },
-       { "_umtx_unlock", 0, 1, { { Umtx, 0 } } },
-       { "sigprocmask", 0, 3, { { Sigprocmask, 0 }, { Sigset, 1 }, { Sigset | 
OUT, 2 } } },
-       { "unmount", 1, 2, { { Name, 0 }, { Int, 1 } } },
-       { "socket", 1, 3, { { Sockdomain, 0 }, { Socktype, 1 }, { Int, 2 } } },
-       { "getrusage", 1, 2, { { Int, 0 }, { Rusage | OUT, 1 } } },
-       { "__getcwd", 1, 2, { { Name | OUT, 0 }, { Int, 1 } } },
-       { "shutdown", 1, 2, { { Int, 0 }, { Shutdown, 1 } } },
-       { "getrlimit", 1, 2, { { Resource, 0 }, { Rlimit | OUT, 1 } } },
-       { "setrlimit", 1, 2, { { Resource, 0 }, { Rlimit | IN, 1 } } },
-       { "utimes", 1, 2,
-         { { Name | IN, 0 }, { Timeval2 | IN, 1 } } },
-       { "lutimes", 1, 2,
-         { { Name | IN, 0 }, { Timeval2 | IN, 1 } } },
-       { "futimes", 1, 2,
-         { { Int, 0 }, { Timeval | IN, 1 } } },
-       { "chflags", 1, 2,
-         { { Name | IN, 0 }, { Hex, 1 } } },
-       { "lchflags", 1, 2,
-         { { Name | IN, 0 }, { Hex, 1 } } },
-       { "pathconf", 1, 2,
-         { { Name | IN, 0 }, { Pathconf, 1 } } },
-       { "truncate", 1, 3,
-         { { Name | IN, 0 }, { Int | IN, 1 }, { Quad | IN, 2 } } },
-       { "ftruncate", 1, 3,
-         { { Int | IN, 0 }, { Int | IN, 1 }, { Quad | IN, 2 } } },
-       { "kill", 1, 2,
-         { { Int | IN, 0 }, { Signal | IN, 1 } } },
-       { "munmap", 1, 2,
-         { { Ptr, 0 }, { Int, 1 } } },
-       { "read", 1, 3,
-         { { Int, 0 }, { BinString | OUT, 1 }, { Int, 2 } } },
-       { "rename", 1, 2,
-         { { Name , 0 } , { Name, 1 } } },
-       { "symlink", 1, 2,
-         { { Name , 0 } , { Name, 1 } } },
-       { 0, 0, 0, { { 0, 0 } } },
+       { .name = "fcntl", .ret_type = 1, .nargs = 3,
+         .args = { { Int, 0 } , { Fcntl, 1 }, { Fcntlflag | OUT, 2 } } },
+       { .name = "readlink", .ret_type = 1, .nargs = 3,
+         .args = { { Name, 0 } , { Readlinkres | OUT, 1 }, { Int, 2 } } },
+       { .name = "lseek", .ret_type = 2, .nargs = 3,
+         .args = { { Int, 0 }, { Quad, 1 + QUAD_ALIGN }, { Whence, 1 + 
QUAD_SLOTS + QUAD_ALIGN } } },
+       { .name = "linux_lseek", .ret_type = 2, .nargs = 3,
+         .args = { { Int, 0 }, { Int, 1 }, { Whence, 2 } } },
+       { .name = "mmap", .ret_type = 2, .nargs = 6,
+         .args = { { Ptr, 0 }, { Int, 1 }, { Mprot, 2 }, { Mmapflags, 3 }, { 
Int, 4 }, { Quad, 5 + QUAD_ALIGN } } },
+       { .name = "mprotect", .ret_type = 1, .nargs = 3,
+         .args = { { Ptr, 0 }, { Int, 1 }, { Mprot, 2 } } },
+       { .name = "open", .ret_type = 1, .nargs = 3,
+         .args = { { Name | IN, 0 } , { Open, 1 }, { Octal, 2 } } },
+       { .name = "mkdir", .ret_type = 1, .nargs = 2,
+         .args = { { Name, 0 } , { Octal, 1 } } },
+       { .name = "linux_open", .ret_type = 1, .nargs = 3,
+         .args = { { Name, 0 }, { Hex, 1 }, { Octal, 2 } } },
+       { .name = "close", .ret_type = 1, .nargs = 1,
+         .args = { { Int, 0 } } },
+       { .name = "link", .ret_type = 0, .nargs = 2,
+         .args = { { Name, 0 }, { Name, 1 } } },
+       { .name = "unlink", .ret_type = 0, .nargs = 1,
+         .args = { { Name, 0 } } },
+       { .name = "chdir", .ret_type = 0, .nargs = 1,
+         .args = { { Name, 0 } } },
+       { .name = "chroot", .ret_type = 0, .nargs = 1,
+         .args = { { Name, 0 } } },
+       { .name = "mknod", .ret_type = 0, .nargs = 3,
+         .args = { { Name, 0 }, { Octal, 1 }, { Int, 3 } } },
+       { .name = "chmod", .ret_type = 0, .nargs = 2,
+         .args = { { Name, 0 }, { Octal, 1 } } },
+       { .name = "chown", .ret_type = 0, .nargs = 3,
+         .args = { { Name, 0 }, { Int, 1 }, { Int, 2 } } },
+       { .name = "mount", .ret_type = 0, .nargs = 4,
+         .args = { { Name, 0 }, { Name, 1 }, { Int, 2 }, { Ptr, 3 } } },
+       { .name = "umount", .ret_type = 0, .nargs = 2,
+         .args = { { Name, 0 }, { Int, 2 } } },
+       { .name = "fstat", .ret_type = 1, .nargs = 2,
+         .args = { { Int, 0 }, { Stat | OUT , 1 } } },
+       { .name = "stat", .ret_type = 1, .nargs = 2,
+         .args = { { Name | IN, 0 }, { Stat | OUT, 1 } } },
+       { .name = "lstat", .ret_type = 1, .nargs = 2,
+         .args = { { Name | IN, 0 }, { Stat | OUT, 1 } } },
+       { .name = "linux_newstat", .ret_type = 1, .nargs = 2,
+         .args = { { Name | IN, 0 }, { Ptr | OUT, 1 } } },
+       { .name = "linux_newfstat", .ret_type = 1, .nargs = 2,
+         .args = { { Int, 0 }, { Ptr | OUT, 1 } } },
+       { .name = "write", .ret_type = 1, .nargs = 3,
+         .args = { { Int, 0 }, { BinString | IN, 1 }, { Int, 2 } } },
+       { .name = "ioctl", .ret_type = 1, .nargs = 3,
+         .args = { { Int, 0 }, { Ioctl, 1 }, { Hex, 2 } } },
+       { .name = "break", .ret_type = 1, .nargs = 1,
+         .args = { { Ptr, 0 } } },
+       { .name = "exit", .ret_type = 0, .nargs = 1,
+         .args = { { Hex, 0 } } },
+       { .name = "access", .ret_type = 1, .nargs = 2,
+         .args = { { Name | IN, 0 }, { Int, 1 } } },
+       { .name = "sigaction", .ret_type = 1, .nargs = 3,
+         .args = { { Signal, 0 }, { Sigaction | IN, 1 }, { Sigaction | OUT, 2 
} } },
+       { .name = "accept", .ret_type = 1, .nargs = 3,
+         .args = { { Int, 0 }, { Sockaddr | OUT, 1 }, { Ptr | OUT, 2 } } },
+       { .name = "bind", .ret_type = 1, .nargs = 3,
+         .args = { { Int, 0 }, { Sockaddr | IN, 1 }, { Int, 2 } } },
+       { .name = "connect", .ret_type = 1, .nargs = 3,
+         .args = { { Int, 0 }, { Sockaddr | IN, 1 }, { Int, 2 } } },
+       { .name = "getpeername", .ret_type = 1, .nargs = 3,
+         .args = { { Int, 0 }, { Sockaddr | OUT, 1 }, { Ptr | OUT, 2 } } },
+       { .name = "getsockname", .ret_type = 1, .nargs = 3,
+         .args = { { Int, 0 }, { Sockaddr | OUT, 1 }, { Ptr | OUT, 2 } } },
+       { .name = "recvfrom", .ret_type = 1, .nargs = 6,
+         .args = { { Int, 0 }, { BinString | OUT, 1 }, { Int, 2 }, { Hex, 3 }, 
{ Sockaddr | OUT, 4 }, { Ptr | OUT, 5 } } },
+       { .name = "sendto", .ret_type = 1, .nargs = 6,
+         .args = { { Int, 0 }, { BinString | IN, 1 }, { Int, 2 }, { Hex, 3 }, 
{ Sockaddr | IN, 4 }, { Ptr | IN, 5 } } },
+       { .name = "execve", .ret_type = 1, .nargs = 3,
+         .args = { { Name | IN, 0 }, { StringArray | IN, 1 }, { StringArray | 
IN, 2 } } },
+       { .name = "linux_execve", .ret_type = 1, .nargs = 3,
+         .args = { { Name | IN, 0 }, { StringArray | IN, 1 }, { StringArray | 
IN, 2 } } },
+       { .name = "kldload", .ret_type = 0, .nargs = 1,
+         .args = { { Name | IN, 0 } } },
+       { .name = "kldunload", .ret_type = 0, .nargs = 1,
+         .args = { { Int, 0 } } },
+       { .name = "kldfind", .ret_type = 0, .nargs = 1,
+         .args = { { Name | IN, 0 } } },
+       { .name = "kldnext", .ret_type = 0, .nargs = 1,
+         .args = { { Int, 0 } } },
+       { .name = "kldstat", .ret_type = 0, .nargs = 2,
+         .args = { { Int, 0 }, { Ptr, 1 } } },
+       { .name = "kldfirstmod", .ret_type = 0, .nargs = 1,
+         .args = { { Int, 0 } } },
+       { .name = "nanosleep", .ret_type = 0, .nargs = 1,
+         .args = { { Timespec, 0 } } },
+       { .name = "select", .ret_type = 1, .nargs = 5,
+         .args = { { Int, 0 }, { Fd_set, 1 }, { Fd_set, 2 }, { Fd_set, 3 }, { 
Timeval, 4 } } },
+       { .name = "poll", .ret_type = 1, .nargs = 3,
+         .args = { { Pollfd, 0 }, { Int, 1 }, { Int, 2 } } },
+       { .name = "gettimeofday", .ret_type = 1, .nargs = 2,
+         .args = { { Timeval | OUT, 0 }, { Ptr, 1 } } },
+       { .name = "clock_gettime", .ret_type = 1, .nargs = 2,
+         .args = { { Int, 0 }, { Timespec | OUT, 1 } } },
+       { .name = "getitimer", .ret_type = 1, .nargs = 2,
+         .args = { { Int, 0 }, { Itimerval | OUT, 2 } } },
+       { .name = "setitimer", .ret_type = 1, .nargs = 3,
+         .args = { { Int, 0 }, { Itimerval, 1 } , { Itimerval | OUT, 2 } } },
+       { .name = "kse_release", .ret_type = 0, .nargs = 1,
+         .args = { { Timespec, 0 } } },
+       { .name = "kevent", .ret_type = 0, .nargs = 6,
+         .args = { { Int, 0 }, { Kevent, 1 }, { Int, 2 }, { Kevent | OUT, 3 }, 
{ Int, 4 }, { Timespec, 5 } } },
+       { .name = "_umtx_lock", .ret_type = 0, .nargs = 1,
+         .args = { { Umtx, 0 } } },
+       { .name = "_umtx_unlock", .ret_type = 0, .nargs = 1,
+         .args = { { Umtx, 0 } } },
+       { .name = "sigprocmask", .ret_type = 0, .nargs = 3,
+         .args = { { Sigprocmask, 0 }, { Sigset, 1 }, { Sigset | OUT, 2 } } },
+       { .name = "unmount", .ret_type = 1, .nargs = 2,
+         .args = { { Name, 0 }, { Int, 1 } } },
+       { .name = "socket", .ret_type = 1, .nargs = 3,
+         .args = { { Sockdomain, 0 }, { Socktype, 1 }, { Int, 2 } } },
+       { .name = "getrusage", .ret_type = 1, .nargs = 2,
+         .args = { { Int, 0 }, { Rusage | OUT, 1 } } },
+       { .name = "__getcwd", .ret_type = 1, .nargs = 2,
+         .args = { { Name | OUT, 0 }, { Int, 1 } } },
+       { .name = "shutdown", .ret_type = 1, .nargs = 2,
+         .args = { { Int, 0 }, { Shutdown, 1 } } },
+       { .name = "getrlimit", .ret_type = 1, .nargs = 2,
+         .args = { { Resource, 0 }, { Rlimit | OUT, 1 } } },
+       { .name = "setrlimit", .ret_type = 1, .nargs = 2,
+         .args = { { Resource, 0 }, { Rlimit | IN, 1 } } },
+       { .name = "utimes", .ret_type = 1, .nargs = 2,
+         .args = { { Name | IN, 0 }, { Timeval2 | IN, 1 } } },
+       { .name = "lutimes", .ret_type = 1, .nargs = 2,
+         .args = { { Name | IN, 0 }, { Timeval2 | IN, 1 } } },
+       { .name = "futimes", .ret_type = 1, .nargs = 2,
+         .args = { { Int, 0 }, { Timeval | IN, 1 } } },
+       { .name = "chflags", .ret_type = 1, .nargs = 2,
+         .args = { { Name | IN, 0 }, { Hex, 1 } } },
+       { .name = "lchflags", .ret_type = 1, .nargs = 2,
+         .args = { { Name | IN, 0 }, { Hex, 1 } } },
+       { .name = "pathconf", .ret_type = 1, .nargs = 2,
+         .args = { { Name | IN, 0 }, { Pathconf, 1 } } },
+       { .name = "truncate", .ret_type = 1, .nargs = 3,
+         .args = { { Name | IN, 0 }, { Int | IN, 1 }, { Quad | IN, 2 } } },
+       { .name = "ftruncate", .ret_type = 1, .nargs = 3,
+         .args = { { Int | IN, 0 }, { Int | IN, 1 }, { Quad | IN, 2 } } },
+       { .name = "kill", .ret_type = 1, .nargs = 2,
+         .args = { { Int | IN, 0 }, { Signal | IN, 1 } } },
+       { .name = "munmap", .ret_type = 1, .nargs = 2,
+         .args = { { Ptr, 0 }, { Int, 1 } } },
+       { .name = "read", .ret_type = 1, .nargs = 3,
+         .args = { { Int, 0 }, { BinString | OUT, 1 }, { Int, 2 } } },
+       { .name = "rename", .ret_type = 1, .nargs = 2,
+         .args = { { Name , 0 } , { Name, 1 } } },
+       { .name = "symlink", .ret_type = 1, .nargs = 2,
+         .args = { { Name , 0 } , { Name, 1 } } },
+       { .name = 0 },
 };
 
 /* Xlat idea taken from strace */
@@ -1077,8 +1104,21 @@ print_syscall(struct trussinfo *trussinf
 
 void
 print_syscall_ret(struct trussinfo *trussinfo, const char *name, int nargs,
-    char **s_args, int errorp, long retval)
+    char **s_args, int errorp, long retval, struct syscall *sc)
 {
+       struct timespec timediff;
+
+       if (trussinfo->flags & COUNTONLY) {
+               if (!sc)
+                       return;
+               clock_gettime(CLOCK_REALTIME, &trussinfo->after);
+               timespecsubt(&trussinfo->after, &trussinfo->before, &timediff);
+               timespecadd(&sc->time, &timediff, &sc->time);
+               sc->ncalls++;
+               if (errorp)
+                       sc->nerror++;
+               return;
+       }
 
        print_syscall(trussinfo, name, nargs, s_args);
        fflush(trussinfo->outfile);
@@ -1088,3 +1128,28 @@ print_syscall_ret(struct trussinfo *trus
                fprintf(trussinfo->outfile, " = %ld (0x%lx)\n", retval, retval);
        }
 }
+
+void
+print_summary(struct trussinfo *trussinfo)
+{
+       struct syscall *sc;
+       struct timespec total = {0, 0};
+       int ncall, nerror;
+
+       fprintf(trussinfo->outfile, "%-20s%15s%8s%8s\n",
+               "syscall", "seconds", "calls", "errors");
+       ncall = nerror = 0;
+       for (sc = syscalls; sc->name != NULL; sc++)
+               if (sc->ncalls) {
+                       fprintf(trussinfo->outfile, "%-20s%5d.%09ld%8d%8d\n",
+                           sc->name, sc->time.tv_sec, sc->time.tv_nsec,
+                           sc->ncalls, sc->nerror);
+                       timespecadd(&total, &sc->time, &total);
+                       ncall += sc->ncalls;
+                       nerror += sc->nerror;
+               }
+       fprintf(trussinfo->outfile, "%20s%15s%8s%8s\n",
+               "", "-------------", "-------", "-------");
+       fprintf(trussinfo->outfile, "%-20s%5d.%09ld%8d%8d\n",
+               "", total.tv_sec, total.tv_nsec, ncall, nerror);
+}

Modified: head/usr.bin/truss/truss.1
==============================================================================
--- head/usr.bin/truss/truss.1  Tue May 12 19:33:36 2009        (r192024)
+++ head/usr.bin/truss/truss.1  Tue May 12 20:42:12 2009        (r192025)
@@ -1,6 +1,6 @@
 .\" $FreeBSD$
 .\"
-.Dd January 22, 2009
+.Dd May 12, 2009
 .Dt TRUSS 1
 .Os
 .Sh NAME
@@ -8,12 +8,12 @@
 .Nd trace system calls
 .Sh SYNOPSIS
 .Nm
-.Op Fl faedDS
+.Op Fl facedDS
 .Op Fl o Ar file
 .Op Fl s Ar strsize
 .Fl p Ar pid
 .Nm
-.Op Fl faedDS
+.Op Fl facedDS
 .Op Fl o Ar file
 .Op Fl s Ar strsize
 .Ar command Op Ar args
@@ -36,6 +36,12 @@ etc.
 Show the argument strings that are passed in each
 .Xr execve 2
 system call.
+.It Fl c
+Do not display individual system calls.
+Instead, before exiting, print a summary containing for each system call:
+the total system time used,
+the number of times the call was invoked,
+and the number of times the call returned with an error.
 .It Fl e
 Show the environment strings that are passed in each
 .Xr execve 2

Modified: head/usr.bin/truss/truss.h
==============================================================================
--- head/usr.bin/truss/truss.h  Tue May 12 19:33:36 2009        (r192024)
+++ head/usr.bin/truss/truss.h  Tue May 12 20:42:12 2009        (r192025)
@@ -33,6 +33,7 @@
 #define NOSIGS             0x00000008
 #define EXECVEARGS         0x00000010
 #define EXECVEENVS         0x00000020
+#define COUNTONLY          0x00000040
 
 struct threadinfo
 {
@@ -70,6 +71,16 @@ struct trussinfo
                }                                                       \
        } while (0)
 
+#define timespecadd(tvp, uvp, vvp)                                     \
+       do {                                                            \
+               (vvp)->tv_sec = (tvp)->tv_sec + (uvp)->tv_sec;          \
+               (vvp)->tv_nsec = (tvp)->tv_nsec + (uvp)->tv_nsec;       \
+               if ((vvp)->tv_nsec > 1000000000) {                              
\
+                       (vvp)->tv_sec++;                                \
+                       (vvp)->tv_nsec -= 1000000000;                   \
+               }                                                       \
+       } while (0)
+
 #define S_NONE  0
 #define S_SCE   1
 #define S_SCX   2
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to