]> git.saurik.com Git - apple/shell_cmds.git/blobdiff - systime/systime.c
shell_cmds-187.tar.gz
[apple/shell_cmds.git] / systime / systime.c
index 746a8bd79be9dbf1c071e8c69e292d08f71fcc53..37cee8be8ccd944d17c26b8277a874496ca82e08 100644 (file)
 #include <stdio.h>
 #include <stdlib.h>
 #include <unistd.h>
+#include <libproc.h>
+#include <mach/mach_time.h>
 
 static void usage(void);
 static void do_print(void);
-static void do_difftime(bool usepercent, uint64_t olduser, uint64_t oldsystem, uint64_t oldidle);
+static void do_difftime(bool usepercent, uint64_t *olduser, uint64_t *oldsystem, uint64_t *oldidle);
+static void do_piddifftime(bool userpercent, int pid, uint64_t *old_pid_user, uint64_t *old_pid_system, uint64_t *old_pid_time);
 static kern_return_t get_processor_time(uint64_t *user, uint64_t *sys, uint64_t *idle);
 static kern_return_t get_processor_count(int *ncpu);
+static mach_timebase_info_data_t timebase_info;
 
 int
 main(int argc, char *argv[])
@@ -43,20 +47,36 @@ main(int argc, char *argv[])
        const char *optu = NULL;
        const char *opts = NULL;
        const char *opti = NULL;
+       const char *tpid = NULL;
+       const char *opt_sleep_time = NULL;
+       int sleep_time = 1;
+       int target_pid;
+       bool systemwide_time = false;
        int pid;
        int status;
        uint64_t olduser, oldsystem, oldidle;
+       uint64_t old_pid_time;
+       uint64_t old_pid_user, old_pid_system;
        kern_return_t kret;
        bool usepercent = false;
+       bool recurring = false;
 
-       while ((ch = getopt(argc, argv, "Ppu:s:i:")) != -1) {
+       while ((ch = getopt(argc, argv, "PrT:t:pu:s:i:")) != -1) {
                switch (ch) {
                case 'P':
                        usepercent = true;
                        break;
+               case 'r':
+                       recurring = true;
+                       break;
+               case 't':
+                       opt_sleep_time = optarg;
+                       break;
+               case 'T':
+                       tpid = optarg;
+                       break;
                case 'p':
-                       do_print();
-                       exit(0);
+                       systemwide_time = true;
                        break;
                case 'u':
                        optu = optarg;
@@ -73,6 +93,63 @@ main(int argc, char *argv[])
                }
        }
 
+       mach_timebase_info(&timebase_info);
+
+       if (opt_sleep_time) {
+               char *endstr;
+               sleep_time = (int)strtoul(opt_sleep_time, &endstr, 0);
+               if (opt_sleep_time[0] == '\0' || endstr[0] != '\0')
+                       usage();
+       }
+       
+       if (systemwide_time) {
+               bool first_pass = true;
+               olduser = oldsystem = oldidle = 0;
+
+               if (recurring != true) {
+                       do_print();
+                       exit(0);
+               }
+               do {
+                       if (first_pass) {
+                               do_difftime(false, &olduser, &oldsystem, &oldidle);
+                               first_pass = false;
+                       } else {
+                               do_difftime(usepercent, &olduser, &oldsystem, &oldidle);
+                       }
+                       sleep(sleep_time);
+               } while (recurring);
+
+               exit(0);
+       }
+
+
+       if (tpid) {
+               char *endstr;
+               bool first_pass = true;
+
+               target_pid = (int)strtoul(tpid, &endstr, 0);
+               if (tpid[0] == '\0' || endstr[0] != '\0')
+                       usage();
+
+               olduser = oldsystem = oldidle = 0;
+               old_pid_user = old_pid_system = old_pid_time = 0;
+               
+               do {    
+                       if (first_pass) {
+                               do_difftime(false, &olduser, &oldsystem, &oldidle);
+                               do_piddifftime(false, target_pid, &old_pid_user, &old_pid_system, &old_pid_time);
+                               first_pass = false;
+                       } else {
+                               do_difftime(usepercent, &olduser, &oldsystem, &oldidle);
+                               do_piddifftime(usepercent, target_pid, &old_pid_user, &old_pid_system, &old_pid_time);
+                       }
+
+                       sleep(sleep_time);
+               } while (recurring);
+               exit(0);
+       }
+
        if (optu || opts || opti) {
                char *endstr;
 
@@ -94,7 +171,7 @@ main(int argc, char *argv[])
                if (opti[0] == '\0' || endstr[0] != '\0')
                        usage();
 
-               do_difftime(usepercent, olduser, oldsystem, oldidle);
+               do_difftime(usepercent, &olduser, &oldsystem, &oldidle);
                exit(0);
        }
 
@@ -104,28 +181,34 @@ main(int argc, char *argv[])
        if (argc == 0)
                usage();
 
-       kret = get_processor_time(&olduser, &oldsystem, &oldidle);
-       if (kret)
-               errx(1, "Error getting processor time: %s (%d)", mach_error_string(kret), kret);
+       do {
+               kret = get_processor_time(&olduser, &oldsystem, &oldidle);
+               if (kret)
+                       errx(1, "Error getting processor time: %s (%d)", mach_error_string(kret), kret);
+
+               switch(pid = vfork()) {
+                       case -1:                        /* error */
+                               perror("time");
+                               exit(1);
+                               /* NOTREACHED */
+                       case 0:                         /* child */
+                               execvp(*argv, argv);
+                               perror(*argv);
+                               _exit((errno == ENOENT) ? 127 : 126);
+                               /* NOTREACHED */
+               }
 
-       switch(pid = vfork()) {
-               case -1:                        /* error */
-                       perror("time");
-                       exit(1);
-                       /* NOTREACHED */
-               case 0:                         /* child */
-                       execvp(*argv, argv);
-                       perror(*argv);
-                       _exit((errno == ENOENT) ? 127 : 126);
-                       /* NOTREACHED */
-       }
+               /* parent */
+               (void)signal(SIGINT, SIG_IGN);
+               (void)signal(SIGQUIT, SIG_IGN);
+               while (wait(&status) != pid);
+               (void)signal(SIGINT, SIG_DFL);
+               (void)signal(SIGQUIT, SIG_DFL);
 
-       /* parent */
-       (void)signal(SIGINT, SIG_IGN);
-       (void)signal(SIGQUIT, SIG_IGN);
-       while (wait(&status) != pid);
+               do_difftime(usepercent, &olduser, &oldsystem, &oldidle);
 
-       do_difftime(usepercent, olduser, oldsystem, oldidle);
+               sleep(sleep_time);
+       } while (recurring);
 
        exit (WIFEXITED(status) ? WEXITSTATUS(status) : EXIT_FAILURE);
 
@@ -135,9 +218,10 @@ main(int argc, char *argv[])
 static void
 usage(void)
 {
-       fprintf(stderr, "usage: systime [-P] utility [argument ...]\n"
-                       "       systime -p\n"
-                       "       systime [-P] -u user -s sys -i idle\n");
+       fprintf(stderr, "usage: systime [-P] [-r] [-t sleep_time] utility [argument ...]\n"
+                       "       systime -p [-r] [-t sleep_time]\n"
+                       "       systime [-P] -u user -s sys -i idle\n"
+                       "       systime [-P] [-r] [-t sleep_time] -T target_pid\n");
        exit(1);
 }
 
@@ -157,7 +241,7 @@ do_print(void)
 }
 
 static void
