Print this page
| Split |
Close |
| Expand all |
| Collapse all |
--- old/usr/src/cmd/ptools/ptime/ptime.c
+++ new/usr/src/cmd/ptools/ptime/ptime.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21 /*
22 22 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
23 23 * Use is subject to license terms.
24 24 *
25 25 * Portions Copyright 2008 Chad Mynhier
26 26 */
27 27 /*
28 28 * Copyright 2016 Joyent, Inc.
29 29 */
30 30
31 31 #include <stdio.h>
32 32 #include <stdlib.h>
33 33 #include <unistd.h>
34 34 #include <fcntl.h>
35 35 #include <string.h>
36 36 #include <errno.h>
37 37 #include <math.h>
38 38 #include <wait.h>
39 39 #include <signal.h>
40 40 #include <sys/types.h>
41 41 #include <sys/time.h>
42 42 #include <signal.h>
43 43 #include <libproc.h>
44 44 #include <limits.h>
45 45 #include "ptools_common.h"
46 46
47 47 static int look(pid_t);
48 48 static void hr_min_sec(char *, long);
49 49 static void prtime(char *, timestruc_t *);
50 50 static int perr(const char *);
51 51
52 52 static void tsadd(timestruc_t *result, timestruc_t *a, timestruc_t *b);
53 53 static void tssub(timestruc_t *result, timestruc_t *a, timestruc_t *b);
54 54 static void hrt2ts(hrtime_t hrt, timestruc_t *tsp);
55 55
56 56 static char *command;
57 57 static char *pidarg;
58 58 static char procname[64];
59 59
60 60 static int Fflag;
61 61 static int mflag;
62 62 static int errflg;
63 63 static int pflag;
64 64 static int pfirst;
65 65
66 66 static int
67 67 ptime_pid(const char *pidstr)
68 68 {
69 69 struct ps_prochandle *Pr;
70 70 pid_t pid;
71 71 int gret;
72 72
73 73 if ((Pr = proc_arg_grab(pidstr, PR_ARG_PIDS,
74 74 Fflag | PGRAB_RDONLY, &gret)) == NULL) {
75 75 (void) fprintf(stderr, "%s: cannot examine %s: %s\n",
76 76 command, pidstr, Pgrab_error(gret));
77 77 return (1);
78 78 }
79 79
80 80 pid = Pstatus(Pr)->pr_pid;
81 81 (void) sprintf(procname, "%d", (int)pid); /* for perr() */
82 82 (void) look(pid);
83 83 Prelease(Pr, 0);
84 84 return (0);
85 85 }
86 86
87 87 int
88 88 main(int argc, char **argv)
89 89 {
90 90 int opt, exit;
91 91 pid_t pid;
92 92 struct siginfo info;
93 93 int status;
94 94 int gret;
95 95 struct ps_prochandle *Pr;
96 96
97 97 if ((command = strrchr(argv[0], '/')) != NULL)
98 98 command++;
99 99 else
100 100 command = argv[0];
101 101
102 102 while ((opt = getopt(argc, argv, "Fhmp:")) != EOF) {
103 103 switch (opt) {
104 104 case 'F': /* force grabbing (no O_EXCL) */
105 105 Fflag = PGRAB_FORCE;
106 106 break;
107 107 case 'm': /* microstate accounting */
108 108 mflag = 1;
109 109 break;
110 110 case 'p':
111 111 pflag = 1;
112 112 pidarg = optarg;
113 113 break;
114 114 default:
115 115 errflg = 1;
116 116 break;
117 117 }
118 118 }
119 119
120 120 argc -= optind;
121 121 argv += optind;
122 122
123 123 if (((pidarg != NULL) ^ (argc < 1)) || errflg) {
124 124 (void) fprintf(stderr,
125 125 "usage:\t%s [-mh] [-p pidlist | command [ args ... ]]\n",
126 126 command);
127 127 (void) fprintf(stderr,
128 128 " (time a command using microstate accounting)\n");
129 129 return (1);
130 130 }
131 131
132 132 if (pflag) {
133 133 char *pp;
134 134
135 135 exit = 0;
136 136 (void) signal(SIGINT, SIG_IGN);
137 137 (void) signal(SIGQUIT, SIG_IGN);
138 138
139 139 pp = strtok(pidarg, ", ");
140 140 if (pp == NULL) {
141 141 (void) fprintf(stderr, "%s: invalid argument for -p\n",
142 142 command);
143 143 return (1);
144 144 }
145 145 exit = ptime_pid(pp);
146 146 while ((pp = strtok(NULL, ", ")) != NULL) {
147 147 exit |= ptime_pid(pp);
148 148 }
149 149 return (exit);
150 150 }
151 151
152 152
153 153 if ((Pr = Pcreate(argv[0], &argv[0], &gret, NULL, 0)) == NULL) {
154 154 (void) fprintf(stderr, "%s: failed to exec %s: %s\n",
155 155 command, argv[0], Pcreate_error(gret));
156 156 return (1);
157 157 }
158 158 if (Psetrun(Pr, 0, 0) == -1) {
159 159 (void) fprintf(stderr, "%s: failed to set running %s: "
160 160 "%s\n", command, argv[0], strerror(errno));
161 161 return (1);
162 162 }
163 163
164 164 pid = Pstatus(Pr)->pr_pid;
165 165
166 166 (void) sprintf(procname, "%d", (int)pid); /* for perr() */
167 167 (void) signal(SIGINT, SIG_IGN);
168 168 (void) signal(SIGQUIT, SIG_IGN);
169 169
170 170 (void) waitid(P_PID, pid, &info, WEXITED | WNOWAIT);
171 171
172 172 (void) look(pid);
173 173
174 174 (void) waitpid(pid, &status, 0);
175 175
176 176 if (WIFEXITED(status))
177 177 return (WEXITSTATUS(status));
178 178
179 179 if (WIFSIGNALED(status)) {
180 180 int sig = WTERMSIG(status);
181 181 char name[SIG2STR_MAX];
182 182
183 183 (void) fprintf(stderr, "%s: command terminated "
184 184 "abnormally by %s\n", command,
185 185 proc_signame(sig, name, sizeof (name)));
186 186 }
187 187
188 188 return (status | WCOREFLG); /* see time(1) */
189 189 }
190 190
191 191 static int
192 192 look(pid_t pid)
193 193 {
194 194 char pathname[PATH_MAX];
195 195 int rval = 0;
196 196 int fd;
197 197 psinfo_t psinfo;
198 198 prusage_t prusage;
199 199 timestruc_t real, user, sys;
200 200 hrtime_t hrtime;
201 201 prusage_t *pup = &prusage;
202 202
203 203 pfirst++;
204 204
205 205 if (proc_get_psinfo(pid, &psinfo) < 0)
206 206 return (perr("read psinfo"));
207 207
208 208 (void) proc_snprintf(pathname, sizeof (pathname), "/proc/%d/usage",
209 209 (int)pid);
210 210 if ((fd = open(pathname, O_RDONLY)) < 0)
211 211 return (perr("open usage"));
212 212
213 213 if (read(fd, &prusage, sizeof (prusage)) != sizeof (prusage))
214 214 rval = perr("read usage");
215 215 else {
216 216 if (pidarg) {
217 217 hrtime = gethrtime();
218 218 hrt2ts(hrtime, &real);
219 219 } else {
220 220 real = pup->pr_term;
221 221 }
222 222 tssub(&real, &real, &pup->pr_create);
223 223 user = pup->pr_utime;
224 224 sys = pup->pr_stime;
225 225 if (!mflag)
226 226 tsadd(&sys, &sys, &pup->pr_ttime);
227 227
228 228 if (!pflag || pfirst > 1)
229 229 (void) fprintf(stderr, "\n");
230 230 if (pflag)
231 231 (void) fprintf(stderr, "%d:\t%.70s\n",
232 232 (int)psinfo.pr_pid, psinfo.pr_psargs);
233 233 prtime("real", &real);
234 234 prtime("user", &user);
235 235 prtime("sys", &sys);
236 236
237 237 if (mflag) {
238 238 prtime("trap", &pup->pr_ttime);
239 239 prtime("tflt", &pup->pr_tftime);
240 240 prtime("dflt", &pup->pr_dftime);
241 241 prtime("kflt", &pup->pr_kftime);
242 242 prtime("lock", &pup->pr_ltime);
243 243 prtime("slp", &pup->pr_slptime);
244 244 prtime("lat", &pup->pr_wtime);
245 245 prtime("stop", &pup->pr_stoptime);
246 246 }
247 247 }
248 248
249 249 (void) close(fd);
250 250 return (rval);
251 251 }
252 252
253 253 static void
254 254 hr_min_sec(char *buf, long sec)
255 255 {
256 256 if (sec >= 3600)
257 257 (void) sprintf(buf, "%ld:%.2ld:%.2ld",
258 258 sec / 3600, (sec % 3600) / 60, sec % 60);
259 259 else if (sec >= 60)
260 260 (void) sprintf(buf, "%ld:%.2ld",
261 261 sec / 60, sec % 60);
262 262 else
263 263 (void) sprintf(buf, "%ld", sec);
264 264 }
265 265
266 266 static void
267 267 prtime(char *name, timestruc_t *ts)
268 268 {
269 269 char buf[32];
270 270
271 271 hr_min_sec(buf, ts->tv_sec);
272 272
273 273 (void) fprintf(stderr, "%-4s %8s.%.9u\n",
274 274 name, buf, (uint_t)ts->tv_nsec);
275 275 }
276 276
277 277 static int
278 278 perr(const char *s)
279 279 {
280 280 if (s)
281 281 (void) fprintf(stderr, "%s: ", procname);
282 282 else
283 283 s = procname;
284 284 perror(s);
285 285 return (1);
286 286 }
287 287
288 288 static void
289 289 tsadd(timestruc_t *result, timestruc_t *a, timestruc_t *b)
290 290 {
291 291 result->tv_sec = a->tv_sec + b->tv_sec;
292 292 if ((result->tv_nsec = a->tv_nsec + b->tv_nsec) >= 1000000000) {
293 293 result->tv_nsec -= 1000000000;
294 294 result->tv_sec += 1;
295 295 }
296 296 }
297 297
298 298 static void
299 299 tssub(timestruc_t *result, timestruc_t *a, timestruc_t *b)
300 300 {
301 301 result->tv_sec = a->tv_sec - b->tv_sec;
302 302 if ((result->tv_nsec = a->tv_nsec - b->tv_nsec) < 0) {
303 303 result->tv_nsec += 1000000000;
304 304 result->tv_sec -= 1;
305 305 }
306 306 }
307 307
308 308 static void
309 309 hrt2ts(hrtime_t hrt, timestruc_t *tsp)
310 310 {
311 311 tsp->tv_sec = hrt / NANOSEC;
312 312 tsp->tv_nsec = hrt % NANOSEC;
313 313 }
|
↓ open down ↓ |
313 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX