#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <pthread.h>

#define CHUNK_SIZE (20<<20)
#define SLEEP_TIME_SEC 	2
#define NUM_THREAD	12
#define QUIT		1000

int quit;

void alloc_thp()
{
	int i;
	int ret;
	char *ptr;

	/* should be aligned with 2M which is THP page size */
	ret = posix_memalign((void**)&ptr, 2<<20, CHUNK_SIZE);
	if (ret) {
		fprintf(stderr, "fail to allocate\n");
		return;
	}
		
	memset(ptr, 'a', CHUNK_SIZE);
	ret = madvise(ptr, CHUNK_SIZE, 5);
	if (ret) {
		perror("fail to madvise");
		return;
	}

	sleep(SLEEP_TIME_SEC);

	memset(ptr, 'b', CHUNK_SIZE);
	sleep(SLEEP_TIME_SEC);

	for (i = 0; i < CHUNK_SIZE; i++) {
		if (ptr[i] != 'b') {
			fprintf(stderr, "fail to verify\n");
			fprintf(stderr, "Something wrong\n");
			return;
		}
	}

	free(ptr);
}

void *thread_alloc(void *priv)
{
	int n = 0;

	while(!quit) {
		alloc_thp();
		if (!(n++ % 5))
			printf("I'm working\n");
		if (n == QUIT)
			return;
	}
}

int main()
{
	int i, ret;
	pthread_t thread[NUM_THREAD];

	for (i = 0; i < NUM_THREAD; i++) {
		ret = pthread_create(&thread[i], NULL, thread_alloc, NULL);
		if (ret) {
			perror("fail to create thread\n");
			return 1;
		}
	}

	scanf("%d", &quit);
	for (i = 0; i < NUM_THREAD; i++)
		pthread_join(thread[i], NULL);

	printf("Test Done\n");	
	return 0;
}