| GCC Code Coverage Report | |||||||||||||||||||||
        
  | 
    |||||||||||||||||||||
| Line | Branch | Exec | Source | 
1  | 
    /* $OpenBSD: main.c,v 1.16 2016/08/14 22:29:01 krw Exp $ */  | 
    ||
2  | 
    /*  | 
    ||
3  | 
    * Copyright (c) 1994 Christopher G. Demetriou  | 
    ||
4  | 
    * All rights reserved.  | 
    ||
5  | 
    *  | 
    ||
6  | 
    * Redistribution and use in source and binary forms, with or without  | 
    ||
7  | 
    * modification, are permitted provided that the following conditions  | 
    ||
8  | 
    * are met:  | 
    ||
9  | 
    * 1. Redistributions of source code must retain the above copyright  | 
    ||
10  | 
    * notice, this list of conditions and the following disclaimer.  | 
    ||
11  | 
    * 2. Redistributions in binary form must reproduce the above copyright  | 
    ||
12  | 
    * notice, this list of conditions and the following disclaimer in the  | 
    ||
13  | 
    * documentation and/or other materials provided with the distribution.  | 
    ||
14  | 
    * 3. All advertising materials mentioning features or use of this software  | 
    ||
15  | 
    * must display the following acknowledgement:  | 
    ||
16  | 
    * This product includes software developed by Christopher G. Demetriou.  | 
    ||
17  | 
    * 4. The name of the author may not be used to endorse or promote products  | 
    ||
18  | 
    * derived from this software without specific prior written permission  | 
    ||
19  | 
    *  | 
    ||
20  | 
    * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR  | 
    ||
21  | 
    * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES  | 
    ||
22  | 
    * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  | 
    ||
23  | 
    * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,  | 
    ||
24  | 
    * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT  | 
    ||
25  | 
    * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,  | 
    ||
26  | 
    * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY  | 
    ||
27  | 
    * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT  | 
    ||
28  | 
    * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF  | 
    ||
29  | 
    * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.  | 
    ||
30  | 
    */  | 
    ||
31  | 
    |||
32  | 
    /*  | 
    ||
33  | 
    * sa: system accounting  | 
    ||
34  | 
    */  | 
    ||
35  | 
    |||
36  | 
    #include <sys/types.h>  | 
    ||
37  | 
    #include <sys/acct.h>  | 
    ||
38  | 
    #include <ctype.h>  | 
    ||
39  | 
    #include <err.h>  | 
    ||
40  | 
    #include <fcntl.h>  | 
    ||
41  | 
    #include <signal.h>  | 
    ||
42  | 
    #include <stdio.h>  | 
    ||
43  | 
    #include <stdlib.h>  | 
    ||
44  | 
    #include <string.h>  | 
    ||
45  | 
    #include <unistd.h>  | 
    ||
46  | 
    #include "extern.h"  | 
    ||
47  | 
    #include "pathnames.h"  | 
    ||
48  | 
    |||
49  | 
    static int acct_load(char *, int);  | 
    ||
50  | 
    static uint64_t decode_comp_t(comp_t);  | 
    ||
51  | 
    static int cmp_comm(const char *, const char *);  | 
    ||
52  | 
    static int cmp_usrsys(const DBT *, const DBT *);  | 
    ||
53  | 
    static int cmp_avgusrsys(const DBT *, const DBT *);  | 
    ||
54  | 
    static int cmp_dkio(const DBT *, const DBT *);  | 
    ||
55  | 
    static int cmp_avgdkio(const DBT *, const DBT *);  | 
    ||
56  | 
    static int cmp_cpumem(const DBT *, const DBT *);  | 
    ||
57  | 
    static int cmp_avgcpumem(const DBT *, const DBT *);  | 
    ||
58  | 
    static int cmp_calls(const DBT *, const DBT *);  | 
    ||
59  | 
    |||
60  | 
    int aflag, bflag, cflag, dflag, Dflag, fflag, iflag, jflag, kflag;  | 
    ||
61  | 
    int Kflag, lflag, mflag, qflag, rflag, sflag, tflag, uflag, vflag;  | 
    ||
