/*
 * 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, 0);

	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);
	if (!name) {
		fprintf(stderr, "failed to allocate event name\n");
		return;
	}

	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, 0);
	if (ret)
		cout << "stop failing\n";
}

void perf_event::process(void *cookie)
{
	struct perf_event_header *header;

	if (perf_fd < 0)
		return;

	while (pc->data_tail != pc->data_head ) {
		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;
}
