2 * Copyright (c) 2012 Apple Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
21 * @APPLE_LICENSE_HEADER_END@
24 typedef char *kobject_description_t
[512];
25 #include <mach/mach.h>
34 #include <mach/mach_time.h>
36 #include <libiosexec.h>
38 static void usage(void);
39 static void do_print(void);
40 static void do_difftime(bool usepercent
, uint64_t *olduser
, uint64_t *oldsystem
, uint64_t *oldidle
);
41 static void do_piddifftime(bool userpercent
, int pid
, uint64_t *old_pid_user
, uint64_t *old_pid_system
, uint64_t *old_pid_time
);
42 static kern_return_t
get_processor_time(uint64_t *user
, uint64_t *sys
, uint64_t *idle
);
43 static kern_return_t
get_processor_count(int *ncpu
);
44 static mach_timebase_info_data_t timebase_info
;
47 main(int argc
, char *argv
[])
50 const char *optu
= NULL
;
51 const char *opts
= NULL
;
52 const char *opti
= NULL
;
53 const char *tpid
= NULL
;
54 const char *opt_sleep_time
= NULL
;
57 bool systemwide_time
= false;
60 uint64_t olduser
, oldsystem
, oldidle
;
61 uint64_t old_pid_time
;
62 uint64_t old_pid_user
, old_pid_system
;
64 bool usepercent
= false;
65 bool recurring
= false;
67 while ((ch
= getopt(argc
, argv
, "PrT:t:pu:s:i:")) != -1) {
76 opt_sleep_time
= optarg
;
82 systemwide_time
= true;
99 mach_timebase_info(&timebase_info
);
101 if (opt_sleep_time
) {
103 sleep_time
= (int)strtoul(opt_sleep_time
, &endstr
, 0);
104 if (opt_sleep_time
[0] == '\0' || endstr
[0] != '\0')
108 if (systemwide_time
) {
109 bool first_pass
= true;
110 olduser
= oldsystem
= oldidle
= 0;
112 if (recurring
!= true) {
118 do_difftime(false, &olduser
, &oldsystem
, &oldidle
);
121 do_difftime(usepercent
, &olduser
, &oldsystem
, &oldidle
);
132 bool first_pass
= true;
134 target_pid
= (int)strtoul(tpid
, &endstr
, 0);
135 if (tpid
[0] == '\0' || endstr
[0] != '\0')
138 olduser
= oldsystem
= oldidle
= 0;
139 old_pid_user
= old_pid_system
= old_pid_time
= 0;
143 do_difftime(false, &olduser
, &oldsystem
, &oldidle
);
144 do_piddifftime(false, target_pid
, &old_pid_user
, &old_pid_system
, &old_pid_time
);
147 do_difftime(usepercent
, &olduser
, &oldsystem
, &oldidle
);
148 do_piddifftime(usepercent
, target_pid
, &old_pid_user
, &old_pid_system
, &old_pid_time
);
156 if (optu
|| opts
|| opti
) {
161 olduser
= strtoull(optu
, &endstr
, 0);
162 if (optu
[0] == '\0' || endstr
[0] != '\0')
167 oldsystem
= strtoull(opts
, &endstr
, 0);
168 if (opts
[0] == '\0' || endstr
[0] != '\0')
173 oldidle
= strtoull(opti
, &endstr
, 0);
174 if (opti
[0] == '\0' || endstr
[0] != '\0')
177 do_difftime(usepercent
, &olduser
, &oldsystem
, &oldidle
);
188 kret
= get_processor_time(&olduser
, &oldsystem
, &oldidle
);
190 errx(1, "Error getting processor time: %s (%d)", mach_error_string(kret
), kret
);
192 switch(pid
= vfork()) {
200 _exit((errno
== ENOENT
) ? 127 : 126);
205 (void)signal(SIGINT
, SIG_IGN
);
206 (void)signal(SIGQUIT
, SIG_IGN
);
207 while (wait(&status
) != pid
);
208 (void)signal(SIGINT
, SIG_DFL
);
209 (void)signal(SIGQUIT
, SIG_DFL
);
211 do_difftime(usepercent
, &olduser
, &oldsystem
, &oldidle
);
216 exit (WIFEXITED(status
) ? WEXITSTATUS(status
) : EXIT_FAILURE
);
224 fprintf(stderr
, "usage: systime [-P] [-r] [-t sleep_time] utility [argument ...]\n"
225 " systime -p [-r] [-t sleep_time]\n"
226 " systime [-P] -u user -s sys -i idle\n"
227 " systime [-P] [-r] [-t sleep_time] -T target_pid\n");
234 uint64_t user
, system
, idle
;
237 kret
= get_processor_time(&user
, &system
, &idle
);
239 errx(1, "Error getting processor time: %s (%d)", mach_error_string(kret
), kret
);
241 printf("systime_user=%llu\n", user
);
242 printf("systime_sys=%llu\n", system
);
243 printf("systime_idle=%llu\n", idle
);
247 do_difftime(bool usepercent
, uint64_t *olduser
, uint64_t *oldsystem
, uint64_t *oldidle
)
249 uint64_t user
, system
, idle
;
250 uint64_t userelapsed
, systemelapsed
, idleelapsed
, totalelapsed
;
253 kret
= get_processor_time(&user
, &system
, &idle
);
255 errx(1, "Error getting processor time: %s (%d)", mach_error_string(kret
), kret
);
257 userelapsed
= user
- *olduser
;
258 systemelapsed
= system
- *oldsystem
;
259 idleelapsed
= idle
- *oldidle
;
260 totalelapsed
= userelapsed
+ systemelapsed
+ idleelapsed
;
263 fprintf(stderr
, "%1.02f%% user %1.02f%% sys %1.02f%% idle\n",
264 ((double)userelapsed
* 100)/totalelapsed
,
265 ((double)systemelapsed
* 100)/totalelapsed
,
266 ((double)idleelapsed
* 100)/totalelapsed
);
270 kret
= get_processor_count(&ncpu
);
272 errx(1, "Error getting processor count: %s (%d)", mach_error_string(kret
), kret
);
274 fprintf(stderr
, "%1.02f real %1.02f user %1.02f sys\n",
275 ((double)totalelapsed
) / 1000 /* ms per sec */ / ncpu
,
276 ((double)userelapsed
) / 1000,
277 ((double)systemelapsed
) / 1000);
285 do_piddifftime(bool usepercent
, int pid
, uint64_t *old_pid_user
, uint64_t *old_pid_system
, uint64_t *old_pid_time
)
287 uint64_t pid_user
, pid_system
, pid_time
;
288 uint64_t userelapsed
, systemelapsed
, totalelapsed
;
289 struct proc_taskinfo info
;
292 size
= proc_pidinfo(pid
, PROC_PIDTASKINFO
, 0, &info
, sizeof(info
));
293 if (size
== PROC_PIDTASKINFO_SIZE
) {
294 pid_user
= info
.pti_total_user
;
295 pid_system
= info
.pti_total_system
;
297 fprintf(stderr
, "Error in proc_pidinfo(): %s",
302 pid_time
= mach_absolute_time();
304 userelapsed
= pid_user
- *old_pid_user
;
305 systemelapsed
= pid_system
- *old_pid_system
;
306 totalelapsed
= pid_time
- *old_pid_time
;
309 fprintf(stderr
, "Pid %d: %1.02f%% user %1.02f%% sys\n",
311 ((double)userelapsed
* 100)/totalelapsed
,
312 ((double)systemelapsed
* 100)/totalelapsed
);
314 fprintf(stderr
, "Pid %d: %1.02f user %1.02f sys\n",
316 (((double)userelapsed
) * timebase_info
.numer
/ timebase_info
.denom
) / 1000000000,
317 (((double)systemelapsed
) * timebase_info
.numer
/ timebase_info
.denom
) / 1000000000);
320 *old_pid_user
= pid_user
;
321 *old_pid_system
= pid_system
;
322 *old_pid_time
= pid_time
;
327 get_processor_time(uint64_t *user
, uint64_t *sys
, uint64_t *idle
)
329 host_name_port_t host
;
331 host_cpu_load_info_data_t host_load
;
332 mach_msg_type_number_t count
;
334 host
= mach_host_self();
336 count
= HOST_CPU_LOAD_INFO_COUNT
;
338 kret
= host_statistics(host
, HOST_CPU_LOAD_INFO
, (host_info_t
)&host_load
, &count
);
342 *user
= ((uint64_t)host_load
.cpu_ticks
[CPU_STATE_USER
]) * 10 /* ms per tick */;
343 *sys
= ((uint64_t)host_load
.cpu_ticks
[CPU_STATE_SYSTEM
]) * 10;
344 *idle
= ((uint64_t)host_load
.cpu_ticks
[CPU_STATE_IDLE
]) * 10;
350 get_processor_count(int *ncpu
)
352 host_name_port_t host
;
354 host_basic_info_data_t hi
;
355 mach_msg_type_number_t count
;
357 host
= mach_host_self();
359 count
= HOST_BASIC_INFO_COUNT
;
361 kret
= host_info(host
, HOST_BASIC_INFO
, (host_info_t
)&hi
, &count
);
365 *ncpu
= hi
.avail_cpus
;