#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#define __STDC_FORMAT_MACROS
#include <inttypes.h>


void Usage(void){
	printf("Usage:\n");
	printf("\t./thp-limit [pages_total(4K)] [pages_per_pass] [target_percent_time_scanning(percent of bandwidth spent scanning total)] [estimated_max_mem_GiBps(GiB/s)]\n");
	//printf("\tuint64_t input expected for each argument\n\n");
	printf("\tOutput:\n");
	printf("\ttime_to_scan_all_pages (unbounded 100 percent estimate)\n");
	printf("\tGiBps_limit (speed at target percentage)\n");
	printf("\ttotal_scan_time (in seconds)\n");
	printf("\tscan_sleep_millisecs (milliseconds)\n");
	printf("\talloc_sleep_millisecs (recommended\n");
	printf("\tnumber_of_passes\n");
}


int main(int argc, char **argv){
	uint64_t page_size = 4096;
	uint64_t pages_total;
	uint64_t pages_per_pass;
	uint64_t target_percent_time_scanning;
	uint64_t estimated_max_mem_GiBps;

	double total_scan_time;
	uint64_t number_of_passes;
	uint64_t scan_sleep_millisecs;
	uint64_t alloc_sleep_millisecs;
	double GiBps_limit;
	double time_to_scan_all_pages;
	//uint64_t num1;
	double tmp1;

	if(argc != 5){
		Usage();
		return 0;
	}
	pages_total = (uint64_t)strtoull(argv[1], NULL, 0);
	pages_per_pass = (uint64_t)strtoull(argv[2], NULL, 0);
	target_percent_time_scanning = (uint64_t)strtoull(argv[3], NULL, 0);
	estimated_max_mem_GiBps = (uint64_t)strtoull(argv[4], NULL, 0);

	number_of_passes = pages_total/pages_per_pass;

	tmp1 = (double)target_percent_time_scanning/100;
	GiBps_limit = estimated_max_mem_GiBps*tmp1;
	tmp1 = pages_total*page_size/1073741824;
	time_to_scan_all_pages = tmp1/estimated_max_mem_GiBps;

	//tmp1 = (double)target_percent_time_scanning/100;
	//total_scan_time = time_to_scan_all_pages*tmp1;

	total_scan_time = tmp1/GiBps_limit;

	tmp1 = total_scan_time/number_of_passes*1000;
	scan_sleep_millisecs = (uint64_t)tmp1;
	alloc_sleep_millisecs = scan_sleep_millisecs*4;

	printf("time_to_scan_all_pages: %lfs\n", time_to_scan_all_pages);
	printf("GiBps_limit: %lfGiB/s\n", GiBps_limit);
	printf("total_scan_time: %lfs\n", total_scan_time);
	printf("scan_sleep_millisecs: %" PRIu64 "ms\n", scan_sleep_millisecs);
	printf("alloc_sleep_millisecs: %" PRIu64 "ms\n", alloc_sleep_millisecs);
	printf("number_of_passes: %" PRIu64 "\n", number_of_passes);

	return 0;
}