62  | 
    int cutoff = 1;  | 
    ||
63  | 
    |||
64  | 
    static char	*dfltargv[] = { _PATH_ACCT }; | 
    ||
65  | 
    static int dfltargc = (sizeof(dfltargv)/sizeof(char *));  | 
    ||
66  | 
    |||
67  | 
    /* default to comparing by sum of user + system time */  | 
    ||
68  | 
    cmpf_t sa_cmp = cmp_usrsys;  | 
    ||
69  | 
    |||
70  | 
    int  | 
    ||
71  | 
    main(int argc, char **argv)  | 
    ||
72  | 
    { | 
    ||
73  | 
    int ch;  | 
    ||
74  | 
    int error = 0;  | 
    ||
75  | 
    10  | 
    const char *errstr;  | 
    |
76  | 
    extern char *__progname;  | 
    ||
77  | 
    |||
78  | 
    ✗✓ | 5  | 
    	if (pledge("stdio rpath wpath cpath getpw flock", NULL) == -1) | 
    
79  | 
    err(1, "pledge");  | 
    ||
80  | 
    |||
81  | 
    ✓✓ | 30  | 
    while ((ch = getopt(argc, argv, "abcdDfijkKlmnqrstuv:")) != -1)  | 
    
82  | 
    ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✓✗✓ ✗✗✗✗  | 
    10  | 
    		switch (ch) { | 
    
83  | 
    case 'a':  | 
    ||
84  | 
    /* print all commands */  | 
    ||
85  | 
    aflag = 1;  | 
    ||
86  | 
    break;  | 
    ||
87  | 
    case 'b':  | 
    ||
88  | 
    /* sort by per-call user/system time average */  | 
    ||
89  | 
    bflag = 1;  | 
    ||
90  | 
    sa_cmp = cmp_avgusrsys;  | 
    ||
91  | 
    break;  | 
    ||
92  | 
    case 'c':  | 
    ||
93  | 
    /* print percentage total time */  | 
    ||
94  | 
    cflag = 1;  | 
    ||
95  | 
    break;  | 
    ||
96  | 
    case 'd':  | 
    ||
97  | 
    /* sort by averge number of disk I/O ops */  | 
    ||
98  | 
    dflag = 1;  | 
    ||
99  | 
    sa_cmp = cmp_avgdkio;  | 
    ||
100  | 
    break;  | 
    ||
101  | 
    case 'D':  | 
    ||
102  | 
    /* print and sort by total disk I/O ops */  | 
    ||
103  | 
    Dflag = 1;  | 
    ||
104  | 
    sa_cmp = cmp_dkio;  | 
    ||
105  | 
    break;  | 
    ||
106  | 
    case 'f':  | 
    ||
107  | 
    /* force no interactive threshold comprison */  | 
    ||
108  | 
    fflag = 1;  | 
    ||
109  | 
    break;  | 
    ||
110  | 
    case 'i':  | 
    ||
111  | 
    /* do not read in summary file */  | 
    ||
112  | 
    iflag = 1;  | 
    ||
113  | 
    break;  | 
    ||
114  | 
    case 'j':  | 
    ||
115  | 
    /* instead of total minutes, give sec/call */  | 
    ||
116  | 
    jflag = 1;  | 
    ||
117  | 
    break;  | 
    ||
118  | 
    case 'k':  | 
    ||
119  | 
    /* sort by cpu-time average memory usage */  | 
    ||
120  | 
    kflag = 1;  | 
    ||
121  | 
    sa_cmp = cmp_avgcpumem;  | 
    ||
122  | 
    break;  | 
    ||
123  | 
    case 'K':  | 
    ||
124  | 
    /* print and sort by cpu-storage integral */  | 
    ||
125  | 
    sa_cmp = cmp_cpumem;  | 
    ||
126  | 
    Kflag = 1;  | 
    ||
127  | 
    break;  | 
    ||
128  | 
    case 'l':  | 
    ||
129  | 
    /* separate system and user time */  | 
    ||
130  | 
    lflag = 1;  | 
    ||
131  | 
    break;  | 
    ||
132  | 
    case 'm':  | 
    ||
133  | 
    /* print procs and time per-user */  | 
    ||
134  | 
    mflag = 1;  | 
    ||
135  | 
    break;  | 
    ||
136  | 
    case 'n':  | 
    ||
137  | 
    /* sort by number of calls */  | 
    ||
138  | 
    sa_cmp = cmp_calls;  | 
    ||
139  | 
    break;  | 
    ||
140  | 
    case 'q':  | 
    ||
141  | 
    /* quiet; error messages only */  | 
    ||
142  | 
    5  | 
    qflag = 1;  | 
    |
143  | 
    5  | 
    break;  | 
    |
144  | 
    case 'r':  | 
    ||
145  | 
    /* reverse order of sort */  | 
    ||
146  | 
    rflag = 1;  | 
    ||
147  | 
    break;  | 
    ||
148  | 
    case 's':  | 
    ||
149  | 
    /* merge accounting file into summaries */  | 
    ||
150  | 
    5  | 
    sflag = 1;  | 
    |
151  | 
    5  | 
    break;  | 
    |
152  | 
    case 't':  | 
    ||
153  | 
    /* report ratio of user and system times */  | 
    ||
154  | 
    tflag = 1;  | 
    ||
155  | 
    break;  | 
    ||
156  | 
    case 'u':  | 
    ||
157  | 
    /* first, print uid and command name */  | 
    ||
158  | 
    uflag = 1;  | 
    ||
159  | 
    break;  | 
    ||
160  | 
    case 'v':  | 
    ||
161  | 
    /* cull junk */  | 
    ||
162  | 
    vflag = 1;  | 
    ||
163  | 
    cutoff = strtonum(optarg, 1, INT_MAX, &errstr);  | 
    ||
164  | 
    if (errstr)  | 
    ||
165  | 
    errx(1, "-v %s: %s", optarg, errstr);  | 
    ||
166  | 
    break;  | 
    ||
167  | 
    case '?':  | 
    ||
168  | 
    default:  | 
    ||
169  | 
    (void)fprintf(stderr,  | 
    ||
170  | 
    "usage: %s [-abcDdfijKklmnqrstu] [-v cutoff]"  | 
    ||
171  | 
    " [file ...]\n", __progname);  | 
    ||
172  | 
    exit(1);  | 
    ||
173  | 
    }  | 
    ||
174  | 
    |||
175  | 
    5  | 
    argc -= optind;  | 
    |
176  | 
    5  | 
    argv += optind;  | 
    |
177  | 
    |||
178  | 
    /* various argument checking */  | 
    ||
179  | 
    ✗✓ | 5  | 
    if (fflag && !vflag)  | 
    
180  | 
    errx(1, "only one of -f requires -v");  | 
    ||
181  | 
    ✗✓ | 5  | 
    if (fflag && aflag)  | 
    
182  | 
    errx(1, "only one of -a and -v may be specified");  | 
    ||
183  | 
    /* XXX need more argument checking */  | 
    ||
184  | 
    |||
185  | 
    ✓✗ | 5  | 
    	if (!uflag) { | 
    
186  | 
    /* initialize tables */  | 
    ||
187  | 
    ✗✓✗✗ ✗✓  | 
    10  | 
    if ((sflag || (!mflag && !qflag)) && pacct_init() != 0)  | 
    
188  | 
    errx(1, "process accounting initialization failed");  | 
    ||
189  | 
    ✗✓✗✗ ✗✓  | 
    10  | 
    if ((sflag || (mflag && !qflag)) && usracct_init() != 0)  | 
    
190  | 
    errx(1, "user accounting initialization failed");  | 
    ||
191  | 
    }  | 
    ||
192  | 
    |||
193  | 
    ✓✗ | 5  | 
    	if (argc == 0) { | 
    
194  | 
    5  | 
    argc = dfltargc;  | 
    |
195  | 
    argv = dfltargv;  | 
    ||
196  | 
    5  | 
    }  | 
    |
197  | 
    |||
198  | 
    /* for each file specified */  | 
    ||
199  | 
    ✓✓ | 20  | 
    	for (; argc > 0; argc--, argv++) { | 
    
200  | 
    int fd;  | 
    ||
201  | 
    |||
202  | 
    /*  | 
    ||
203  | 
    * load the accounting data from the file.  | 
    ||
204  | 
    * if it fails, go on to the next file.  | 
    ||
205  | 
    */  | 
    ||
206  | 
    5  | 
    fd = acct_load(argv[0], sflag);  | 
    |
207  | 
    ✗✓ | 5  | 
    if (fd < 0)  | 
    
208  | 
    continue;  | 
    ||
209  | 
    |||
210  | 
    ✓✗ | 5  | 
    		if (!uflag && sflag) { | 
    
211  | 
    #ifndef DEBUG  | 
    ||
212  | 
    5  | 
    sigset_t nmask, omask;  | 
    |
213  | 
    int unmask = 1;  | 
    ||
214  | 
    |||
215  | 
    /*  | 
    ||
216  | 
    * block most signals so we aren't interrupted during  | 
    ||
217  | 
    * the update.  | 
    ||
218  | 
    */  | 
    ||
219  | 
    ✗✓ | 5  | 
    			if (sigfillset(&nmask) == -1) { | 
    
220  | 
    				warn("sigfillset"); | 
    ||
221  | 
    unmask = 0;  | 
    ||
222  | 
    error = 1;  | 
    ||
223  | 
    }  | 
    ||
224  | 
    ✓✗✗✓ | 
    10  | 
    if (unmask &&  | 
    
225  | 
    5  | 
    			    (sigprocmask(SIG_BLOCK, &nmask, &omask) == -1)) { | 
    |
226  | 
    				warn("couldn't set signal mask "); | 
    ||
227  | 
    unmask = 0;  | 
    ||
228  | 
    error = 1;  | 
    ||
229  | 
    }  | 
    ||
230  | 
    #endif /* DEBUG */  | 
    ||
231  | 
    |||
232  | 
    /*  | 
    ||
233  | 
    * truncate the accounting data file ASAP, to avoid  | 
    ||
234  | 
    * losing data. don't worry about errors in updating  | 
    ||
235  | 
    * the saved stats; better to underbill than overbill,  | 
    ||
236  | 
    * but we want every accounting record intact.  | 
    ||
237  | 
    */  | 
    ||
238  | 
    ✗✓ | 5  | 
    			if (ftruncate(fd, 0) == -1) { | 
    
239  | 
    				warn("couldn't truncate %s", *argv); | 
    ||
240  | 
    error = 1;  | 
    ||
241  | 
    }  | 
    ||
242  | 
    |||
243  | 
    /*  | 
    ||
244  | 
    * update saved user and process accounting data.  | 
    ||
245  | 
    * note errors for later.  | 
    ||
246  | 
    */  | 
    ||
247  | 
    ✓✗✗✓ | 
    10  | 
    if (pacct_update() != 0 || usracct_update() != 0)  | 
    
248  | 
    error = 1;  | 
    ||
249  | 
    |||
250  | 
    #ifndef DEBUG  | 
    ||
251  | 
    /*  | 
    ||
252  | 
    * restore signals  | 
    ||
253  | 
    */  | 
    ||
254  | 
    ✓✗✗✓ | 
    10  | 
    if (unmask &&  | 
    
255  | 
    5  | 
    			    (sigprocmask(SIG_SETMASK, &omask, NULL) == -1)) { | 
    |
256  | 
    				warn("couldn't restore signal mask"); | 
    ||
257  | 
    error = 1;  | 
    ||
258  | 
    }  | 
    ||
259  | 
    #endif /* DEBUG */  | 
    ||
260  | 
    5  | 
    }  | 
    |
261  | 
    |||
262  | 
    /*  | 
    ||
263  | 
    * close the opened accounting file  | 
    ||
264  | 
    */  | 
    ||
265  | 
    ✗✓ | 5  | 
    		if (close(fd) == -1) { | 
    
266  | 
    			warn("close %s", *argv); | 
    ||
267  | 
    error = 1;  | 
    ||
268  | 
    }  | 
    ||
269  | 
    5  | 
    }  | 
    |
270  | 
    |||
271  | 
    ✗✓ | 5  | 
    	if (!uflag && !qflag) { | 
    
272  | 
    /* print any results we may have obtained. */  | 
    ||
273  | 
    if (!mflag)  | 
    ||
274  | 
    pacct_print();  | 
    ||
275  | 
    else  | 
    ||
276  | 
    usracct_print();  | 
    ||
277  | 
    }  | 
    ||
278  | 
    |||
279  | 
    ✓✗ | 5  | 
    	if (!uflag) { | 
    
280  | 
    /* finally, deallocate databases */  | 
    ||
281  | 
    ✗✓✗✗ | 
    5  | 
    if (sflag || (!mflag && !qflag))  | 
    
282  | 
    5  | 
    pacct_destroy();  | 
    |
283  | 
    ✗✓✗✗ | 
    5  | 
    if (sflag || (mflag && !qflag))  | 
    
284  | 
    5  | 
    usracct_destroy();  | 
    |
285  | 
    }  | 
    ||
286  | 
    |||
287  | 
    exit(error);  | 
    ||
288  | 
    }  | 
    ||