-do_difftime(bool usepercent, uint64_t olduser, uint64_t oldsystem, uint64_t oldidle)
+do_difftime(bool usepercent, uint64_t *olduser, uint64_t *oldsystem, uint64_t *oldidle)
 {
        uint64_t user, system, idle;
        uint64_t userelapsed, systemelapsed, idleelapsed, totalelapsed;
@@ -167,9 +251,9 @@ do_difftime(bool usepercent, uint64_t olduser, uint64_t oldsystem, uint64_t oldi
        if (kret)
                errx(1, "Error getting processor time: %s (%d)", mach_error_string(kret), kret);
 
-       userelapsed = user - olduser;
-       systemelapsed = system - oldsystem;
-       idleelapsed = idle - oldidle;
+       userelapsed = user - *olduser;
+       systemelapsed = system - *oldsystem;
+       idleelapsed = idle - *oldidle;
        totalelapsed = userelapsed + systemelapsed + idleelapsed;
 
        if (usepercent) {
@@ -189,6 +273,51 @@ do_difftime(bool usepercent, uint64_t olduser, uint64_t oldsystem, uint64_t oldi
                                ((double)userelapsed) / 1000,
                                ((double)systemelapsed) / 1000);
        }
+       *olduser = user;
+       *oldsystem = system;
+       *oldidle = idle;
+}
+
+static void
+do_piddifftime(bool usepercent, int pid, uint64_t *old_pid_user, uint64_t *old_pid_system, uint64_t *old_pid_time)
+{
+       uint64_t pid_user, pid_system, pid_time;
+       uint64_t userelapsed, systemelapsed, totalelapsed;
+       struct proc_taskinfo info;
+       int size;
+
+       size = proc_pidinfo(pid, PROC_PIDTASKINFO, 0, &info, sizeof(info));
+       if (size == PROC_PIDTASKINFO_SIZE) {
+               pid_user = info.pti_total_user;
+               pid_system = info.pti_total_system;
+       } else {
+               fprintf(stderr, "Error in proc_pidinfo(): %s",
+                               strerror(errno));
+               exit(1);
+       }
+
+       pid_time = mach_absolute_time();
+
+       userelapsed = pid_user - *old_pid_user;
+       systemelapsed = pid_system - *old_pid_system;
+       totalelapsed = pid_time - *old_pid_time;
+
+       if (usepercent) {
+               fprintf(stderr, "Pid %d: %1.02f%% user %1.02f%% sys\n",
+                          pid,
+                          ((double)userelapsed * 100)/totalelapsed,
+                          ((double)systemelapsed * 100)/totalelapsed);
+       } else {
+               fprintf(stderr, "Pid %d: %1.02f user %1.02f sys\n",
+                               pid,
+                               (((double)userelapsed) * timebase_info.numer / timebase_info.denom) / 1000000000,
+                               (((double)systemelapsed) * timebase_info.numer / timebase_info.denom) / 1000000000);
+       }
+
+       *old_pid_user = pid_user;
+       *old_pid_system = pid_system;
+       *old_pid_time = pid_time;
+
 }
 
 static kern_return_t