<commit_before>#include <unistd.h>
#include <fcntl.h>

#include "pagemap-cache.h"
#include "compiler.h"
#include "xmalloc.h"
#include "util.h"
#include "log.h"
#include "vma.h"

#undef	LOG_PREFIX
#define LOG_PREFIX "pagemap-cache: "

/* To carry up to 2M of physical memory */
#define PMC_SHIFT		(21)
#define PMC_SIZE		(1ul << PMC_SHIFT)
#define PMC_MASK		(~(PMC_SIZE - 1))
#define PMC_SIZE_GAP		(PMC_SIZE / 4)

#define PAGEMAP_LEN(addr)	(PAGEMAP_PFN(addr) * sizeof(u64))

static inline void pmc_reset(pmc_t *pmc)
{
	memzero(pmc, sizeof(*pmc));
	pmc->fd = -1;
}

static inline void pmc_zap(pmc_t *pmc)
{
	pmc->start = pmc->end = 0;
}

int pmc_init(pmc_t *pmc, pid_t pid, struct list_head *vma_head, size_t size)
{
	size_t map_size = max(size, (size_t)PMC_SIZE);
	pmc_reset(pmc);

	BUG_ON(!vma_head);

	pmc->pid	= pid;
	pmc->fd		= open_proc(pid, "pagemap");
	pmc->map_len	= PAGEMAP_LEN(map_size);
	pmc->map	= xmalloc(pmc->map_len);
	pmc->vma_head	= vma_head;

	if (!pmc->map || pmc->fd < 0) {
		pr_err("Failed to init pagemap for %d\n", pid);
		pmc_fini(pmc);
		return -1;
	}

	pr_debug("created for pid %d (takes %zu bytes)\n", pid, pmc->map_len);

	return 0;
}

static inline u64 *__pmc_get_map(pmc_t *pmc, unsigned long addr)
{
	return &pmc->map[PAGEMAP_PFN(addr - pmc->start)];
}

static int pmc_fill_cache(pmc_t *pmc, struct vma_area *vma)
{
	unsigned long low = vma->e->start & PMC_MASK;
	unsigned long high = low + PMC_SIZE;
	size_t len = vma_area_len(vma);
	size_t size_map;

	pmc->start = vma->e->start;
	pmc->end = vma->e->end;

	pr_debug("filling VMA %lx-%lx (%zuK) [l:%lx h:%lx]\n",
		 (long)vma->e->start, (long)vma->e->end, len >> 10, low, high);

	/*
	 * If we meet a small VMA, lets try to fit 2M cache
	 * window at least 75% full, otherwise left as a plain
	 * "one vma at a time" read. Note the VMAs in cache must
	 * fit in solid manner, iow -- either the whole vma fits<commit_msg>pagema-cache: Don't exceed task size on hight bound<commit_after>#include <unistd.h>
#include <fcntl.h>

#include "pagemap-cache.h"
#include "compiler.h"
#include "xmalloc.h"
#include "util.h"
#include "log.h"
#include "vma.h"

#undef	LOG_PREFIX
#define LOG_PREFIX "pagemap-cache: "

/* To carry up to 2M of physical memory */
#define PMC_SHIFT		(21)
#define PMC_SIZE		(1ul << PMC_SHIFT)
#define PMC_MASK		(~(PMC_SIZE - 1))
#define PMC_SIZE_GAP		(PMC_SIZE / 4)

#define PAGEMAP_LEN(addr)	(PAGEMAP_PFN(addr) * sizeof(u64))

static inline void pmc_reset(pmc_t *pmc)
{
	memzero(pmc, sizeof(*pmc));
	pmc->fd = -1;
}

static inline void pmc_zap(pmc_t *pmc)
{
	pmc->start = pmc->end = 0;
}

int pmc_init(pmc_t *pmc, pid_t pid, struct list_head *vma_head, size_t size)
{
	size_t map_size = max(size, (size_t)PMC_SIZE);
	pmc_reset(pmc);

	BUG_ON(!vma_head);

	pmc->pid	= pid;
	pmc->fd		= open_proc(pid, "pagemap");
	pmc->map_len	= PAGEMAP_LEN(map_size);
	pmc->map	= xmalloc(pmc->map_len);
	pmc->vma_head	= vma_head;

	if (!pmc->map || pmc->fd < 0) {
		pr_err("Failed to init pagemap for %d\n", pid);
		pmc_fini(pmc);
		return -1;
	}

	pr_debug("created for pid %d (takes %zu bytes)\n", pid, pmc->map_len);

	return 0;
}

static inline u64 *__pmc_get_map(pmc_t *pmc, unsigned long addr)
{
	return &pmc->map[PAGEMAP_PFN(addr - pmc->start)];
}

static int pmc_fill_cache(pmc_t *pmc, struct vma_area *vma)
{
	unsigned long low = vma->e->start & PMC_MASK;
	unsigned long high = low + PMC_SIZE;
	size_t len = vma_area_len(vma);
	size_t size_map;

	if (high > TASK_SIZE)
		high = TASK_SIZE;

	pmc->start = vma->e->start;
	pmc->end = vma->e->end;

	pr_debug("filling VMA %lx-%lx (%zuK) [l:%lx h:%lx]\n",
		 (long)vma->e->start, (long)vma->e->end, len >> 10, low, high);

	/*
	 * If we meet a small VMA, lets try to fit 2M cache
	 * window at least 75% full, otherwise left as a plain
	 * "one vma at a time" read. Note the VMAs in cache must
	 * fit in solid manner, iow -- either the whole vma fits
{'fraction_non_alphanumeric': 0.15911431513903193, 'fraction_numerical': 0.010298661174047374, 'mean_word_length': 4.152519893899204, 'pattern_counts': {'":': 0, '<': 13, '<?xml version=': 0, '>': 64, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7342333', 'n_tokens_mistral': 1789, 'n_tokens_neox': 1739, 'n_words': 431}