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

static volatile sig_atomic_t signal_received = 0;

static void handle_signal(int signo)
{
	signal_received = 1;
}

int
main(int argc, char **argv)
{
	int	num_signals;
	int	parent_pid = getpid();
	int	child_pid;

	if (argc != 2)
	{
		printf("invalid number of arguments\n");
		exit(1);
	}

	if (signal(SIGURG, handle_signal) == SIG_ERR)
	{
		printf("failed to set signal\n");
		exit(2);
	}

	num_signals = atoi(argv[1]);

	printf("nmm_signals = %d\n", num_signals);

	child_pid = fork();

	if (child_pid != 0)
	{
		int cnt = 0;
		int waiting = 0;

		struct timeval time_start;
		struct timeval time_end;

		int duration;

		/* sleep a bit, so that child starts */
		usleep(10000);

		gettimeofday(&time_start, NULL);

		while (cnt < num_signals)
		{
			if (waiting == 0)
			{
				/* send signal to child */
				waiting = 1;
				kill(child_pid, SIGURG);
			}

			/* have received response? */
			if (signal_received)
			{
				signal_received = 0;
				waiting = 0;
				cnt++;

				if (cnt % 100000 == 0)
				{
			                gettimeofday(&time_end, NULL);

        			        duration = (time_end.tv_sec - time_start.tv_sec) * 1000000 +
							(time_end.tv_usec - time_start.tv_usec);

			                printf("parent: sent %d signals in %d us (%.2f)\n", cnt, duration, (duration * 1.0 / cnt));
				}
			}
		}

		gettimeofday(&time_end, NULL);

		duration = (time_end.tv_sec - time_start.tv_sec) * 1000000 + (time_end.tv_usec - time_start.tv_usec);

		printf("parent: sent %d signals in %d us (%.2f us)\n", cnt, duration, duration * 1.0 / cnt);

		printf("signals / sec = %.2f\n", cnt / (duration / 1000000.0));
	}
	else
	{
		/* wait for signal, send signal back */
		while (1)
		{
			if (signal_received)
			{
				signal_received = 0;
				kill(parent_pid, SIGURG);
			}
		}
	}

	return 0;
}
