]> git.saurik.com Git - apple/shell_cmds.git/blob - systime/systime.c
746a8bd79be9dbf1c071e8c69e292d08f71fcc53
[apple/shell_cmds.git] / systime / systime.c
1 /*
2 * Copyright (c) 2012 Apple Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
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
11 * file.
12 *
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.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23
24 #include <mach/mach.h>
25 #include <err.h>
26 #include <errno.h>
27 #include <stdbool.h>
28 #include <stdint.h>
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <unistd.h>
32
33 static void usage(void);
34 static void do_print(void);
35 static void do_difftime(bool usepercent, uint64_t olduser, uint64_t oldsystem, uint64_t oldidle);
36 static kern_return_t get_processor_time(uint64_t *user, uint64_t *sys, uint64_t *idle);
37 static kern_return_t get_processor_count(int *ncpu);
38
39 int
40 main(int argc, char *argv[])
41 {
42 int ch;
43 const char *optu = NULL;
44 const char *opts = NULL;
45 const char *opti = NULL;
46 int pid;
47 int status;
48 uint64_t olduser, oldsystem, oldidle;
49 kern_return_t kret;
50 bool usepercent = false;
51
52 while ((ch = getopt(argc, argv, "Ppu:s:i:")) != -1) {
53 switch (ch) {
54 case 'P':
55 usepercent = true;
56 break;
57 case 'p':
58 do_print();
59 exit(0);
60 break;
61 case 'u':
62 optu = optarg;
63 break;
64 case 's':
65 opts = optarg;
66 break;
67 case 'i':
68 opti = optarg;
69 break;
70 case '?':
71 default:
72 usage();
73 }
74 }
75
76 if (optu || opts || opti) {
77 char *endstr;
78
79 if (!optu)
80 usage();
81 olduser = strtoull(optu, &endstr, 0);
82 if (optu[0] == '\0' || endstr[0] != '\0')
83 usage();
84
85 if (!opts)
86 usage();
87 oldsystem = strtoull(opts, &endstr, 0);
88 if (opts[0] == '\0' || endstr[0] != '\0')
89 usage();
90
91 if (!opti)
92 usage();
93 oldidle = strtoull(opti, &endstr, 0);
94 if (opti[0] == '\0' || endstr[0] != '\0')
95 usage();
96
97 do_difftime(usepercent, olduser, oldsystem, oldidle);
98 exit(0);
99 }
100
101 argc -= optind;
102 argv += optind;
103
104 if (argc == 0)
105 usage();
106
107 kret = get_processor_time(&olduser, &oldsystem, &oldidle);
108 if (kret)
109 errx(1, "Error getting processor time: %s (%d)", mach_error_string(kret), kret);
110
111 switch(pid = vfork()) {
112 case -1: /* error */
113 perror("time");
114 exit(1);
115 /* NOTREACHED */
116 case 0: /* child */
117 execvp(*argv, argv);
118 perror(*argv);
119 _exit((errno == ENOENT) ? 127 : 126);
120 /* NOTREACHED */
121 }
122
123 /* parent */
124 (void)signal(SIGINT, SIG_IGN);
125 (void)signal(SIGQUIT, SIG_IGN);
126 while (wait(&status) != pid);
127
128 do_difftime(usepercent, olduser, oldsystem, oldidle);
129
130 exit (WIFEXITED(status) ? WEXITSTATUS(status) : EXIT_FAILURE);
131
132 return 0;
133 }
134
135 static void
136 usage(void)
137 {
138 fprintf(stderr, "usage: systime [-P] utility [argument ...]\n"
139 " systime -p\n"
140 " systime [-P] -u user -s sys -i idle\n");
141 exit(1);
142 }
143
144 static void
145 do_print(void)
146 {
147 uint64_t user, system, idle;
148 kern_return_t kret;
149
150 kret = get_processor_time(&user, &system, &idle);
151 if (kret)
152 errx(1, "Error getting processor time: %s (%d)", mach_error_string(kret), kret);
153
154 printf("systime_user=%llu\n", user);
155 printf("systime_sys=%llu\n", system);
156 printf("systime_idle=%llu\n", idle);
157 }
158
159 static void
160 do_difftime(bool usepercent, uint64_t olduser, uint64_t oldsystem, uint64_t oldidle)
161 {
162 uint64_t user, system, idle;
163 uint64_t userelapsed, systemelapsed, idleelapsed, totalelapsed;
164 kern_return_t kret;
165
166 kret = get_processor_time(&user, &system, &idle);
167 if (kret)
168 errx(1, "Error getting processor time: %s (%d)", mach_error_string(kret), kret);
169
170 userelapsed = user - olduser;
171 systemelapsed = system - oldsystem;
172 idleelapsed = idle - oldidle;
173 totalelapsed = userelapsed + systemelapsed + idleelapsed;
174
175 if (usepercent) {
176 fprintf(stderr, "%1.02f%% user %1.02f%% sys %1.02f%% idle\n",
177 ((double)userelapsed * 100)/totalelapsed,
178 ((double)systemelapsed * 100)/totalelapsed,
179 ((double)idleelapsed * 100)/totalelapsed);
180 } else {
181 int ncpu;
182
183 kret = get_processor_count(&ncpu);
184 if (kret)
185 errx(1, "Error getting processor count: %s (%d)", mach_error_string(kret), kret);
186
187 fprintf(stderr, "%1.02f real %1.02f user %1.02f sys\n",
188 ((double)totalelapsed) / 1000 /* ms per sec */ / ncpu,
189 ((double)userelapsed) / 1000,
190 ((double)systemelapsed) / 1000);
191 }
192 }
193
194 static kern_return_t
195 get_processor_time(uint64_t *user, uint64_t *sys, uint64_t *idle)
196 {
197 host_name_port_t host;
198 kern_return_t kret;
199 host_cpu_load_info_data_t host_load;
200 mach_msg_type_number_t count;
201
202 host = mach_host_self();
203
204 count = HOST_CPU_LOAD_INFO_COUNT;
205
206 kret = host_statistics(host, HOST_CPU_LOAD_INFO, (host_info_t)&host_load, &count);
207 if (kret)
208 return kret;
209
210 *user = ((uint64_t)host_load.cpu_ticks[CPU_STATE_USER]) * 10 /* ms per tick */;
211 *sys = ((uint64_t)host_load.cpu_ticks[CPU_STATE_SYSTEM]) * 10;
212 *idle = ((uint64_t)host_load.cpu_ticks[CPU_STATE_IDLE]) * 10;
213
214 return KERN_SUCCESS;
215 }
216
217 static kern_return_t
218 get_processor_count(int *ncpu)
219 {
220 host_name_port_t host;
221 kern_return_t kret;
222 host_basic_info_data_t hi;
223 mach_msg_type_number_t count;
224
225 host = mach_host_self();
226
227 count = HOST_BASIC_INFO_COUNT;
228
229 kret = host_info(host, HOST_BASIC_INFO, (host_info_t)&hi, &count);
230 if (kret)
231 return kret;
232
233 *ncpu = hi.avail_cpus;
234
235 return KERN_SUCCESS;
236 }