xref: /onnv-gate/usr/src/cmd/wbem/provider/tools/rds/rdimpl.c (revision 0:68f95e015346)
1*0Sstevel@tonic-gate /*
2*0Sstevel@tonic-gate  * CDDL HEADER START
3*0Sstevel@tonic-gate  *
4*0Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*0Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*0Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*0Sstevel@tonic-gate  * with the License.
8*0Sstevel@tonic-gate  *
9*0Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*0Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*0Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*0Sstevel@tonic-gate  * and limitations under the License.
13*0Sstevel@tonic-gate  *
14*0Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*0Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*0Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*0Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*0Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*0Sstevel@tonic-gate  *
20*0Sstevel@tonic-gate  * CDDL HEADER END
21*0Sstevel@tonic-gate  */
22*0Sstevel@tonic-gate /*
23*0Sstevel@tonic-gate  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
24*0Sstevel@tonic-gate  * Use is subject to license terms.
25*0Sstevel@tonic-gate  */
26*0Sstevel@tonic-gate 
27*0Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
28*0Sstevel@tonic-gate 
29*0Sstevel@tonic-gate #include <sys/types.h>
30*0Sstevel@tonic-gate #include <sys/resource.h>
31*0Sstevel@tonic-gate #include <sys/loadavg.h>
32*0Sstevel@tonic-gate #include <sys/time.h>
33*0Sstevel@tonic-gate #include <sys/stat.h>
34*0Sstevel@tonic-gate #include <sys/swap.h>
35*0Sstevel@tonic-gate #include <sys/utsname.h>
36*0Sstevel@tonic-gate 
37*0Sstevel@tonic-gate #include <stdio.h>
38*0Sstevel@tonic-gate #include <stdlib.h>
39*0Sstevel@tonic-gate #include <unistd.h>
40*0Sstevel@tonic-gate #include <dirent.h>
41*0Sstevel@tonic-gate #include <string.h>
42*0Sstevel@tonic-gate #include <errno.h>
43*0Sstevel@tonic-gate #include <poll.h>
44*0Sstevel@tonic-gate #include <ctype.h>
45*0Sstevel@tonic-gate #include <fcntl.h>
46*0Sstevel@tonic-gate #include <limits.h>
47*0Sstevel@tonic-gate #include <time.h>
48*0Sstevel@tonic-gate #include <project.h>
49*0Sstevel@tonic-gate #include <libintl.h>
50*0Sstevel@tonic-gate #include <pthread.h>
51*0Sstevel@tonic-gate 
52*0Sstevel@tonic-gate #include "rdimpl.h"
53*0Sstevel@tonic-gate #include "rdutil.h"
54*0Sstevel@tonic-gate #include "rdtable.h"
55*0Sstevel@tonic-gate #include "rdfile.h"
56*0Sstevel@tonic-gate #include "rdlist.h"
57*0Sstevel@tonic-gate 
58*0Sstevel@tonic-gate /* global variables */
59*0Sstevel@tonic-gate 
60*0Sstevel@tonic-gate extern pthread_mutex_t listLock;
61*0Sstevel@tonic-gate 
62*0Sstevel@tonic-gate list_t	lwps;		/* list of lwps/processes */
63*0Sstevel@tonic-gate list_t	users;		/* list of users */
64*0Sstevel@tonic-gate list_t	projects;	/* list of projects */
65*0Sstevel@tonic-gate list_t	processes;	/* list of processes */
66*0Sstevel@tonic-gate 
67*0Sstevel@tonic-gate sys_info_t sys_info;
68*0Sstevel@tonic-gate 
69*0Sstevel@tonic-gate jmp_buf dm_jmpbuffer;
70*0Sstevel@tonic-gate char	errmsg[NL_TEXTMAX];	/* error message max 255 */
71*0Sstevel@tonic-gate 
72*0Sstevel@tonic-gate static float	total_mem;	/* total memory usage */
73*0Sstevel@tonic-gate static float	total_cpu;	/* total cpu usage */
74*0Sstevel@tonic-gate static char *nullstr = "null";
75*0Sstevel@tonic-gate static double		loadavg[3];
76*0Sstevel@tonic-gate static DIR		*procdir;
77*0Sstevel@tonic-gate 
78*0Sstevel@tonic-gate 
79*0Sstevel@tonic-gate /*
80*0Sstevel@tonic-gate  * Add a LWP entry to the specifed list.
81*0Sstevel@tonic-gate  */
82*0Sstevel@tonic-gate lwp_info_t *
83*0Sstevel@tonic-gate list_add_lwp(list_t *list, pid_t pid, id_t lwpid)
84*0Sstevel@tonic-gate {
85*0Sstevel@tonic-gate 	lwp_info_t *lwp;
86*0Sstevel@tonic-gate 
87*0Sstevel@tonic-gate 	if (list->l_head == NULL) {
88*0Sstevel@tonic-gate 		list->l_head = list->l_tail = lwp = Zalloc(sizeof (lwp_info_t));
89*0Sstevel@tonic-gate 	} else {
90*0Sstevel@tonic-gate 		lwp = Zalloc(sizeof (lwp_info_t));
91*0Sstevel@tonic-gate 		lwp->li_prev = list->l_tail;
92*0Sstevel@tonic-gate 		((lwp_info_t *)list->l_tail)->li_next = lwp;
93*0Sstevel@tonic-gate 		list->l_tail = lwp;
94*0Sstevel@tonic-gate 	}
95*0Sstevel@tonic-gate 	lwp->li_lwpsinfo = Zalloc(sizeof (lwpsinfo_t));
96*0Sstevel@tonic-gate 	lwp->li_psinfo = Zalloc(sizeof (psinfo_t));
97*0Sstevel@tonic-gate 	lwp->li_psinfo->pr_pid = pid;
98*0Sstevel@tonic-gate 	lwp->li_lwpsinfo->pr_lwpid = lwpid;
99*0Sstevel@tonic-gate 	lwpid_add(lwp, pid, lwpid);
100*0Sstevel@tonic-gate 	list->l_count++;
101*0Sstevel@tonic-gate 	return (lwp);
102*0Sstevel@tonic-gate }
103*0Sstevel@tonic-gate 
104*0Sstevel@tonic-gate 
105*0Sstevel@tonic-gate /*
106*0Sstevel@tonic-gate  * Remove an LWP entry from the specified list.
107*0Sstevel@tonic-gate  */
108*0Sstevel@tonic-gate static void
109*0Sstevel@tonic-gate list_remove_lwp(list_t *list, lwp_info_t *lwp)
110*0Sstevel@tonic-gate {
111*0Sstevel@tonic-gate 
112*0Sstevel@tonic-gate 	if (lwp->li_prev)
113*0Sstevel@tonic-gate 		lwp->li_prev->li_next = lwp->li_next;
114*0Sstevel@tonic-gate 	else
115*0Sstevel@tonic-gate 		list->l_head = lwp->li_next;	/* removing the head */
116*0Sstevel@tonic-gate 	if (lwp->li_next)
117*0Sstevel@tonic-gate 		lwp->li_next->li_prev = lwp->li_prev;
118*0Sstevel@tonic-gate 	else
119*0Sstevel@tonic-gate 		list->l_tail = lwp->li_prev;	/* removing the tail */
120*0Sstevel@tonic-gate 	lwpid_del(lwp->li_psinfo->pr_pid, lwp->li_lwpsinfo->pr_lwpid);
121*0Sstevel@tonic-gate 	if (lwpid_pidcheck(lwp->li_psinfo->pr_pid) == 0)
122*0Sstevel@tonic-gate 		fds_rm(lwp->li_psinfo->pr_pid);
123*0Sstevel@tonic-gate 	list->l_count--;
124*0Sstevel@tonic-gate 	Free(lwp->li_lwpsinfo);
125*0Sstevel@tonic-gate 	Free(lwp->li_psinfo);
126*0Sstevel@tonic-gate 	Free(lwp);
127*0Sstevel@tonic-gate }
128*0Sstevel@tonic-gate 
129*0Sstevel@tonic-gate 
130*0Sstevel@tonic-gate /*
131*0Sstevel@tonic-gate  * Remove entry from the specified list.
132*0Sstevel@tonic-gate  */
133*0Sstevel@tonic-gate static void
134*0Sstevel@tonic-gate list_remove_id(list_t *list, id_info_t *id)
135*0Sstevel@tonic-gate {
136*0Sstevel@tonic-gate 
137*0Sstevel@tonic-gate 	if (id->id_prev)
138*0Sstevel@tonic-gate 		id->id_prev->id_next = id->id_next;
139*0Sstevel@tonic-gate 	else
140*0Sstevel@tonic-gate 		list->l_head = id->id_next;	/* removing the head */
141*0Sstevel@tonic-gate 	if (id->id_next)
142*0Sstevel@tonic-gate 		id->id_next->id_prev = id->id_prev;
143*0Sstevel@tonic-gate 	else
144*0Sstevel@tonic-gate 		list->l_tail = id->id_prev;	/* removing the tail */
145*0Sstevel@tonic-gate 
146*0Sstevel@tonic-gate 	list->l_count--;
147*0Sstevel@tonic-gate 	/* anly free if doesn't point to static 'nullstr' def */
148*0Sstevel@tonic-gate 	if (id->id_name != nullstr)
149*0Sstevel@tonic-gate 		Free(id->id_name);
150*0Sstevel@tonic-gate 	Free(id);
151*0Sstevel@tonic-gate }
152*0Sstevel@tonic-gate 
153*0Sstevel@tonic-gate 
154*0Sstevel@tonic-gate /*
155*0Sstevel@tonic-gate  * Empty the specified list.
156*0Sstevel@tonic-gate  * If it's an LWP list, this will traverse /proc to
157*0Sstevel@tonic-gate  * restore microstate accounting to its original value.
158*0Sstevel@tonic-gate  */
159*0Sstevel@tonic-gate void
160*0Sstevel@tonic-gate list_clear(list_t *list)
161*0Sstevel@tonic-gate {
162*0Sstevel@tonic-gate 	if (list->l_type == LT_LWPS) {
163*0Sstevel@tonic-gate 		lwp_info_t	*lwp = list->l_tail;
164*0Sstevel@tonic-gate 		lwp_info_t	*lwp_tmp;
165*0Sstevel@tonic-gate 
166*0Sstevel@tonic-gate 		fd_closeall();
167*0Sstevel@tonic-gate 		while (lwp) {
168*0Sstevel@tonic-gate 			lwp_tmp = lwp;
169*0Sstevel@tonic-gate 			lwp = lwp->li_prev;
170*0Sstevel@tonic-gate 			list_remove_lwp(&lwps, lwp_tmp);
171*0Sstevel@tonic-gate 		}
172*0Sstevel@tonic-gate 	} else {
173*0Sstevel@tonic-gate 		id_info_t *id = list->l_head;
174*0Sstevel@tonic-gate 		id_info_t *nextid;
175*0Sstevel@tonic-gate 		while (id) {
176*0Sstevel@tonic-gate 			nextid = id->id_next;
177*0Sstevel@tonic-gate 			/* anly free if doesn't point to static 'nullstr' def */
178*0Sstevel@tonic-gate 			if (id->id_name != nullstr)
179*0Sstevel@tonic-gate 				Free(id->id_name);
180*0Sstevel@tonic-gate 			Free(id);
181*0Sstevel@tonic-gate 			id = nextid;
182*0Sstevel@tonic-gate 		}
183*0Sstevel@tonic-gate 		list->l_count = 0;
184*0Sstevel@tonic-gate 		list->l_head = list->l_tail = NULL;
185*0Sstevel@tonic-gate 	}
186*0Sstevel@tonic-gate }
187*0Sstevel@tonic-gate 
188*0Sstevel@tonic-gate 
189*0Sstevel@tonic-gate /*
190*0Sstevel@tonic-gate  * Calculate a process' statistics from its lwp statistics.
191*0Sstevel@tonic-gate  */
192*0Sstevel@tonic-gate static void
193*0Sstevel@tonic-gate id_update(id_info_t *id, lwp_info_t *lwp, int l_type) {
194*0Sstevel@tonic-gate 	char usrname[LOGNAME_MAX+1];
195*0Sstevel@tonic-gate 	char projname[PROJNAME_MAX+1];
196*0Sstevel@tonic-gate 
197*0Sstevel@tonic-gate 	/*
198*0Sstevel@tonic-gate 	 * When an id is processed first time in an update run its
199*0Sstevel@tonic-gate 	 * id_alive flag set to false.
200*0Sstevel@tonic-gate 	 * The next values are gauges, their old values from the previous
201*0Sstevel@tonic-gate 	 * calculation should be set to null.
202*0Sstevel@tonic-gate 	 * The names and timestamp must be set once.
203*0Sstevel@tonic-gate 	 */
204*0Sstevel@tonic-gate 	if (id->id_alive == B_FALSE) {
205*0Sstevel@tonic-gate 		id->id_hpsize = 0;
206*0Sstevel@tonic-gate 		id->id_size = 0;
207*0Sstevel@tonic-gate 		id->id_rssize = 0;
208*0Sstevel@tonic-gate 		id->id_pctmem = 0;
209*0Sstevel@tonic-gate 		id->id_timestamp = 0;
210*0Sstevel@tonic-gate 		id->id_time = 0;
211*0Sstevel@tonic-gate 		id->id_pctcpu = 0;
212*0Sstevel@tonic-gate 		id->id_nlwps = 0;
213*0Sstevel@tonic-gate 		id->id_nproc = 0;
214*0Sstevel@tonic-gate 		id->id_pid = (int)-1;
215*0Sstevel@tonic-gate 		id->id_taskid	= lwp->li_psinfo->pr_taskid;
216*0Sstevel@tonic-gate 		id->id_projid	= lwp->li_psinfo->pr_projid;
217*0Sstevel@tonic-gate 		id->id_psetid	= lwp->li_lwpsinfo->pr_bindpset;
218*0Sstevel@tonic-gate 		id->id_uid	= lwp->li_psinfo->pr_uid;
219*0Sstevel@tonic-gate 		if (l_type == LT_USERS) {
220*0Sstevel@tonic-gate 			getusrname(id->id_uid, usrname, LOGNAME_MAX+1);
221*0Sstevel@tonic-gate 			id->id_name = Realloc(id->id_name,
222*0Sstevel@tonic-gate 					strlen(usrname) + 1);
223*0Sstevel@tonic-gate 			(void) strcpy(id->id_name, usrname);
224*0Sstevel@tonic-gate 		} else if (l_type == LT_PROJECTS) {
225*0Sstevel@tonic-gate 			getprojname(id->id_projid, projname, PROJNAME_MAX);
226*0Sstevel@tonic-gate 			id->id_name = Realloc(id->id_name,
227*0Sstevel@tonic-gate 					strlen(projname) + 1);
228*0Sstevel@tonic-gate 			(void) strcpy(id->id_name, projname);
229*0Sstevel@tonic-gate 		} else {
230*0Sstevel@tonic-gate 			id->id_name = nullstr;
231*0Sstevel@tonic-gate 		}
232*0Sstevel@tonic-gate 		id->id_timestamp = get_timestamp();
233*0Sstevel@tonic-gate 		/* mark this id as changed in this update run */
234*0Sstevel@tonic-gate 		id->id_alive = B_TRUE;
235*0Sstevel@tonic-gate 	}
236*0Sstevel@tonic-gate 
237*0Sstevel@tonic-gate 	if (lwp->li_psinfo->pr_nlwp > 0) {
238*0Sstevel@tonic-gate 	    id->id_nlwps++;
239*0Sstevel@tonic-gate 	}
240*0Sstevel@tonic-gate 
241*0Sstevel@tonic-gate 	/*
242*0Sstevel@tonic-gate 	 * The next values are calculated only one time for each pid.
243*0Sstevel@tonic-gate 	 */
244*0Sstevel@tonic-gate 	if ((id->id_pid != lwp->li_psinfo->pr_pid) &&
245*0Sstevel@tonic-gate 		(lwp->rlwpid == lwp->li_lwpsinfo->pr_lwpid)) {
246*0Sstevel@tonic-gate 		id->id_nproc++;
247*0Sstevel@tonic-gate 		id->id_hpsize	+= (lwp->li_hpsize/1024);
248*0Sstevel@tonic-gate 		id->id_size	+= lwp->li_psinfo->pr_size;
249*0Sstevel@tonic-gate 		id->id_rssize	+= lwp->li_psinfo->pr_rssize;
250*0Sstevel@tonic-gate 		id->id_pctmem	+= FRC2PCT(lwp->li_psinfo->pr_pctmem);
251*0Sstevel@tonic-gate 		id->id_pid	= lwp->li_psinfo->pr_pid;
252*0Sstevel@tonic-gate 		if (l_type == LT_PROCESS)
253*0Sstevel@tonic-gate 			total_mem += FRC2PCT(lwp->li_psinfo->pr_pctmem);
254*0Sstevel@tonic-gate 	}
255*0Sstevel@tonic-gate 
256*0Sstevel@tonic-gate 	id->id_pctcpu	+= FRC2PCT(lwp->li_lwpsinfo->pr_pctcpu);
257*0Sstevel@tonic-gate 	if (l_type == LT_PROCESS)
258*0Sstevel@tonic-gate 		total_cpu += FRC2PCT(lwp->li_lwpsinfo->pr_pctcpu);
259*0Sstevel@tonic-gate 	id->id_time	+= TIME2SEC(lwp->li_lwpsinfo->pr_time);
260*0Sstevel@tonic-gate 	id->id_usr	+= lwp->li_usr;
261*0Sstevel@tonic-gate 	id->id_sys	+= lwp->li_sys;
262*0Sstevel@tonic-gate 	id->id_ttime	+= lwp->li_ttime;
263*0Sstevel@tonic-gate 	id->id_tpftime	+= lwp->li_tpftime;
264*0Sstevel@tonic-gate 	id->id_dpftime	+= lwp->li_dpftime;
265*0Sstevel@tonic-gate 	id->id_kpftime	+= lwp->li_kpftime;
266*0Sstevel@tonic-gate 	id->id_lck	+= lwp->li_lck;
267*0Sstevel@tonic-gate 	id->id_slp	+= lwp->li_slp;
268*0Sstevel@tonic-gate 	id->id_lat	+= lwp->li_lat;
269*0Sstevel@tonic-gate 	id->id_stime	+= lwp->li_stime;
270*0Sstevel@tonic-gate 	id->id_minf	+= lwp->li_minf;
271*0Sstevel@tonic-gate 	id->id_majf	+= lwp->li_majf;
272*0Sstevel@tonic-gate 	id->id_nswap	+= lwp->li_nswap;
273*0Sstevel@tonic-gate 	id->id_inblk	+= lwp->li_inblk;
274*0Sstevel@tonic-gate 	id->id_oublk	+= lwp->li_oublk;
275*0Sstevel@tonic-gate 	id->id_msnd	+= lwp->li_msnd;
276*0Sstevel@tonic-gate 	id->id_mrcv	+= lwp->li_mrcv;
277*0Sstevel@tonic-gate 	id->id_sigs	+= lwp->li_sigs;
278*0Sstevel@tonic-gate 	id->id_vctx	+= lwp->li_vctx;
279*0Sstevel@tonic-gate 	id->id_ictx	+= lwp->li_ictx;
280*0Sstevel@tonic-gate 	id->id_scl	+= lwp->li_scl;
281*0Sstevel@tonic-gate 	id->id_ioch	+= lwp->li_ioch;
282*0Sstevel@tonic-gate }
283*0Sstevel@tonic-gate 
284*0Sstevel@tonic-gate static void
285*0Sstevel@tonic-gate list_update(list_t *list, lwp_info_t *lwp)
286*0Sstevel@tonic-gate {
287*0Sstevel@tonic-gate 	id_info_t *id;
288*0Sstevel@tonic-gate 	if (list->l_head == NULL) {			/* first element */
289*0Sstevel@tonic-gate 		list->l_head = list->l_tail = id = Zalloc(sizeof (id_info_t));
290*0Sstevel@tonic-gate 		id_update(id, lwp, list->l_type);
291*0Sstevel@tonic-gate 		list->l_count++;
292*0Sstevel@tonic-gate 		return;
293*0Sstevel@tonic-gate 	}
294*0Sstevel@tonic-gate 
295*0Sstevel@tonic-gate 	for (id = list->l_head; id; id = id->id_next) {
296*0Sstevel@tonic-gate 		if ((list->l_type == LT_PROCESS) &&
297*0Sstevel@tonic-gate 			(id->id_pid != lwp->li_psinfo->pr_pid))
298*0Sstevel@tonic-gate 			continue;
299*0Sstevel@tonic-gate 		if ((list->l_type == LT_USERS) &&
300*0Sstevel@tonic-gate 			(id->id_uid != lwp->li_psinfo->pr_uid))
301*0Sstevel@tonic-gate 			continue;
302*0Sstevel@tonic-gate 		if ((list->l_type == LT_PROJECTS) &&
303*0Sstevel@tonic-gate 			(id->id_projid != lwp->li_psinfo->pr_projid))
304*0Sstevel@tonic-gate 			continue;
305*0Sstevel@tonic-gate 		id_update(id, lwp, list->l_type);
306*0Sstevel@tonic-gate 		return;
307*0Sstevel@tonic-gate 	}
308*0Sstevel@tonic-gate 
309*0Sstevel@tonic-gate 	/* a new element */
310*0Sstevel@tonic-gate 	id = list->l_tail;
311*0Sstevel@tonic-gate 	id->id_next = Zalloc(sizeof (id_info_t));
312*0Sstevel@tonic-gate 	id->id_next->id_prev = list->l_tail;
313*0Sstevel@tonic-gate 	id->id_next->id_next = NULL;
314*0Sstevel@tonic-gate 	list->l_tail = id->id_next;
315*0Sstevel@tonic-gate 	id = list->l_tail;
316*0Sstevel@tonic-gate 	id_update(id, lwp, list->l_type);
317*0Sstevel@tonic-gate 	list->l_count++;
318*0Sstevel@tonic-gate }
319*0Sstevel@tonic-gate 
320*0Sstevel@tonic-gate /*
321*0Sstevel@tonic-gate  * This procedure removes all dead procs/user/.. from the specified list.
322*0Sstevel@tonic-gate  */
323*0Sstevel@tonic-gate static void
324*0Sstevel@tonic-gate list_refresh_id(list_t *list)
325*0Sstevel@tonic-gate {
326*0Sstevel@tonic-gate 	id_info_t *id, *id_next;
327*0Sstevel@tonic-gate 
328*0Sstevel@tonic-gate 	if (!(list->l_type & LT_PROCESS) && !(list->l_type & LT_USERS) &&
329*0Sstevel@tonic-gate 		!(list->l_type & LT_TASKS) && !(list->l_type & LT_PROJECTS) &&
330*0Sstevel@tonic-gate 		!(list->l_type & LT_PSETS)) {
331*0Sstevel@tonic-gate 		return;
332*0Sstevel@tonic-gate 	}
333*0Sstevel@tonic-gate 	id = list->l_head;
334*0Sstevel@tonic-gate 
335*0Sstevel@tonic-gate 	while (id) {
336*0Sstevel@tonic-gate 		if (id->id_alive == B_FALSE) {	/* id is dead */
337*0Sstevel@tonic-gate 			id_next = id->id_next;
338*0Sstevel@tonic-gate 			list_remove_id(list, id);
339*0Sstevel@tonic-gate 			id = id_next;
340*0Sstevel@tonic-gate 		} else {
341*0Sstevel@tonic-gate 
342*0Sstevel@tonic-gate 			/* normalize total mem and cpu across all processes. */
343*0Sstevel@tonic-gate 			if (total_mem >= 100)
344*0Sstevel@tonic-gate 				id->id_pctmem = (100 * id->id_pctmem) /
345*0Sstevel@tonic-gate 						total_mem;
346*0Sstevel@tonic-gate 			if (total_cpu >= 100)
347*0Sstevel@tonic-gate 				id->id_pctcpu = (100 * id->id_pctcpu) /
348*0Sstevel@tonic-gate 						total_cpu;
349*0Sstevel@tonic-gate 
350*0Sstevel@tonic-gate 			id->id_alive = B_FALSE;
351*0Sstevel@tonic-gate 			id = id->id_next;
352*0Sstevel@tonic-gate 		}
353*0Sstevel@tonic-gate 	}
354*0Sstevel@tonic-gate }
355*0Sstevel@tonic-gate 
356*0Sstevel@tonic-gate /*
357*0Sstevel@tonic-gate  * This procedure removes all dead lwps from the specified lwp list.
358*0Sstevel@tonic-gate  */
359*0Sstevel@tonic-gate static void
360*0Sstevel@tonic-gate list_refresh(list_t *list)
361*0Sstevel@tonic-gate {
362*0Sstevel@tonic-gate 	lwp_info_t *lwp, *lwp_next;
363*0Sstevel@tonic-gate 
364*0Sstevel@tonic-gate 	if (!(list->l_type & LT_LWPS))
365*0Sstevel@tonic-gate 		return;
366*0Sstevel@tonic-gate 	lwp = list->l_head;
367*0Sstevel@tonic-gate 
368*0Sstevel@tonic-gate 	while (lwp) {
369*0Sstevel@tonic-gate 		if (lwp->li_alive == B_FALSE) {	/* lwp is dead */
370*0Sstevel@tonic-gate 			lwp_next = lwp->li_next;
371*0Sstevel@tonic-gate 			list_remove_lwp(&lwps, lwp);
372*0Sstevel@tonic-gate 			lwp = lwp_next;
373*0Sstevel@tonic-gate 		} else {
374*0Sstevel@tonic-gate 			lwp->li_alive = B_FALSE;
375*0Sstevel@tonic-gate 			lwp = lwp->li_next;
376*0Sstevel@tonic-gate 		}
377*0Sstevel@tonic-gate 	}
378*0Sstevel@tonic-gate }
379*0Sstevel@tonic-gate 
380*0Sstevel@tonic-gate 
381*0Sstevel@tonic-gate /*
382*0Sstevel@tonic-gate  * Update a LWP entry according to the specified usage data.
383*0Sstevel@tonic-gate  */
384*0Sstevel@tonic-gate static void
385*0Sstevel@tonic-gate lwp_update(lwp_info_t *lwp, struct prusage *usage_buf)
386*0Sstevel@tonic-gate {
387*0Sstevel@tonic-gate 	lwp->li_usr	= (double)(TIME2NSEC(usage_buf->pr_utime) -
388*0Sstevel@tonic-gate 			TIME2NSEC(lwp->li_usage.pr_utime)) / NANOSEC;
389*0Sstevel@tonic-gate 	lwp->li_sys	= (double)(TIME2NSEC(usage_buf->pr_stime) -
390*0Sstevel@tonic-gate 			TIME2NSEC(lwp->li_usage.pr_stime)) / NANOSEC;
391*0Sstevel@tonic-gate 	lwp->li_ttime	= (double)(TIME2NSEC(usage_buf->pr_ttime) -
392*0Sstevel@tonic-gate 			TIME2NSEC(lwp->li_usage.pr_ttime)) / NANOSEC;
393*0Sstevel@tonic-gate 	lwp->li_tpftime = (double)(TIME2NSEC(usage_buf->pr_tftime) -
394*0Sstevel@tonic-gate 			TIME2NSEC(lwp->li_usage.pr_tftime)) / NANOSEC;
395*0Sstevel@tonic-gate 	lwp->li_dpftime = (double)(TIME2NSEC(usage_buf->pr_dftime) -
396*0Sstevel@tonic-gate 			TIME2NSEC(lwp->li_usage.pr_dftime)) / NANOSEC;
397*0Sstevel@tonic-gate 	lwp->li_kpftime = (double)(TIME2NSEC(usage_buf->pr_kftime) -
398*0Sstevel@tonic-gate 			TIME2NSEC(lwp->li_usage.pr_kftime)) / NANOSEC;
399*0Sstevel@tonic-gate 	lwp->li_lck	= (double)(TIME2NSEC(usage_buf->pr_ltime) -
400*0Sstevel@tonic-gate 			TIME2NSEC(lwp->li_usage.pr_ltime)) / NANOSEC;
401*0Sstevel@tonic-gate 	lwp->li_slp	= (double)(TIME2NSEC(usage_buf->pr_slptime) -
402*0Sstevel@tonic-gate 			TIME2NSEC(lwp->li_usage.pr_slptime)) / NANOSEC;
403*0Sstevel@tonic-gate 	lwp->li_lat	= (double)(TIME2NSEC(usage_buf->pr_wtime) -
404*0Sstevel@tonic-gate 			TIME2NSEC(lwp->li_usage.pr_wtime)) / NANOSEC;
405*0Sstevel@tonic-gate 	lwp->li_stime	= (double)(TIME2NSEC(usage_buf->pr_stoptime) -
406*0Sstevel@tonic-gate 			TIME2NSEC(lwp->li_usage.pr_stoptime)) / NANOSEC;
407*0Sstevel@tonic-gate 	lwp->li_minf = usage_buf->pr_minf - lwp->li_usage.pr_minf;
408*0Sstevel@tonic-gate 	lwp->li_majf = usage_buf->pr_majf - lwp->li_usage.pr_majf;
409*0Sstevel@tonic-gate 	lwp->li_nswap = usage_buf->pr_nswap - lwp->li_usage.pr_nswap;
410*0Sstevel@tonic-gate 	lwp->li_inblk = usage_buf->pr_inblk - lwp->li_usage.pr_inblk;
411*0Sstevel@tonic-gate 	lwp->li_oublk = usage_buf->pr_oublk -lwp->li_usage.pr_oublk;
412*0Sstevel@tonic-gate 	lwp->li_msnd = usage_buf->pr_msnd - lwp->li_usage.pr_msnd;
413*0Sstevel@tonic-gate 	lwp->li_mrcv = usage_buf->pr_mrcv - lwp->li_usage.pr_mrcv;
414*0Sstevel@tonic-gate 	lwp->li_sigs = usage_buf->pr_sigs - lwp->li_usage.pr_sigs;
415*0Sstevel@tonic-gate 	lwp->li_vctx = usage_buf->pr_vctx - lwp->li_usage.pr_vctx;
416*0Sstevel@tonic-gate 	lwp->li_ictx = usage_buf->pr_ictx - lwp->li_usage.pr_ictx;
417*0Sstevel@tonic-gate 	lwp->li_scl = usage_buf->pr_sysc - lwp->li_usage.pr_sysc;
418*0Sstevel@tonic-gate 	lwp->li_ioch = usage_buf->pr_ioch - lwp->li_usage.pr_ioch;
419*0Sstevel@tonic-gate 	lwp->li_timestamp = TIME2NSEC(usage_buf->pr_tstamp);
420*0Sstevel@tonic-gate 	(void) memcpy(&lwp->li_usage, usage_buf, sizeof (prusage_t));
421*0Sstevel@tonic-gate }
422*0Sstevel@tonic-gate 
423*0Sstevel@tonic-gate 
424*0Sstevel@tonic-gate /*
425*0Sstevel@tonic-gate  * This is the meat of the /proc scanner.
426*0Sstevel@tonic-gate  * It will visit every single LWP in /proc.
427*0Sstevel@tonic-gate  */
428*0Sstevel@tonic-gate static void
429*0Sstevel@tonic-gate collect_lwp_data()
430*0Sstevel@tonic-gate {
431*0Sstevel@tonic-gate 	char *pidstr;
432*0Sstevel@tonic-gate 	pid_t pid;
433*0Sstevel@tonic-gate 	id_t lwpid;
434*0Sstevel@tonic-gate 	size_t entsz;
435*0Sstevel@tonic-gate 	long nlwps, nent, i;
436*0Sstevel@tonic-gate 	char *buf, *ptr;
437*0Sstevel@tonic-gate 	char pfile[MAX_PROCFS_PATH];
438*0Sstevel@tonic-gate 
439*0Sstevel@tonic-gate 	fds_t *fds;
440*0Sstevel@tonic-gate 	lwp_info_t *lwp;
441*0Sstevel@tonic-gate 
442*0Sstevel@tonic-gate 	dirent_t *direntp;
443*0Sstevel@tonic-gate 
444*0Sstevel@tonic-gate 	prheader_t	header_buf;
445*0Sstevel@tonic-gate 	psinfo_t	psinfo_buf;
446*0Sstevel@tonic-gate 	prusage_t	usage_buf;
447*0Sstevel@tonic-gate 	lwpsinfo_t	*lwpsinfo_buf;
448*0Sstevel@tonic-gate 	prusage_t	*lwpusage_buf;
449*0Sstevel@tonic-gate 
450*0Sstevel@tonic-gate 	log_msg("->collect_lwp_data(): %d files open\n", fd_count());
451*0Sstevel@tonic-gate 	for (rewinddir(procdir); (direntp = readdir(procdir)); ) {
452*0Sstevel@tonic-gate 		pidstr = direntp->d_name;
453*0Sstevel@tonic-gate 		if (pidstr[0] == '.')	/* skip "." and ".."  */
454*0Sstevel@tonic-gate 			continue;
455*0Sstevel@tonic-gate 		pid = atoi(pidstr);
456*0Sstevel@tonic-gate 		if (pid == 0 || pid == 2 || pid == 3)
457*0Sstevel@tonic-gate 			continue;	/* skip sched, pageout and fsflush */
458*0Sstevel@tonic-gate 
459*0Sstevel@tonic-gate 		fds = fds_get(pid);	/* get ptr to file descriptors */
460*0Sstevel@tonic-gate 
461*0Sstevel@tonic-gate 		/*
462*0Sstevel@tonic-gate 		 * Here we are going to read information about
463*0Sstevel@tonic-gate 		 * current process (pid) from /proc/pid/psinfo file.
464*0Sstevel@tonic-gate 		 * If process has more than one lwp, we also should
465*0Sstevel@tonic-gate 		 * read /proc/pid/lpsinfo for information about all lwps.
466*0Sstevel@tonic-gate 		 */
467*0Sstevel@tonic-gate 		(void) snprintf(pfile, MAX_PROCFS_PATH,
468*0Sstevel@tonic-gate 			"/proc/%s/psinfo", pidstr);
469*0Sstevel@tonic-gate 		if ((fds->fds_psinfo = fd_open(pfile, O_RDONLY,
470*0Sstevel@tonic-gate 			fds->fds_psinfo)) == NULL)
471*0Sstevel@tonic-gate 			continue;
472*0Sstevel@tonic-gate 		if (pread(fd_getfd(fds->fds_psinfo), &psinfo_buf,
473*0Sstevel@tonic-gate 			sizeof (struct psinfo), 0) != sizeof (struct psinfo)) {
474*0Sstevel@tonic-gate 			fd_close(fds->fds_psinfo);
475*0Sstevel@tonic-gate 			continue;
476*0Sstevel@tonic-gate 		}
477*0Sstevel@tonic-gate 
478*0Sstevel@tonic-gate 		fd_close(fds->fds_psinfo);
479*0Sstevel@tonic-gate 
480*0Sstevel@tonic-gate 		nlwps = psinfo_buf.pr_nlwp + psinfo_buf.pr_nzomb;
481*0Sstevel@tonic-gate 		if (nlwps > 1) {
482*0Sstevel@tonic-gate 			(void) snprintf(pfile, MAX_PROCFS_PATH,
483*0Sstevel@tonic-gate 				"/proc/%s/lpsinfo", pidstr);
484*0Sstevel@tonic-gate 			if ((fds->fds_lpsinfo = fd_open(pfile, O_RDONLY,
485*0Sstevel@tonic-gate 			    fds->fds_lpsinfo)) == NULL)
486*0Sstevel@tonic-gate 				continue;
487*0Sstevel@tonic-gate 			entsz = sizeof (struct prheader);
488*0Sstevel@tonic-gate 			if (pread(fd_getfd(fds->fds_lpsinfo), &header_buf,
489*0Sstevel@tonic-gate 				entsz, 0) != entsz) {
490*0Sstevel@tonic-gate 				fd_close(fds->fds_lpsinfo);
491*0Sstevel@tonic-gate 				continue;
492*0Sstevel@tonic-gate 			}
493*0Sstevel@tonic-gate 			nent = header_buf.pr_nent;
494*0Sstevel@tonic-gate 			entsz = header_buf.pr_entsize * nent;
495*0Sstevel@tonic-gate 			ptr = buf = Malloc(entsz);
496*0Sstevel@tonic-gate 			if (pread(fd_getfd(fds->fds_lpsinfo), buf,
497*0Sstevel@tonic-gate 			    entsz, sizeof (struct prheader)) != entsz) {
498*0Sstevel@tonic-gate 				fd_close(fds->fds_lpsinfo);
499*0Sstevel@tonic-gate 				Free(buf);
500*0Sstevel@tonic-gate 				continue;
501*0Sstevel@tonic-gate 			}
502*0Sstevel@tonic-gate 
503*0Sstevel@tonic-gate 			fd_close(fds->fds_lpsinfo);
504*0Sstevel@tonic-gate 
505*0Sstevel@tonic-gate 			for (i = 0; i < nent;
506*0Sstevel@tonic-gate 				i++, ptr += header_buf.pr_entsize) {
507*0Sstevel@tonic-gate 				/*LINTED ALIGNMENT*/
508*0Sstevel@tonic-gate 				lwpsinfo_buf = (lwpsinfo_t *)ptr;
509*0Sstevel@tonic-gate 				lwpid = lwpsinfo_buf->pr_lwpid;
510*0Sstevel@tonic-gate 				if ((lwp = lwpid_get(pid, lwpid)) == NULL) {
511*0Sstevel@tonic-gate 					lwp = list_add_lwp(&lwps, pid, lwpid);
512*0Sstevel@tonic-gate 				}
513*0Sstevel@tonic-gate 				if (i == 0)
514*0Sstevel@tonic-gate 					lwp->rlwpid = lwpid;
515*0Sstevel@tonic-gate 				(void) memcpy(lwp->li_psinfo, &psinfo_buf,
516*0Sstevel@tonic-gate 					sizeof (psinfo_t) -
517*0Sstevel@tonic-gate 					sizeof (lwpsinfo_t));
518*0Sstevel@tonic-gate 				lwp->li_alive = B_TRUE;
519*0Sstevel@tonic-gate 				(void) memcpy(lwp->li_lwpsinfo,
520*0Sstevel@tonic-gate 					lwpsinfo_buf, sizeof (lwpsinfo_t));
521*0Sstevel@tonic-gate 			}
522*0Sstevel@tonic-gate 			Free(buf);
523*0Sstevel@tonic-gate 		} else {
524*0Sstevel@tonic-gate 			lwpid = psinfo_buf.pr_lwp.pr_lwpid;
525*0Sstevel@tonic-gate 			if ((lwp = lwpid_get(pid, lwpid)) == NULL) {
526*0Sstevel@tonic-gate 				lwp = list_add_lwp(&lwps, pid, lwpid);
527*0Sstevel@tonic-gate 			}
528*0Sstevel@tonic-gate 			lwp->rlwpid = lwpid;
529*0Sstevel@tonic-gate 			(void) memcpy(lwp->li_psinfo, &psinfo_buf,
530*0Sstevel@tonic-gate 					sizeof (psinfo_t) -
531*0Sstevel@tonic-gate 					sizeof (lwpsinfo_t));
532*0Sstevel@tonic-gate 			lwp->li_alive = B_TRUE;
533*0Sstevel@tonic-gate 			(void) memcpy(lwp->li_lwpsinfo,
534*0Sstevel@tonic-gate 				&psinfo_buf.pr_lwp, sizeof (lwpsinfo_t));
535*0Sstevel@tonic-gate 			lwp->li_lwpsinfo->pr_pctcpu =
536*0Sstevel@tonic-gate 					lwp->li_psinfo->pr_pctcpu;
537*0Sstevel@tonic-gate 		}
538*0Sstevel@tonic-gate 
539*0Sstevel@tonic-gate 		/*
540*0Sstevel@tonic-gate 		 * At this part of scandir we read additional information
541*0Sstevel@tonic-gate 		 * about processes from /proc/pid/usage file.
542*0Sstevel@tonic-gate 		 * Again, if process has more than one lwp, then we
543*0Sstevel@tonic-gate 		 * will get information about all its lwps from
544*0Sstevel@tonic-gate 		 * /proc/pid/lusage file.
545*0Sstevel@tonic-gate 		 */
546*0Sstevel@tonic-gate 		if (nlwps > 1) {
547*0Sstevel@tonic-gate 			(void) snprintf(pfile, MAX_PROCFS_PATH,
548*0Sstevel@tonic-gate 				"/proc/%s/lusage", pidstr);
549*0Sstevel@tonic-gate 			if ((fds->fds_lusage = fd_open(pfile, O_RDONLY,
550*0Sstevel@tonic-gate 				fds->fds_lusage)) == NULL)
551*0Sstevel@tonic-gate 				continue;
552*0Sstevel@tonic-gate 			entsz = sizeof (struct prheader);
553*0Sstevel@tonic-gate 			if (pread(fd_getfd(fds->fds_lusage), &header_buf,
554*0Sstevel@tonic-gate 				entsz, 0) != entsz) {
555*0Sstevel@tonic-gate 				fd_close(fds->fds_lusage);
556*0Sstevel@tonic-gate 				continue;
557*0Sstevel@tonic-gate 			}
558*0Sstevel@tonic-gate 
559*0Sstevel@tonic-gate 			nent = header_buf.pr_nent;
560*0Sstevel@tonic-gate 			entsz = header_buf.pr_entsize * nent;
561*0Sstevel@tonic-gate 			buf = Malloc(entsz);
562*0Sstevel@tonic-gate 			if (pread(fd_getfd(fds->fds_lusage), buf,
563*0Sstevel@tonic-gate 				entsz, sizeof (struct prheader)) != entsz) {
564*0Sstevel@tonic-gate 				fd_close(fds->fds_lusage);
565*0Sstevel@tonic-gate 				Free(buf);
566*0Sstevel@tonic-gate 				continue;
567*0Sstevel@tonic-gate 			}
568*0Sstevel@tonic-gate 
569*0Sstevel@tonic-gate 			fd_close(fds->fds_lusage);
570*0Sstevel@tonic-gate 
571*0Sstevel@tonic-gate 			for (i = 1, ptr = buf + header_buf.pr_entsize; i < nent;
572*0Sstevel@tonic-gate 				i++, ptr += header_buf.pr_entsize) {
573*0Sstevel@tonic-gate 				/*LINTED ALIGNMENT*/
574*0Sstevel@tonic-gate 				lwpusage_buf = (prusage_t *)ptr;
575*0Sstevel@tonic-gate 				lwpid = lwpusage_buf->pr_lwpid;
576*0Sstevel@tonic-gate 				if ((lwp = lwpid_get(pid, lwpid)) == NULL)
577*0Sstevel@tonic-gate 					continue;
578*0Sstevel@tonic-gate 				lwp_update(lwp, lwpusage_buf);
579*0Sstevel@tonic-gate 			}
580*0Sstevel@tonic-gate 			Free(buf);
581*0Sstevel@tonic-gate 		} else {
582*0Sstevel@tonic-gate 			(void) snprintf(pfile, MAX_PROCFS_PATH,
583*0Sstevel@tonic-gate 				"/proc/%s/usage", pidstr);
584*0Sstevel@tonic-gate 			if ((fds->fds_usage = fd_open(pfile, O_RDONLY,
585*0Sstevel@tonic-gate 				fds->fds_usage)) == NULL)
586*0Sstevel@tonic-gate 				continue;
587*0Sstevel@tonic-gate 			entsz = sizeof (prusage_t);
588*0Sstevel@tonic-gate 			if (pread(fd_getfd(fds->fds_usage), &usage_buf,
589*0Sstevel@tonic-gate 				entsz, 0) != entsz) {
590*0Sstevel@tonic-gate 				fd_close(fds->fds_usage);
591*0Sstevel@tonic-gate 				continue;
592*0Sstevel@tonic-gate 			}
593*0Sstevel@tonic-gate 
594*0Sstevel@tonic-gate 			fd_close(fds->fds_usage);
595*0Sstevel@tonic-gate 
596*0Sstevel@tonic-gate 			lwpid = psinfo_buf.pr_lwp.pr_lwpid;
597*0Sstevel@tonic-gate 			if ((lwp = lwpid_get(pid, lwpid)) == NULL)
598*0Sstevel@tonic-gate 				continue;
599*0Sstevel@tonic-gate 			lwp_update(lwp, &usage_buf);
600*0Sstevel@tonic-gate 		}
601*0Sstevel@tonic-gate 	}
602*0Sstevel@tonic-gate 	list_refresh(&lwps);
603*0Sstevel@tonic-gate 	fd_update();
604*0Sstevel@tonic-gate 	log_msg("<-collect_lwp_data(): %d files open\n", fd_count());
605*0Sstevel@tonic-gate }
606*0Sstevel@tonic-gate 
607*0Sstevel@tonic-gate 
608*0Sstevel@tonic-gate /*
609*0Sstevel@tonic-gate  * Create linked lists of users, projects and sets.
610*0Sstevel@tonic-gate  *
611*0Sstevel@tonic-gate  * Updates of the process, users and projects lists are done in
612*0Sstevel@tonic-gate  * a critical section so that the consumer of these lists will
613*0Sstevel@tonic-gate  * always get consistent data.
614*0Sstevel@tonic-gate  */
615*0Sstevel@tonic-gate static void
616*0Sstevel@tonic-gate list_create()
617*0Sstevel@tonic-gate {
618*0Sstevel@tonic-gate 	struct utsname	utsn;
619*0Sstevel@tonic-gate 	lwp_info_t *lwp;
620*0Sstevel@tonic-gate 	hrtime_t t1, t2, t3;
621*0Sstevel@tonic-gate 	double d;
622*0Sstevel@tonic-gate 	int rv;
623*0Sstevel@tonic-gate 
624*0Sstevel@tonic-gate 	lwp = lwps.l_head;
625*0Sstevel@tonic-gate 	total_mem = 0;
626*0Sstevel@tonic-gate 	total_cpu = 0;
627*0Sstevel@tonic-gate 	log_msg("->list_create()\n");
628*0Sstevel@tonic-gate 	t1 = gethrtime();
629*0Sstevel@tonic-gate 	if ((rv = pthread_mutex_lock(&listLock)) == 0) {
630*0Sstevel@tonic-gate 	    t2 = gethrtime();
631*0Sstevel@tonic-gate 	    d = (double)(t2 - t1) / 1000000000.0;
632*0Sstevel@tonic-gate 	    log_msg("Scanner process lock wait was %1.5f sec\n", d);
633*0Sstevel@tonic-gate 
634*0Sstevel@tonic-gate 	    while (lwp) {
635*0Sstevel@tonic-gate 			list_update(&processes, lwp);
636*0Sstevel@tonic-gate 			list_update(&users, lwp);
637*0Sstevel@tonic-gate 			list_update(&projects, lwp);
638*0Sstevel@tonic-gate 			lwp = lwp->li_next;
639*0Sstevel@tonic-gate 	    }
640*0Sstevel@tonic-gate 	    list_refresh_id(&processes);
641*0Sstevel@tonic-gate 	    list_refresh_id(&users);
642*0Sstevel@tonic-gate 	    list_refresh_id(&projects);
643*0Sstevel@tonic-gate 	    /* release the mutex */
644*0Sstevel@tonic-gate 	    if ((rv = pthread_mutex_unlock(&listLock)) != 0) {
645*0Sstevel@tonic-gate 			log_msg("pthread_mutex_unlock failed with %d\n", rv);
646*0Sstevel@tonic-gate 	    }
647*0Sstevel@tonic-gate 
648*0Sstevel@tonic-gate 	    t3 = gethrtime();
649*0Sstevel@tonic-gate 
650*0Sstevel@tonic-gate 	    d = (double)(t3 - t2) / 1000000000.0;
651*0Sstevel@tonic-gate 	    log_msg("Scanner process lock time was %1.5f sec\n", d);
652*0Sstevel@tonic-gate 
653*0Sstevel@tonic-gate 	} else {
654*0Sstevel@tonic-gate 	    log_msg("pthread_mutex_lock failed with %d\n", rv);
655*0Sstevel@tonic-gate 	}
656*0Sstevel@tonic-gate 
657*0Sstevel@tonic-gate 	if (uname(&utsn) != -1) {
658*0Sstevel@tonic-gate 		sys_info.name =
659*0Sstevel@tonic-gate 			Realloc(sys_info.name, strlen(utsn.sysname) + 1);
660*0Sstevel@tonic-gate 		(void) strcpy(sys_info.name, utsn.sysname);
661*0Sstevel@tonic-gate 		sys_info.nodename =
662*0Sstevel@tonic-gate 			Realloc(sys_info.nodename, strlen(utsn.nodename) + 1);
663*0Sstevel@tonic-gate 		(void) strcpy(sys_info.nodename, utsn.nodename);
664*0Sstevel@tonic-gate 	} else {
665*0Sstevel@tonic-gate 		log_err("uname()\n");
666*0Sstevel@tonic-gate 	}
667*0Sstevel@tonic-gate 
668*0Sstevel@tonic-gate 	log_msg("<-list_create()\n");
669*0Sstevel@tonic-gate }
670*0Sstevel@tonic-gate 
671*0Sstevel@tonic-gate 
672*0Sstevel@tonic-gate static void
673*0Sstevel@tonic-gate collect_data() {
674*0Sstevel@tonic-gate 
675*0Sstevel@tonic-gate 	collect_lwp_data();
676*0Sstevel@tonic-gate 	if (getloadavg(loadavg, 3) == -1)
677*0Sstevel@tonic-gate 		dmerror("cannot get load average\n");
678*0Sstevel@tonic-gate }
679*0Sstevel@tonic-gate 
680*0Sstevel@tonic-gate 
681*0Sstevel@tonic-gate void
682*0Sstevel@tonic-gate monitor_stop()
683*0Sstevel@tonic-gate {
684*0Sstevel@tonic-gate 	/* store the list state */
685*0Sstevel@tonic-gate 	if (ltdb_file != NULL)
686*0Sstevel@tonic-gate 		(void) list_store(ltdb_file);
687*0Sstevel@tonic-gate 	list_clear(&lwps);
688*0Sstevel@tonic-gate 	list_clear(&processes);
689*0Sstevel@tonic-gate 	list_clear(&users);
690*0Sstevel@tonic-gate 	list_clear(&projects);
691*0Sstevel@tonic-gate 	fd_exit();
692*0Sstevel@tonic-gate }
693*0Sstevel@tonic-gate 
694*0Sstevel@tonic-gate 
695*0Sstevel@tonic-gate /*
696*0Sstevel@tonic-gate  * Initialize the monitor.
697*0Sstevel@tonic-gate  * Creates list data structures.
698*0Sstevel@tonic-gate  * If a saved list data file exists it is loaded.
699*0Sstevel@tonic-gate  * The /proc directory is opened.
700*0Sstevel@tonic-gate  * No actual scanning of /proc is done.
701*0Sstevel@tonic-gate  *
702*0Sstevel@tonic-gate  * Returns 0 if OK or -1 on error (leaving errno unchanged)
703*0Sstevel@tonic-gate  */
704*0Sstevel@tonic-gate int
705*0Sstevel@tonic-gate monitor_start()
706*0Sstevel@tonic-gate {
707*0Sstevel@tonic-gate 
708*0Sstevel@tonic-gate 	if (setjmp(dm_jmpbuffer) == 0) {
709*0Sstevel@tonic-gate 		lwpid_init();
710*0Sstevel@tonic-gate 		fd_init(Setrlimit());
711*0Sstevel@tonic-gate 
712*0Sstevel@tonic-gate 		list_alloc(&lwps, LS_LWPS);
713*0Sstevel@tonic-gate 		list_alloc(&processes, LT_PROCESS);
714*0Sstevel@tonic-gate 		list_alloc(&users, LS_USERS);
715*0Sstevel@tonic-gate 		list_alloc(&projects, LS_PROJECTS);
716*0Sstevel@tonic-gate 
717*0Sstevel@tonic-gate 		list_init(&lwps, LT_LWPS);
718*0Sstevel@tonic-gate 		list_init(&processes, LT_PROCESS);
719*0Sstevel@tonic-gate 		list_init(&users, LT_USERS);
720*0Sstevel@tonic-gate 		list_init(&projects, LT_PROJECTS);
721*0Sstevel@tonic-gate 
722*0Sstevel@tonic-gate 		sys_info.name = NULL;
723*0Sstevel@tonic-gate 		sys_info.nodename = NULL;
724*0Sstevel@tonic-gate 
725*0Sstevel@tonic-gate 		if ((procdir = opendir("/proc")) == NULL)
726*0Sstevel@tonic-gate 			dmerror("cannot open /proc directory\n");
727*0Sstevel@tonic-gate 
728*0Sstevel@tonic-gate 		/* restore the lists state */
729*0Sstevel@tonic-gate 		if (ltdb_file != NULL)
730*0Sstevel@tonic-gate 			(void) list_restore(ltdb_file);
731*0Sstevel@tonic-gate 
732*0Sstevel@tonic-gate 		return (0);
733*0Sstevel@tonic-gate 	} else {
734*0Sstevel@tonic-gate 		return (-1);
735*0Sstevel@tonic-gate 	}
736*0Sstevel@tonic-gate }
737*0Sstevel@tonic-gate 
738*0Sstevel@tonic-gate 
739*0Sstevel@tonic-gate /*
740*0Sstevel@tonic-gate  * Update the monitor data lists.
741*0Sstevel@tonic-gate  * return 0, or -1 on error and leave errno unchanged
742*0Sstevel@tonic-gate  */
743*0Sstevel@tonic-gate int
744*0Sstevel@tonic-gate monitor_update()
745*0Sstevel@tonic-gate {
746*0Sstevel@tonic-gate 	if (setjmp(dm_jmpbuffer) == 0) {
747*0Sstevel@tonic-gate 		collect_data();
748*0Sstevel@tonic-gate 		list_create();
749*0Sstevel@tonic-gate 		return (0);
750*0Sstevel@tonic-gate 	} else {
751*0Sstevel@tonic-gate 		return (-1);
752*0Sstevel@tonic-gate 	}
753*0Sstevel@tonic-gate }
754