#include <sys/time.h>
#include <time.h>
#include <stdlib.h>
#include <stdio.h>
#include <signal.h>

#define	TIME_CYCLE_SEC	10

typedef unsigned long long ull;

static ull max_wait_time = 0;

void termination_handler (int signum) {
	if(signum == SIGINT) {
		printf("----------------------------\n");
		printf("Тест окончен!\n");
		printf ("Максимальная задержка за всё время = %llu микросекунд\n", max_wait_time);
		exit(0);
	}
}

int max_wait_test() {

	signal(SIGINT, termination_handler);

	struct timezone tz;
	tz.tz_minuteswest = 0;
	tz.tz_dsttime = 0;

	struct timeval tv;

	gettimeofday(&tv, &tz);
	ull last_time = ((ull)tv.tv_sec) * 1000000 + (ull)tv.tv_usec;
	ull start_tv_sec = (ull)tv.tv_sec;
	ull last_tv_sec = start_tv_sec;
	ull average_wait_time = 0;

	while( 1 == 1 ) {

		gettimeofday(&tv, &tz);

		ull mcs = ((ull)tv.tv_sec) * 1000000 + (ull)tv.tv_usec;

		ull delta_time = mcs - last_time;

		if(delta_time > max_wait_time)
			max_wait_time = delta_time;

		if(delta_time > average_wait_time)
			average_wait_time = delta_time;


		// noop на несколько наносекунд
        struct timespec wait_ts;
		wait_ts.tv_sec = 0;
		wait_ts.tv_nsec = 10;
		nanosleep(&wait_ts,NULL);

		// Выводим каждые TIME_CYCLE_SEC секунд среднюю задержку за эти TIME_CYCLE_SEC секунд
		if(last_tv_sec + TIME_CYCLE_SEC <= tv.tv_sec) {
			printf("----------------------------\n");
			printf("Время выполнения = %llu секунд\n", last_tv_sec - start_tv_sec);
			printf("Максимальная задержка за %d секунд = %llu микросекунд\n", TIME_CYCLE_SEC, average_wait_time);
			printf ("Максимальная задержка за всё время = %llu микросекунд\n", max_wait_time);
			fflush(stdout);
			gettimeofday(&tv, &tz);
			last_tv_sec = tv.tv_sec;
			mcs = ((ull)tv.tv_sec) * 1000000 + (ull)tv.tv_usec;
			average_wait_time = 0;
		}

		// сохраняем последнюю отметку времени
		last_time = mcs;
	}

	return EXIT_SUCCESS;
}

int main(int argc, char * argv[]) {

	max_wait_test();

	return EXIT_SUCCESS;
}