289  | 
    |||
290  | 
    static int  | 
    ||
291  | 
    acct_load(char *pn, int wr)  | 
    ||
292  | 
    { | 
    ||
293  | 
    10  | 
    struct acct ac;  | 
    |
294  | 
    5  | 
    struct cmdinfo ci;  | 
    |
295  | 
    ssize_t rv;  | 
    ||
296  | 
    int fd, i;  | 
    ||
297  | 
    |||
298  | 
    /*  | 
    ||
299  | 
    * open the file  | 
    ||
300  | 
    */  | 
    ||
301  | 
    5  | 
    fd = open(pn, wr ? O_RDWR : O_RDONLY, 0);  | 
    |
302  | 
    ✗✓ | 5  | 
    	if (fd == -1) { | 
    
303  | 
    		warn("open %s %s", pn, wr ? "for read/write" : "read-only"); | 
    ||
304  | 
    return (-1);  | 
    ||
305  | 
    }  | 
    ||
306  | 
    |||
307  | 
    /*  | 
    ||
308  | 
    * read all we can; don't stat and open because more processes  | 
    ||
309  | 
    * could exit, and we'd miss them  | 
    ||
310  | 
    */  | 
    ||
311  | 
    298128  | 
    	while (1) { | 
    |
312  | 
    /* get one accounting entry and punt if there's an error */  | 
    ||
313  | 
    298128  | 
    rv = read(fd, &ac, sizeof(struct acct));  | 
    |
314  | 
    ✗✓ | 298128  | 
    if (rv == -1)  | 
    
315  | 
    			warn("error reading %s", pn); | 
    ||
316  | 
    ✗✓ | 298128  | 
    else if (rv > 0 && rv < sizeof(struct acct))  | 
    
317  | 
    			warnx("short read of accounting data in %s", pn); | 
    ||
318  | 
    ✓✓ | 298128  | 
    if (rv != sizeof(struct acct))  | 
    
319  | 
    break;  | 
    ||
320  | 
    |||
321  | 
    /* decode it */  | 
    ||
322  | 
    298123  | 
    ci.ci_calls = 1;  | 
    |
323  | 
    ✓✓✓✓ | 
    3607377  | 
    for (i = 0; i < sizeof(ac.ac_comm) && ac.ac_comm[i] != '\0';  | 
    
324  | 
    904719  | 
    		    i++) { | 
    |
325  | 
    unsigned char c = ac.ac_comm[i];  | 
    ||
326  | 
    |||
327  | 
    ✓✗✗✓ | 
    1809438  | 
    			if (!isascii(c) || iscntrl(c)) { | 
    
328  | 
    ci.ci_comm[i] = '?';  | 
    ||
329  | 
    ci.ci_flags |= CI_UNPRINTABLE;  | 
    ||
330  | 
    } else  | 
    ||
331  | 
    904719  | 
    ci.ci_comm[i] = c;  | 
    |
332  | 
    }  | 
    ||
333  | 
    ✓✓ | 298123  | 
    if (ac.ac_flag & AFORK)  | 
    
334  | 
    32448  | 
    ci.ci_comm[i++] = '*';  | 
    |
335  | 
    298123  | 
    ci.ci_comm[i++] = '\0';  | 
    |
336  | 
    298123  | 
    ci.ci_etime = decode_comp_t(ac.ac_etime);  | 
    |
337  | 
    298123  | 
    ci.ci_utime = decode_comp_t(ac.ac_utime);  | 
    |
338  | 
    298123  | 
    ci.ci_stime = decode_comp_t(ac.ac_stime);  | 
    |
339  | 
    298123  | 
    ci.ci_uid = ac.ac_uid;  | 
    |
340  | 
    298123  | 
    ci.ci_mem = ac.ac_mem;  | 
    |
341  | 
    298123  | 
    ci.ci_io = decode_comp_t(ac.ac_io) / AHZ;  | 
    |
342  | 
    |||
343  | 
    ✓✗ | 298123  | 
    		if (!uflag) { | 
    
344  | 
    /* and enter it into the usracct and pacct databases */  | 
    ||
345  | 
    ✗✓✗✗ | 
    298123  | 
    if (sflag || (!mflag && !qflag))  | 
    
346  | 
    298123  | 
    pacct_add(&ci);  | 
    |
347  | 
    ✗✓✗✗ | 
    298123  | 
    if (sflag || (mflag && !qflag))  | 
    
348  | 
    298123  | 
    usracct_add(&ci);  | 
    |
349  | 
    } else if (!qflag)  | 
    ||
350  | 
    			printf("%6u %12.2f cpu %12lluk mem %12llu io %s\n", | 
    ||
351  | 
    ci.ci_uid,  | 
    ||
352  | 
    (ci.ci_utime + ci.ci_stime) / (double) AHZ,  | 
    ||
353  | 
    ci.ci_mem, ci.ci_io, ci.ci_comm);  | 
    ||
354  | 
    }  | 
    ||
355  | 
    |||
356  | 
    /* finally, return the file descriptor for possible truncation */  | 
    ||
357  | 
    5  | 
    return (fd);  | 
    |
358  | 
    5  | 
    }  | 
    |
