#include <signal.h>
#include <stdio.h>
#include <stdlib.h>

#include <unistd.h>
#include <pthread.h>
#include <limits.h>
#include <pthread.h>
#include <time.h>
#include <stdbool.h>
#include <sys/mman.h>

//********************************************************************************************************************
// global functions
//********************************************************************************************************************

static bool bRunning = true;

static void vStop(int sig)
{
	(void)sig;
	bRunning = false;
}

#define iTimers	150
static pthread_t thread[iTimers];

static void *vWorker(void *param)
{
	unsigned int iTime = rand() % 1000;
	struct timespec abstime = {
		.tv_sec = (iTime / 1000),
		.tv_nsec = 1000000 * (iTime % 1000),
	};

	(void)param;

	clock_nanosleep(CLOCK_MONOTONIC, 0, &abstime, NULL);

	return NULL;
}

void *vLoop(void *param)
{
	bool first = true;
	unsigned long i;

	(void)param;

	while (bRunning) {
		usleep(500 * 1000);
		for (i = 0; i < iTimers; i++) {
			pthread_attr_t rThreadAttr;

			pthread_attr_init(&rThreadAttr);
			pthread_attr_setdetachstate(&rThreadAttr, PTHREAD_CREATE_JOINABLE);
			pthread_attr_setstacksize(&rThreadAttr, PTHREAD_STACK_MIN);
			if (!first)
				pthread_join(thread[i], NULL);
			pthread_create(thread + i, &rThreadAttr, vWorker, NULL);
		}
		first = false;
	}

	for (i = 0; i < iTimers; i++)
		pthread_join(thread[i], NULL);

	return 0;
}

int main(int argc, char *argv[])
{
	pthread_t rLoopThread;
	pthread_attr_t rThreadAttr;

	(void)argc;
	(void)argv;

	signal(SIGTERM, vStop);
	signal(SIGINT, vStop);

	mlockall(MCL_FUTURE);

	pthread_attr_init(&rThreadAttr);
	pthread_attr_setdetachstate(&rThreadAttr, PTHREAD_CREATE_JOINABLE);
	pthread_attr_setstacksize(&rThreadAttr, PTHREAD_STACK_MIN);
	pthread_create(&rLoopThread, &rThreadAttr, vLoop, NULL);

	pthread_join(rLoopThread, NULL);

	return 0;
}
