#include <fcntl.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>

int main(int argc, char **argv)
{
	long page_mask;
	int fd;
	long *addr;
	long total = 0;
	struct stat stat;
	size_t i, length;
	bool write = false;

	while (argc > 2) {
		if (!strcmp(argv[1], "-w")) {
			write = true;
			argv++;
			argc--;
		}
	}
	if (argc != 2)
		return 1;
	fd = open(argv[1], O_RDWR);
	if (fd < 0) {
		perror(argv[1]);
		return 1;
	}

	if (fstat(fd, &stat) < 0) {
		perror(argv[1]);
		return 1;
	}

	page_mask = sysconf(_SC_PAGESIZE) - 1;
	if (length > SIZE_MAX)
		length = SIZE_MAX;
	else
		length = stat.st_size;
	length = (length + page_mask) & ~page_mask;
	addr = mmap(NULL, length, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
	if (addr == MAP_FAILED) {
		perror(argv[1]);
		return 1;
	}
printf("addr:%p\n", addr);

	if (madvise(addr, length, MADV_HUGEPAGE) < 0) {
		perror(argv[1]);
		return 1;
	}

	for (i = 0; i < length / sizeof(long); i++)
		if (write)
			addr[i] += total;
		else
			total += addr[i];

	addr[0] = total;
	return 0;
}