refactor perfstat wrapper so it can be used in other functions

This commit is contained in:
Doug MacEachern 2004-07-19 18:13:56 +00:00
parent 310cf063eb
commit 7d6f84e81a
2 changed files with 83 additions and 56 deletions

View File

@ -28,8 +28,6 @@
#include <sys/cfgdb.h> #include <sys/cfgdb.h>
#include <cf.h> #include <cf.h>
#include "libperfstat.h"
#include "user_v5.h" #include "user_v5.h"
#include "utmp_v5.h" #include "utmp_v5.h"
@ -111,6 +109,7 @@ int sigar_os_open(sigar_t **sigar)
(*sigar)->cpuinfo = NULL; (*sigar)->cpuinfo = NULL;
(*sigar)->cpuinfo_size = 0; (*sigar)->cpuinfo_size = 0;
SIGAR_ZERO(&(*sigar)->swaps); SIGAR_ZERO(&(*sigar)->swaps);
SIGAR_ZERO(&(*sigar)->perfstat);
i = getpagesize(); i = getpagesize();
while ((i >>= 1) > 0) { while ((i >>= 1) > 0) {
@ -151,6 +150,9 @@ int sigar_os_close(sigar_t *sigar)
if (sigar->cpuinfo) { if (sigar->cpuinfo) {
free(sigar->cpuinfo); free(sigar->cpuinfo);
} }
if (sigar->perfstat.handle) {
dlclose(sigar->perfstat.handle);
}
free(sigar); free(sigar);
return SIGAR_OK; return SIGAR_OK;
} }
@ -165,6 +167,70 @@ char *sigar_os_error_string(int err)
} }
} }
/*
* the perfstat api is only supported in aix 5.2+
* in order to be binary compatible with 4.3 and 5.1
* we must jump through some hoops. libperfstat.a
* is a static library, we need dynamic.
* libsigar_aixperfstat.so is juat a proxy to libperfstat.a
*/
#define SIGAR_AIXPERFSTAT "/libsigar_aixperfstat.so"
static int sigar_perfstat_init(sigar_t *sigar)
{
perfstat_cpu_func_t pcpu;
void *handle;
char libperfstat[SIGAR_PATH_MAX], *path;
int len;
if (sigar->perfstat.avail == 1) {
return SIGAR_OK;
}
if (sigar->perfstat.avail == -1) {
return ENOENT;
}
path = sigar_get_self_path(sigar);
len = strlen(path);
memcpy(&path[0], sigar->self_path, len);
memcpy(&path[len], SIGAR_AIXPERFSTAT,
sizeof(SIGAR_AIXPERFSTAT));
if (!(handle = dlopen(path, RTLD_LOCAL|RTLD_LAZY))) {
if (SIGAR_LOG_IS_DEBUG(sigar)) {
sigar_log_printf(sigar, SIGAR_LOG_DEBUG,
"failed to open '%s': %s",
path, sigar_strerror(sigar, errno));
}
sigar->perfstat.avail = -1;
return errno;
}
pcpu = (perfstat_cpu_func_t)dlsym(handle,
"sigar_perfstat_cpu_total");
if (!pcpu) {
if (SIGAR_LOG_IS_DEBUG(sigar)) {
sigar_log_printf(sigar, SIGAR_LOG_DEBUG,
"dlsym(sigar_perfstat_cpu_total) failed: %s",
dlerror());
}
dlclose(handle);
sigar->perfstat.avail = -1;
return ENOENT;
}
sigar->perfstat.avail = 1;
sigar->perfstat.handle = handle;
sigar->perfstat.cpu_total = pcpu;
return SIGAR_OK;
}
#define PAGESHIFT(v) \ #define PAGESHIFT(v) \
((v) << sigar->pagesize) ((v) << sigar->pagesize)
@ -1151,67 +1217,18 @@ static char *sigar_get_odm_model(sigar_t *sigar)
#define SIGAR_CPU_CACHE_SIZE \ #define SIGAR_CPU_CACHE_SIZE \
(_system_configuration.L2_cache_size / 1024) (_system_configuration.L2_cache_size / 1024)
/*
* the perfstat api is only supported in aix 5.2+
* in order to be binary compatible with 4.3 and 5.1
* we must jump through some hoops. libperfstat.a
* is a static library, we need dynamic.
* libsigar_aixperfstat.so is juat a proxy to libperfstat.a
*/
#define SIGAR_AIXPERFSTAT "/libsigar_aixperfstat.so"
typedef int (*perfstat_cpu_func_t)(perfstat_id_t *,
perfstat_cpu_total_t *,
int, int);
static int sigar_get_cpu_mhz_perfstat(sigar_t *sigar) static int sigar_get_cpu_mhz_perfstat(sigar_t *sigar)
{ {
int status = 0;
perfstat_cpu_total_t data; perfstat_cpu_total_t data;
perfstat_cpu_func_t pcpu;
void *handle;
char libperfstat[SIGAR_PATH_MAX];
char *path = sigar_get_self_path(sigar);
int len = strlen(path);
memcpy(&path[0], sigar->self_path, len); if (sigar_perfstat_init(sigar) == SIGAR_OK) {
memcpy(&path[len], SIGAR_AIXPERFSTAT, if (sigar->perfstat.cpu_total(0, &data, sizeof(data), 1)) {
sizeof(SIGAR_AIXPERFSTAT)); sigar->cpu_mhz = data.processorHZ / 1000000;
return SIGAR_OK;
if (!(handle = dlopen(path, RTLD_LOCAL|RTLD_LAZY))) {
if (SIGAR_LOG_IS_DEBUG(sigar)) {
sigar_log_printf(sigar, SIGAR_LOG_DEBUG,
"failed to open '%s': %s",
path, sigar_strerror(sigar, errno));
} }
return errno;
} }
pcpu = (perfstat_cpu_func_t)dlsym(handle, return ENOENT;
"sigar_perfstat_cpu_total");
if (!pcpu) {
if (SIGAR_LOG_IS_DEBUG(sigar)) {
sigar_log_printf(sigar, SIGAR_LOG_DEBUG,
"dlsym(sigar_perfstat_cpu_total) failed: %s",
dlerror());
}
dlclose(handle);
return ENOENT;
}
if (pcpu(0, &data, sizeof(data), 1)) {
sigar->cpu_mhz = data.processorHZ / 1000000;
}
else {
dlclose(handle);
return errno;
}
dlclose(handle);
return SIGAR_OK;
} }
static int sigar_get_cpu_mhz(sigar_t *sigar) static int sigar_get_cpu_mhz(sigar_t *sigar)

