/*
 * Copyright 2010, Intel Corporation
 *
 * This file is part of PowerTOP
 *
 * This program file is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by the
 * Free Software Foundation; version 2 of the License.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program in a file named COPYING; if not, write to the
 * Free Software Foundation, Inc,
 * 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301 USA
 * or just google for it.
 *
 * Authors:
 *	Arjan van de Ven <arjan@linux.intel.com>
 */

#include <iostream>
#include <fstream>

#include <unistd.h>
#include <sys/syscall.h>   /* For SYS_xxx definitions */
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>

#include <fcntl.h>

#include "perf_event.h"

/* __NR_perf_event_open in ia64 and alpha is defined elsewhere */
#ifdef __ia64__
#include <asm-generic/unistd.h>
#endif
#ifdef __alpha__
#include <asm-generic/unistd.h>
#endif

#include "perf.h"
#include "../lib.h"
#include "../display.h"

struct pevent *perf_event::pevent;

static int get_trace_type(const char *eventname)
{
	string str;
	int this_trace;

	str = read_sysfs_string("/sys/kernel/debug/tracing/events/%s/id",
					eventname);
	if (str.length() < 1)
		return -1;

	this_trace = strtoull(str.c_str(), NULL, 10);
	return this_trace;
}

static inline int sys_perf_event_open(struct perf_event_attr *attr,
                      pid_t pid, int cpu, int group_fd,
                      unsigned long flags)
{
	attr->size = sizeof(*attr);
	return syscall(__NR_perf_event_open, attr, pid, cpu,
			group_fd, flags);
}

void perf_event::create_perf_event(char *eventname, int _cpu)
{
	struct perf_event_attr attr;
	int ret;

	struct {
		__u64 count;
		__u64 time_enabled;
		__u64 time_running;
		__u64 id;
	} read_data;

	if (perf_fd != -1)
		clear();

	memset(&attr, 0, sizeof(attr));

	attr.read_format	= PERF_FORMAT_TOTAL_TIME_ENABLED |
				  PERF_FORMAT_TOTAL_TIME_RUNNING |
				  PERF_FORMAT_ID;

	attr.sample_freq	= 0;
	attr.sample_period	= 1;
	attr.sample_type	|= PERF_SAMPLE_RAW | PERF_SAMPLE_CPU | PERF_SAMPLE_TIME;

	attr.mmap		= 1;
	attr.comm		= 1;
	attr.inherit		= 0;
	attr.disabled		= 1;

	attr.type		= PERF_TYPE_TRACEPOINT;
	attr.config		= trace_type;

	if (attr.config <= 0)
		return;

	perf_fd = sys_perf_event_open(&attr, -1, _cpu, -1, 0);

	if (perf_fd < 0) {
		reset_display();
		fprintf(stderr, _("PowerTOP %s needs the kernel to support the 'perf' subsystem\n"), POWERTOP_VERSION);
		fprintf(stderr, _("as well as support for trace points in the kernel:\n"));
		fprintf(stderr, "CONFIG_PERF_EVENTS=y\nCONFIG_PERF_COUNTERS=y\nCONFIG_TRACEPOINTS=y\nCONFIG_TRACING=y\n");
		exit(EXIT_FAILURE);
	}
	if (read(perf_fd, &read_data, sizeof(read_data)) == -1) {
		reset_display();
		perror("Unable to read perf file descriptor\n");
		exit(-1);
	}

	fcntl(perf_fd, F_SETFL, O_NONBLOCK);

	perf_mmap = mmap(NULL, (bufsize+1)*getpagesize(),
				PROT_READ | PROT_WRITE, MAP_SHARED, perf_fd, 0);
	if (perf_mmap == MAP_FAILED) {
		fprintf(stderr, "failed to mmap with %d (%s)\n", errno, strerror(errno));
		return;
	}

	ret = ioctl(perf_fd, PERF_EVENT_IOC_ENABLE);

	if (ret < 0) {
		fprintf(stderr, "failed to enable perf \n");
	}

	pc = (perf_event_mmap_page *)perf_mmap;
	data_mmap = (unsigned char *)perf_mmap + getpagesize();


}

void perf_event::set_event_name(const char *event_name)
{
	if (name)
		free(name);
	name = strdup(event_name);
	char *c;

	c = strchr(name, ':');
	if (c)
		*c = '/';

	trace_type = get_trace_type(name);
}

perf_event::~perf_event(void)
{
	if (name)
		free(name);

	if (perf_event::pevent->ref_count == 1) {
		pevent_free(perf_event::pevent);
		perf_event::pevent = NULL;
	} else
		pevent_unref(perf_event::pevent);
}

void perf_event::set_cpu(int _cpu)
{
	cpu = _cpu;
}

static void allocate_pevent(void)
{
	if (!perf_event::pevent)
		perf_event::pevent = pevent_alloc();
	else
		pevent_ref(perf_event::pevent);
}

perf_event::perf_event(const char *event_name, int _cpu, int buffer_size)
{
	allocate_pevent();
	name = NULL;
	perf_fd = -1;
	bufsize = buffer_size;
	cpu = _cpu;
	perf_mmap = NULL;
	trace_type = 0;
	set_event_name(event_name);
}

perf_event::perf_event(void)
{
	allocate_pevent();
	name = NULL;
	perf_fd = -1;
	bufsize = 128;
	perf_mmap = NULL;
	cpu = 0;
	trace_type = 0;
}

void perf_event::start(void)
{
	create_perf_event(name, cpu);
}

void perf_event::stop(void)
{
	int ret;
	ret = ioctl(perf_fd, PERF_EVENT_IOC_DISABLE);
	if (ret)
		cout << "stop failing\n";
}

void perf_event::process(void *cookie)
{
	struct perf_event_header *header;
	int i = 0;

	if (perf_fd < 0)
		return;

	while (pc->data_tail != pc->data_head && i++ < 5000) {
		while (pc->data_tail >= (unsigned int)bufsize * getpagesize())
			pc->data_tail -= bufsize * getpagesize();

		header = (struct perf_event_header *)( (unsigned char *)data_mmap + pc->data_tail);

		if (header->size == 0)
			break;

		pc->data_tail += header->size;

		while (pc->data_tail >= (unsigned int)bufsize * getpagesize())
			pc->data_tail -= bufsize * getpagesize();

		if (header->type == PERF_RECORD_SAMPLE)
			handle_event(header, cookie);
	}
	pc->data_tail = pc->data_head;
}

void perf_event::clear(void)
{
	if (perf_mmap) {
//		memset(perf_mmap, 0, (bufsize)*getpagesize());
		munmap(perf_mmap, (bufsize+1)*getpagesize());
		perf_mmap = NULL;
	}
	if (perf_fd != -1)
		close(perf_fd);
	perf_fd = -1;
}
