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