359  | 
    |||
360  | 
    static uint64_t  | 
    ||
361  | 
    decode_comp_t(comp_t comp)  | 
    ||
362  | 
    { | 
    ||
363  | 
    uint64_t rv;  | 
    ||
364  | 
    |||
365  | 
    /*  | 
    ||
366  | 
    * for more info on the comp_t format, see:  | 
    ||
367  | 
    * /usr/src/sys/kern/kern_acct.c  | 
    ||
368  | 
    * /usr/src/sys/sys/acct.h  | 
    ||
369  | 
    * /usr/src/usr.bin/lastcomm/lastcomm.c  | 
    ||
370  | 
    */  | 
    ||
371  | 
    2384984  | 
    rv = comp & 0x1fff; /* 13 bit fraction */  | 
    |
372  | 
    1192492  | 
    comp >>= 13; /* 3 bit base-8 exponent */  | 
    |
373  | 
    ✓✓ | 2386510  | 
    while (comp--)  | 
    
374  | 
    763  | 
    rv <<= 3;  | 
    |
375  | 
    |||
376  | 
    1192492  | 
    return (rv);  | 
    |
377  | 
    }  | 
    ||
378  | 
    |||
379  | 
    /* sort commands, doing the right thing in terms of reversals */  | 
    ||
380  | 
    static int  | 
    ||
