|
Packit |
d37888 |
/* Copyright (C) 1998-99 Martin Baulig
|
|
Packit |
d37888 |
This file is part of LibGTop 1.0.
|
|
Packit |
d37888 |
|
|
Packit |
d37888 |
Contributed by Martin Baulig <martin@home-of-linux.org>, April 1998.
|
|
Packit |
d37888 |
|
|
Packit |
d37888 |
LibGTop is free software; you can redistribute it and/or modify it
|
|
Packit |
d37888 |
under the terms of the GNU General Public License as published by
|
|
Packit |
d37888 |
the Free Software Foundation; either version 2 of the License,
|
|
Packit |
d37888 |
or (at your option) any later version.
|
|
Packit |
d37888 |
|
|
Packit |
d37888 |
LibGTop is distributed in the hope that it will be useful, but WITHOUT
|
|
Packit |
d37888 |
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
Packit |
d37888 |
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
Packit |
d37888 |
for more details.
|
|
Packit |
d37888 |
|
|
Packit |
d37888 |
You should have received a copy of the GNU General Public License
|
|
Packit |
d37888 |
along with LibGTop; see the file COPYING. If not, write to the
|
|
Packit |
d37888 |
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
|
Packit |
d37888 |
Boston, MA 02110-1301, USA.
|
|
Packit |
d37888 |
*/
|
|
Packit |
d37888 |
|
|
Packit |
d37888 |
#include <config.h>
|
|
Packit |
d37888 |
#include <glibtop/open.h>
|
|
Packit |
d37888 |
#include <glibtop/cpu.h>
|
|
Packit |
d37888 |
#include <glibtop/error.h>
|
|
Packit |
d37888 |
|
|
Packit |
d37888 |
#include <unistd.h>
|
|
Packit |
d37888 |
#include <dlfcn.h>
|
|
Packit |
d37888 |
#include <sys/types.h>
|
|
Packit |
d37888 |
#include <sys/processor.h>
|
|
Packit |
d37888 |
|
|
Packit |
d37888 |
#include <glibtop_private.h>
|
|
Packit |
d37888 |
|
|
Packit |
d37888 |
/* We need to call this when kstat_chain_update() returns new KID.
|
|
Packit |
d37888 |
* In that case all kstat pointers and data are invalid, so we
|
|
Packit |
d37888 |
* need to reread everything. The condition shouldn't happen very
|
|
Packit |
d37888 |
* often.
|
|
Packit |
d37888 |
*/
|
|
Packit |
d37888 |
|
|
Packit |
d37888 |
void
|
|
Packit |
d37888 |
glibtop_get_kstats(glibtop *server)
|
|
Packit |
d37888 |
{
|
|
Packit |
d37888 |
kstat_ctl_t *kc = server->machine->kc;
|
|
Packit |
d37888 |
kstat_t *ksp;
|
|
Packit |
d37888 |
int nproc_same, new_ncpu;
|
|
Packit |
d37888 |
|
|
Packit |
d37888 |
server->ncpu = new_ncpu = sysconf(_SC_NPROCESSORS_CONF);
|
|
Packit |
d37888 |
|
|
Packit |
d37888 |
|
|
Packit |
d37888 |
if(!kc)
|
|
Packit |
d37888 |
{
|
|
Packit |
d37888 |
server->ncpu = new_ncpu;
|
|
Packit |
d37888 |
server->machine->vminfo_kstat = NULL;
|
|
Packit |
d37888 |
server->machine->system = NULL;
|
|
Packit |
d37888 |
server->machine->syspages = NULL;
|
|
Packit |
d37888 |
server->machine->bunyip = NULL;
|
|
Packit |
d37888 |
return;
|
|
Packit |
d37888 |
}
|
|
Packit |
d37888 |
|
|
Packit |
d37888 |
do {
|
|
Packit |
d37888 |
|
|
Packit |
d37888 |
ksp = kstat_lookup(kc, "unix", -1, "vminfo");
|
|
Packit |
d37888 |
server->machine->vminfo_kstat = ksp;
|
|
Packit |
d37888 |
if(ksp)
|
|
Packit |
d37888 |
{
|
|
Packit |
d37888 |
kstat_read(kc, ksp, &server->machine->vminfo);
|
|
Packit |
d37888 |
/* Don't change snaptime if we only need to reinitialize kstats */
|
|
Packit |
d37888 |
if(!(server->machine->vminfo_snaptime))
|
|
Packit |
d37888 |
server->machine->vminfo_snaptime = ksp->ks_snaptime;
|
|
Packit |
d37888 |
}
|
|
Packit |
d37888 |
|
|
Packit |
d37888 |
/* We don't know why was kstat chain invalidated. It could have
|
|
Packit |
d37888 |
been because the number of processors changed. The sysconf()
|
|
Packit |
d37888 |
man page says that values returned won't change during the
|
|
Packit |
d37888 |
life time of a process, but let's hope that's just an error in
|
|
Packit |
d37888 |
the documentation. */
|
|
Packit |
d37888 |
|
|
Packit |
d37888 |
if((nproc_same = new_ncpu) == server->ncpu)
|
|
Packit |
d37888 |
{
|
|
Packit |
d37888 |
int checked, i;
|
|
Packit |
d37888 |
char cpu[20];
|
|
Packit |
d37888 |
|
|
Packit |
d37888 |
for(i = 0, checked = 0; i < GLIBTOP_NCPU || checked == new_ncpu; ++i)
|
|
Packit |
d37888 |
if(!server->machine->cpu_stat_kstat[i])
|
|
Packit |
d37888 |
|
|
Packit |
d37888 |
{
|
|
Packit |
d37888 |
sprintf(cpu, "cpu_stat%d", i);
|
|
Packit |
d37888 |
if(!(server->machine->cpu_stat_kstat[i] =
|
|
Packit |
d37888 |
kstat_lookup(kc, "cpu_stat", -1, cpu)))
|
|
Packit |
d37888 |
{
|
|
Packit |
d37888 |
nproc_same = 0;
|
|
Packit |
d37888 |
break;
|
|
Packit |
d37888 |
}
|
|
Packit |
d37888 |
++checked;
|
|
Packit |
d37888 |
}
|
|
Packit |
d37888 |
}
|
|
Packit |
d37888 |
|
|
Packit |
d37888 |
if(!nproc_same)
|
|
Packit |
d37888 |
{
|
|
Packit |
d37888 |
processorid_t p;
|
|
Packit |
d37888 |
int found;
|
|
Packit |
d37888 |
char cpu[20];
|
|
Packit |
d37888 |
|
|
Packit |
d37888 |
server->ncpu = new_ncpu = MIN(new_ncpu, GLIBTOP_NCPU);
|
|
Packit |
d37888 |
|
|
Packit |
d37888 |
for(p = 0, found = 0; p < GLIBTOP_NCPU && found != new_ncpu; ++p)
|
|
Packit |
d37888 |
{
|
|
Packit |
d37888 |
if(p_online(p, P_STATUS) < 0)
|
|
Packit |
d37888 |
{
|
|
Packit |
d37888 |
server->machine->cpu_stat_kstat[p] = NULL;
|
|
Packit |
d37888 |
continue;
|
|
Packit |
d37888 |
}
|
|
Packit |
d37888 |
sprintf(cpu, "cpu_stat%d", (int)p);
|
|
Packit |
d37888 |
server->machine->cpu_stat_kstat[p] =
|
|
Packit |
d37888 |
kstat_lookup(kc, "cpu_stat", -1, cpu);
|
|
Packit |
d37888 |
++found;
|
|
Packit |
d37888 |
}
|
|
Packit |
d37888 |
}
|
|
Packit |
d37888 |
|
|
Packit |
d37888 |
server->machine->system = kstat_lookup(kc, "unix", -1, "system_misc");
|
|
Packit |
d37888 |
server->machine->syspages = kstat_lookup(kc, "unix", -1, "system_pages");
|
|
Packit |
d37888 |
server->machine->bunyip = kstat_lookup(kc, "bunyip", -1, "mempages");
|
|
Packit |
d37888 |
|
|
Packit |
d37888 |
} while(kstat_chain_update(kc) > 0 &&
|
|
Packit |
d37888 |
(new_ncpu = sysconf(_SC_NPROCESSORS_CONF)));
|
|
Packit |
d37888 |
|
|
Packit |
d37888 |
/* We'll ignore -1 from kstat_chain_update here, since it really
|
|
Packit |
d37888 |
shouldn't happen */
|
|
Packit |
d37888 |
}
|
|
Packit |
d37888 |
|
|
Packit |
d37888 |
void
|
|
Packit |
d37888 |
glibtop_open_s (glibtop *server, const char *program_name,
|
|
Packit |
d37888 |
const unsigned long features, const unsigned flags)
|
|
Packit |
d37888 |
{
|
|
Packit |
d37888 |
kstat_ctl_t *kc;
|
|
Packit |
d37888 |
kstat_t *ksp;
|
|
Packit |
d37888 |
kstat_named_t *kn;
|
|
Packit |
d37888 |
int i, page;
|
|
Packit |
d37888 |
void *dl;
|
|
Packit |
d37888 |
|
|
Packit |
d37888 |
server->name = program_name;
|
|
Packit |
d37888 |
|
|
Packit |
d37888 |
page = sysconf(_SC_PAGESIZE) >> 10;
|
|
Packit |
d37888 |
for(i = 0; page; ++i, page >>= 1);
|
|
Packit |
d37888 |
server->machine->pagesize = i - 1;
|
|
Packit |
d37888 |
server->machine->ticks = sysconf(_SC_CLK_TCK);
|
|
Packit |
d37888 |
if(server->machine->kc)
|
|
Packit |
d37888 |
kstat_close(server->machine->kc);
|
|
Packit |
d37888 |
server->machine->kc = kc = kstat_open ();
|
|
Packit |
d37888 |
|
|
Packit |
d37888 |
#if 0
|
|
Packit |
d37888 |
for (ksp = server->machine->kc->kc_chain; ksp != NULL; ksp = ksp->ks_next) {
|
|
Packit |
d37888 |
if (!strcmp (ksp->ks_class, "vm") && !strcmp (ksp->ks_name, "vminfo")) {
|
|
Packit |
d37888 |
server->machine->vminfo_kstat = ksp;
|
|
Packit |
d37888 |
kstat_read (server->machine->kc, ksp, &server->machine->vminfo);
|
|
Packit |
d37888 |
server->machine->vminfo_snaptime = ksp->ks_snaptime;
|
|
Packit |
d37888 |
continue;
|
|
Packit |
d37888 |
}
|
|
Packit |
d37888 |
|
|
Packit |
d37888 |
if (!strcmp (ksp->ks_class, "misc") && !strncmp (ksp->ks_name, "cpu_stat", 8)) {
|
|
Packit |
d37888 |
int cpu;
|
|
Packit |
d37888 |
|
|
Packit |
d37888 |
if ((sscanf (ksp->ks_name+8, "%d", &cpu) != 1) || (cpu > 63))
|
|
Packit |
d37888 |
continue;
|
|
Packit |
d37888 |
|
|
Packit |
d37888 |
if (cpu >= server->ncpu)
|
|
Packit |
d37888 |
server->ncpu = cpu+1;
|
|
Packit |
d37888 |
|
|
Packit |
d37888 |
server->machine->cpu_stat_kstat [cpu] = ksp;
|
|
Packit |
d37888 |
continue;
|
|
Packit |
d37888 |
}
|
|
Packit |
d37888 |
}
|
|
Packit |
d37888 |
|
|
Packit |
d37888 |
#endif
|
|
Packit |
d37888 |
|
|
Packit |
d37888 |
if (!kc)
|
|
Packit |
d37888 |
glibtop_warn_io_r (server, "kstat_open ()");
|
|
Packit |
d37888 |
|
|
Packit |
d37888 |
server->ncpu = -1; /* Force processor detection */
|
|
Packit |
d37888 |
server->machine->vminfo_snaptime = 0; /* Force snaptime read */
|
|
Packit |
d37888 |
glibtop_get_kstats(server);
|
|
Packit |
d37888 |
|
|
Packit |
d37888 |
server->machine->boot = 0;
|
|
Packit |
d37888 |
if((ksp = server->machine->system) && kstat_read(kc, ksp, NULL) >= 0)
|
|
Packit |
d37888 |
{
|
|
Packit |
d37888 |
kn = (kstat_named_t *)kstat_data_lookup(ksp, "boot_time");
|
|
Packit |
d37888 |
if(kn)
|
|
Packit |
d37888 |
switch(kn->data_type)
|
|
Packit |
d37888 |
{
|
|
Packit |
d37888 |
#ifdef KSTAT_DATA_INT32
|
|
Packit |
d37888 |
case KSTAT_DATA_INT32: server->machine->boot = kn->value.i32;
|
|
Packit |
d37888 |
break;
|
|
Packit |
d37888 |
case KSTAT_DATA_UINT32: server->machine->boot = kn->value.ui32;
|
|
Packit |
d37888 |
break;
|
|
Packit |
d37888 |
case KSTAT_DATA_INT64: server->machine->boot = kn->value.i64;
|
|
Packit |
d37888 |
break;
|
|
Packit |
d37888 |
case KSTAT_DATA_UINT64: server->machine->boot = kn->value.ui64;
|
|
Packit |
d37888 |
break;
|
|
Packit |
d37888 |
#else
|
|
Packit |
d37888 |
case KSTAT_DATA_LONG: server->machine->boot = kn->value.l;
|
|
Packit |
d37888 |
break;
|
|
Packit |
d37888 |
case KSTAT_DATA_ULONG: server->machine->boot = kn->value.ul;
|
|
Packit |
d37888 |
break;
|
|
Packit |
d37888 |
case KSTAT_DATA_LONGLONG: server->machine->boot = kn->value.ll;
|
|
Packit |
d37888 |
break;
|
|
Packit |
d37888 |
case KSTAT_DATA_ULONGLONG: server->machine->boot = kn->value.ull;
|
|
Packit |
d37888 |
break;
|
|
Packit |
d37888 |
#endif
|
|
Packit |
d37888 |
}
|
|
Packit |
d37888 |
}
|
|
Packit |
d37888 |
|
|
Packit |
d37888 |
/* Now let's have a bit of magic dust... */
|
|
Packit |
d37888 |
|
|
Packit |
d37888 |
#if GLIBTOP_SOLARIS_RELEASE >= 50600
|
|
Packit |
d37888 |
|
|
Packit |
d37888 |
dl = dlopen("/usr/lib/libproc.so", RTLD_LAZY);
|
|
Packit |
d37888 |
if(server->machine->libproc)
|
|
Packit |
d37888 |
dlclose(server->machine->libproc);
|
|
Packit |
d37888 |
server->machine->libproc = dl;
|
|
Packit |
d37888 |
if(dl)
|
|
Packit |
d37888 |
{
|
|
Packit |
d37888 |
void *func;
|
|
Packit |
d37888 |
|
|
Packit |
d37888 |
func = dlsym(dl, "Pobjname"); /* Solaris 8 */
|
|
Packit |
d37888 |
if(!func)
|
|
Packit |
d37888 |
func = dlsym(dl, "proc_objname"); /* Solaris 7 */
|
|
Packit |
d37888 |
server->machine->objname = (void (*)
|
|
Packit |
d37888 |
(void *, uintptr_t, const char *, size_t))func;
|
|
Packit |
d37888 |
server->machine->pgrab = (struct ps_prochandle *(*)(pid_t, int, int *))
|
|
Packit |
d37888 |
dlsym(dl, "Pgrab");
|
|
Packit |
d37888 |
server->machine->pfree = (void (*)(void *))dlsym(dl, "Pfree");
|
|
Packit |
d37888 |
|
|
Packit |
d37888 |
}
|
|
Packit |
d37888 |
else
|
|
Packit |
d37888 |
{
|
|
Packit |
d37888 |
server->machine->objname = NULL;
|
|
Packit |
d37888 |
server->machine->pgrab = NULL;
|
|
Packit |
d37888 |
server->machine->pfree = NULL;
|
|
Packit |
d37888 |
}
|
|
Packit |
d37888 |
#endif
|
|
Packit |
d37888 |
server->machine->me = getpid();
|
|
Packit |
d37888 |
}
|