diff --git a/sysdeps/solaris/ChangeLog b/sysdeps/solaris/ChangeLog index 372ee29f..5667b055 100644 --- a/sysdeps/solaris/ChangeLog +++ b/sysdeps/solaris/ChangeLog @@ -1,8 +1,53 @@ +1999-05-02 Drazen Kacar + + * glibtop_machine.h: added fields for page size, clock ticks and + boot time. These are constants. Also added three new kstats. + + * open.c (glibtop_get_kstats): Initialize kstats in *server. + We need to call this at init time (obviously) and each time + kstat_chain_update() says that kstat chain has changed. In this + case all kstat pointers and data are invalid, so we need to + reinitialize everything. + + (glibtop_open_s): Made it call glibtop_get_kstats(). Added + initialization for run time constants in struct machine. + + * cpu.c (glibtop_get_cpu_s): Call kstat_chain_update(). + See if processor is on-line and set bits in xcpu_flags. + Added frequency (bad name, should have been ticks). + + * swap.c (glibtop_get_swap_s): Call kstat_chain_update(). + I probably broke vminfo_snaptime consistency. Fix later. + + * uptime.c (glibtop_get_uptime_s): Implemented uptime and boot_time. + Still looking for a sane way to get idletime. + + * mem.c (glibtop_get_mem_s): Implemented. Will use bunyip + module if it's loaded. Or when it gets loaded. kstat_chain_update() + is our friend. And with a friends like that... + + * loadavg.c (glibtop_get_loadavg_s): Solaris 2.6 code brought + into sync with everything else. + + * msg_limits.c (glibtop_init_msg_limits_s): Implemented. + + * sem_limits.c (glibtop_get_sem_limits_s): Implemented. + + Solaris takes kernel modularity too seriously. We can't get + IPC configuration data if the kernel module is not loaded and + it won't be loaded until some process actually asks for a + particular IPC resource. There's no way to tell our applications + about this. Possible API additions? + + All three IPC functions should go into daemon, but I'm keeping + them in the normal library because I can't build daemon yet. All + praise 64 bits! + 1999-04-29 Drazen Kacar - * glibtop_machine.h: add field for kvm descriptor. + * glibtop_machine.h: added field for kvm descriptor. - * open.c: add code for opening kernel name space. + * open.c: added code for opening kernel name space. * shm_limits.c: implemented. diff --git a/sysdeps/solaris/cpu.c b/sysdeps/solaris/cpu.c index fe7ef147..d35ff10c 100644 --- a/sysdeps/solaris/cpu.c +++ b/sysdeps/solaris/cpu.c @@ -25,11 +25,15 @@ #include #include +#include +#include + static const unsigned long _glibtop_sysdeps_cpu = -(1 << GLIBTOP_CPU_TOTAL) + (1 << GLIBTOP_CPU_USER) + -(1 << GLIBTOP_CPU_SYS) + (1 << GLIBTOP_CPU_IDLE) + -(1 << GLIBTOP_XCPU_TOTAL) + (1 << GLIBTOP_XCPU_USER) + -(1 << GLIBTOP_XCPU_SYS) + (1 << GLIBTOP_XCPU_IDLE); +(1L << GLIBTOP_CPU_TOTAL) + (1L << GLIBTOP_CPU_USER) + +(1L << GLIBTOP_CPU_SYS) + (1L << GLIBTOP_CPU_IDLE) + +(1L << GLIBTOP_XCPU_TOTAL) + (1L << GLIBTOP_XCPU_USER) + +(1L << GLIBTOP_XCPU_SYS) + (1L << GLIBTOP_XCPU_IDLE) + +(1L << GLIBTOP_CPU_FREQUENCY) + (1L << GLIBTOP_XCPU_FLAGS); /* Init function. */ @@ -46,18 +50,34 @@ glibtop_get_cpu_s (glibtop *server, glibtop_cpu *buf) { kstat_ctl_t *kc = server->machine.kc; cpu_stat_t cpu_stat; - int cpu, ncpu; + processorid_t cpu; + int ncpu, found; kid_t ret; memset (buf, 0, sizeof (glibtop_cpu)); + if(!kc) + return; + switch(kstat_chain_update(kc)) + { + case -1: assert(0); /* Debugging purposes, shouldn't happen */ + case 0: break; + default: glibtop_get_kstats(server); + } ncpu = server->ncpu; - if (ncpu > GLIBTOP_NCPU) ncpu = GLIBTOP_NCPU; + if (ncpu > GLIBTOP_NCPU) + ncpu = GLIBTOP_NCPU; - for (cpu = 0; cpu < ncpu; cpu++) { + for (cpu = 0, found = 0; cpu < GLIBTOP_NCPU && found != ncpu; cpu++) + { kstat_t *ksp = server->machine.cpu_stat_kstat [cpu]; if (!ksp) continue; + ++found; + if(p_online(cpu, P_STATUS) == P_ONLINE) + buf->xcpu_flags |= (1L << cpu); + else + continue; ret = kstat_read (kc, ksp, &cpu_stat); if (ret == -1) { @@ -66,8 +86,8 @@ glibtop_get_cpu_s (glibtop *server, glibtop_cpu *buf) } buf->xcpu_idle [cpu] = cpu_stat.cpu_sysinfo.cpu [CPU_IDLE]; - buf->xcpu_user [cpu] = cpu_stat.cpu_sysinfo.cpu [CPU_IDLE]; - buf->xcpu_sys [cpu] = cpu_stat.cpu_sysinfo.cpu [CPU_IDLE]; + buf->xcpu_user [cpu] = cpu_stat.cpu_sysinfo.cpu [CPU_USER]; + buf->xcpu_sys [cpu] = cpu_stat.cpu_sysinfo.cpu [CPU_KERNEL]; buf->xcpu_total [cpu] = buf->xcpu_idle [cpu] + buf->xcpu_user [cpu] + buf->xcpu_sys [cpu]; @@ -78,6 +98,7 @@ glibtop_get_cpu_s (glibtop *server, glibtop_cpu *buf) } buf->total = buf->idle + buf->user + buf->sys; + buf->frequency = server->machine.ticks; buf->flags = _glibtop_sysdeps_cpu; } diff --git a/sysdeps/solaris/glibtop_machine.h b/sysdeps/solaris/glibtop_machine.h index 01aa54eb..2d77471b 100644 --- a/sysdeps/solaris/glibtop_machine.h +++ b/sysdeps/solaris/glibtop_machine.h @@ -50,6 +50,14 @@ struct _glibtop_machine vminfo_t vminfo; kstat_t *cpu_stat_kstat [64]; + + kstat_t *system; /* boot_time & avenrun* where needed */ + kstat_t *syspages; /* memory usage */ + kstat_t *bunyip; /* more memory usage */ + + int pagesize; /* in kilobytes */ + int ticks; /* clock ticks, as returned by sysconf(_SC_CLK_TCK) */ + unsigned boot; /* boot time, it's ui32 in kstat */ }; END_LIBGTOP_DECLS diff --git a/sysdeps/solaris/loadavg.c b/sysdeps/solaris/loadavg.c index 8629acb9..9f4d4a37 100644 --- a/sysdeps/solaris/loadavg.c +++ b/sysdeps/solaris/loadavg.c @@ -27,12 +27,13 @@ #ifdef HAVE_GETLOADAVG #include #else +#include #include #include #endif static const unsigned long _glibtop_sysdeps_loadavg = -(1 << GLIBTOP_LOADAVG_LOADAVG); +(1L << GLIBTOP_LOADAVG_LOADAVG); /* Init function. */ @@ -49,8 +50,7 @@ glibtop_get_loadavg_s (glibtop *server, glibtop_loadavg *buf) { #ifndef HAVE_GETLOADAVG kstat_ctl_t *kc; - static kstat_t *ksp = NULL; - kid_t k; + kstat_t *ksp; int i; static char *avestrings[] = { "avenrun_1min", "avenrun_5min", @@ -62,20 +62,25 @@ glibtop_get_loadavg_s (glibtop *server, glibtop_loadavg *buf) if (getloadavg (buf->loadavg, 3)) return; #else - kc = server->machine.kc; - if((k = kstat_chain_update(kc)) < 0) - return; - if(k || !ksp) - if(!(ksp = kstat_lookup(kc, "unix", 0, "system_misc"))) - return; - if(kstat_read(kc, ksp, 0) < 0) - return; + if(!(kc = server->machine.kc)) + return; + switch(kstat_chain_update(kc)) + { + case -1: assert(0); /* Debugging, shouldn't happen */ + case 0: break; + default: glibtop_get_kstats(server); + } + if(!(ksp = server->machine.system)) + return; + if(kstat_read(kc, ksp, NULL) < 0) + return; for(i = 0; i < 3; ++i) /* Do we have a countof macro? */ { kstat_named_t *kn; + kn = (kstat_named_t *)kstat_data_lookup(ksp, avestrings[i]); if(kn) - buf->loadavg[i] = (double)kn->value.ul / FSCALE; + buf->loadavg[i] = (double)kn->value.ul / FSCALE; } #endif buf->flags = _glibtop_sysdeps_loadavg; diff --git a/sysdeps/solaris/mem.c b/sysdeps/solaris/mem.c index 8a2c31a5..c712db06 100644 --- a/sysdeps/solaris/mem.c +++ b/sysdeps/solaris/mem.c @@ -24,14 +24,25 @@ #include #include -static const unsigned long _glibtop_sysdeps_mem = 0; +#include +#include + +static const unsigned long _glibtop_sysdeps_mem_os_sysconf = +(1L << GLIBTOP_MEM_TOTAL); +static const unsigned long _glibtop_sysdeps_mem_os_kstat = +(1L << GLIBTOP_MEM_FREE) + (1L << GLIBTOP_MEM_USED) + +(1L << GLIBTOP_MEM_LOCKED); +static const unsigned long _glibtop_sysdeps_mem_bunyip = +(1L << GLIBTOP_MEM_SHARED) + (1L << GLIBTOP_MEM_BUFFER) + +(1L << GLIBTOP_MEM_USER); /* Init function. */ void glibtop_init_mem_s (glibtop *server) { - server->sysdeps.mem = _glibtop_sysdeps_mem; + server->sysdeps.mem = _glibtop_sysdeps_mem_os_sysconf + + _glibtop_sysdeps_mem_os_kstat + _glibtop_sysdeps_mem_bunyip; } /* Provides information about memory usage. */ @@ -39,5 +50,72 @@ glibtop_init_mem_s (glibtop *server) void glibtop_get_mem_s (glibtop *server, glibtop_mem *buf) { - memset (buf, 0, sizeof (glibtop_mem)); + kstat_ctl_t *kc = server->machine.kc; + kstat_t *ksp; + kstat_named_t *kn; + int pagesize = server->machine.pagesize; + + memset (buf, 0, sizeof (glibtop_mem)); + + buf->total = (u_int64_t)sysconf(_SC_PHYS_PAGES) * pagesize; + buf->flags = _glibtop_sysdeps_mem_os_sysconf; + + if(!kc) + return; + switch(kstat_chain_update(kc)) + { + case -1: assert(0); /* Debugging purposes, shouldn't happen */ + case 0: break; + default: glibtop_get_kstats(server); + } + + if((ksp = server->machine.syspages) && kstat_read(kc, ksp, NULL) >= 0) + { + kn = (kstat_named_t *)kstat_data_lookup(ksp, "pagesfree"); + if(kn) + { +#ifdef _LP64 + buf->free = kn->value.ui64 * pagesize; +#else + buf->free = kn->value.ui32 * pagesize; +#endif + buf->used = buf->total - buf->free; + } + kn = (kstat_named_t *)kstat_data_lookup(ksp, "pageslocked"); + if(kn) +#ifdef _LP64 + buf->locked = kn->value.ui64 * pagesize; +#else + buf->locked = kn->value.ui32 * pagesize; +#endif + buf->flags += _glibtop_sysdeps_mem_os_kstat; + } + + /* Bunyip module provides data in multiples of system page size */ + + if((ksp = server->machine.bunyip) && kstat_read(kc, ksp, NULL) >= 0) + { + kn = (kstat_named_t *)kstat_data_lookup(ksp, "pages_anon"); + if(kn) +#ifdef _LP64 + buf->user = kn->value.ui64 * pagesize; +#else + buf->user = kn->value.ui32 * pagesize; +#endif + kn = (kstat_named_t *)kstat_data_lookup(ksp, "pages_exec"); + if(kn) +#ifdef _LP64 + buf->shared = kn->value.ui64 * pagesize; +#else + buf->shared = kn->value.ui32 * pagesize; +#endif + kn = (kstat_named_t *)kstat_data_lookup(ksp, "pages_vnode"); + if(kn) +#ifdef _LP64 + buf->buffer = kn->value.ui64 * pagesize; +#else + buf->buffer = kn->value.ui32 * pagesize; +#endif + buf->flags += _glibtop_sysdeps_mem_bunyip; + } } diff --git a/sysdeps/solaris/open.c b/sysdeps/solaris/open.c index ac0213b4..02803b13 100644 --- a/sysdeps/solaris/open.c +++ b/sysdeps/solaris/open.c @@ -23,18 +23,106 @@ #include -/* Opens pipe to gtop server. Returns 0 on success and -1 on error. */ +#include +#include +#include + +/* We need to call this when kstat_chain_update() returns new KID. + * In that case all kstat pointers and data are invalid, so we + * need to reread everything. The condition shouldn't happen very + * often. + */ + +void +glibtop_get_kstats(glibtop *server) +{ + kstat_ctl_t *kc = server->machine.kc; + kstat_t *ksp; + int nproc_same, new_ncpu; + + new_ncpu = sysconf(_SC_NPROCESSORS_CONF); + + if(!kc) + { + server->ncpu = new_ncpu; + server->machine.vminfo_kstat = NULL; + server->machine.system = NULL; + server->machine.bunyip = NULL; + return; + } + + ksp = kstat_lookup(kc, "unix", -1, "vminfo"); + server->machine.vminfo_kstat = ksp; + if(ksp) + { + kstat_read(kc, ksp, &server->machine.vminfo); + server->machine.vminfo_snaptime = ksp->ks_snaptime; + } + + /* We don't know why was kstat chain invalidated. It could have + been because the number of processors changed. The sysconf() + man page says that values returned won't change during the + life time of a process, but let's hope that's just an error in + the documentation. */ + + if(nproc_same = new_ncpu == server->ncpu) + { + int checked, i; + char cpu[20]; + + for(i = 0, checked = 0; i < GLIBTOP_NCPU || checked == new_ncpu; ++i) + if(server->machine.cpu_stat_kstat[i]) + { + sprintf(cpu, "cpu_stat%d", i); + if(!(server->machine.cpu_stat_kstat[i] = + kstat_lookup(kc, "cpu_stat", -1, cpu))) + { + nproc_same = 0; + break; + } + ++checked; + } + } + if(!nproc_same) + { + processorid_t p; + int found; + char cpu[20]; + + if(new_ncpu > GLIBTOP_NCPU) + new_ncpu = GLIBTOP_NCPU; + server->ncpu = new_ncpu; + for(p = 0, found = 0; p < GLIBTOP_NCPU && found != new_ncpu; ++p) + { + if(p_online(p, P_STATUS) < 0) + continue; + sprintf(cpu, "cpu_stat%d", (int)p); + server->machine.cpu_stat_kstat[p] = + kstat_lookup(kc, "cpu_stat", -1, cpu); + ++found; + } + } + + server->machine.system = kstat_lookup(kc, "unix", -1, "system_misc"); + server->machine.syspages = kstat_lookup(kc, "unix", -1, "system_pages"); + server->machine.bunyip = kstat_lookup(kc, "bunyip", -1, "mempages"); +} void glibtop_open_s (glibtop *server, const char *program_name, const unsigned long features, const unsigned flags) { + kstat_ctl_t *kc; kstat_t *ksp; + kstat_named_t *kn; server->name = program_name; - server->machine.kc = kstat_open (); + server->machine.pagesize = sysconf(_SC_PAGESIZE) >> 10; + server->machine.ticks = sysconf(_SC_CLK_TCK); + server->machine.kc = kc = kstat_open (); +#if 0 for (ksp = server->machine.kc->kc_chain; ksp != NULL; ksp = ksp->ks_next) { if (!strcmp (ksp->ks_class, "vm") && !strcmp (ksp->ks_name, "vminfo")) { server->machine.vminfo_kstat = ksp; @@ -57,8 +145,21 @@ glibtop_open_s (glibtop *server, const char *program_name, } } - if (!server->machine.kc) - glibtop_error_io_r (server, "kstat_open ()"); +#endif + + if (!kc) + glibtop_warn_io_r (server, "kstat_open ()"); + + server->ncpu = -1; /* Force processor detection */ + glibtop_get_kstats(server); + + server->machine.boot = 0; + if((ksp = server->machine.system) && kstat_read(kc, ksp, NULL) >= 0) + { + kn = (kstat_named_t *)kstat_data_lookup(ksp, "boot_time"); + if(kn) + server->machine.boot = kn->value.ui32; + } server->machine.kd = kvm_open(NULL, NULL, NULL, O_RDONLY, NULL); if(!server->machine.kd) diff --git a/sysdeps/solaris/swap.c b/sysdeps/solaris/swap.c index 8d79003d..9cf6a617 100644 --- a/sysdeps/solaris/swap.c +++ b/sysdeps/solaris/swap.c @@ -25,11 +25,12 @@ #include #include +#include #include static const unsigned long _glibtop_sysdeps_swap = -(1 << GLIBTOP_SWAP_TOTAL) + (1 << GLIBTOP_SWAP_USED) + -(1 << GLIBTOP_SWAP_FREE); +(1L << GLIBTOP_SWAP_TOTAL) + (1L << GLIBTOP_SWAP_USED) + +(1L << GLIBTOP_SWAP_FREE); /* Init function. */ @@ -55,6 +56,12 @@ glibtop_get_swap_s (glibtop *server, glibtop_swap *buf) if (!ksp) return; + switch(kstat_chain_update(kc)) + { + case -1: assert(0); /* Debugging, shouldn't happen */ + case 0: break; + default: glibtop_get_kstats(server); + } ret = kstat_read (kc, ksp, &vminfo); if (ret == -1) { diff --git a/sysdeps/solaris/uptime.c b/sysdeps/solaris/uptime.c index a6189448..5c313e9e 100644 --- a/sysdeps/solaris/uptime.c +++ b/sysdeps/solaris/uptime.c @@ -24,7 +24,10 @@ #include #include -static const unsigned long _glibtop_sysdeps_uptime = 0; +#include + +static const unsigned long _glibtop_sysdeps_uptime = +(1L << GLIBTOP_UPTIME_UPTIME) + (1L <machine.boot)) + return; + buf->boot_time = server->machine.boot; + buf->uptime = time(NULL) - server->machine.boot; + + buf->flags = _glibtop_sysdeps_uptime; }