/*
 * 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 <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"
#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;
}