381  | 
    cmp_comm(const char *s1, const char *s2)  | 
    ||
382  | 
    { | 
    ||
383  | 
    int rv;  | 
    ||
384  | 
    |||
385  | 
    rv = strcmp(s1, s2);  | 
    ||
386  | 
    if (rv == 0)  | 
    ||
387  | 
    rv = -1;  | 
    ||
388  | 
    return (rflag ? rv : -rv);  | 
    ||
389  | 
    }  | 
    ||
390  | 
    |||
391  | 
    /* sort by total user and system time */  | 
    ||
392  | 
    static int  | 
    ||
393  | 
    cmp_usrsys(const DBT *d1, const DBT *d2)  | 
    ||
394  | 
    { | 
    ||
395  | 
    struct cmdinfo c1, c2;  | 
    ||
396  | 
    uint64_t t1, t2;  | 
    ||
397  | 
    |||
398  | 
    memcpy(&c1, d1->data, sizeof(c1));  | 
    ||
399  | 
    memcpy(&c2, d2->data, sizeof(c2));  | 
    ||
400  | 
    |||
401  | 
    t1 = c1.ci_utime + c1.ci_stime;  | 
    ||
402  | 
    t2 = c2.ci_utime + c2.ci_stime;  | 
    ||
403  | 
    |||
404  | 
    if (t1 < t2)  | 
    ||
405  | 
    return -1;  | 
    ||
406  | 
    else if (t1 == t2)  | 
    ||
407  | 
    return (cmp_comm(c1.ci_comm, c2.ci_comm));  | 
    ||
408  | 
    else  | 
    ||
409  | 
    return 1;  | 
    ||
410  | 
    }  | 
    ||
