Blame src/libpfm-3.y/lib/pfmlib_os_linux.c

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
}