1*486c6fdaSRichard Lowe /*
2*486c6fdaSRichard Lowe * CDDL HEADER START
3*486c6fdaSRichard Lowe *
4*486c6fdaSRichard Lowe * The contents of this file are subject to the terms of the
5*486c6fdaSRichard Lowe * Common Development and Distribution License (the "License").
6*486c6fdaSRichard Lowe * You may not use this file except in compliance with the License.
7*486c6fdaSRichard Lowe *
8*486c6fdaSRichard Lowe * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*486c6fdaSRichard Lowe * or http://www.opensolaris.org/os/licensing.
10*486c6fdaSRichard Lowe * See the License for the specific language governing permissions
11*486c6fdaSRichard Lowe * and limitations under the License.
12*486c6fdaSRichard Lowe *
13*486c6fdaSRichard Lowe * When distributing Covered Code, include this CDDL HEADER in each
14*486c6fdaSRichard Lowe * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*486c6fdaSRichard Lowe * If applicable, add the following below this CDDL HEADER, with the
16*486c6fdaSRichard Lowe * fields enclosed by brackets "[]" replaced with your own identifying
17*486c6fdaSRichard Lowe * information: Portions Copyright [yyyy] [name of copyright owner]
18*486c6fdaSRichard Lowe *
19*486c6fdaSRichard Lowe * CDDL HEADER END
20*486c6fdaSRichard Lowe */
21*486c6fdaSRichard Lowe /*
22*486c6fdaSRichard Lowe * Copyright (c) 2008-2009, Intel Corporation.
23*486c6fdaSRichard Lowe * All Rights Reserved.
24*486c6fdaSRichard Lowe */
25*486c6fdaSRichard Lowe
26*486c6fdaSRichard Lowe #include <unistd.h>
27*486c6fdaSRichard Lowe #include <libintl.h>
28*486c6fdaSRichard Lowe #include <stdio.h>
29*486c6fdaSRichard Lowe #include <stdlib.h>
30*486c6fdaSRichard Lowe #include <string.h>
31*486c6fdaSRichard Lowe #include <ctype.h>
32*486c6fdaSRichard Lowe #include <procfs.h>
33*486c6fdaSRichard Lowe #include <fcntl.h>
34*486c6fdaSRichard Lowe #include <sys/types.h>
35*486c6fdaSRichard Lowe #include <sys/stat.h>
36*486c6fdaSRichard Lowe
37*486c6fdaSRichard Lowe #include "latencytop.h"
38*486c6fdaSRichard Lowe
39*486c6fdaSRichard Lowe /* Pipe that breaks the event loop (and exits early) */
40*486c6fdaSRichard Lowe static int signal_pipe[2];
41*486c6fdaSRichard Lowe
42*486c6fdaSRichard Lowe /*
43*486c6fdaSRichard Lowe * Get current system time in milliseconds (1e-3).
44*486c6fdaSRichard Lowe */
45*486c6fdaSRichard Lowe uint64_t
lt_millisecond(void)46*486c6fdaSRichard Lowe lt_millisecond(void)
47*486c6fdaSRichard Lowe {
48*486c6fdaSRichard Lowe struct timeval p;
49*486c6fdaSRichard Lowe (void) gettimeofday(&p, NULL);
50*486c6fdaSRichard Lowe return ((uint64_t)p.tv_sec * 1000 + p.tv_usec / 1000);
51*486c6fdaSRichard Lowe }
52*486c6fdaSRichard Lowe
53*486c6fdaSRichard Lowe /*
54*486c6fdaSRichard Lowe * Check if we are out of memory.
55*486c6fdaSRichard Lowe */
56*486c6fdaSRichard Lowe void
lt_check_null(void * p)57*486c6fdaSRichard Lowe lt_check_null(void *p)
58*486c6fdaSRichard Lowe {
59*486c6fdaSRichard Lowe if (p == NULL) {
60*486c6fdaSRichard Lowe (void) fprintf(stderr, "Out of memory!\n");
61*486c6fdaSRichard Lowe g_assert(0);
62*486c6fdaSRichard Lowe exit(2);
63*486c6fdaSRichard Lowe }
64*486c6fdaSRichard Lowe }
65*486c6fdaSRichard Lowe
66*486c6fdaSRichard Lowe /*
67*486c6fdaSRichard Lowe * Safe malloc.
68*486c6fdaSRichard Lowe */
69*486c6fdaSRichard Lowe void *
lt_malloc(size_t size)70*486c6fdaSRichard Lowe lt_malloc(size_t size)
71*486c6fdaSRichard Lowe {
72*486c6fdaSRichard Lowe void *ret = malloc(size);
73*486c6fdaSRichard Lowe
74*486c6fdaSRichard Lowe lt_check_null(ret);
75*486c6fdaSRichard Lowe
76*486c6fdaSRichard Lowe return (ret);
77*486c6fdaSRichard Lowe }
78*486c6fdaSRichard Lowe
79*486c6fdaSRichard Lowe /*
80*486c6fdaSRichard Lowe * Safe alloc with memory cleared.
81*486c6fdaSRichard Lowe * It is named "zalloc" because its signature is different from
82*486c6fdaSRichard Lowe * calloc() in stdlib.
83*486c6fdaSRichard Lowe */
84*486c6fdaSRichard Lowe void *
lt_zalloc(size_t size)85*486c6fdaSRichard Lowe lt_zalloc(size_t size)
86*486c6fdaSRichard Lowe {
87*486c6fdaSRichard Lowe void *ret = calloc(size, 1);
88*486c6fdaSRichard Lowe
89*486c6fdaSRichard Lowe lt_check_null(ret);
90*486c6fdaSRichard Lowe
91*486c6fdaSRichard Lowe return (ret);
92*486c6fdaSRichard Lowe }
93*486c6fdaSRichard Lowe
94*486c6fdaSRichard Lowe /*
95*486c6fdaSRichard Lowe * Safe strdup.
96*486c6fdaSRichard Lowe */
97*486c6fdaSRichard Lowe char *
lt_strdup(const char * str)98*486c6fdaSRichard Lowe lt_strdup(const char *str)
99*486c6fdaSRichard Lowe {
100*486c6fdaSRichard Lowe char *ret = strdup(str);
101*486c6fdaSRichard Lowe
102*486c6fdaSRichard Lowe lt_check_null(ret);
103*486c6fdaSRichard Lowe
104*486c6fdaSRichard Lowe return (ret);
105*486c6fdaSRichard Lowe }
106*486c6fdaSRichard Lowe
107*486c6fdaSRichard Lowe /*
108*486c6fdaSRichard Lowe * Get string for current time, e.g. YYYY-MM-DD
109*486c6fdaSRichard Lowe */
110*486c6fdaSRichard Lowe void
lt_time_str(char * buffer,int len)111*486c6fdaSRichard Lowe lt_time_str(char *buffer, int len)
112*486c6fdaSRichard Lowe {
113*486c6fdaSRichard Lowe struct tm tms;
114*486c6fdaSRichard Lowe time_t t;
115*486c6fdaSRichard Lowe int i;
116*486c6fdaSRichard Lowe
117*486c6fdaSRichard Lowe (void) time(&t);
118*486c6fdaSRichard Lowe (void) gmtime_r(&t, &tms);
119*486c6fdaSRichard Lowe (void) asctime_r(&tms, buffer, len);
120*486c6fdaSRichard Lowe
121*486c6fdaSRichard Lowe for (i = strlen(buffer)-1; i > 0; --i) {
122*486c6fdaSRichard Lowe
123*486c6fdaSRichard Lowe if (isspace(buffer[i])) {
124*486c6fdaSRichard Lowe buffer[i] = '\0';
125*486c6fdaSRichard Lowe } else {
126*486c6fdaSRichard Lowe break;
127*486c6fdaSRichard Lowe }
128*486c6fdaSRichard Lowe }
129*486c6fdaSRichard Lowe }
130*486c6fdaSRichard Lowe
131*486c6fdaSRichard Lowe /*
132*486c6fdaSRichard Lowe * Retrieves the process's executable name and arguments from /proc.
133*486c6fdaSRichard Lowe */
134*486c6fdaSRichard Lowe char *
lt_get_proc_field(pid_t pid,lt_field_t field)135*486c6fdaSRichard Lowe lt_get_proc_field(pid_t pid, lt_field_t field)
136*486c6fdaSRichard Lowe {
137*486c6fdaSRichard Lowe char name[PATH_MAX];
138*486c6fdaSRichard Lowe int fd;
139*486c6fdaSRichard Lowe int ret;
140*486c6fdaSRichard Lowe psinfo_t psinfo;
141*486c6fdaSRichard Lowe
142*486c6fdaSRichard Lowe (void) snprintf(name, PATH_MAX, "/proc/%d/psinfo", (int)pid);
143*486c6fdaSRichard Lowe fd = open(name, O_RDONLY);
144*486c6fdaSRichard Lowe
145*486c6fdaSRichard Lowe if (fd == -1) {
146*486c6fdaSRichard Lowe return (NULL);
147*486c6fdaSRichard Lowe }
148*486c6fdaSRichard Lowe
149*486c6fdaSRichard Lowe ret = read(fd, (char *)&psinfo, sizeof (psinfo_t));
150*486c6fdaSRichard Lowe (void) close(fd);
151*486c6fdaSRichard Lowe
152*486c6fdaSRichard Lowe if (ret < 0) {
153*486c6fdaSRichard Lowe return (NULL);
154*486c6fdaSRichard Lowe }
155*486c6fdaSRichard Lowe
156*486c6fdaSRichard Lowe switch (field) {
157*486c6fdaSRichard Lowe case LT_FIELD_FNAME:
158*486c6fdaSRichard Lowe return (lt_strdup(psinfo.pr_fname));
159*486c6fdaSRichard Lowe case LT_FIELD_PSARGS:
160*486c6fdaSRichard Lowe return (lt_strdup(psinfo.pr_psargs));
161*486c6fdaSRichard Lowe }
162*486c6fdaSRichard Lowe return (NULL);
163*486c6fdaSRichard Lowe }
164*486c6fdaSRichard Lowe
165*486c6fdaSRichard Lowe /*
166*486c6fdaSRichard Lowe * Helper function to update the data structure.
167*486c6fdaSRichard Lowe */
168*486c6fdaSRichard Lowe void
lt_update_stat_value(lt_stat_data_t * entry,lt_stat_type_t type,uint64_t value)169*486c6fdaSRichard Lowe lt_update_stat_value(lt_stat_data_t *entry,
170*486c6fdaSRichard Lowe lt_stat_type_t type, uint64_t value)
171*486c6fdaSRichard Lowe {
172*486c6fdaSRichard Lowe switch (type) {
173*486c6fdaSRichard Lowe case LT_STAT_COUNT:
174*486c6fdaSRichard Lowe entry->lt_s_count += value;
175*486c6fdaSRichard Lowe break;
176*486c6fdaSRichard Lowe case LT_STAT_SUM:
177*486c6fdaSRichard Lowe entry->lt_s_total += value;
178*486c6fdaSRichard Lowe break;
179*486c6fdaSRichard Lowe case LT_STAT_MAX:
180*486c6fdaSRichard Lowe if (value > entry->lt_s_max) {
181*486c6fdaSRichard Lowe entry->lt_s_max = value;
182*486c6fdaSRichard Lowe }
183*486c6fdaSRichard Lowe break;
184*486c6fdaSRichard Lowe default:
185*486c6fdaSRichard Lowe break;
186*486c6fdaSRichard Lowe }
187*486c6fdaSRichard Lowe }
188*486c6fdaSRichard Lowe
189*486c6fdaSRichard Lowe /*
190*486c6fdaSRichard Lowe * Helper function to sort on total.
191*486c6fdaSRichard Lowe */
192*486c6fdaSRichard Lowe int
lt_sort_by_total_desc(lt_stat_entry_t * a,lt_stat_entry_t * b)193*486c6fdaSRichard Lowe lt_sort_by_total_desc(lt_stat_entry_t *a, lt_stat_entry_t *b)
194*486c6fdaSRichard Lowe {
195*486c6fdaSRichard Lowe g_assert(a != NULL && b != NULL);
196*486c6fdaSRichard Lowe /*
197*486c6fdaSRichard Lowe * lt_s_total is of type int64_t, so we can't simply return
198*486c6fdaSRichard Lowe * (b->lt_se_data.lt_s_total - a->lt_se_data.lt_s_total).
199*486c6fdaSRichard Lowe */
200*486c6fdaSRichard Lowe if (b->lt_se_data.lt_s_total > a->lt_se_data.lt_s_total) {
201*486c6fdaSRichard Lowe return (1);
202*486c6fdaSRichard Lowe } else if (b->lt_se_data.lt_s_total < a->lt_se_data.lt_s_total) {
203*486c6fdaSRichard Lowe return (-1);
204*486c6fdaSRichard Lowe } else {
205*486c6fdaSRichard Lowe return (0);
206*486c6fdaSRichard Lowe }
207*486c6fdaSRichard Lowe }
208*486c6fdaSRichard Lowe
209*486c6fdaSRichard Lowe /*
210*486c6fdaSRichard Lowe * Helper function to sort on max.
211*486c6fdaSRichard Lowe */
212*486c6fdaSRichard Lowe int
lt_sort_by_max_desc(lt_stat_entry_t * a,lt_stat_entry_t * b)213*486c6fdaSRichard Lowe lt_sort_by_max_desc(lt_stat_entry_t *a, lt_stat_entry_t *b)
214*486c6fdaSRichard Lowe {
215*486c6fdaSRichard Lowe g_assert(a != NULL && b != NULL);
216*486c6fdaSRichard Lowe
217*486c6fdaSRichard Lowe if (b->lt_se_data.lt_s_max > a->lt_se_data.lt_s_max) {
218*486c6fdaSRichard Lowe return (1);
219*486c6fdaSRichard Lowe } else if (b->lt_se_data.lt_s_max < a->lt_se_data.lt_s_max) {
220*486c6fdaSRichard Lowe return (-1);
221*486c6fdaSRichard Lowe } else {
222*486c6fdaSRichard Lowe return (0);
223*486c6fdaSRichard Lowe }
224*486c6fdaSRichard Lowe }
225*486c6fdaSRichard Lowe
226*486c6fdaSRichard Lowe /*
227*486c6fdaSRichard Lowe * Helper function to sort on count.
228*486c6fdaSRichard Lowe */
229*486c6fdaSRichard Lowe int
lt_sort_by_count_desc(lt_stat_entry_t * a,lt_stat_entry_t * b)230*486c6fdaSRichard Lowe lt_sort_by_count_desc(lt_stat_entry_t *a, lt_stat_entry_t *b)
231*486c6fdaSRichard Lowe {
232*486c6fdaSRichard Lowe g_assert(a != NULL && b != NULL);
233*486c6fdaSRichard Lowe
234*486c6fdaSRichard Lowe if (b->lt_se_data.lt_s_count > a->lt_se_data.lt_s_count) {
235*486c6fdaSRichard Lowe return (1);
236*486c6fdaSRichard Lowe } else if (b->lt_se_data.lt_s_count < a->lt_se_data.lt_s_count) {
237*486c6fdaSRichard Lowe return (-1);
238*486c6fdaSRichard Lowe } else {
239*486c6fdaSRichard Lowe return (0);
240*486c6fdaSRichard Lowe }
241*486c6fdaSRichard Lowe }
242*486c6fdaSRichard Lowe
243*486c6fdaSRichard Lowe /*
244*486c6fdaSRichard Lowe * Helper function to sort on average.
245*486c6fdaSRichard Lowe */
246*486c6fdaSRichard Lowe int
lt_sort_by_avg_desc(lt_stat_entry_t * a,lt_stat_entry_t * b)247*486c6fdaSRichard Lowe lt_sort_by_avg_desc(lt_stat_entry_t *a, lt_stat_entry_t *b)
248*486c6fdaSRichard Lowe {
249*486c6fdaSRichard Lowe double avg_a, avg_b;
250*486c6fdaSRichard Lowe
251*486c6fdaSRichard Lowe g_assert(a != NULL && b != NULL);
252*486c6fdaSRichard Lowe
253*486c6fdaSRichard Lowe avg_a = (double)a->lt_se_data.lt_s_total / a->lt_se_data.lt_s_count;
254*486c6fdaSRichard Lowe avg_b = (double)b->lt_se_data.lt_s_total / b->lt_se_data.lt_s_count;
255*486c6fdaSRichard Lowe
256*486c6fdaSRichard Lowe if (avg_b > avg_a) {
257*486c6fdaSRichard Lowe return (1);
258*486c6fdaSRichard Lowe } else if (avg_b < avg_a) {
259*486c6fdaSRichard Lowe return (-1);
260*486c6fdaSRichard Lowe } else {
261*486c6fdaSRichard Lowe return (0);
262*486c6fdaSRichard Lowe }
263*486c6fdaSRichard Lowe }
264*486c6fdaSRichard Lowe
265*486c6fdaSRichard Lowe /*
266*486c6fdaSRichard Lowe * Create pipe for signal handler and wakeup.
267*486c6fdaSRichard Lowe */
268*486c6fdaSRichard Lowe void
lt_gpipe_init(void)269*486c6fdaSRichard Lowe lt_gpipe_init(void)
270*486c6fdaSRichard Lowe {
271*486c6fdaSRichard Lowe (void) pipe(signal_pipe);
272*486c6fdaSRichard Lowe }
273*486c6fdaSRichard Lowe
274*486c6fdaSRichard Lowe /*
275*486c6fdaSRichard Lowe * Close the pipe used in signal handler.
276*486c6fdaSRichard Lowe */
277*486c6fdaSRichard Lowe void
lt_gpipe_deinit(void)278*486c6fdaSRichard Lowe lt_gpipe_deinit(void)
279*486c6fdaSRichard Lowe {
280*486c6fdaSRichard Lowe (void) close(signal_pipe[0]);
281*486c6fdaSRichard Lowe (void) close(signal_pipe[1]);
282*486c6fdaSRichard Lowe }
283*486c6fdaSRichard Lowe
284*486c6fdaSRichard Lowe /*
285*486c6fdaSRichard Lowe * Break early from the main loop.
286*486c6fdaSRichard Lowe */
287*486c6fdaSRichard Lowe void
lt_gpipe_break(const char * ch)288*486c6fdaSRichard Lowe lt_gpipe_break(const char *ch)
289*486c6fdaSRichard Lowe {
290*486c6fdaSRichard Lowe (void) write(signal_pipe[1], ch, 1);
291*486c6fdaSRichard Lowe }
292*486c6fdaSRichard Lowe
293*486c6fdaSRichard Lowe int
lt_gpipe_readfd(void)294*486c6fdaSRichard Lowe lt_gpipe_readfd(void)
295*486c6fdaSRichard Lowe {
296*486c6fdaSRichard Lowe return (signal_pipe[0]);
297*486c6fdaSRichard Lowe }
298*486c6fdaSRichard Lowe
299*486c6fdaSRichard Lowe /*
300*486c6fdaSRichard Lowe * Check if the given file exists.
301*486c6fdaSRichard Lowe */
302*486c6fdaSRichard Lowe int
lt_file_exist(const char * name)303*486c6fdaSRichard Lowe lt_file_exist(const char *name)
304*486c6fdaSRichard Lowe {
305*486c6fdaSRichard Lowe struct stat64 st;
306*486c6fdaSRichard Lowe
307*486c6fdaSRichard Lowe if (stat64(name, &st) == 0) {
308*486c6fdaSRichard Lowe return (1);
309*486c6fdaSRichard Lowe } else {
310*486c6fdaSRichard Lowe return (0);
311*486c6fdaSRichard Lowe }
312*486c6fdaSRichard Lowe }
313