411  | 
    |||
412  | 
    /* sort by average user and system time */  | 
    ||
413  | 
    static int  | 
    ||
414  | 
    cmp_avgusrsys(const DBT *d1, const DBT *d2)  | 
    ||
415  | 
    { | 
    ||
416  | 
    struct cmdinfo c1, c2;  | 
    ||
417  | 
    double t1, t2;  | 
    ||
418  | 
    |||
419  | 
    memcpy(&c1, d1->data, sizeof(c1));  | 
    ||
420  | 
    memcpy(&c2, d2->data, sizeof(c2));  | 
    ||
421  | 
    |||
422  | 
    t1 = c1.ci_utime + c1.ci_stime;  | 
    ||
423  | 
    t1 /= (double) (c1.ci_calls ? c1.ci_calls : 1);  | 
    ||
424  | 
    |||
425  | 
    t2 = c2.ci_utime + c2.ci_stime;  | 
    ||
426  | 
    t2 /= (double) (c2.ci_calls ? c2.ci_calls : 1);  | 
    ||
427  | 
    |||
428  | 
    if (t1 < t2)  | 
    ||
429  | 
    return -1;  | 
    ||
430  | 
    else if (t1 == t2)  | 
    ||
431  | 
    return (cmp_comm(c1.ci_comm, c2.ci_comm));  | 
    ||
432  | 
    else  | 
    ||
433  | 
    return 1;  | 
    ||
434  | 
    }  | 
    ||
