#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[])
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;
}
}
+ 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;
if (opti[0] == '\0' || endstr[0] != '\0')
usage();
- do_difftime(usepercent, olduser, oldsystem, oldidle);
+ do_difftime(usepercent, &olduser, &oldsystem, &oldidle);
exit(0);
}
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);
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);
}
}
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;
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) {
((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