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 #include <mach/mach.h>
33 #include <mach/mach_time.h>
35 static void usage(void);
36 static void do_print(void);
37 static void do_difftime(bool usepercent
, uint64_t *olduser
, uint64_t *oldsystem
, uint64_t *oldidle
);
38 static void do_piddifftime(bool userpercent
, int pid
, uint64_t *old_pid_user
, uint64_t *old_pid_system
, uint64_t *old_pid_time
);
39 static kern_return_t
get_processor_time(uint64_t *user
, uint64_t *sys
, uint64_t *idle
);
40 static kern_return_t
get_processor_count(int *ncpu
);
41 static mach_timebase_info_data_t timebase_info
;
44 main(int argc
, char *argv
[])
47 const char *optu
= NULL
;
48 const char *opts
= NULL
;
49 const char *opti
= NULL
;
50 const char *tpid
= NULL
;
51 const char *opt_sleep_time
= NULL
;
54 bool systemwide_time
= false;
57 uint64_t olduser
, oldsystem
, oldidle
;
58 uint64_t old_pid_time
;
59 uint64_t old_pid_user
, old_pid_system
;
61 bool usepercent
= false;
62 bool recurring
= false;
64 while ((ch
= getopt(argc
, argv
, "PrT:t:pu:s:i:")) != -1) {
73 opt_sleep_time
= optarg
;
79 systemwide_time
= true;
96 mach_timebase_info(&timebase_info
);
100 sleep_time
= (int)strtoul(opt_sleep_time
, &endstr
, 0);
101 if (opt_sleep_time
[0] == '\0' || endstr
[0] != '\0')
105 if (systemwide_time
) {
106 bool first_pass
= true;
107 olduser
= oldsystem
= oldidle
= 0;
109 if (recurring
!= true) {
115 do_difftime(false, &olduser
, &oldsystem
, &oldidle
);
118 do_difftime(usepercent
, &olduser
, &oldsystem
, &oldidle
);
129 bool first_pass
= true;
131 target_pid
= (int)strtoul(tpid
, &endstr
, 0);
132 if (tpid
[0] == '\0' || endstr
[0] != '\0')
135 olduser
= oldsystem
= oldidle
= 0;
136 old_pid_user
= old_pid_system
= old_pid_time
= 0;
140 do_difftime(false, &olduser
, &oldsystem
, &oldidle
);
141 do_piddifftime(false, target_pid
, &old_pid_user
, &old_pid_system
, &old_pid_time
);
144 do_difftime(usepercent
, &olduser
, &oldsystem
, &oldidle
);
145 do_piddifftime(usepercent
, target_pid
, &old_pid_user
, &old_pid_system
, &old_pid_time
);
153 if (optu
|| opts
|| opti
) {
158 olduser
= strtoull(optu
, &endstr
, 0);
159 if (optu
[0] == '\0' || endstr
[0] != '\0')
164 oldsystem
= strtoull(opts
, &endstr
, 0);
165 if (opts
[0] == '\0' || endstr
[0] != '\0')
170 oldidle
= strtoull(opti
, &endstr
, 0);
171 if (opti
[0] == '\0' || endstr
[0] != '\0')
174 do_difftime(usepercent
, &olduser
, &oldsystem
, &oldidle
);
185 kret
= get_processor_time(&olduser
, &oldsystem
, &oldidle
);
187 errx(1, "Error getting processor time: %s (%d)", mach_error_string(kret
), kret
);
189 switch(pid
= vfork()) {
197 _exit((errno
== ENOENT
) ? 127 : 126);
202 (void)signal(SIGINT
, SIG_IGN
);
203 (void)signal(SIGQUIT
, SIG_IGN
);
204 while (wait(&status
) != pid
);
205 (void)signal(SIGINT
, SIG_DFL
);
206 (void)signal(SIGQUIT
, SIG_DFL
);
208 do_difftime(usepercent
, &olduser
, &oldsystem
, &oldidle
);
213 exit (WIFEXITED(status
) ? WEXITSTATUS(status
) : EXIT_FAILURE
);
221 fprintf(stderr
, "usage: systime [-P] [-r] [-t sleep_time] utility [argument ...]\n"
222 " systime -p [-r] [-t sleep_time]\n"
223 " systime [-P] -u user -s sys -i idle\n"
224 " systime [-P] [-r] [-t sleep_time] -T target_pid\n");
231 uint64_t user
, system
, idle
;
234 kret
= get_processor_time(&user
, &system
, &idle
);
236 errx(1, "Error getting processor time: %s (%d)", mach_error_string(kret
), kret
);
238 printf("systime_user=%llu\n", user
);
239 printf("systime_sys=%llu\n", system
);
240 printf("systime_idle=%llu\n", idle
);
244 do_difftime(bool usepercent
, uint64_t *olduser
, uint64_t *oldsystem
, uint64_t *oldidle
)
246 uint64_t user
, system
, idle
;
247 uint64_t userelapsed
, systemelapsed
, idleelapsed
, totalelapsed
;
250 kret
= get_processor_time(&user
, &system
, &idle
);
252 errx(1, "Error getting processor time: %s (%d)", mach_error_string(kret
), kret
);
254 userelapsed
= user
- *olduser
;
255 systemelapsed
= system
- *oldsystem
;
256 idleelapsed
= idle
- *oldidle
;
257 totalelapsed
= userelapsed
+ systemelapsed
+ idleelapsed
;
260 fprintf(stderr
, "%1.02f%% user %1.02f%% sys %1.02f%% idle\n",
261 ((double)userelapsed
* 100)/totalelapsed
,
262 ((double)systemelapsed
* 100)/totalelapsed
,
263 ((double)idleelapsed
* 100)/totalelapsed
);
267 kret
= get_processor_count(&ncpu
);
269 errx(1, "Error getting processor count: %s (%d)", mach_error_string(kret
), kret
);
271 fprintf(stderr
, "%1.02f real %1.02f user %1.02f sys\n",
272 ((double)totalelapsed
) / 1000 /* ms per sec */ / ncpu
,
273 ((double)userelapsed
) / 1000,
274 ((double)systemelapsed
) / 1000);
282 do_piddifftime(bool usepercent
, int pid
, uint64_t *old_pid_user
, uint64_t *old_pid_system
, uint64_t *old_pid_time
)
284 uint64_t pid_user
, pid_system
, pid_time
;
285 uint64_t userelapsed
, systemelapsed
, totalelapsed
;
286 struct proc_taskinfo info
;
289 size
= proc_pidinfo(pid
, PROC_PIDTASKINFO
, 0, &info
, sizeof(info
));
290 if (size
== PROC_PIDTASKINFO_SIZE
) {
291 pid_user
= info
.pti_total_user
;
292 pid_system
= info
.pti_total_system
;
294 fprintf(stderr
, "Error in proc_pidinfo(): %s",
299 pid_time
= mach_absolute_time();
301 userelapsed
= pid_user
- *old_pid_user
;
302 systemelapsed
= pid_system
- *old_pid_system
;
303 totalelapsed
= pid_time
- *old_pid_time
;
306 fprintf(stderr
, "Pid %d: %1.02f%% user %1.02f%% sys\n",
308 ((double)userelapsed
* 100)/totalelapsed
,
309 ((double)systemelapsed
* 100)/totalelapsed
);
311 fprintf(stderr
, "Pid %d: %1.02f user %1.02f sys\n",
313 (((double)userelapsed
) * timebase_info
.numer
/ timebase_info
.denom
) / 1000000000,
314 (((double)systemelapsed
) * timebase_info
.numer
/ timebase_info
.denom
) / 1000000000);
317 *old_pid_user
= pid_user
;
318 *old_pid_system
= pid_system
;
319 *old_pid_time
= pid_time
;
324 get_processor_time(uint64_t *user
, uint64_t *sys
, uint64_t *idle
)
326 host_name_port_t host
;
328 host_cpu_load_info_data_t host_load
;
329 mach_msg_type_number_t count
;
331 host
= mach_host_self();
333 count
= HOST_CPU_LOAD_INFO_COUNT
;
335 kret
= host_statistics(host
, HOST_CPU_LOAD_INFO
, (host_info_t
)&host_load
, &count
);
339 *user
= ((uint64_t)host_load
.cpu_ticks
[CPU_STATE_USER
]) * 10 /* ms per tick */;
340 *sys
= ((uint64_t)host_load
.cpu_ticks
[CPU_STATE_SYSTEM
]) * 10;
341 *idle
= ((uint64_t)host_load
.cpu_ticks
[CPU_STATE_IDLE
]) * 10;
347 get_processor_count(int *ncpu
)
349 host_name_port_t host
;
351 host_basic_info_data_t hi
;
352 mach_msg_type_number_t count
;
354 host
= mach_host_self();
356 count
= HOST_BASIC_INFO_COUNT
;
358 kret
= host_info(host
, HOST_BASIC_INFO
, (host_info_t
)&hi
, &count
);
362 *ncpu
= hi
.avail_cpus
;