435  | 
    |||
436  | 
    /* sort by total number of disk I/O operations */  | 
    ||
437  | 
    static int  | 
    ||
438  | 
    cmp_dkio(const DBT *d1, const DBT *d2)  | 
    ||
439  | 
    { | 
    ||
440  | 
    struct cmdinfo c1, c2;  | 
    ||
441  | 
    |||
442  | 
    memcpy(&c1, d1->data, sizeof(c1));  | 
    ||
443  | 
    memcpy(&c2, d2->data, sizeof(c2));  | 
    ||
444  | 
    |||
445  | 
    if (c1.ci_io < c2.ci_io)  | 
    ||
446  | 
    return -1;  | 
    ||
447  | 
    else if (c1.ci_io == c2.ci_io)  | 
    ||
448  | 
    return (cmp_comm(c1.ci_comm, c2.ci_comm));  | 
    ||
449  | 
    else  | 
    ||
450  | 
    return 1;  | 
    ||
451  | 
    }  | 
    ||
452  | 
    |||
453  | 
    /* sort by average number of disk I/O operations */  | 
    ||
454  | 
    static int  | 
    ||
455  | 
    cmp_avgdkio(const DBT *d1, const DBT *d2)  | 
    ||
456  | 
    { | 
    ||
457  | 
    struct cmdinfo c1, c2;  | 
    ||
458  | 
    double n1, n2;  | 
    ||
459  | 
    |||
460  | 
    memcpy(&c1, d1->data, sizeof(c1));  | 
    ||
461  | 
    memcpy(&c2, d2->data, sizeof(c2));  | 
    ||
462  | 
    |||
463  | 
    n1 = (double) c1.ci_io / (double) (c1.ci_calls ? c1.ci_calls : 1);  | 
    ||
464  | 
    n2 = (double) c2.ci_io / (double) (c2.ci_calls ? c2.ci_calls : 1);  | 
    ||
465  | 
    |||
466  | 
    if (n1 < n2)  | 
    ||
467  | 
    return -1;  | 
    ||
468  | 
    else if (n1 == n2)  | 
    ||
469  | 
    return (cmp_comm(c1.ci_comm, c2.ci_comm));  | 
    ||
470  | 
    else  | 
    ||
471  | 
    return 1;  | 
    ||
472  | 
    }  | 
    ||
