|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* pfmlib_os.c: set of functions OS dependent functions
|
|
Packit |
577717 |
*
|
|
Packit |
577717 |
* Copyright (c) 2003-2006 Hewlett-Packard Development Company, L.P.
|
|
Packit |
577717 |
* Contributed by Stephane Eranian <eranian@hpl.hp.com>
|
|
Packit |
577717 |
*
|
|
Packit |
577717 |
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
Packit |
577717 |
* of this software and associated documentation files (the "Software"), to deal
|
|
Packit |
577717 |
* in the Software without restriction, including without limitation the rights
|
|
Packit |
577717 |
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
|
Packit |
577717 |
* of the Software, and to permit persons to whom the Software is furnished to do so,
|
|
Packit |
577717 |
* subject to the following conditions:
|
|
Packit |
577717 |
*
|
|
Packit |
577717 |
* The above copyright notice and this permission notice shall be included in all
|
|
Packit |
577717 |
* copies or substantial portions of the Software.
|
|
Packit |
577717 |
*
|
|
Packit |
577717 |
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
|
Packit |
577717 |
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
|
Packit |
577717 |
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
|
Packit |
577717 |
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
|
|
Packit |
577717 |
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
|
|
Packit |
577717 |
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
#ifndef _GNU_SOURCE
|
|
Packit |
577717 |
#define _GNU_SOURCE /* for getline */
|
|
Packit |
577717 |
#endif
|
|
Packit |
577717 |
#include <sys/types.h>
|
|
Packit |
577717 |
#include <stdint.h>
|
|
Packit |
577717 |
#include <stdio.h>
|
|
Packit |
577717 |
#include <stdarg.h>
|
|
Packit |
577717 |
#include <string.h>
|
|
Packit |
577717 |
#include <stdlib.h>
|
|
Packit |
577717 |
#include <unistd.h>
|
|
Packit |
577717 |
#include <errno.h>
|
|
Packit |
577717 |
#include <sys/utsname.h>
|
|
Packit |
577717 |
#include <perfmon/perfmon.h>
|
|
Packit |
577717 |
|
|
Packit |
577717 |
#include <perfmon/pfmlib.h>
|
|
Packit |
577717 |
#include "pfmlib_priv.h"
|
|
Packit |
577717 |
|
|
Packit |
577717 |
int _pfmlib_sys_base; /* syscall base */
|
|
Packit |
577717 |
int _pfmlib_major_version; /* kernel perfmon major version */
|
|
Packit |
577717 |
int _pfmlib_minor_version; /* kernel perfmon minor version */
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* helper function to retrieve one value from /proc/cpuinfo
|
|
Packit |
577717 |
* for internal libpfm use only
|
|
Packit |
577717 |
* attr: the attribute (line) to look for
|
|
Packit |
577717 |
* ret_buf: a buffer to store the value of the attribute (as a string)
|
|
Packit |
577717 |
* maxlen : number of bytes of capacity in ret_buf
|
|
Packit |
577717 |
*
|
|
Packit |
577717 |
* ret_buf is null terminated.
|
|
Packit |
577717 |
*
|
|
Packit |
577717 |
* Return:
|
|
Packit |
577717 |
* 0 : attribute found, ret_buf populated
|
|
Packit |
577717 |
* -1: attribute not found
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
int
|
|
Packit |
577717 |
__pfm_getcpuinfo_attr(const char *attr, char *ret_buf, size_t maxlen)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
FILE *fp = NULL;
|
|
Packit |
577717 |
int ret = -1;
|
|
Packit |
577717 |
size_t attr_len, buf_len = 0;
|
|
Packit |
577717 |
char *p, *value = NULL;
|
|
Packit |
577717 |
char *buffer = NULL;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (attr == NULL || ret_buf == NULL || maxlen < 1)
|
|
Packit |
577717 |
return -1;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
attr_len = strlen(attr);
|
|
Packit |
577717 |
|
|
Packit |
577717 |
fp = fopen("/proc/cpuinfo", "r");
|
|
Packit |
577717 |
if (fp == NULL)
|
|
Packit |
577717 |
return -1;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
while(getline(&buffer, &buf_len, fp) != -1){
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* skip blank lines */
|
|
Packit |
577717 |
if (*buffer == '\n')
|
|
Packit |
577717 |
continue;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
p = strchr(buffer, ':');
|
|
Packit |
577717 |
if (p == NULL)
|
|
Packit |
577717 |
goto error;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* p+2: +1 = space, +2= firt character
|
|
Packit |
577717 |
* strlen()-1 gets rid of \n
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
*p = '\0';
|
|
Packit |
577717 |
value = p+2;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
value[strlen(value)-1] = '\0';
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (!strncmp(attr, buffer, attr_len))
|
|
Packit |
577717 |
break;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
strncpy(ret_buf, value, maxlen-1);
|
|
Packit |
577717 |
ret_buf[maxlen-1] = '\0';
|
|
Packit |
577717 |
ret = 0;
|
|
Packit |
577717 |
error:
|
|
Packit |
577717 |
free(buffer);
|
|
Packit |
577717 |
fclose(fp);
|
|
Packit |
577717 |
return ret;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
#if defined(__x86_64__)
|
|
Packit |
577717 |
static void adjust__pfmlib_sys_base(int version)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
#ifdef CONFIG_PFMLIB_ARCH_CRAYXT
|
|
Packit |
577717 |
_pfmlib_sys_base = 273;
|
|
Packit |
577717 |
#else
|
|
Packit |
577717 |
switch(version) {
|
|
Packit |
577717 |
case 29:
|
|
Packit |
577717 |
case 28:
|
|
Packit |
577717 |
case 27:
|
|
Packit |
577717 |
_pfmlib_sys_base = 295;
|
|
Packit |
577717 |
break;
|
|
Packit |
577717 |
case 26:
|
|
Packit |
577717 |
case 25:
|
|
Packit |
577717 |
_pfmlib_sys_base = 288;
|
|
Packit |
577717 |
break;
|
|
Packit |
577717 |
case 24:
|
|
Packit |
577717 |
default: /* 2.6.24 as default */
|
|
Packit |
577717 |
_pfmlib_sys_base = 286;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
#endif
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
#elif defined(__i386__)
|
|
Packit |
577717 |
static void adjust__pfmlib_sys_base(int version)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
switch(version) {
|
|
Packit |
577717 |
case 29:
|
|
Packit |
577717 |
case 28:
|
|
Packit |
577717 |
case 27:
|
|
Packit |
577717 |
_pfmlib_sys_base = 333;
|
|
Packit |
577717 |
break;
|
|
Packit |
577717 |
case 26:
|
|
Packit |
577717 |
case 25:
|
|
Packit |
577717 |
_pfmlib_sys_base = 327;
|
|
Packit |
577717 |
break;
|
|
Packit |
577717 |
case 24:
|
|
Packit |
577717 |
default: /* 2.6.24 as default */
|
|
Packit |
577717 |
_pfmlib_sys_base = 325;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
#elif defined(__mips__)
|
|
Packit |
577717 |
#if (_MIPS_SIM == _ABIN32) || (_MIPS_SIM == _MIPS_SIM_NABI32)
|
|
Packit |
577717 |
static void adjust__pfmlib_sys_base(int version)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
_pfmlib_sys_base = 6000;
|
|
Packit |
577717 |
#ifdef CONFIG_PFMLIB_ARCH_SICORTEX
|
|
Packit |
577717 |
_pfmlib_sys_base += 279;
|
|
Packit |
577717 |
#else
|
|
Packit |
577717 |
switch(version) {
|
|
Packit |
577717 |
case 29:
|
|
Packit |
577717 |
case 28:
|
|
Packit |
577717 |
case 27:
|
|
Packit |
577717 |
_pfmlib_sys_base += 293;
|
|
Packit |
577717 |
break;
|
|
Packit |
577717 |
case 26:
|
|
Packit |
577717 |
case 25:
|
|
Packit |
577717 |
_pfmlib_sys_base += 287;
|
|
Packit |
577717 |
break;
|
|
Packit |
577717 |
case 24:
|
|
Packit |
577717 |
default: /* 2.6.24 as default */
|
|
Packit |
577717 |
_pfmlib_sys_base += 284;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
#endif
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
#elif (_MIPS_SIM == _ABIO32) || (_MIPS_SIM == _MIPS_SIM_ABI32)
|
|
Packit |
577717 |
static void adjust__pfmlib_sys_base(int version)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
_pfmlib_sys_base = 4000;
|
|
Packit |
577717 |
#ifdef CONFIG_PFMLIB_ARCH_SICORTEX
|
|
Packit |
577717 |
_pfmlib_sys_base += 316;
|
|
Packit |
577717 |
#else
|
|
Packit |
577717 |
switch(version) {
|
|
Packit |
577717 |
case 29:
|
|
Packit |
577717 |
case 28:
|
|
Packit |
577717 |
case 27:
|
|
Packit |
577717 |
_pfmlib_sys_base += 330;
|
|
Packit |
577717 |
break;
|
|
Packit |
577717 |
case 26:
|
|
Packit |
577717 |
case 25:
|
|
Packit |
577717 |
_pfmlib_sys_base += 324;
|
|
Packit |
577717 |
break;
|
|
Packit |
577717 |
case 24:
|
|
Packit |
577717 |
default: /* 2.6.24 as default */
|
|
Packit |
577717 |
_pfmlib_sys_base += 321;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
#endif
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
#elif (_MIPS_SIM == _ABI64) || (_MIPS_SIM == _MIPS_SIM_ABI64)
|
|
Packit |
577717 |
static void adjust__pfmlib_sys_base(int version)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
_pfmlib_sys_base = 5000;
|
|
Packit |
577717 |
#ifdef CONFIG_PFMLIB_ARCH_SICORTEX
|
|
Packit |
577717 |
_pfmlib_sys_base += 275;
|
|
Packit |
577717 |
#else
|
|
Packit |
577717 |
switch(version) {
|
|
Packit |
577717 |
case 29:
|
|
Packit |
577717 |
case 28:
|
|
Packit |
577717 |
case 27:
|
|
Packit |
577717 |
_pfmlib_sys_base += 289;
|
|
Packit |
577717 |
break;
|
|
Packit |
577717 |
case 26:
|
|
Packit |
577717 |
case 25:
|
|
Packit |
577717 |
_pfmlib_sys_base += 283;
|
|
Packit |
577717 |
break;
|
|
Packit |
577717 |
case 24:
|
|
Packit |
577717 |
default: /* 2.6.24 as default */
|
|
Packit |
577717 |
_pfmlib_sys_base += 280;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
#endif
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
#endif
|
|
Packit |
577717 |
#elif defined(__ia64__)
|
|
Packit |
577717 |
static void adjust__pfmlib_sys_base(int version)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
switch(version) {
|
|
Packit |
577717 |
case 29:
|
|
Packit |
577717 |
case 28:
|
|
Packit |
577717 |
case 27:
|
|
Packit |
577717 |
_pfmlib_sys_base = 1319;
|
|
Packit |
577717 |
break;
|
|
Packit |
577717 |
case 26:
|
|
Packit |
577717 |
case 25:
|
|
Packit |
577717 |
_pfmlib_sys_base = 1313;
|
|
Packit |
577717 |
break;
|
|
Packit |
577717 |
case 24:
|
|
Packit |
577717 |
default: /* 2.6.24 as default */
|
|
Packit |
577717 |
_pfmlib_sys_base = 1310;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
#elif defined(__powerpc__)
|
|
Packit |
577717 |
static void adjust__pfmlib_sys_base(int version)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
switch(version) {
|
|
Packit |
577717 |
case 29:
|
|
Packit |
577717 |
case 28:
|
|
Packit |
577717 |
case 27:
|
|
Packit |
577717 |
_pfmlib_sys_base = 319;
|
|
Packit |
577717 |
break;
|
|
Packit |
577717 |
case 26:
|
|
Packit |
577717 |
case 25:
|
|
Packit |
577717 |
_pfmlib_sys_base = 313;
|
|
Packit |
577717 |
break;
|
|
Packit |
577717 |
case 24:
|
|
Packit |
577717 |
default: /* 2.6.24 as default */
|
|
Packit |
577717 |
_pfmlib_sys_base = 310;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
#elif defined(__sparc__)
|
|
Packit |
577717 |
static void adjust__pfmlib_sys_base(int version)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
switch(version) {
|
|
Packit |
577717 |
case 28:
|
|
Packit |
577717 |
_pfmlib_sys_base = 324;
|
|
Packit |
577717 |
break;
|
|
Packit |
577717 |
case 27:
|
|
Packit |
577717 |
_pfmlib_sys_base = 323;
|
|
Packit |
577717 |
break;
|
|
Packit |
577717 |
case 26:
|
|
Packit |
577717 |
case 25:
|
|
Packit |
577717 |
_pfmlib_sys_base = 317;
|
|
Packit |
577717 |
break;
|
|
Packit |
577717 |
case 24:
|
|
Packit |
577717 |
default: /* 2.6.24 as default */
|
|
Packit |
577717 |
_pfmlib_sys_base = 310;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
#elif defined(__crayx2)
|
|
Packit |
577717 |
static inline void adjust__pfmlib_sys_base(int version)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
_pfmlib_sys_base = 294;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
#else
|
|
Packit |
577717 |
static inline void adjust__pfmlib_sys_base(int version)
|
|
Packit |
577717 |
{}
|
|
Packit |
577717 |
#endif
|
|
Packit |
577717 |
|
|
Packit |
577717 |
static void
|
|
Packit |
577717 |
pfm_init_syscalls_hardcoded(void)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
struct utsname b;
|
|
Packit |
577717 |
char *p, *s;
|
|
Packit |
577717 |
int ret, v;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* get version information
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
ret = uname(&b);
|
|
Packit |
577717 |
if (ret == -1)
|
|
Packit |
577717 |
return;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* expect major number 2
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
s= b.release;
|
|
Packit |
577717 |
p = strchr(s, '.');
|
|
Packit |
577717 |
if (!p)
|
|
Packit |
577717 |
return;
|
|
Packit |
577717 |
*p = '\0';
|
|
Packit |
577717 |
v = atoi(s);
|
|
Packit |
577717 |
if (v != 2)
|
|
Packit |
577717 |
return;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* expect 2.6
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
s = ++p;
|
|
Packit |
577717 |
p = strchr(s, '.');
|
|
Packit |
577717 |
if (!p)
|
|
Packit |
577717 |
return;
|
|
Packit |
577717 |
*p = '\0';
|
|
Packit |
577717 |
v = atoi(s);
|
|
Packit |
577717 |
if (v != 6)
|
|
Packit |
577717 |
return;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
s = ++p;
|
|
Packit |
577717 |
while (*p >= '0' && *p <= '9') p++;
|
|
Packit |
577717 |
*p = '\0';
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* v is subversion: 23, 24 25 */
|
|
Packit |
577717 |
v = atoi(s);
|
|
Packit |
577717 |
|
|
Packit |
577717 |
adjust__pfmlib_sys_base(v);
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
static int
|
|
Packit |
577717 |
pfm_init_syscalls_sysfs(void)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
FILE *fp;
|
|
Packit |
577717 |
int ret;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
fp = fopen("/sys/kernel/perfmon/syscall", "r");
|
|
Packit |
577717 |
if (!fp)
|
|
Packit |
577717 |
return -1;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
ret = fscanf(fp, "%d", &_pfmlib_sys_base);
|
|
Packit |
577717 |
|
|
Packit |
577717 |
fclose(fp);
|
|
Packit |
577717 |
return ret == 1 ? 0 : -1;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
static int
|
|
Packit |
577717 |
pfm_init_version_sysfs(void)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
FILE *fp;
|
|
Packit |
577717 |
char *p;
|
|
Packit |
577717 |
char v[8];
|
|
Packit |
577717 |
int ret;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
fp = fopen("/sys/kernel/perfmon/version", "r");
|
|
Packit |
577717 |
if (!fp)
|
|
Packit |
577717 |
return -1;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
ret = fscanf(fp, "%s", v);
|
|
Packit |
577717 |
if (ret != 1)
|
|
Packit |
577717 |
goto skip;
|
|
Packit |
577717 |
p = strchr(v, '.');
|
|
Packit |
577717 |
if (p) {
|
|
Packit |
577717 |
*p++ = '\0';
|
|
Packit |
577717 |
_pfmlib_major_version = atoi(v);
|
|
Packit |
577717 |
_pfmlib_minor_version = atoi(p);
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
skip:
|
|
Packit |
577717 |
fclose(fp);
|
|
Packit |
577717 |
return ret == 1 ? 0 : -1;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
|
|
Packit |
577717 |
void
|
|
Packit |
577717 |
pfm_init_syscalls(void)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
int ret;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* first try via sysfs
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
ret = pfm_init_syscalls_sysfs();
|
|
Packit |
577717 |
if (ret)
|
|
Packit |
577717 |
pfm_init_syscalls_hardcoded();
|
|
Packit |
577717 |
|
|
Packit |
577717 |
ret = pfm_init_version_sysfs();
|
|
Packit |
577717 |
if (ret) {
|
|
Packit |
577717 |
_pfmlib_major_version = 3;
|
|
Packit |
577717 |
_pfmlib_minor_version = 0;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
__pfm_vbprintf("sycall base %d\n", _pfmlib_sys_base);
|
|
Packit |
577717 |
__pfm_vbprintf("major version %d\nminor version %d\n",
|
|
Packit |
577717 |
_pfmlib_major_version,
|
|
Packit |
577717 |
_pfmlib_minor_version);
|
|
Packit |
577717 |
}
|