rdimpl.c revision 458cf4d67cff5ff99a68a866b7657f1b1d6fe61c
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2007 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
#include <sys/resource.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <dirent.h>
#include <string.h>
#include <errno.h>
#include <poll.h>
#include <ctype.h>
#include <fcntl.h>
#include <limits.h>
#include <time.h>
#include <project.h>
#include <libintl.h>
#include <pthread.h>
#include "rdimpl.h"
#include "rdutil.h"
#include "rdtable.h"
#include "rdfile.h"
#include "rdlist.h"
/* global variables */
extern pthread_mutex_t listLock;
static float total_mem; /* total memory usage */
static float total_cpu; /* total cpu usage */
static char *nullstr = "null";
static double loadavg[3];
/*
* Add a LWP entry to the specifed list.
*/
{
} else {
}
return (lwp);
}
/*
* Remove an LWP entry from the specified list.
*/
static void
{
else
else
}
/*
* Remove entry from the specified list.
*/
static void
{
else
else
/* anly free if doesn't point to static 'nullstr' def */
}
/*
* Empty the specified list.
* If it's an LWP list, this will traverse /proc to
* restore microstate accounting to its original value.
*/
void
{
fd_closeall();
while (lwp) {
}
} else {
while (id) {
/* anly free if doesn't point to static 'nullstr' def */
}
}
}
/*
* Calculate a process' statistics from its lwp statistics.
*/
static void
/*
* When an id is processed first time in an update run its
* id_alive flag set to false.
* The next values are gauges, their old values from the previous
* calculation should be set to null.
* The names and timestamp must be set once.
*/
id->id_timestamp = 0;
} else if (l_type == LT_PROJECTS) {
} else {
}
/* mark this id as changed in this update run */
}
}
/*
* The next values are calculated only one time for each pid.
*/
if (l_type == LT_PROCESS)
}
if (l_type == LT_PROCESS)
}
static void
{
return;
}
continue;
continue;
continue;
return;
}
/* a new element */
}
/*
*/
static void
{
return;
}
while (id) {
} else {
/* normalize total mem and cpu across all processes. */
if (total_mem >= 100)
if (total_cpu >= 100)
}
}
}
/*
* This procedure removes all dead lwps from the specified lwp list.
*/
static void
{
return;
while (lwp) {
} else {
}
}
}
/*
* Update a LWP entry according to the specified usage data.
*/
static void
{
}
/*
* This is the meat of the /proc scanner.
* It will visit every single LWP in /proc.
*/
static void
{
char *pidstr;
char pfile[MAX_PROCFS_PATH];
continue;
continue; /* skip sched, pageout and fsflush */
/*
* Here we are going to read information about
* If process has more than one lwp, we also should
*/
continue;
continue;
}
if (nlwps > 1) {
continue;
continue;
}
continue;
}
for (i = 0; i < nent;
/*LINTED ALIGNMENT*/
}
if (i == 0)
sizeof (psinfo_t) - sizeof (lwpsinfo_t));
lwpsinfo_buf, sizeof (lwpsinfo_t));
}
} else {
}
sizeof (psinfo_t) - sizeof (lwpsinfo_t));
}
/*
* At this part of scandir we read additional information
* Again, if process has more than one lwp, then we
* will get information about all its lwps from
*/
if (nlwps > 1) {
continue;
continue;
}
continue;
}
/*LINTED ALIGNMENT*/
continue;
}
} else {
continue;
continue;
}
continue;
}
}
list_refresh(&lwps);
fd_update();
}
/*
* Create linked lists of users, projects and sets.
*
* Updates of the process, users and projects lists are done in
* a critical section so that the consumer of these lists will
* always get consistent data.
*/
static void
{
double d;
int rv;
total_mem = 0;
total_cpu = 0;
log_msg("->list_create()\n");
log_msg("Scanner process lock wait was %1.5f sec\n", d);
while (lwp) {
}
/* release the mutex */
log_msg("Scanner process lock time was %1.5f sec\n", d);
} else {
}
} else {
log_err("uname()\n");
}
log_msg("<-list_create()\n");
}
static void
collect_data() {
dmerror("cannot get load average\n");
}
void
{
/* store the list state */
(void) list_store(ltdb_file);
list_clear(&lwps);
list_clear(&users);
fd_exit();
}
/*
* Initialize the monitor.
* Creates list data structures.
* If a saved list data file exists it is loaded.
* The /proc directory is opened.
* No actual scanning of /proc is done.
*
* Returns 0 if OK or -1 on error (leaving errno unchanged)
*/
int
{
if (setjmp(dm_jmpbuffer) == 0) {
lwpid_init();
dmerror("cannot open /proc directory\n");
/* restore the lists state */
(void) list_restore(ltdb_file);
return (0);
} else {
return (-1);
}
}
/*
* Update the monitor data lists.
* return 0, or -1 on error and leave errno unchanged
*/
int
{
if (setjmp(dm_jmpbuffer) == 0) {
collect_data();
list_create();
return (0);
} else {
return (-1);
}
}