473  | 
    |||
474  | 
    /* sort by the cpu-storage integral */  | 
    ||
475  | 
    static int  | 
    ||
476  | 
    cmp_cpumem(const DBT *d1, const DBT *d2)  | 
    ||
477  | 
    { | 
    ||
478  | 
    struct cmdinfo c1, c2;  | 
    ||
479  | 
    |||
480  | 
    memcpy(&c1, d1->data, sizeof(c1));  | 
    ||
481  | 
    memcpy(&c2, d2->data, sizeof(c2));  | 
    ||
482  | 
    |||
483  | 
    if (c1.ci_mem < c2.ci_mem)  | 
    ||
484  | 
    return -1;  | 
    ||
485  | 
    else if (c1.ci_mem == c2.ci_mem)  | 
    ||
486  | 
    return (cmp_comm(c1.ci_comm, c2.ci_comm));  | 
    ||
487  | 
    else  | 
    ||
488  | 
    return 1;  | 
    ||
489  | 
    }  | 
    ||
490  | 
    |||
491  | 
    /* sort by the cpu-time average memory usage */  | 
    ||
492  | 
    static int  | 
    ||
493  | 
    cmp_avgcpumem(const DBT *d1, const DBT *d2)  | 
    ||
494  | 
    { | 
    ||
495  | 
    struct cmdinfo c1, c2;  | 
    ||
496  | 
    uint64_t t1, t2;  | 
    ||
497  | 
    double n1, n2;  | 
    ||
498  | 
    |||
499  | 
    memcpy(&c1, d1->data, sizeof(c1));  | 
    ||
500  | 
    memcpy(&c2, d2->data, sizeof(c2));  | 
    ||
501  | 
    |||
502  | 
    t1 = c1.ci_utime + c1.ci_stime;  | 
    ||
503  | 
    t2 = c2.ci_utime + c2.ci_stime;  | 
    ||
504  | 
    |||
505  | 
    n1 = (double) c1.ci_mem / (double) (t1 ? t1 : 1);  | 
    ||
506  | 
    n2 = (double) c2.ci_mem / (double) (t2 ? t2 : 1);  | 
    ||
507  | 
    |||
508  | 
    if (n1 < n2)  | 
    ||
509  | 
    return -1;  | 
    ||
510  | 
    else if (n1 == n2)  | 
    ||
511  | 
    return (cmp_comm(c1.ci_comm, c2.ci_comm));  | 
    ||
512  | 
    else  | 
    ||
513  | 
    return 1;  | 
    ||
514  | 
    }  | 
    ||
515  | 
    |||
516  | 
    /* sort by the number of invocations */  | 
    ||
517  | 
    static int  | 
    ||
518  | 
    cmp_calls(const DBT *d1, const DBT *d2)  | 
    ||
519  | 
    { | 
    ||
520  | 
    struct cmdinfo c1, c2;  | 
    ||
521  | 
    |||
522  | 
    memcpy(&c1, d1->data, sizeof(c1));  | 
    ||
523  | 
    memcpy(&c2, d2->data, sizeof(c2));  | 
    ||
524  | 
    |||
525  | 
    if (c1.ci_calls < c2.ci_calls)  | 
    ||
526  | 
    return -1;  | 
    ||
527  | 
    else if (c1.ci_calls == c2.ci_calls)  | 
    ||
528  | 
    return (cmp_comm(c1.ci_comm, c2.ci_comm));  | 
    ||
529  | 
    else  | 
    ||
530  | 
    return 1;  | 
    ||
531  | 
    }  | 
    
| Generated by: GCOVR (Version 3.3) |