/**
 * @file opd_anon.c
 * Anonymous region handling.
 *
 * Our caching of maps has some problems: if we get tgid reuse,
 * and it's the same application, we might end up with wrong
 * maps. The same happens in an unmap-remap case. There's not much
 * we can do about this, we just hope it's not too common...
 *
 * What is relatively common is expanding anon maps, which leaves us
 * with lots of separate sample files.
 *
 * @remark Copyright 2005 OProfile authors
 * @remark Read the file COPYING
 *
 * @author John Levon
 */

#include "opd_anon.h"
#include "opd_trans.h"
#include "opd_sfile.h"
#include "opd_printf.h"
#include "op_libiberty.h"

#include <limits.h>
#include <stdlib.h>
#include <stdio.h>

#define HASH_SIZE 1024
#define HASH_BITS (HASH_SIZE - 1)

#define LRU_SIZE 1000
#define LRU_AMOUNT (LRU_SIZE/5)

static struct list_head hashes[HASH_SIZE];
static struct list_head lru;
static size_t nr_lru;

/* never called in buffer-processing context, so we don't need
 * to update struct transient. Note the 'U' of LRU is based on
 * parsing time, not actual use.
 */
static void do_lru(struct transient * trans)
{
	size_t nr_to_kill = LRU_AMOUNT;
	struct list_head * pos;
	struct list_head * pos2;
	struct anon_mapping * entry;

	list_for_each_safe(pos, pos2, &lru) {
		entry = list_entry(pos, struct anon_mapping, lru_list);
		if (trans->anon == entry)
			clear_trans_current(trans);
		if (trans->last_anon == entry)
			clear_trans_last(trans);
		list_del(&entry->list);
		list_del(&entry->lru_list);
		--nr_lru;
		free(entry);
		if (nr_to_kill-- == 0)
			break;
	}

	sfile_clear_anon();
}


static unsigned long hash_anon(pid_t tgid, cookie_t app)
{
	return ((app >> DCOOKIE_SHIFT) ^ (tgid >> 2)) & (HASH_SIZE - 1);
}
 

static void clear_anon_maps(struct transient * trans)
{
	unsigned long hash = hash_anon(trans->tgid, trans->app_cookie);
	pid_t tgid = trans->tgid;
	cookie_t app = trans->app_cookie;
	struct list_head * pos;
	struct list_head * pos2;
	struct anon_mapping * entry;

	clear_trans_current(trans);

	list_for_each_safe(pos, pos2, &hashes[hash]) {
		entry = list_entry(pos, struct anon_mapping, list);
		if (entry->tgid == tgid && entry->app_cookie == app) {
			if (trans->last_anon == entry)
				clear_trans_last(trans);
			list_del(&entry->list);
			list_del(&entry->lru_list);
			--nr_lru;
			free(entry);
		}
	}

	sfile_clear_anon();
	if (vmisc) {
		char const * name = verbose_cookie(app);
		printf("Cleared anon maps for tgid %u (%s).\n", tgid, name);
	}
}


static void
add_anon_mapping(struct transient * trans, vma_t start, vma_t end)
{
	unsigned long hash = hash_anon(trans->tgid, trans->app_cookie);
	struct anon_mapping * m = xmalloc(sizeof(struct anon_mapping));
	m->tgid = trans->tgid;
	m->app_cookie = trans->app_cookie;
	m->start = start;
	m->end = end;
	list_add_tail(&m->list, &hashes[hash]);
	list_add_tail(&m->lru_list, &lru);
	if (++nr_lru == LRU_SIZE)
		do_lru(trans);
	if (vmisc) {
		char const * name = verbose_cookie(m->app_cookie);
		printf("Added anon map 0x%llx-0x%llx for tgid %u (%s).\n",
		       start, end, m->tgid, name);
	}
}


/* 42000000-4212f000 r-xp 00000000 16:03 424334 /lib/tls/libc-2.3.2.so */
static void get_anon_maps(struct transient * trans)
{
	FILE * fp = NULL;
	char buf[PATH_MAX];
	unsigned long start;
	unsigned long end;
	int ret;

	snprintf(buf, PATH_MAX, "/proc/%d/maps", trans->tgid);
	fp = fopen(buf, "r");
	if (!fp)
		return;

	while (fgets(buf, PATH_MAX, fp) != NULL) {
		char tmp[20];
		/* Note that this actually includes all mappings,
		 * since we want stuff like [heap]
		 */
		ret = sscanf(buf, "%lx-%lx %20s %20s %20s %20s %20s",
		             &start, &end, tmp, tmp, tmp, tmp, tmp);
		if (ret < 6)
			continue;

		add_anon_mapping(trans, start, end);
	}

	fclose(fp);
}


static int
anon_match(struct transient const * trans, struct anon_mapping const * anon)
{
	if (!anon)
		return 0;
	if (trans->tgid != anon->tgid)
		return 0;
	if (trans->app_cookie != anon->app_cookie)
		return 0;
	if (trans->pc < anon->start)
		return 0;
	return (trans->pc < anon->end);
}


struct anon_mapping * find_anon_mapping(struct transient * trans)
{
	unsigned long hash = hash_anon(trans->tgid, trans->app_cookie);
	struct list_head * pos;
	struct anon_mapping * entry;
	int tried = 0;

	if (anon_match(trans, trans->anon))
		return (trans->anon);

retry:
	list_for_each(pos, &hashes[hash]) {
		entry = list_entry(pos, struct anon_mapping, list);
		if (anon_match(trans, entry))
			goto success;
	}

	if (!tried) {
		clear_anon_maps(trans);
		get_anon_maps(trans);
		tried = 1;
		goto retry;
	}

	return NULL;

success:
	/*
	 * Typically, there's one big mapping that matches. Let's go
	 * faster.
	 */
	list_del(&entry->list);
	list_add(&entry->list, &hashes[hash]);

	verbprintf(vmisc, "Found range 0x%llx-0x%llx for tgid %u, pc %llx.\n",
	           entry->start, entry->end, (unsigned int)entry->tgid,
		   trans->pc);
	return entry;
}


void anon_init(void)
{
	size_t i;

	for (i = 0; i < HASH_SIZE; ++i)
		list_init(&hashes[i]);

	list_init(&lru);
}