View File

@ -5,6 +5,7 @@
#include <errno.h> #include <errno.h>
#include <dlfcn.h> #include <dlfcn.h>
#include <procinfo.h> #include <procinfo.h>
#include "libperfstat.h"
enum { enum {
KOFFSET_LOADAVG, KOFFSET_LOADAVG,
@ -26,6 +27,10 @@ typedef int (*vminfo_func_t) (void *, int, int);
typedef int (*proc_fd_func_t) (sigar_t *, sigar_pid_t, sigar_proc_fd_t *); typedef int (*proc_fd_func_t) (sigar_t *, sigar_pid_t, sigar_proc_fd_t *);
typedef int (*perfstat_cpu_func_t)(perfstat_id_t *,
perfstat_cpu_total_t *,
int, int);
struct sigar_t { struct sigar_t {
SIGAR_T_BASE; SIGAR_T_BASE;
int kmem; int kmem;
@ -33,6 +38,11 @@ struct sigar_t {
long koffsets[KOFFSET_MAX]; long koffsets[KOFFSET_MAX];
vminfo_func_t getvminfo; vminfo_func_t getvminfo;
proc_fd_func_t getprocfd; proc_fd_func_t getprocfd;
struct {
int avail;
perfstat_cpu_func_t cpu_total;
void *handle;
} perfstat;
int pagesize; int pagesize;
swaps_t swaps; swaps_t swaps;
time_t last_getprocs; time_t last_getprocs;